[OpenSCAD] recursion limit on concat()

Ronaldo Persiano rcmpersiano at gmail.com
Tue Oct 15 10:31:56 EDT 2019


 kitwallace <kit.wallace at gmail.com> wrote:

>
> The (corrected and as a result simpler) recursive version of this function
> is used in this version of the  l-system code
>

The last version you referred defines a string_to_points() function which
still is unable to have the tail recursion eliminated.
Applying your correction to my alternative recursion version, it becomes:

function string_to_points(s,step=1,angle=90,pos=[0,0,0],dir=0,i=0,ps=[]) =

    i == len(s)
      ? ps
      : string_to_points(s,
                         step,
                         angle,
                         s[i]=="F" ||s[i]=="A" || s[i]=="B" // newpos
                           ? pos + step*[cos(dir), sin(dir)]
                           : pos,
                         s[i]=="+"                          // newdir
                           ? dir + angle
                           : s[i]=="-"
                              ? dir - angle
                              : dir,
                        i+1,
                        concat([pos],ps) );


And now it will be eligible to tail recursion elimination.

With that correction, the iterative version also gets simpler and don't
need any explicit concat() (neither 'each'):

function string_to_points(s,step=1,angle=90,pos=[0,0,0],dir=0) =
  [for( i  = 0;

        i <= len(s);

        c   = s[i],
        pos = c=="F" ||c=="A" || c=="B"
               ? pos + step*[cos(dir), sin(dir)]
               : pos,
        dir = c=="+"
              ? dir + angle
              : c=="-"
                ? dir - angle
                : dir,
        i   = i+1 )
       pos ];

The Hilbert curve fails at k=5


This failure is due to something else: the 'for' in module path() has more
then 9999 elements. This is an arbitrary (and low) limit in OpenSCAD range
'for's.
As an workaround, you may consider the following code with two nested 'for'
meant to 'cheat' the limit rule:

module path(points,width,closed=false) {
  r=width/2;
  for (j=[0:len(points)/1000]) { // this { brace pair is mandatory
   for(i=[0:min(999,len(points)-2-1000*j)]) {
    hull() {
        translate(points[1000*j+i]) circle(r);
        translate(points[1000*j+i+1]) circle(r);
    }
   }
  }
  if (closed) {
    hull() {
        translate(points[len(points)-1]) circle(r);
        translate(points[0]) circle(r);
    }
  }
};


It should work up to 999999 elements in 'points'.

Now, Hilbert curve works with k=6 which has 13651 points and with the 54611
points generated when k=7.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.openscad.org/pipermail/discuss_lists.openscad.org/attachments/20191015/e2562400/attachment.html>


More information about the Discuss mailing list