One of the simplest things you can draw is a polygon. There are many ways to draw them in Nell. To draw an equilateral triangle with sides of length 1 you could use the program (poly00.nll).
START : L(1) T(2*pi/3) L(1) T(2*pi/3) L(1) T(2*pi/3);
nell poly00.nll START 6 | nellsvg 1 1 in 0.02 1 > poly00.svg
The exterior angles of an equilateral triangle are all equal to
120 degrees = 2*pi/3 radians, hence the
commands. The last
T(2*pi/3) command is strictly not
necessary. It just returns the direction to where it was at the
The program (poly00.nll) will produce an svg where each line is a separate path. To group all the lines into a single path, we simply put angle brackets around the command string as shown in program (poly00a.nll)
START : <L(1) T(2*pi/3) L(1) T(2*pi/3) L(1) T(2*pi/3)>;
nell poly00a.nll START 6 | nellsvg 1 1 in 0.02 1 > poly00a.svg
This produces an svg where the triangle is a single path, but the path is still open, i.e. the first point is not connected to the last point. A triangle that is a single closed path is produced by program (poly01.nll)
START : <L(1) T(2*pi/3) L(1) T(2*pi/3) Z()>;
nell poly01.nll START 6 | nellsvg 1 1 in 0.02 1 > poly01.svg
Note that the last L(1) command has been left out since it is implicit in the Z() command which closes the path and sets the current position and direction to what it was at the start of the path.
You can use this same technique for drawing regular polygons with any number of sides, but instead of writing out the L commands for each side explicitly, you can use a substitution command. The program (poly02.nll) shows how to do this to draw a pentagon.
SIDE : L(1) T(2*pi/5); START : M(0.5) <S(SIDE,4) Z()>;
nell poly02.nll START 6 | nellsvg 2 2 in 0.02 1 > poly02.svg
The command string labeled
SIDE draws one side of the
pentagon, and we use it four times inside the path to draw four sides
of the polygon with the final
Z command completing the last
side. The initial
M(0.5) command starts the drawing at the
point (0.5,0) so that the entire pentagon is in the positive first
With a substitution command and a variable definition we can easily
generalize this to a program that will draw a polygon with
Program (poly03.nll) shows how it's done.
n = 6; SIDE : L(1) T(2*pi/n); START : M(0.5) <S(SIDE,n-1) Z()>
nell poly03.nll START 6 | nellsvg 2 2 in 0.02 1 > poly03.svg
In (poly03.nll) we've defined the variable
n which is
set equal to 6 at the beginning of the program. If you run the
program like this it will produce a hexagon. Set
n = 8; and
it will produce an octagon and so on.
So much for drawing single regular polygons. Now let's see how easy it is to create drawings with multiple polygons. You can easily make a series of nested regular polygons using a double set of substitutions. Program (poly04.nll) shows how it's done.
n=3; SIDE : L(1) T(2*pi/n); POLY : <S(SIDE,n-1) Z()> A(n,n+1); START : M(1) S(POLY,6);
nell poly04.nll START 6 | nellsvg 3 3 in 0.02 1 > poly04.svg
In (poly04.nll) we've used the
A command that assigns
a new value to a variable, which in this case is the number of sides
in the next polygon to draw. The
POLY command string is
substituted 6 times with the value of
n incremented each
time, starting with the value 3. The result is that a triangle,
square, pentagon, hexagon, heptagon, and octagon are drawn, all
starting at the same point and sharing a common side. The
M(1) command sets the starting point for all polygons to
(1,0) so they are horizontally centered on a 3 by 3 canvas.
Program (poly05.nll) shows how to arrange five pentagons so that they form a pentagon.
SIDE : L(1) T(-2*pi/5); POLY : <S(SIDE,4) Z()> M(1) T(2*pi/5); START : P(2,2) S(POLY,5);
nell poly05.nll START 6 | nellsvg 5 5 in 0.02 1 > poly05.svg
Here we've used the
P command to position the starting point
at (2,2). This centers the drawing on a 5 by 5 canvas. The
POLY command string draws a pentagon, moves one unit in
the current direction and changes direction by
2*pi/5 so that
the next pentagon can be drawn.
The program (poly06.nll) draws a pentagram inside a pentagon.
d = (1+sqrt(5))/2; PENTAGON : <L(1) T(2*pi/5) L(1) T(2*pi/5) L(1) T(2*pi/5) L(1) T(2*pi/5) Z()>; PENTAGRAM : T(pi/5) <L(d) T(4*pi/5) L(d) T(4*pi/5) L(d) T(4*pi/5) L(d) T(4*pi/5) Z()>; START : M(0.5) S(PENTAGON,1) S(PENTAGRAM,1);
nell poly06.nll START 6 | nellsvg 2 2 in 0.02 1 > poly06.svg
The program (poly07.nll) draws concentric triangles starting with the outer triangle and going in.
n = 6; l = 2; dl = l/n; dr = dl/sqrt(3); a = 2*pi/3; TRI : <L(l) T(a) L(l) T(a) Z()> T(pi/6) M(dr) T(-pi/6) A(l,l-dl); START : S(TRI,n);
nell poly07.nll START 6 | nellsvg 2 2 in 0.02 1 > poly07.svg
n defines the number of triangles to draw. The
l is the length of a side of the outer triangle. The
dl is the amount by which the length of the triangle
side changes as you go in. The variable
dr is the length by
which you move in to draw the next triangle. As an exercise see if
you can modify the program so the inner triangle is drawn first and
the outer last.
You can generalize (poly07.nll) to draw concentric polygons with any number of sides. The program (conpoly.nll) shows how to do it.
ns=6; number of sides n=12; number of polygons l=2; length of a side dl=l/n; dr=dl/(2*sin(pi/ns)); a=2*pi/ns; b=pi*(ns-2)/(2*ns); SIDE : L(l) T(a); POLY : <S(SIDE,ns-1) Z()> T(b) M(dr) T(-b) A(l,l-dl); START : M(1) S(POLY,n);
nell conpoly.nll START 10 | nellsvg 4 4 in 0.02 1 > conpoly.svg
The program defines the variable
ns that specifies the number
of sides for the polygons and the variable
b which is the
angle to turn to move to the beginning of the next inner polygon.
A variation on the concentric polygons is to rotate each of the inner polygons by half the exterior angle. The program (rconpoly.nll) shows how to do it.
ns=8; number of sides n=28; number of polygons l=2; length of a side a=2*pi/ns; rl = cos(a/2); SIDE : L(l) T(a); POLY : <S(SIDE,ns-1) Z()> M(l/2) T(a/2) A(l,l*rl); START : M(sqrt(2)) S(POLY,n);
nell rconpoly.nll START 10 | nellsvg 4.83 4.83 in 0.02 1 > rconpoly.svg
We can also easily tile polygons. The program (tritile.nll) will create a tiling using triangles.
n = 8; l = 0.5; r = 1.0; d = r*l; a = 2*pi/3; T1 : <L(l) T(a) L(l) T(a) Z()> M(d); T2 : [S(T1,n)] T(a/2) M(d) T(-a/2) [S(T1,n-1)]; T3 : [S(T2,1)] T(pi/2) M(d*sqrt(3)) T(-pi/2); START : S(T3,n/2);
nell tritile.nll START 10 | nellsvg 4 4 in 0.02 1 > tritile.svg
n is the number of triangles per row,
is the length of a triangle side and
r determines the tile
r=1 gives an exact fit,
an overlap, and
r>1 adds space between the triangles. For
r=1.25 we get this:
The program (hextile.nll) will create a tiling using hexagons.
a = pi/3; s = 0.5; r = 1.0; d = r*s*sqrt(3); n = 4; T1 : L(s) T(a); T2 : <S(T1,5) Z()>; T3 : S(T2,1) T(a/2) M(d) T(-a/2) S(T2,1) T(-a/2) M(d) T(a/2); T4 : [S(T3,n)] T(pi/2) M(d) T(-pi/2); START : M(0.25) S(T4,n);
nell hextile.nll START 10 | nellsvg 6.25 4.0 in 0.02 1 > hextile.svg
Again the variable
r determines the spacing. For
r=1 there is no space between the hexagons. For
r=0.5 the hexagons overlap as in the following figure.