POV-Ray : Newsgroups : povray.unofficial.patches : Question about applying a user defined function into density functions Server Time
4 Dec 2024 14:01:42 EST (-0500)
  Question about applying a user defined function into density functions (Message 1 to 4 of 4)  
From: Antonio Ferrari
Subject: Question about applying a user defined function into density functions
Date: 5 Oct 2007 09:30:00
Message: <web.47063b40f8b04a964e64f15d0@news.povray.org>
I'd like that the density is a function
of the minimal distance of V from the external surface of O: for V internal,
density[V] = density_function(minimal_distance(O,V)). In particular I'd like
a function the make the density greater when moving toward the interior of
O, where the increment could be linear, exponential, logarithmic, etc.

Is there a function for calculating the minimal distance of an internal
point V from the contour of O?

Some time ago I had the following idea: calculating the dimensions X, Y and
Z of the box containing O. Subdivide both X, Y and Z into n segments. Use
of 3 innested loops for x, y and z axis in order to cycle the segments and
see if the are or are not part of the interior of O. This is a sort of
sampling method. The greater n is, the more accurate the samples are. Then
I needed an algorithm for finding interior points at first level,
second level, third level, etc. The greater the level, the higher the
density, for example.

Let suppose that the intersection of the object with a plane is (in 2D) as
follows:

  @@@@@@@@@
 @         @
@           @
@           @
 @         @
  @@@@@@@@@

Let's do our considerations in 2D, but they can be extended in 3D easily.

  @@@@@@@@@
 @111111111@
@12222222221@
@123333333321@
@12222222221@
 @111111111@
  @@@@@@@@@

What I'd want isn't a generic Your_Function with parameters x, y or z. What
I want is a density function with only a parameter d, where d is the
distance of the vector V=<x,y,z> from the contour of the surface, V inside
the object. It's obvious that there are some preconditions to impose...

Look at the 2D section... Let's consider a linear density function.
Your_Function conincide with the distance. So, for point at distance 1,
density is 1; for points at distance 2, density is 2; and so on...........


NOW Tim have suggested another an interesting idea... follow his answer:

"Tim Attwood" <tim### [at] comcastnet> wrote:
> There isn't a built in function for this, because there isn't a single
> answer
> to how far a minimal distance point is from the surface. You can use
> trace to collect a sample of distances from the surface in random
> directions to appoximate the minimal distance of a voxel from the
> surface.
>
> #include "rand.inc"
> #macro distToSurface(Obj, vec, samp, rsd)
>    #local dist = 1000000;
>    #local c=0;
>    #while (c<samp)
>       #local rdir = VRand_On_Sphere(rsd);
>       #declare Norm = <0, 0, 0>;
>       #local hit = trace(Obj, vec, rdir, Norm);
>       #if (vlength(Norm) != 0)
>          #local dist = min(dist, vlength(hit - vec));
>       #end
>       #local c=c+1;
>    #end
> #end

Inspired by this macro I've tried to write a patch in order to "cable" it
into source code. So, I've modified express.cpp and I've added a new token
similar to TRACE_TOKEN. Substancially I've added the function "mdistance"
that takes four parameters:

mdistance(OBJECT_IDENTIFIER, V, nr_samples, [VECTOR_IDENTIFIER])

Parameters are:

- An object ID
- A vector V
- samples is an integer greater than 0
- VECTOR_IDENTIFIER is an optional vector ID

What the function do: it generates nr_samples in random directions trying to
find the minimal distance of the point V from the surface of the Object. At
every iteration uses the code of trace and vlength function for calculating
the distance from the Object. At the end it returns the minimal distance. If
a vector_identifier is given, the point on the surface with minimal distance
from V is stored into it.

What TO DO:

1 - Check if V is inside or outside the object -> if outside, always returns
0;
2 - Improve random number generator
3 - Add some optimization passes. At first step a rough minimal distance is
found; at second step further rays are traced in a space closed to what is
found at step 1.
4 - Some check, for some particular / complex objects (I dont't know how to
do it...)

I haven't tested the code yet, because I'm out of Linux and with Cygwin I've
no time to play.

