Question about recursive function

classic Classic list List threaded Threaded
7 messages Options
Reply | Threaded
Open this post in threaded view
|

Question about recursive function

kdtop
Hello all.  First time poster, but long-time OpenSCAD user (2+ yrs).

I have the following code.  

//Obtain vector of points on circumference of circle of radius = 50, start
angle=10, end angle=45, step of 2 degrees
circum_pts1 = circum_pts([[]], 10, 50, 2, 45);  
echo(circum_pts1);

function circum_pts(pts, angle, rad, angle_step = 1, end_angle=360) =
  let(x =rad * cos(angle))
  let(y =rad * sin(angle))  
  angle < (end_angle+1) ?
    concat(pts, [[x,y]], circum_pts(pts, angle+angle_step, rad, angle_step,
end_angle))
  :
    pts;
//-- End function ------------

This outputs the following value for result

ECHO: [[], [49.2404, 8.68241], [], [48.9074, 10.3956], [], [48.5148,
12.0961], [], [48.0631, 13.7819], [], [47.5528, 15.4508], [], [46.9846,
17.101], [], [46.3592, 18.7303], [], [45.6773, 20.3368], [], [44.9397,
21.9186], [], [44.1474, 23.4736], [], [43.3013, 25], [], [42.4024, 26.496],
[], [41.4519, 27.9596], [], [40.4508, 29.3893], [], [39.4005, 30.7831], [],
[38.3022, 32.1394], [], [37.1572, 33.4565], [], [35.967, 34.7329], []]

Notice that every other value is a null value.  I can program around this,
but would like to figure out how to avoid.  

Any ideas?

Thanks
Kevin Toppenberg





--
Sent from: http://forum.openscad.org/

_______________________________________________
OpenSCAD mailing list
[hidden email]
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
Reply | Threaded
Open this post in threaded view
|

Re: Question about recursive function

kdtop
Let's see, working on this some more....

The following code gets rid of the every-other bad value.  So this is almost there.   It just has a final null value that I wish I could get rid of.

Thanks
Kevin

//Obtain vector of points on circumference of circle of radius = 50, start angle=0, end angle=90, step of 10 degrees
circum_pts1 = circum_pts(0, 50, 10, 90);  
echo(circum_pts1);

function circum_pts(angle, rad, angle_step = 1, end_angle=360) = 
  let(x =rad * cos(angle))
  let(y =rad * sin(angle))  
  angle <= (end_angle) ? 
    concat([[x,y]], circum_pts(angle+angle_step, rad, angle_step, end_angle)) 
  : 
    [[]];
//-- End function ------------

ECHO: [[50, 0], [49.2404, 8.68241], [46.9846, 17.101], [43.3013, 25], [38.3022, 32.1394], [32.1394, 38.3022], [25, 43.3013], [17.101, 46.9846], [8.68241, 49.2404], [0, 50], []]




On Sun, Nov 11, 2018 at 5:11 PM kdtop <[hidden email]> wrote:
Hello all.  First time poster, but long-time OpenSCAD user (2+ yrs).

I have the following code. 

//Obtain vector of points on circumference of circle of radius = 50, start
angle=10, end angle=45, step of 2 degrees
circum_pts1 = circum_pts([[]], 10, 50, 2, 45); 
echo(circum_pts1);

function circum_pts(pts, angle, rad, angle_step = 1, end_angle=360) =
  let(x =rad * cos(angle))
  let(y =rad * sin(angle)) 
  angle < (end_angle+1) ?
    concat(pts, [[x,y]], circum_pts(pts, angle+angle_step, rad, angle_step,
end_angle))
  :
    pts;
//-- End function ------------

This outputs the following value for result

ECHO: [[], [49.2404, 8.68241], [], [48.9074, 10.3956], [], [48.5148,
12.0961], [], [48.0631, 13.7819], [], [47.5528, 15.4508], [], [46.9846,
17.101], [], [46.3592, 18.7303], [], [45.6773, 20.3368], [], [44.9397,
21.9186], [], [44.1474, 23.4736], [], [43.3013, 25], [], [42.4024, 26.496],
[], [41.4519, 27.9596], [], [40.4508, 29.3893], [], [39.4005, 30.7831], [],
[38.3022, 32.1394], [], [37.1572, 33.4565], [], [35.967, 34.7329], []]

Notice that every other value is a null value.  I can program around this,
but would like to figure out how to avoid. 

Any ideas?

Thanks
Kevin Toppenberg





--
Sent from: http://forum.openscad.org/

_______________________________________________
OpenSCAD mailing list
[hidden email]
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org

