POV-Ray : Newsgroups : povray.general : Macro return value on failure Server Time: 19 Dec 2018 13:20:52 GMT
 Macro return value on failure (Message 1 to 6 of 6)
 From: Mike Horvath Subject: Macro return value on failure Date: 22 Jul 2018 01:55:50 Message: <5b53e426\$1@news.povray.org>
```I have two macros that calculate the intersection of two lines and
return a 2D vector <x,y>.

################################################

#macro line(p1, p2)
#local A = (p1.y - p2.y);
#local B = (p2.x - p1.x);
#local C = (p1.x * p2.y - p2.x*p1.y);
<A,B,-C>
#end

#macro line_intersection(l1, l2)
#local D  = l1.x * l2.y - l1.y * l2.x;
#local Dx = l1.z * l2.y - l1.y * l2.z;
#local Dy = l1.x * l2.z - l1.z * l2.x;
#if (D != 0)
#local out_x = Dx / D;
#local out_y = Dy / D;
#local out_value = <out_x,out_y>;
#else
#local out_value = false;
#end
out_value
#end

#declare L1 = line(<0,1>, <2,3>);
#declare L2 = line(<2,3>, <0,4>);
#declare R = line_intersection(L1, L2);
//#if (R != false)
#debug concat("\n\n\nIntersection detected: <", vstr(2,R,",",0,-1),
">\n\n\n")
//#else
//    #debug concat"No single intersection point detected")
//#end

################################################

Normally this works okay, but it is possible for the macro to fail if
the lines are coinciding. But, how can I signal a failure? I tried
passing the result to a conditional statement, but POVRay then complains
that it needs a float value but got a color value. There also is no
"null" or "undefined" value in POVRay SDL. I would appreciate some tips,
thanks.

Mike
```
 From: clipka Subject: Re: Macro return value on failure Date: 22 Jul 2018 02:45:38 Message: <5b53efd2\$1@news.povray.org>
```Am 22.07.2018 um 03:57 schrieb Mike Horvath:
> I have two macros that calculate the intersection of two lines and
> return a 2D vector <x,y>.
...

> Normally this works okay, but it is possible for the macro to fail if
> the lines are coinciding. But, how can I signal a failure? I tried
> passing the result to a conditional statement, but POVRay then complains
> that it needs a float value but got a color value. There also is no
> "null" or "undefined" value in POVRay SDL. I would appreciate some tips,
> thanks.

You could return a 3D vector, using the 3rd dimension for a status value.

If you are using POV-Ray v3.8.0, you could also use:

#macro Line_Intersection(...)
...
#if (D != 0)
...
#local Out_Value = <out_x,out_y>;
#local Out_Ok = true;
#else
#local Out_Value = <0,0>;
#local Out_Ok = false;
#end
(Out_Value, Out_Ok)
#end
...
#declare (R, R_Ok) = Line_Intersection(...);
#if (R_ok)
...
#else
...
#end

(As an unrelated side note, it is highly recommended to /not/ use
all-lowercase variable names; such names might be used as new keywords
in future versions without special notice.)
```
 From: Mike Horvath Subject: Re: Macro return value on failure Date: 22 Jul 2018 04:04:36 Message: <5b540254\$1@news.povray.org>
```On 7/21/2018 10:45 PM, clipka wrote:
> You could return a 3D vector, using the 3rd dimension for a status value.
>
> If you are using POV-Ray v3.8.0, you could also use:
>
>      #macro Line_Intersection(...)
>          ...
>          #if (D != 0)
>              ...
>              #local Out_Value = <out_x,out_y>;
>              #local Out_Ok = true;
>          #else
>              #local Out_Value = <0,0>;
>              #local Out_Ok = false;
>          #end
>          (Out_Value, Out_Ok)
>      #end
>      ...
>      #declare (R, R_Ok) = Line_Intersection(...);
>      #if (R_ok)
>          ...
>      #else
>          ...
>      #end
>
>
> (As an unrelated side note, it is highly recommended to /not/ use
> all-lowercase variable names; such names might be used as new keywords
> in future versions without special notice.)
>

Thanks!

Now I am afraid because I use lower case for variable names almost
exclusively.

:(
```
 From: JimT Subject: Re: Macro return value on failure Date: 23 Jul 2018 14:40:01 Message:
