POV-Ray : Newsgroups : povray.general : Fitting a gothic trefoil into an equilateral triangle : Re: Fitting a gothic trefoil into an equilateral triangle Server Time
4 Aug 2024 14:26:13 EDT (-0400)
  Re: Fitting a gothic trefoil into an equilateral triangle  
From:
Date: 17 Jul 2003 21:25:36
Message: <3f174c90$1@news.povray.org>
Hi Mark!

(This thread isn't old: my last post is only 10 days ago! For me "old"
means "months ago" if it's a thread I've started or replied to.)

Steps is neither a string nor a "normal" variable: it is a macro parameter.
When POV-Ray sees, for example,

   Stairs (4) /* some transformations */ }

then Stairs is recognized as the name of a macro because it was defined by

   #macro Stairs (Steps)
     // rest of macro skipped here

This tells POV-Ray to create a new variable named Steps which is local
to the macro (i.e. destroyed at exit of the macro) and to store the
parameter value (in this example 4) in it. The effect is the same as
if the line

   #local Steps = 4;

were executed at entry into the macro. Now the loop

   #declare Step = 0;
   #while (Step<Steps)
     Stair () translate Step*<StairDepth, StairHeight, 0> }
     #declare Step = Step+1;
     #end//while Step

starts with Step=0, which is <Steps (=4 here), so makes a Stair,
increments Step to 1, this is <Steps, so makes another Stair,
increments Step to 2, this is <Steps, so makes another Stair,
increments Step to 3, this is <Steps, so makes another Stair,
increments Step to 4, this is  not <Steps, so exits.

At the next invocation of Stairs the old value of Steps is forgotten;
a new Steps variable is created containing the new parameter value.

More generally, a macro defined by, for example,

   #macro MyMacro (A_Number, A_String, An_Object)
     // ...
     #end

and invoked by

   MyMacro ( 42, "Whoa!", sphere { <1,2,3>, 4 } )

will create new variables

   A_Number with value 42
   A_String with value "Whoa!"
   An_Object with value sphere { <1,2,3>, 4 }

as if

   #local A_Number = 42;
   #local A_String = "Whoa!"
   #local An_Object= sphere { <1,2,3>, 4 }

were executed, then the macro body (everything between
"#macro MyMacro (A_Number, A_String, An_Object)" and the "#end" that
belongs to #macro, indicated by "// ..." above) will be parsed by POV-Ray,
then the local variables A_Number, A_String, An_Object are destroyed, and
parsing continues after the invocation. A macro without parameters is
sort of "copy and paste" operation (like my Stair()-macro which simply
delivers a box). Parameters allow introduction of varying elements
(everything that is allowed on the right side of the "=" of a #local
statement is allowed as parameter).


<ADVANCED STUFF>

The macro body may even modify the parameters, and when a macro invocation
gives a single declared (or "#local"ed) variable (not an expression) as
parameter value, then this variable gets the value of its associated local
parameter variable at exit of the macro. If for example the above macro is
invoked as

   MyMacro (MyNumber, MyString, MyObject)

then the variables MyNumber, MyString, MyObject reflect the values of
A_Number, A_String, An_Object just before exit of the macro as if

   #declare MyNumber = A_Number;
   #declare MyString = A_String
   #declare MyObject = An_Object

were executed just before exit of the macro.

A simple example:

   #macro Add (Value, Sum)
     #local Sum = Sum+Value;
     #end

   #declare Result = 0; // start with 0 as current value of Result
   Add (5, Result) // add 5 to the current value of Result, giving 5
   Add (7, Result) // add 7 to the current value of Result, giving 12
   Add (3, Result) // add 3 to the current value of Result, giving 15

   #debug str(Result, 5, 0) // output Result to message window
   #debug "\n" // start a new line in message window

The invocation "Add (5, Result)" is replaced by POV-Ray by

   #local Value = 5; // get first parameter, store it in local variable
   #local Sum = Result; // get second parameter, store it in local variable

   #local Sum = Sum+Value; // body of macro, uses the local variables
                           // associated to the parameters

   #declare Result = Sum; // return the value of the second parameter's
                        // local variable to the variable given for
                        // this second parameter

   // The first parameter "5" is not a variable, so nothing is returned
   // ( "#declare 5 = Value;" is nonsense )

   #undef Value // the local variable Value is destroyed
   #undef Sum // the local variable Sum is destroyed

In short: 5 is used for Value, Result is used for Sum. 5 can't get a new
value, but Result can.
Similar with the other invocations.
Of course,

   #declare A_different_Result = 1762345;
   Add (76235, A_different_Result)
   Add (87656, A_different_Result)

also is possible, even intermixed with the above invocations of Add,
because Add is "told" which variable to use.

<END OF ADVANCED STUFF>


I hope this helps in understanding my macros (and macros in general).
You might want to read "6.2.8  User Defined Macros" for more information
(or ask again!).

   Sputnik


P.S. Why did you think Steps is a string?

P.P.S. You meant   "Steps"  , not   "Steps,"  , didn't you?

P.P.P.S. String comparison is not possible with "<" etc., look for
         strcmp in "6.1.3.6  Float Functions".


Post a reply to this message

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