Staff (Retired)
Tile JSL part 2

In part 1 the penrose tiling generator stored its results in a data table. The graph in part 1 contained lines of different gray levels, indicating how many times each line was drawn. The tiles are not emitted from the generator as polygons, just a bunch of loose and repeated edges. Part 2 JSL won't be using the data table; instead an associative array will collect the line segments using their X-Y coordinates as a key. The data for each key will be a list of all the other endpoints associated with the X-Y location. After the associative array is built, the JSL will work through it to extract unique polygons (the kites and the darts) and identify the kites and darts for the orange and blue coloring.

``````// see previous posts...
DELTA = PI()/5;
cx=0;
cy=0;
ca=-DELTA;
repeat=1;
W=function({lev},{sx,sy,sa},// "YBF2+ZRF4-XBF[-YBF4-WRF]2+";
lev--;if(lev>= 0,
Y(lev);B(lev);F(lev);NUMB(2);PLUS();Z(lev);R(lev);F(lev);NUMB(4);SUB();X(lev);B(lev);F(lev);sx=cx;sy=cy;sa=ca;SUB();Y(lev);B(lev);F(lev);NUMB(4);SUB();W(lev);R(lev);F(lev);cx=sx;cy=sy;ca=sa;NUMB(2);PLUS();
));
X= function({lev},{sx,sy,sa},// "+YBF2-ZRF[3-WRF2-XBF]+";
lev--;if(lev>= 0,
PLUS();Y(lev);B(lev);F(lev);NUMB(2);SUB();Z(lev);R(lev);F(lev);sx=cx;sy=cy;sa=ca;NUMB(3);SUB();W(lev);R(lev);F(lev);NUMB(2);SUB();X(lev);B(lev);F(lev);cx=sx;cy=sy;ca=sa;PLUS();
));
Y=function({lev},{sx,sy,sa},//"-WRF2+XBF[3+YBF2+ZRF]-";
lev--;if(lev>= 0,
SUB();W(lev);R(lev);F(lev);NUMB(2);PLUS();X(lev);B(lev);F(lev);sx=cx;sy=cy;sa=ca;NUMB(3);PLUS();Y(lev);B(lev);F(lev);NUMB(2);PLUS();Z(lev);R(lev);F(lev);cx=sx;cy=sy;ca=sa;SUB();
));
Z=function({lev},{sx,sy,sa},// "2-YBF4+WRF[+ZRF4+XBF]2-XBF";
lev--;if(lev>= 0,
NUMB(2);SUB();Y(lev);B(lev);F(lev);NUMB(4);PLUS();W(lev);R(lev);F(lev);sx=cx;sy=cy;sa=ca;PLUS();Z(lev);R(lev);F(lev);NUMB(4);PLUS();X(lev);B(lev);F(lev);cx=sx;cy=sy;ca=sa;NUMB(2);SUB();X(lev);B(lev);F(lev);
));
B = function({lev},0);
F = Function( {lev}, /*draw cx,cy,ca*/
If( lev == 0,
new_xpos = cx + 20 * Cos( ca );
new_ypos = cy - 20 * Sin( ca );
key1 = key( cx, cy );
If( !(aa << Contains( key1 )),
aa[key1] = [=> 0]   // <<< new code for Associative Array
);
key2 = key( new_xpos, new_ypos );
If( !(aa << Contains( key2 )),
aa[key2] = [=> 0]   // <<< new code for Associative Array
);
cx = new_xpos;
cy = new_ypos;
aa[key1][key2]++;
aa[key2][key1]++;
)
);
R = function({lev},0);
PLUS=function({},ca += DELTA * repeat; repeat = 1);
SUB=function({},ca -= DELTA * repeat; repeat = 1);
NUMB=function({n},repeat=n); // 2,3,4
aa = associativearray();
key = function({x,y}, (round(x,5))|/(round(y,5)););   // <<< new code for Associative Array
//AXIOM = "2+2+2+2+";
level=7;//5;//8;
scale=50;//50;
sbscale=2;//.4;//1;
local({i,sx,sy,sa},
for(i=1,i<=5,i++,
sx=cx;sy=cy;sa=ca;
X(level);
cx=sx;cy=sy;ca=sa;
NUMB(2);
PLUS();
);
);
// http://www.maths.surrey.ac.uk/hosted-sites/R.Knott/Fibonacci/fibFormula.html
// seems to be a Fibonacci sequence.  estimate the axis size.
size = 22 * (1.61803398874989 ^ level);
pts0 = aa << getkeys;
/////////////  new code for Associative Array follows /////////////
nkite = 0;
ndart = 0;
kites=associativearray();
darts=associativearray();
shrink = function({a,b,c,d},{r=J(2,4,0),x=(a+b+c+d)/4, s=.2}, // shrink the polygon toward the middle
r=a+s*(x-a)||b+s*(x-b)||c+s*(x-c)||d+s*(x-d);
r;
);
While( N Items( pt0 = Remove From( pts0, 1 ) ) == 1,
pt0 = pt0[1];
pts1 = (aa[pt0]) << getkeys;
While( N Items( pt1 = Remove From( pts1, 1 ) ) == 1,
pt1 = pt1[1];
pts2 = (aa[pt1]) << getkeys;
While( N Items( pt2 = Remove From( pts2, 1 ) ) == 1,
pt2 = pt2[1];
If( !All( pt0 == pt2 ),
pts3 = (aa[pt2]) << getkeys;
While( N Items( pt3 = Remove From( pts3, 1 ) ) == 1,
pt3 = pt3[1];
If( !All( pt1 == pt3 ),
pts4 = (aa[pt3]) << getkeys;
While( N Items( pt4 = Remove From( pts4, 1 ) ) == 1,
pt4 = pt4[1];
If( All( pt0 == pt4 ),
// keep only CW paths (or CCW, don't really care, but not both)
keep = Det( pt0 - pt1 || pt2 - pt1 ); // x1y2-x2y1 cross product winding
If( keep > 0,
//Show( pt0, pt1, pt2, pt3, pt4,keep,"\!n" )
d1 = Sqrt( (pt0[1] - pt2[1]) ^ 2 + (pt0[2] - pt2[2]) ^ 2 );
d2 = Sqrt( (pt1[1] - pt3[1]) ^ 2 + (pt1[2] - pt3[2]) ^ 2 );
If( d1 / 2 < d2 < d1 * 2,
nkite++;
kites[nkite] = shrink( pt0, pt1, pt2, pt3 );
,
ndart++;
darts[ndart] = shrink( pt0, pt1, pt2, pt3 );
);
);
);
);
);
);
);
);
);
aa[pt0] = {}; // this vertex has generated all of its polys, don't generate more if we come back to it
);
show(nkite,ndart);
New Window( "Example",
Graph Box(framesize(900,900),xscale(-size,size),yscale(-size,size),
Fill Color( hlscolor(.05,.6,.7) );
for(i=1,i<=nkite,i++,
Polygon( kites[i][1,0], kites[i][2,0] );
);
Fill Color( hlscolor(.55,.4,.95) );
for(i=1,i<=ndart,i++,
Polygon( darts[i][1,0], darts[i][2,0] );
);
)
);
``````

Next week: how to make a 3D surface from the tiles. Part 3 will use the kite and dart arrays from Part 2.

update 26may2017: code repair after web site conversion