Now my question: could such a function be used in density functions? For
example could I write a density function like A+B*mdistance(x, y, z)^C,
with A, B, C real values ????

If such a function would work, I'd have found a method for calculating the
density as a function of the (minimal) distance of a point from the
surface. This could help me to better USE medias BETTER for having
subsurface scattering results...

If the function can't be used, I'll have to find other solutions or
pathes...


static void Parse_MDistance(DBL & mdist) {

   OBJECT *Object;
   INTERSECTION Intersect;
   RAY    Ray;
   VECTOR Local_Normal;
   VECTOR Res;

   GET (LEFT_PAREN_TOKEN);

   EXPECT
     CASE (OBJECT_ID_TOKEN)
       Object = (OBJECT *)Token.Data;
       EXIT
     END_CASE

     OTHERWISE
       Object = NULL;
       UNGET
       EXIT
     END_CASE
   END_EXPECT

   if (Object == NULL) Error ("Object identifier expected.");

   Parse_Comma();

   Initialize_Ray_Containers( &Ray );
   Parse_Vector(Ray.Initial);
   Parse_Comma();
   int nr_iterations = (int)Parse_Float();
   if (nr_iterations < 1) nr_iterations = 1; // 1 or a greater value ??

   srand( (unsigned int)time(0) );
   mdist = 999999; // how much big ??
   VECTOR MVect;

   for (int itr = 0; itr < nr_iterations; itr = itr + 1) {

  Ray.Direction[X]=((DBL)rand()/INT_MAX)-0.5; // is there a better random
generator (srad48, etc.) ??
  Ray.Direction[Y]=((DBL)rand()/INT_MAX)-0.5;
 Ray.Direction[Z]=((DBL)rand()/INT_MAX)-0.5;
 VNormalizeEq( Ray.Direction );

 VECTOR normal_vector;
 normal_vector[X]=0.0;
 normal_vector[Y]=0.0;
  normal_vector[Z]=0.0;

 if ( Intersection( &Intersect, Object, &Ray ) ) {
        Assign_Vector( Res, Intersect.IPoint );
        Normal( Local_Normal, Intersect.Object, &Intersect );
  }
  else {
        Res[X]=Res[Y]=Res[Z]=0;
        Local_Normal[X] = Local_Normal[Y] = Local_Normal[Z] = 0;
  }

 Destroy_IStacks(); // this line here or out of FOR cycle ????

  if ( sqrt(Local_Normal[X] * Local_Normal[X] + Local_Normal[Y] *
Local_Normal[Y] + Local_Normal[Z] * Local_Normal[Z]) != 0 ) {
     VECTOR vect2;
     vect2[X] = Res[X] - Ray.Initial[X];
     vect2[Y] = Res[Y] - Ray.Initial[Y];
     vect2[Z] = Res[Z] - Ray.Initial[Z];
     DBL vl = sqrt(vect2[X] * vect2[X] + vect2[Y] * vect2[Y] + vect2[Z] *
vect2[Z]);
            if ( vl < mdist) {
               mdist = vl;
              MVect[X] = Res[X];
              MVect[Y] = Res[Y];
              MVect[Z] = Res[Z];
           }
     }

  }

  EXPECT
     CASE (VECTOR_FUNCT_TOKEN)
       /* All of these functions return a VECTOR result */
       if(Token.Function_Id == VECTOR_ID_TOKEN)
       {
         Assign_Vector((DBL *)Token.Data, MVect);
       }
       else
       {
         UNGET
       }
       EXIT
     END_CASE

     OTHERWISE
       UNGET
       EXIT
     END_CASE
  END_EXPECT

  GET (RIGHT_PAREN_TOKEN);

}



Bye,
Antonio Ferrari


Post a reply to this message

From: Antonio Ferrari
Subject: Re: Question about applying a user defined function into density functions
Date: 5 Oct 2007 09:45:00
Message: <web.47063e9ef0b2498d4e64f15d0@news.povray.org>
> Now my question: could such a function be used in density functions? For
> example could I write a density function like A+B*mdistance(x, y, z)^C,
> with A, B, C real values ????

I auto-correct myself... the function I'de like is

A+B*mdistance(Obj, <x, y, z>, 1000)^C


