POV-Ray : Newsgroups : povray.advanced-users : Implicit loops in function(x,y,z) Server Time
1 Jul 2024 05:33:01 EDT (-0400)
  Implicit loops in function(x,y,z) (Message 1 to 10 of 18)  
Goto Latest 10 Messages Next 8 Messages >>>
From: slehar
Subject: Implicit loops in function(x,y,z)
Date: 14 Jul 2008 11:00:00
Message: <web.487b67e61050228f75a90cb0@news.povray.org>
I am having endless trouble trying to define a density function that varies as a
function of (x,y,z) position, due to confusion over a kind of "implicit loop"
concept in POV-Ray. Does anyone know a manual page or user post on this
subject, or even what this "implicit loop" concept is officially called? (I
made up that term for lack of a better one)

The issue involves a parameterized function like:

#declare densityfunc = function( x, y, z) {
  sqrt((x*x)+(y*y))
}

The actual values of (x,y,z) are (<1,0,0> <0,1,0> <0,0,1>), but the term "x*x"
in the density function does NOT mean <1,0,0> * <1,0,0>, but rather, x
represents a whole array of values, something like:

..... -9 -8 -7 -6 -5 -4 -3 -2 -1 0 1 2 3 4 5 6 7 8 9 ...

and the density function above is equivalent to a loop in a regular programming
language something like:

double Array[zSize][ySize][xSize];

for(iz=0; iz<zSize; iz++){
  for(iy=0; iy<ySize; iy++){
    for(ix=0; ix<xSize; ix++){
      Array[z][y][x] = sqrt((x[ix]*x[ix]) + (y[iy]*y[iy]));
    }
  }
}

which creates a whole 3-D array of values in the density function. But all that
looping occurs implicitly or invisibly in POV-Ray, which causes
endless confusion. For example this code

#declare densityfunc = function( x, y, z) {
  #declare xSqr = x*x;
  #declare ySqr = y*y;
  sqrt(xSqr+ySqr)
}

produces Parse Error: Expected 'operand', vector function 'vector identifier'
found instead.

The problem is that the #declare xSqr = x*x sets xSqr = <1,0,0>*<1,0,0> (=
<1,0,0>) which is now a *vector* and not the value of x at some location in the
density function!

So sometimes x is the vector <1,0,0>, and other times it is ...-2,-1,0,1,2....
What gives?


Post a reply to this message

From: Warp
Subject: Re: Implicit loops in function(x,y,z)
Date: 14 Jul 2008 11:13:23
Message: <487b6d13@news.povray.org>
slehar <sle### [at] gmailcom> wrote:
> which creates a whole 3-D array of values in the density function. But all that
> looping occurs implicitly or invisibly in POV-Ray, which causes
> endless confusion.

  No 3D array is created from your function. Your function is simply evaluated
for points in space when it's needed.

  For example, if you are using that function as a media density, when a
ray hits the media container, the inside of the container is sampled along
that ray. In other words, points on that ray are calculated, and your
function is evaluated for those points.

  Your function is not evaluated *explicitly* in a loop. It's just evaluated
any time a value from it is required for some spatial point (regardless of
which point it is or how it was calculated).

> #declare densityfunc = function( x, y, z) {
>   #declare xSqr = x*x;
>   #declare ySqr = y*y;
>   sqrt(xSqr+ySqr)
> }

  This is a completely different issue.

  I know that it's confusing for the 'function' syntax to be *similar*
to the SDL. However, inside a "function" block the language used is
completely separate and distinct from the SDL. It has nothing to do
with the SDL.

  Your #declare lines are SDL and thus are *not* parsed as part of your
function. They are evaluated as SDL. In the SDL namespace 'x' has a
completely different meaning than in your function namespace. (In SDL
'x' is a constant which value is <1, 0, 0>).

  If you want to avoid confusion, don't use 'x', 'y' or 'z' as your