_______________________________________________
OpenSCAD mailing list
[hidden email]
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
Reply | Threaded
Open this post in threaded view
|

Re: Question about recursive function

JordanBrown
In reply to this post by kdtop
On 11/11/2018 2:10 PM, kdtop wrote:
Hello all.  First time poster, but long-time OpenSCAD user (2+ yrs).

I have the following code.  

//Obtain vector of points on circumference of circle of radius = 50, start
angle=10, end angle=45, step of 2 degrees
circum_pts1 = circum_pts([[]], 10, 50, 2, 45);  
echo(circum_pts1);

function circum_pts(pts, angle, rad, angle_step = 1, end_angle=360) = 
  let(x =rad * cos(angle))
  let(y =rad * sin(angle))  
  angle < (end_angle+1) ? 
    concat(pts, [[x,y]], circum_pts(pts, angle+angle_step, rad, angle_step,
end_angle)) 
  : 
    pts;
//-- End function ------------

This outputs the following value for result

ECHO: [[], [49.2404, 8.68241], [], [48.9074, 10.3956], [], [48.5148,
12.0961], [], [48.0631, 13.7819], [], [47.5528, 15.4508], [], [46.9846,
17.101], [], [46.3592, 18.7303], [], [45.6773, 20.3368], [], [44.9397,
21.9186], [], [44.1474, 23.4736], [], [43.3013, 25], [], [42.4024, 26.496],
[], [41.4519, 27.9596], [], [40.4508, 29.3893], [], [39.4005, 30.7831], [],
[38.3022, 32.1394], [], [37.1572, 33.4565], [], [35.967, 34.7329], []]

Notice that every other value is a null value.  I can program around this,
but would like to figure out how to avoid.  

Every call to circum_pts receives a "pts" array and returns that array, with a point and a recursive call to circum_pts appended.  Nothing ever makes pts be anything other than what is initially passed in.

The initial call to circum_pts passes an array consisting of one empty array.  To that it appends the first [x,y] pair and the results from a recursive call, so the result of that concat is [ [ ], [ x1, y1 ], <recurse> ].  The first recursive call receives the same array-of-empty-array, and so its concat is similarly [ [ ], [ x2, y2 ], <recurse> ], and so when that gets returned, the result of the initial concat is [ [ ], [ x1, y1 ], [ ], [ x2, y2 ], <recurse> ].  And so on.

The first step is to eliminate that "pts" parameter.  It doesn't do anything except contribute these empty arrays.
//Obtain vector of points on circumference of circle of radius = 50, start angle=10, end angle=45, step of 2 degrees
circum_pts1 = circum_pts(10, 50, 2, 45);  
echo(circum_pts1);

function circum_pts(angle, rad, angle_step = 1, end_angle=360) = 
  let(x =rad * cos(angle))
  let(y =rad * sin(angle))  
  angle < (end_angle+1) ? 
    concat([[x,y]], circum_pts(angle+angle_step, rad, angle_step, end_angle)) 
  : 
    [];
//-- End function ------------

Note that the empty array at the end of the loop contributes no elements to the concatenation, and that addresses the problem you saw in your second message.

But really you're better off avoiding recursion entirely and using a list comprehension:

function circum_pts2(angle, rad, angle_step, end_angle) = [
    for (i = [angle:angle_step:end_angle]) [
        rad * cos(i),
        rad * sin(i)
    ]
];




  


_______________________________________________
OpenSCAD mailing list
[hidden email]
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
Reply | Threaded
Open this post in threaded view
|

Re: Question about recursive function

Parkinbot
In reply to this post by kdtop
I wouldn't code such a function as recursive function. It is much faster and
straight forward to code it as simple loop:

circum_pts1 = circum_pts(0, 50, 2, 90);  
echo(circum_pts1);
polygon(circum_pts1);  // visual control

function circum_pts(angle, rad, angle_step = 1, end_angle=360) =
[for(i=[angle:angle_step:end_angle]) rad*[cos(i), sin(i)]];




--
Sent from: http://forum.openscad.org/

_______________________________________________
OpenSCAD mailing list
[hidden email]
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
Reply | Threaded
Open this post in threaded view
|

Re: Question about recursive function

kdtop
I like your solution of having this all in 1 line.  I didn't realize that one could use the following pattern:

<for loop producing scalar> * [vector dependent on loop variable]

thanks!

Kevin

On Mon, Nov 12, 2018 at 7:03 AM Parkinbot <[hidden email]> wrote:
I wouldn't code such a function as recursive function. It is much faster and
straight forward to code it as simple loop:

