





 
 




 
 


I have an isosuface made from multiple functions that is working quite nicely
but I want to rearrange the order of the functions to see the different(?)
results. The code is complex, so I'll leave out the ugly function details and
syntax. The following is just pseudo code.
Right now, it is like this (very simplified):
isosurface{
function{A + B + C + D}
....
}
Only four, thankfully! :)
Does the order of the functions matter when POVray evaluates them? Or are they
evaluated 'all at once' regardless of the order?
If the ordering does matter, what would be the most efficient way to set up
'switches' at the beginning of the scene to easily change the order of A,B,C and
D? Possibilities that occur to me would be some kind of combination of
#switch/#case, or #if blocks, or select(?), or maybe an array; but I want the
topofcode selection process to be relatively easy something like
#declare FUNCTION_ORDER= <C,A,D,B>;
.... and without having to make multiple copies of the functions for all of the
different permutations.
Any ideas?
(BTW: #if and #switch/#case do work well in the body of the isosurface, within
the main function, to at least eliminate certain parts. Probably not good code
practice, but it causes no problems AFAIK.)
Post a reply to this message


 
 




 
 


hi,
"Kenneth" <kdw### [at] gmailcom> wrote:
> ... but I want the
> topofcode selection process to be relatively easy something like
> #declare FUNCTION_ORDER= <C,A,D,B>;
> .... and without having to make multiple copies of the functions for all of the
> different permutations.
>
> Any ideas?
you could supply some integer corresponding to eg a #case via the commandline,
using the "declare=myInt=N" option switch.
re the function stuff (sticking my neck out :)), I'd say 'A + B' will be
evaluated as per the expression (parser) syntax:
<https://wiki.povray.org/content/Reference:Numeric_Expressions#Operators>
regards, jr.
Post a reply to this message


 
 


From: Thomas de Groot
Subject: Re: isosurface: Does the order of multiple functions matter?
Date: 28 Jan 2023 07:30:08
Message: <63d51550$1@news.povray.org>



 
 


Op 2812023 om 11:25 schreef Kenneth:
> I have an isosuface made from multiple functions that is working quite nicely
> but I want to rearrange the order of the functions to see the different(?)
> results. The code is complex, so I'll leave out the ugly function details and
> syntax. The following is just pseudo code.
>
> Right now, it is like this (very simplified):
> isosurface{
> function{A + B + C + D}
> ....
> }
>
> Only four, thankfully! :)
>
> Does the order of the functions matter when POVray evaluates them? Or are they
> evaluated 'all at once' regardless of the order?
>
> If the ordering does matter, what would be the most efficient way to set up
> 'switches' at the beginning of the scene to easily change the order of A,B,C and
> D? Possibilities that occur to me would be some kind of combination of
> #switch/#case, or #if blocks, or select(?), or maybe an array; but I want the
> topofcode selection process to be relatively easy something like
> #declare FUNCTION_ORDER= <C,A,D,B>;
> .... and without having to make multiple copies of the functions for all of the
> different permutations.
>
> Any ideas?
>
Funny you ask that, I am currently also wondering about the same. ;)
I get the impression that it does not really matter, however, when in
doubt, I tend to use parentheses to isolate/group some parts.
My example here (from a project  not isosurfaces  I am slowly working on):
function(x,z) { 2*( f_bozo(5*(x0.5), 0, 5*(z0.5)) *
f_granite(15*(x0.5), 0, 15*(z0.5)) ) * f_spherical(2.1*(x0.5), 0,
2.1*(z0.5))}
uses multiplicators, which is somewhat easier to visualise for me, but I
think I did not really got surprises when I experimented with + or .
Fun to experiment with indeed.
> (BTW: #if and #switch/#case do work well in the body of the isosurface, within
> the main function, to at least eliminate certain parts. Probably not good code
> practice, but it causes no problems AFAIK.)
>
As long as it does what is intended...

Thomas
Post a reply to this message


 
 




 
 