```> >
> > (As an unrelated side note, it is highly recommended to /not/ use
> > all-lowercase variable names; such names might be used as new keywords
> > in future versions without special notice.)
> >
>
> Thanks!
>
> Now I am afraid because I use lower case for variable names almost
> exclusively.
>
> :(

I too am afraid. Many of my local variables are all lower case, though my #macro

Something that doesn't seem to be well known (or maybe clipka has warned against
it in the past) is if you #declare a variable before you pass it into a #macro
and change it using #local in the #macro, when the #macro finishes it retains
the changed value. Obviously (since clipka says so) you can pass back the 3rd
component of a 3 vector, but then you would have to unpack the <x,y>
intersection point from the <x,y,z> vector. I would just add a 3rd argument to
line_intersection() and use that as the switch.

#version 3.7;
#include "colors.inc"
global_settings { assumed_gamma 1.0 }
//
#macro line(p1, p2)
#local A = (p1.y - p2.y);
#local B = (p2.x - p1.x);
#local C = (p1.x * p2.y - p2.x*p1.y);
<A,B,-C>
#end

#macro line_intersection(l1, l2, unique_int_point)
#local D  = l1.x * l2.y - l1.y * l2.x;
#local Dx = l1.z * l2.y - l1.y * l2.z;
#local Dy = l1.x * l2.z - l1.z * l2.x;
#if (D != 0)
#local out_x = Dx / D;
#local out_y = Dy / D;
#local out_value = <out_x,out_y>;
#local unique_int_point = 1;
#else
#local out_value = <0,0>;
#local unique_int_point = 0;
#end
out_value
#end

#declare p1 = <0,1>;
#declare p2 = <2,3>;
#declare p3 = <2,6>;
//#declare p3 = <2,3>;
#declare p4 = <0,4>;
#declare L1 = line(p1, p2);
#declare L2 = line(p3, p4);
#declare unique_int_point = 1;
//
#declare R  = line_intersection(L1, L2, unique_int_point);
//
#if(unique_int_point = 1)
#debug concat("\n\n\n Intersection detected: <", vstr(2,R,",",0,-1),">\n\n\n")
sphere{R 0.1 pigment{Blue}}
#else
#debug concat("\n\n\n No single intersection point detected.\n\n\n")
#end
//
cylinder{p1 p2 0.05 pigment{Red}}
cylinder{p3 p4 0.05 pigment{Green}}
//
camera{orthographic location <0,0,-100> look_at <0,-0.00001,0> angle 12}
background{White}
```
 From: Mike Horvath Subject: Re: Macro return value on failure Date: 23 Jul 2018 22:49:40 Message: <5b565b84\$1@news.povray.org>
```On 7/23/2018 10:37 AM, JimT wrote:
>>>
>>> (As an unrelated side note, it is highly recommended to /not/ use
>>> all-lowercase variable names; such names might be used as new keywords
>>> in future versions without special notice.)
>>>
>>
>> Thanks!
>>
>> Now I am afraid because I use lower case for variable names almost
>> exclusively.
>>
>> :(
>
> I too am afraid. Many of my local variables are all lower case, though my #macro
>
> Something that doesn't seem to be well known (or maybe clipka has warned against
> it in the past) is if you #declare a variable before you pass it into a #macro
> and change it using #local in the #macro, when the #macro finishes it retains
> the changed value. Obviously (since clipka says so) you can pass back the 3rd
> component of a 3 vector, but then you would have to unpack the <x,y>
> intersection point from the <x,y,z> vector. I would just add a 3rd argument to
> line_intersection() and use that as the switch.
>
> #version 3.7;
> #include "colors.inc"
> global_settings { assumed_gamma 1.0 }
> //
> #macro line(p1, p2)
>   #local A = (p1.y - p2.y);
>   #local B = (p2.x - p1.x);
>   #local C = (p1.x * p2.y - p2.x*p1.y);
>   <A,B,-C>
> #end
>
> #macro line_intersection(l1, l2, unique_int_point)
>   #local D  = l1.x * l2.y - l1.y * l2.x;
>   #local Dx = l1.z * l2.y - l1.y * l2.z;
>   #local Dy = l1.x * l2.z - l1.z * l2.x;
>   #if (D != 0)
>    #local out_x = Dx / D;
>    #local out_y = Dy / D;
>    #local out_value = <out_x,out_y>;
>       #local unique_int_point = 1;
>   #else
>    #local out_value = <0,0>;
>    #local unique_int_point = 0;
>   #end
>   out_value
> #end
>
> #declare p1 = <0,1>;
> #declare p2 = <2,3>;
> #declare p3 = <2,6>;
> //#declare p3 = <2,3>;
> #declare p4 = <0,4>;
> #declare L1 = line(p1, p2);
> #declare L2 = line(p3, p4);
> #declare unique_int_point = 1;
> //
> #declare R  = line_intersection(L1, L2, unique_int_point);
> //
> #if(unique_int_point = 1)
>    #debug concat("\n\n\n Intersection detected: <", vstr(2,R,",",0,-1),">\n\n\n")
>    sphere{R 0.1 pigment{Blue}}
> #else
>    #debug concat("\n\n\n No single intersection point detected.\n\n\n")
> #end
> //
> cylinder{p1 p2 0.05 pigment{Red}}
> cylinder{p3 p4 0.05 pigment{Green}}
> //
> camera{orthographic location <0,0,-100> look_at <0,-0.00001,0> angle 12}
> light_source{<0,0,-100> color rgb <1,1,1>  shadowless}
> background{White}
>
>
>

Wow, I thought local variables only worked in the local scope. E.g. the
globally declared variable in the code you supplied would retain its
original value.

Mike
```
 From: clipka Subject: Re: Macro return value on failure Date: 24 Jul 2018 08:09:26 Message: <5b56deb6\$1@news.povray.org>
```Am 24.07.2018 um 00:49 schrieb Mike Horvath:

> Wow, I thought local variables only worked in the local scope. E.g. the
> globally declared variable in the code you supplied would retain its
> original value.

For clarification - what JimT is describing is the following behaviour:

#macro Foo(A)
#local A = 42;
#end

#declare A = 1; // just for clarification
#declare X = 1;
Foo(X)
#debug concat("A = ",str(A,0,0),"\n") // still 1
#debug concat("X = ",str(X,0,0),"\n") // now 42

So `#local A` in a macro does not change the global variable named `A`.
It does, however, change the macro parameter named `A`. If a global
variable happens to be passed to that macro parameter, that global
variable (no matter what its name outside the macro) is also changed.

This call-by-reference behaviour is intentional, as a means to pass
additional information back out of a macro.
```