POV-Ray : Newsgroups : povray.advanced-users : function select logic : Re: function select logic Server Time
2 May 2024 21:37:35 EDT (-0400)
  Re: function select logic  
From: clipka
Date: 23 Nov 2016 17:18:35
Message: <583615bb$1@news.povray.org>
Am 23.11.2016 um 21:50 schrieb Mike Horvath:
> On 11/23/2016 12:19 PM, Bald Eagle wrote:
>> #declare LimitRange = function (Number) {
>>  select (Number,      // Input
>>  666,        // special flag value for values less than zero
>>  select (1-Number, 666, Number)  // second select operation
>>  )        // 1 - 0 = 1
>> }         // 1 - 1 = 0
>>          // 1 - 1.1 = - 0.1
>>          // so using (1 - Number) then filters out numbers greater than 1
>> #for (Number, -1, 2, 0.5)
>>  #declare Result = LimitRange (Number);
>>  #debug concat( "Number = ", str(Number, 3, 1),  "     Result = ",
>> str(Result,
>> 3, 1), "\n")
>> #end
> 
> Can this be used to generate an isosurface? Will the 666 break an
> isosurface?

Don't listen to that man.

Isosurfaces need contiguous functions, and the key to "discarding" some
set of coordinates from an isosurface is via the threshold.

You want to find a function f(x,y,z) and a threshold T so that
f(x,y,z)<T if all of R, G and B are within the range 0..1, f(x,y,z)>T if
any is outside that range, and f(x,y,z)=0 if any is exactly on a border
of the range. You also want f(x,y,z) to increase reasonably steadily
near the borders.

In other words, you need a function that gives you a kind of estimate
how close you are to the border, with f<T indicating that you are on the
inside, f>T that you are on the outside.

If you only had R and the upper bound of 1 to worry about, the task
would be easy-peasy: All you'd need is a threshold, and a reasonably
smooth function that is below that threshold for inside points, and
above the threshold for outside points. You already have that:

    T = 1
    f(x,y,z) = R(x,y,z)

If you only had R and the lower bound of 0 to worry about, the task is
also not too difficult: Again you already have a threshold; the function
R won't fit as-is though, as it would be below the threshold outside,
and above the threshold inside. But that can easily be fixed:

    T = 0
    f(x,y,z) = -R(x,y,z)

However, if you have to worry about both the upper and lower bound, you
need a function that "dips" below the threshold between the bounds; The
mathematical absolute is a good basis for this; for example, the
following would test for the bounds -1 and 1:

    T = 1
    f(x,y,z) = abs(R(x,y,z))

This doesn't perfectly fit your problem, as the lower bound is wrong.
Now we don't have any trivial single operation that could fix that, but
changing the threshold will change the total width of the interval while
keeping its center unaffected, and adding a constant to the abs()
parameter will change the center while keeping its total width
unaffected. So after some deliberation, we'll end up with:

    T = 0.5
    f(x,y,z) = abs(R(x,y,z)-0.5)

At R=0 this evaluates to:

    f = abs(0-0.5) = abs(-0.5) = 0.5 = T

and at R=1 it evaluates to:

    f = abs(1-0.5) = abs(0.5) = 0.5 = T


Now that we have figured out how to test for R being inside the bounds,
we can move on to G and B: Obviously the basic principle is the same, so
all we need to figure out is how to combine the three:

    T = 0.5
    fR(x,y,z) = abs(R(x,y,z)-0.5)
    fG(x,y,z) = abs(G(x,y,z)-0.5)
    fB(x,y,z) = abs(B(x,y,z)-0.5)

We need to find a single function f(x,y,z) so that f<T if all of
fR,fG,fB are smaller than T, but f>T if any is larger than T.

It turns out that max(fR,fG,fB) should give us exactly that. So we end
up with:

    T = 0.5
    f(x,y,z) = max (
      abs(R(x,y,z)-0.5),
      abs(G(x,y,z)-0.5),
      abs(B(x,y,z)-0.5)
    )


Post a reply to this message

Copyright 2003-2023 Persistence of Vision Raytracer Pty. Ltd.