Thomas de Groot <tho### [at] degrootorg> wrote:
>
> Funny you ask that, I am currently also wondering about the same. ;)
>
It must be the Vulcan 'mindmeld'!
> I get the impression that it does not really matter, however, when in
> doubt, I tend to use parentheses to isolate/group some parts.
>
For multiplication of functions, I readily agree. It's the addition of functions
that has me puzzled. Strangely, I have never given much thought to the order of
them until now.
My present code is *so* complex for both the isosurface and matching texture
(pigment) functions that I cannot easily discern how the functions interact
visually, or if the order of them really matters.
I guess I should set up a muchsimplified test with maybe two functions, and
switch them around to see...perhaps using a box function as the main object,
then sin(...) and f_noise3d for A and B. Or some other simple yet clearly
'different' pair of distortions. I'm still not entirely sure of what to expect,
or if I could even understand the visual difference when switching the two. It
is an interesting experiment to try, but difficult to previsualize the outcome.
I suppose that if there is *any* change at all, then the order does matter.
Post a reply to this message


 
 




 
 


"Kenneth" <kdw### [at] gmailcom> wrote:
> Right now, it is like this (very simplified):
> isosurface{
> function{A + B + C + D}
> ....
> }
Since you only have addition (or subtraction), your function is both associative
and commutative with respect to the relevant terms.
If you had multiplication or division, it would (also) be distributive with
respect to the affected terms.
Once you start to do things that are "termspecific", like daisychaining
functions together like A(B(C(D(n)))) or having the need to enclose things in
parentheses to get the proper sign or Order of Operations, then you need to be
organized and aware of the consequences of changing things around.
you may have 5  x + a, or 5  x a, which is different than 5  (x+a) and 5 
(xa).
5a/x will be different than (5a)/x
same with 5a*x and (5a)*x
So, you can use an online equation solver to evaluate the equation in symbolic
terms, or to plug in values. You can also evaluate parts of your functions in
POVRay and send the result to the #debug stream.
#declare A = function (N) {sqrt(N)}
#declare Result = A (27);
#debug concat (str(Result, 0, DecimalPlaces), " \n")
If you are unsure about changing things around, then you can start to separate
terms in your functions into subfunctions and then start to recombine them.
#declare A = function (X, Y, Z, N) {(3*X + pow (Y, 3))/Z*sqrt(N)}
#declare Asub1 = function (X, Y, Z, N) {(3*X + pow (Y, 3))/Z}
#declare Asub1a = function (X, Y, Z, N) {3*X+pow (Y, 3)}
#declare Asub2a = function (X, Y, Z, N) {3*X}
#declare Asub2b = function (X, Y, Z, N) {pow (Y, 3)}
#declare Asub1b = function (X, Y, Z, N) {Asub2a (X, Y, Z, N) + Asub2b (X, Y, Z,
N)}
#declare Asub1c = function (X, Y, Z, N) {Asub1b (X, Y, Z, N)/ Z}
#declare Asub2c = function (X, Y, Z, N) {sqrt(N)}
#declare Asub3 = function (Term1, Term2) {Asub1c (X, Y, Z, N) * Asub2c (X, Y, Z,
N)}
*before 1st coffee, untested code
So you can see inside the curly brackets how the functions get simpler, but due
to the nature of POVRay's function parser, the expressions to evaluate those
can get more complex. It is however, good practice to understand the finer bits
of the function syntax and why things go wrong, and how they can go wrong in a
hurry.
If you do you evaluations with a macro and declaring local identifiers to be the
result of chains of operations, then you can get the answers you need in the
#debug stream, and use that as a guide to getting it right in the invisible and
complicated operations that happen in functions and isosurfaces.
Your mission, Kenneth, should you choose/decide to accept it, is to concatenate
these functions and successfully render an errorfree isosurface. As always,
should you or any of your POVRay collaborators be caught or killed, the Dev
Team will disavow any knowledge of your actions. This message will selfdestruct
in ten POV units. Good luck, Kenneth.
Post a reply to this message


 
 




 
 