Post a reply to this message

From: Antonio Ferrari
Subject: Re: Question about applying a user defined function into density functions
Date: 9 Oct 2007 09:10:01
Message: <web.470b7cbef0b2498d4e64f15d0@news.povray.org>
"Antonio Ferrari" <nomail@nomail> wrote:
> > Now my question: could such a function be used in density functions? For
> > example could I write a density function like A+B*mdistance(x, y, z)^C,
> > with A, B, C real values ????
>
> I auto-correct myself... the function I'de like is
>
> A+B*mdistance(Obj, <x, y, z>, 1000)^C

No responses arrive unfortunately :(

Anyway I think that such a formula will not work!

Since my idea is to use mdistance as density function, I suppose that I have
to implement it into media.cpp code and not into express.cpp.


Post a reply to this message

From: Grassblade
Subject: Re: Question about applying a user defined function into density functions
Date: 9 Oct 2007 16:40:00
Message: <web.470be6b3f0b2498d44bccc1e0@news.povray.org>
"Antonio Ferrari" <nomail@nomail> wrote:
> I'd like that the density is a function
> of the minimal distance of V from the external surface of O: for V internal,
> density[V] = density_function(minimal_distance(O,V)). In particular I'd like
> a function the make the density greater when moving toward the interior of
> O, where the increment could be linear, exponential, logarithmic, etc.
>
> Is there a function for calculating the minimal distance of an internal
> point V from the contour of O?
>
If the surface is continuous, I'd imagine that there is such a function.
> <Snip>
> What I'd want isn't a generic Your_Function with parameters x, y or z. What
> I want is a density function with only a parameter d, where d is the
> distance of the vector V=<x,y,z> from the contour of the surface, V inside
> the object. It's obvious that there are some preconditions to impose...
>
Supposing you do have the generic Your_Function (x,y,z) that returns d, all
you have to do is to invert said function. Assuming it can be inverted,
that is. ;-)
> <Snip>
> mdistance(OBJECT_IDENTIFIER, V, nr_samples, [VECTOR_IDENTIFIER])
>
> Parameters are:
>
> - An object ID
> - A vector V
> - samples is an integer greater than 0
> - VECTOR_IDENTIFIER is an optional vector ID
>
> What the function do: it generates nr_samples in random directions trying to
> find the minimal distance of the point V from the surface of the Object. At
> every iteration uses the code of trace and vlength function for calculating
> the distance from the Object. At the end it returns the minimal distance.
Personally, I dislike brute force approaches, but if that's ok for you who
am I to argue. I would rather use a smallish number of samples, pick the
smallest, then use a optimisation algorithm like steepest descent (very
easy to code) or nonlinear conjugate gradient to find the "true" minimum in
a small number of iterations. Optimisation algorithms are local in nature,
so using an adequate number of samples to get in the vicinity of the global
minimum is paramount.
> If
> a vector_identifier is given, the point on the surface with minimal distance
> from V is stored into it.
>
> What TO DO:
>
> 1 - Check if V is inside or outside the object -> if outside, always returns
> 0;
> 2 - Improve random number generator
Mersenne twister is what you want. Available in a number of programming
languages:
http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/VERSIONS/eversions.html
> 3 - Add some optimization passes. At first step a rough minimal distance is
> found; at second step further rays are traced in a space closed to what is
> found at step 1.
> 4 - Some check, for some particular / complex objects (I dont't know how to
> do it...)
>
> I haven't tested the code yet, because I'm out of Linux and with Cygwin I've
> no time to play.
>
> Now my question: could such a function be used in density functions? For
> example could I write a density function like A+B*mdistance(x, y, z)^C,
> with A, B, C real values ????
You *can* use functions to specify densities. See
http://news.povray.org/povray.advanced-users/thread/%3Cweb.46a617d4ef6472d8f75a90cb0@news.povray.org%3E/
The big problem I see with this method is that you'd have a blocky
definition to your media (at least I *think*). It might work if your
density voxels are of a size with the pixels of the final image, but that
would almost certainly mean really long parsing time to get all the
distances.
The best solution IMO is to make use of isosurfaces' threshold.


Post a reply to this message

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