function parameters, but use something else, for example:

#declare densityfunc = function(X, Y, Z) { ... };

  X, Y and Z have no default meaning in SDL, so they will cause less
confusion and clearer error messages.

  SDL code can be used to build functions, but once they have been built,
the function itself knows nothing about the SDL. The function will be
the same as if you had manually replaced every SDL command and identifier
with their equivalent interpreted value.

> So sometimes x is the vector <1,0,0>, and other times it is ...-2,-1,0,1,2....

  Don't use "x" as the name of your function parameter, if you want to
avoid confusion. Use something else, as I suggested above.

-- 
                                                          - Warp


Post a reply to this message

From: slehar
Subject: Re: Implicit loops in function(x,y,z)
Date: 14 Jul 2008 11:55:00
Message: <web.487b763d26dbfbf0f75a90cb0@news.povray.org>
Warp <war### [at] tagpovrayorg> wrote:
> inside a "function" block the language used is
> completely separate and distinct from the SDL. It has nothing to do
> with the SDL.
>
>   Your #declare lines are SDL and thus are *not* parsed as part of your
> function. They are evaluated as SDL.

Do you mean that you cannot #declare temporary variables in a function?

#declare densityfunc = function( px, py, pz) {
  #declare pxVal = px;
  #declare pyVal = py;
  atan2(pyVal, pxVal)
}

You can only use the values directly?

#declare densityfunc = function( px, py, pz) {
  atan2(py, px)
}


Post a reply to this message

From: Warp
Subject: Re: Implicit loops in function(x,y,z)
Date: 14 Jul 2008 12:14:24
Message: <487b7b60@news.povray.org>
slehar <sle### [at] gmailcom> wrote:
> Do you mean that you cannot #declare temporary variables in a function?

  The SDL and a user-defined function are completely separate namespaces.
You cannot mix them.
  The only thing you can do with SDL is to generate content for the function,
but the SDL doesn't see the function in any way or form.

  It's a big like if you used #write commands to generate a program in C.
The C program knows nothing about the SDL, and the SDL knows nothing about
C. Their only relation was that the SDL was used to generate the C source
code.

  It's not much different with user-defined functions: They don't know
anything about each other (even though you can use SDL to generate the
contents of a function).

  Yes, I know it's a bit confusing because these two distinct languages
look a bit alike (both use, for example, mathematical functions named
in the same way).

  You cannot have any kind of variables (besides the function parameters)
in functions, because the function syntax doesn't support them.

> #declare densityfunc = function( px, py, pz) {
>   #declare pxVal = px;
>   #declare pyVal = py;
>   atan2(pyVal, pxVal)
> }

  When POV-Ray finds the #declare, it jumps to the SDL parser (until
the #declare ends in the semi-colon). In that context it doesn't know
what 'px' or 'py' means because they don't exist in the SDL namespace.

  If you assigned pxVal and pyVal something else, eg. 1 and 2, then
it would work. However, what is happening is that you are simply generating
the function contents using SDL (in other words, POV-Ray substitutes pxVal
with 1 and pyVal with 2 when it encounters them, and then the function
parser sees them as numeral values).

> You can only use the values directly?

  You can only use function parameter names in the function because
those are the only things defined inside the function's namespace.

-- 
                                                          - Warp


Post a reply to this message

From: slehar
Subject: Re: Implicit loops in function(x,y,z)
Date: 14 Jul 2008 12:50:01
Message: <web.487b835026dbfbf0f75a90cb0@news.povray.org>
Thanks very much for your help, that clears things up a bit for me!


Post a reply to this message

From: slehar
Subject: Re: Implicit loops in function(x,y,z)
Date: 14 Jul 2008 14:55:01
Message: <web.487b9ff826dbfbf0f75a90cb0@news.povray.org>
So it seems you can't do logical tests on the values of the parameters in a
function either!