"Kenneth" <kdw### [at] gmailcom> wrote:
>
> For multiplication of functions, I readily agree. It's the addition of functions
> that has me puzzled...
>
> I guess I should set up a muchsimplified test with maybe two functions, and
> switch them around to see...
Well, I did the test. With *three* simple functions! To make a long story short:
The order of the functions does not matter. Perhaps I should have expected that,
although it wasn't obvious to my way of thinking :(
So the bigger question of how to easily switch them around is... of no
importance, ha. Sorry for the wasted brain power, lads. I'm actually not
disappointed it at least makes my code simpler!
Thanks for the comments and suggestions though; they always get me to think more
deeply.
In case you want to try the quick test (no need for 'highquality' settings
here):

#declare BUMPS_F =
function{pattern{bumps scale .2}}
#declare GRANITE_F =
function{pattern{granite scale 3}}
#declare SIN_F = function(x){sin(7*pi*x)}
isosurface{
function { sqrt(pow(x,2)+pow(y,2)+pow(z,2)).7 // sphere
// switch these around...
+ BUMPS_F(x,y,z)*.5
 GRANITE_F(x,y,z)*.5
 SIN_F(x)*.2
}
threshold 0
accuracy .01
max_gradient 8
contained_by{box{1.1,1.1}}
pigment{ rgb 1}
}
Post a reply to this message


 
 




 
 


"jr" <cre### [at] gmailcom> wrote:
>
> you could supply some integer corresponding to eg a #case via the commandline,
> using the "declare=myInt=N" option switch.
That's interesting; I didn't think of it. Thanks.
>
> re the function stuff (sticking my neck out :)), I'd say 'A + B' will be
> evaluated as per the expression (parser) syntax:
> <https://wiki.povray.org/content/Reference:Numeric_Expressions#Operators>
>
"( ) expressions in parentheses first"
Apparently, that doesn't work in my function example:
+ (BUMPS_F(x,y,z)*.5)
...again makes no difference when switched around in the function order. If I'm
writing it correctly.
It does seem that the entire set of functions is evaluated 'all at once',
regardless.
Post a reply to this message


 
 




 
 


"Bald Eagle" <cre### [at] netscapenet> wrote:
>
> Since you only have addition (or subtraction), your function is both
> associative and commutative with respect to the relevant terms.
Associative? Commutative?? Egads, who came up with those terms?? I have a vague
recollection of those things from... 100 years ago... :P Subjunctive,
prepositional... oh, wait, those are Englishlanguage terms...
>
>
> You can also evaluate parts of your functions in
> POVRay and send the result to the #debug stream.
>
> #declare A = function (N) {sqrt(N)}
> #declare Result = A (27);
> #debug concat (str(Result, 0, DecimalPlaces), " \n")
Good idea; although in my case it's more of a visual result like the bumps
pattern affecting an isosurface. I have no clue as to how debug might be used
there.
>
> If you are unsure about changing things around, then you can start to separate
> terms in your functions into subfunctions and then start to recombine them.
> [snip]
That's really neat, and useful. I *still* struggle with understanding the finer
points of function use. Your examples (here and through the years) have been a
godsend...if I can only remember them! In my current code project, many are the
times that I came up with a workable solution only by sheer trialanderror,
discarding one failed attempt after another. It's like trying to discern the
finer points of a 'foreign language' when I don't know or remember the subtle
underlying rules, from lack of practice.
Post a reply to this message


 
 




 
 