circum_pts1 = circum_pts(0, 50, 2, 90); 
echo(circum_pts1);
polygon(circum_pts1);  // visual control

function circum_pts(angle, rad, angle_step = 1, end_angle=360) =
[for(i=[angle:angle_step:end_angle]) rad*[cos(i), sin(i)]];




--
Sent from: http://forum.openscad.org/

_______________________________________________
OpenSCAD mailing list
[hidden email]
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org

_______________________________________________
OpenSCAD mailing list
[hidden email]
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
Reply | Threaded
Open this post in threaded view
|

Re: Question about recursive function

runsun
kdtop wrote
> I like your solution of having this all in 1 line.  I didn't realize that
> one could use the following pattern:
> <for loop producing scalar>
>  * [vector dependent on loop variable]

Good to know some basic tips, too:

> 1. a*[b,c] = [ab,ac];
> 2. a*[b,c,d] = [ab,ac,ad];
> 3. [a,b]*[c,d] = ac + bd;
> 4. [a,b,c]*[d,e,f] = ad + be + cf;
> 5. [a,b,c]*[c,d] = undef;
> 6. [a,b]*[d,e,f] = undef;

And, for points P,Q,R:

> a. (P+Q)/2 = the mid point between P,Q;
>     (P+Q+R)/3 = the centroid point (the gravity) of PQR;
>
> b. n*[P,Q] = a line parallel to line PQ;
>     n*[P,Q,R] = a plane parallel to plane PQR;
>
> c. iP+jQ is:
>    --- on line PQ if i+j=1; // 1.2P -0.2Q
>    --- within PQ line segment if i+j=1 AND i,j>0 ; // 0.2P + 0.8Q
>
> d. iP+jQ+kR is:
>    --- on plane PQR if i+j+k = 1; // 0.2P + 1.1Q - 0.3R
>    --- within PQR triangle if i+j+k=1 AND i,j,k>0 ; // 0.2P + 0.5Q + 0.3R

 




-----

$  Runsun Pan, PhD $ libs: scadx , doctest , faces ( git ), offline doc ( git ), runscad.py ( 2 , git ), editor of choice: CudaText  ( OpenSCAD lexer );&nbsp;$ Tips ;&nbsp;$ Snippets

--
Sent from: http://forum.openscad.org/

_______________________________________________
OpenSCAD mailing list
[hidden email]
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
$ Runsun Pan, PhD
$ libs: scadx, doctest, faces(git), offline doc(git), runscad.py(2,git), editor of choice: CudaText ( OpenSCAD lexer); $ Tips; $ Snippets
Reply | Threaded
Open this post in threaded view
|

Re: Question about recursive function

kdtop
Very cool.  Thanks!

Kevin

On Wed, Nov 14, 2018 at 9:45 PM runsun <[hidden email]> wrote:
kdtop wrote
> I like your solution of having this all in 1 line.  I didn't realize that
> one could use the following pattern:
> <for loop producing scalar>
>  * [vector dependent on loop variable]

Good to know some basic tips, too:

> 1. a*[b,c] = [ab,ac];
> 2. a*[b,c,d] = [ab,ac,ad];
> 3. [a,b]*[c,d] = ac + bd;
> 4. [a,b,c]*[d,e,f] = ad + be + cf;
> 5. [a,b,c]*[c,d] = undef;
> 6. [a,b]*[d,e,f] = undef;

And, for points P,Q,R:

> a. (P+Q)/2 = the mid point between P,Q;
>     (P+Q+R)/3 = the centroid point (the gravity) of PQR;
>
> b. n*[P,Q] = a line parallel to line PQ;
>     n*[P,Q,R] = a plane parallel to plane PQR;
>
> c. iP+jQ is:
>    --- on line PQ if i+j=1; // 1.2P -0.2Q
>    --- within PQ line segment if i+j=1 AND i,j>0 ; // 0.2P + 0.8Q
>
> d. iP+jQ+kR is:
>    --- on plane PQR if i+j+k = 1; // 0.2P + 1.1Q - 0.3R
>    --- within PQR triangle if i+j+k=1 AND i,j,k>0 ; // 0.2P + 0.5Q + 0.3R






-----

$  Runsun Pan, PhD $ libs: scadx , doctest , faces ( git ), offline doc ( git ), runscad.py ( 2 , git ), editor of choice: CudaText  ( OpenSCAD lexer );&nbsp;$ Tips ;&nbsp;$ Snippets

--
Sent from: http://forum.openscad.org/

_______________________________________________
OpenSCAD mailing list
[hidden email]
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org

_______________________________________________
OpenSCAD mailing list
[hidden email]
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org