#declare densityfunc = function(px,py,pz) {
  #if(px > 0 | py < 0)
    atan2(py,px)
  #else
    pi - atan2(py,px)
  #end
}

Parse Error: ... undeclared identifier 'px'

That makes it kind of difficult to use functions like atan2() that can behave
differently in different quadrants. How would you get around this kind of
thing? How can I make the function use one equation in some quadrants and a
different equation in other quadrants?


Post a reply to this message

From: Warp
Subject: Re: Implicit loops in function(x,y,z)
Date: 14 Jul 2008 15:05:33
Message: <487ba37d@news.povray.org>
slehar <sle### [at] gmailcom> wrote:
> So it seems you can't do logical tests on the values of the parameters in a
> function either!

  Any #-command is SDL. Any SDL-declared identifier is SDL. You can't use
them in functions (except to build the function body).

> #declare densityfunc = function(px,py,pz) {
>   #if(px > 0 | py < 0)
>     atan2(py,px)
>   #else
>     pi - atan2(py,px)
>   #end
> }

  Why would you want to use two versions of atan2(), given that it works
with all possible values of the parameters?

  Anyways, the user-defined function syntax has a function called select()
which you can use to test for conditions and select different functions
depending on them.

-- 
                                                          - Warp


Post a reply to this message

From: Mike Williams
Subject: Re: Implicit loops in function(x,y,z)
Date: 15 Jul 2008 01:50:16
Message: <gg$T6rCHpDfIFw14@econym.demon.co.uk>
Wasn't it slehar who wrote:
>
>So it seems you can't do logical tests on the values of the parameters in a
>function either!
>
>#declare densityfunc = function(px,py,pz) {
>  #if(px > 0 | py < 0)
>    atan2(py,px)
>  #else
>    pi - atan2(py,px)
>  #end
>}
>
>Parse Error: ... undeclared identifier 'px'
>
>That makes it kind of difficult to use functions like atan2() that can behave
>differently in different quadrants. How would you get around this kind of
>thing? How can I make the function use one equation in some quadrants and a
>different equation in other quadrants?

#if doesn't work inside a function. You have to use select().
   select((px>0|py<0),pi-atan2(py,px),atan2(py,px))
[Hint, "true" is -1, "false" is 0]

However, since px and py are constants (they don't vary with the 
location within the function) you can write

   #if(px > 0 | py < 0)
     #declare A = atan2(py,px);
   #else
     #declare A = pi - atan2(py,px);
   #end

function { ...  A ... }

And as a side effect, the function evaluates faster because you're not 
performing all those atan() calculations for every point evaluated by 
the function.

-- 
Mike Williams
Gentleman of Leisure


Post a reply to this message

From: Blue Herring
Subject: Re: Implicit loops in function(x,y,z)
Date: 15 Jul 2008 09:47:24
Message: <487caa6c@news.povray.org>
Warp wrote:
> slehar <sle### [at] gmailcom> wrote:
>> So it seems you can't do logical tests on the values of the parameters in a
>> function either!
> 
>   Any #-command is SDL. Any SDL-declared identifier is SDL. You can't use
> them in functions (except to build the function body).

To make things even more confusing, declared functions CAN be called by 
SDL during parse time.  For example:

#declare Foo = function(A) { A + 3 }
#declare Bar = Foo(6);

-- 
-The Mildly Infamous Blue Herring


Post a reply to this message

From: Warp
Subject: Re: Implicit loops in function(x,y,z)
Date: 15 Jul 2008 10:17:58
Message: <487cb195@news.povray.org>
Blue Herring <pov### [at] bherringcotsenet> wrote:
> To make things even more confusing, declared functions CAN be called by 
> SDL during parse time.

  The function name, once #declared, is in the SDL namespace, and the SDL
can call that function. I don't think that's so confusing.

-- 
                                                          - Warp


Post a reply to this message

Goto Latest 10 Messages Next 8 Messages >>>

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