"Kenneth" <kdw### [at] gmailcom> wrote:
> Good idea; although in my case it's more of a visual result like the bumps
> pattern affecting an isosurface. I have no clue as to how debug might be used
> there.
Well, there are a number of ways that you can do these things.
you always do #declare A = function {pigment {bumps}}
and then use that to calculate numbers for your debug stream.
Another I do a lot is make a graph along one axis (usually x).
That way I can cycle through X with a loop, calculate the result, and make a
little sphere at <X, Result, 0> to see WTH is going on.
> That's really neat, and useful. I *still* struggle with understanding the finer
> points of function use. Your examples (here and through the years) have been a
> godsend...if I can only remember them!
Well, thanks  but remember, the only reason I got "this good" is because jr had
that media project, and Bill Pokorny walked me through a lot of the practical
details of using functions, and then I just practiced, practiced, practiced.
> In my current code project, many are the
> times that I came up with a workable solution only by sheer trialanderror,
> discarding one failed attempt after another. It's like trying to discern the
> finer points of a 'foreign language' when I don't know or remember the subtle
> underlying rules, from lack of practice.
Absolutely. Don't think that I don't do exactly the same thing ALL THE TIME.
The key, really, is looking at any given function and asking "what do the things
inside the curly braces need to be fully evaluated"?
And often, that's a matter of going back one daisychained function and asking
the same thing. And then doing that again.
Because if you have A which needs X, and B which needs Y, and C which needs Z,
and D which needs W, then if you have A(B(C(D()))), your function A needs: A
(X, Y, Z, W) {}, and so on, as you go further down into the curly braces.
It can be mindbending, and a real mess on the screen, but going through the
simpler functions and making the mistakes that are easier to track down because
there are fewer places for the error to be allows you to learn to "think ahead"
and keep a running tab of things that could/usually go wrong. Notes in the code
or on paper usually help me remember what the cryptic POVRay error heiroglyphs
actually MEAN in a practical sense.
The other thing that helps to work this all out in your head is to not delete
code that doesn't work. Otherwise you wind up coding the same mistakes over
and over again.
Do a #switch #case #break #end block, and copypaste #case 1 into #case 2 and
then edit case 2. If that fails, work on case 3. That way you have a running
documentation of what you've tried, what the results look like, notes on why it
failed, what worked, etc.
You can then copypaste the working code into a new scene that just works, but
retain that developmental test scene for your records. Heck, post it here, so
that people struggling with the same issues can follow along and really see how
one goes from fail to success. What doesn;t work is often more important to
know than what does, since there's so much more of it to go wading through.
Glad you're getting it all to work out.
 BW
Post a reply to this message


 
 


From: Alain Martel
Subject: Re: isosurface: Does the order of multiple functions matter?
Date: 28 Jan 2023 12:27:51
Message: <63d55b17$1@news.povray.org>



 
 


Le 20230128 à 05:25, Kenneth a écrit :
> I have an isosuface made from multiple functions that is working quite nicely
> but I want to rearrange the order of the functions to see the different(?)
> results. The code is complex, so I'll leave out the ugly function details and
> syntax. The following is just pseudo code.
>
> Right now, it is like this (very simplified):
> isosurface{
> function{A + B + C + D}
> ....
> }
>
> Only four, thankfully! :)
>
> Does the order of the functions matter when POVray evaluates them? Or are they
> evaluated 'all at once' regardless of the order?
>
> If the ordering does matter, what would be the most efficient way to set up
> 'switches' at the beginning of the scene to easily change the order of A,B,C and
> D? Possibilities that occur to me would be some kind of combination of
> #switch/#case, or #if blocks, or select(?), or maybe an array; but I want the
> topofcode selection process to be relatively easy something like
> #declare FUNCTION_ORDER= <C,A,D,B>;
> .... and without having to make multiple copies of the functions for all of the
> different permutations.
>
> Any ideas?
>
> (BTW: #if and #switch/#case do work well in the body of the isosurface, within
> the main function, to at least eliminate certain parts. Probably not good code
> practice, but it causes no problems AFAIK.)
>
The order should have no effect in this case. As long as you have all
additions or all multiplications, shuffling the terms won't change the
end result.
BUT, remember that AB is different from BA and A/B is also different
from B/A.
Post a reply to this message


 
 




 

