Nell - cover image

Nell Blog

This is the blog for the book: Nell: An SVG Drawing Language. We will post new drawings here and other information about the book and related software.

Tesseract Projections

May 10, 2021

Here are four B4 Coxeter plane projections of a tesseract arranged in a square pattern.

The Nell program (tesseract.nll) shown below was used to create the figure.

; nell tesseract.nll START 3 | nellsvg 5 5 in 0.02 1 > tess.svg
l=1;
a = pi/2;
b = pi/4;
SQ :  M(l) T(b);
P1 : M(l/sqrt(2)) S(SQ,8) M(l+l*sqrt(2)) S(SQ,8);
START : [S(P1,1)] P(0,l+l*sqrt(2)) [S(P1,1)];

The command line for generating the svg is shown as a comment on the first line of the program.

Danger Radiation Symbol

July 28, 2020

We recently needed a "Danger Radiation" sign, so we figured why not draw the symbol in the Nell language. With the resulting svg we could customize it in inkscape to make a nice sign.

The Nell program shown below is used to create the figure.

; Draws a danger radiation symbol
; nell dangerrad.nll START 2 | nellsvg 5.2 5.2 in 0.03 1 > dangerrad.svg
;
stang = pi/3; start angle
swang = pi/3; sweep angle
WEDGE : <R(1,1,stang,-swang) L(1) M(-2) R(2,2,0,swang) L(-1)> M(-1) T(stang);
START : P(2.6,2.6) C(0.5) S(WEDGE,3) C(2.5);

The command line for generating the svg is shown as a comment on the second line of the program.

The three wedges of the radiation symbol should each be a closed path so they can be colored and shaded in inkscape the way we'd like. Using arcs to create the wedges seems the most straightforward way. Arcs have, up to now, not been allowed to be a part of a path in the Nell language. We have now modified the language to enable this. Download the software and recompile it to use this new feature. Only nellsvg.c has changed, so that's the only program that has to be recompiled.

Note that if you use a Nell path closing commmand, Z(), in a path that has an arc command, R(rx,ry,a,da), in it, then the path will only close to the beginning of the last arc which is not necessarily the beginning of the defined path. You can get around this weirdness by manually closing the path instead of using Z() as we have done in the above program.

Below is the finished sign that we completed in inkscape.

Total Internal Reflection

June 17, 2020

The image above shows a point source of light in water. When a ray meets the air/water interface it is refracted according to Snell's law. When the ray's incident angle is greater than the critical angle, it no longer crosses over into air but is reflected back down into the water. This is called total internal reflection.

The Nell program shown below is used to create the figure.

; This shows internal reflection of light from water to a water/air boundary.
; nell waterair.nll START 3 | nellsvg 6 3 in 0.02 1 > waterair.svg
n0 = 4/3;         water index of refraction
n1 = 1;           air index of refraction
tc = asin(n1/n0); critical angle
dt = 5*pi/180;   change in angle
k = 12; number of steps of size dt to take (not including start at t0 = 0)
t0 = 0;  ray start angle
tir = pi-2*t0; internal reflection angle
t1 = if(t0>tc,t0+tir,asin(n0*sin(t0)/n1)); internal reflection angle or angle from Snell's law
s = 1.0; vertical distance from light source to water/air junction
l0 = s/cos(t0); ray length from light source to water/air junction
CALC1 : A(t0,t0+dt) A(tir,pi-2*t0) A(t1,if(t0>tc,t0+tir,asin(n0*sin(t0)/n1))) A(l0,s/cos(t0));
INIT : P(3,0.1) D(pi/2); initialize position & direction
RAYL : S(INIT,1) <T(t0) L(l0) T(t1-t0) L(1)> S(CALC1,1); draw a left-half ray
RAYR : S(INIT,1) <T(-t0) L(l0) T(t0-t1) L(1)> S(CALC1,1); draw a right-half ray
BOUNDARY : [M(s) [T(pi/2) L(3)] T(-pi/2) L(3)]; draw the water/air boundary
START : S(RAYL,k+1) A(t0,0) S(CALC1,1) S(RAYR,k) S(INIT,1) S(BOUNDARY,1);

The command line for generating the svg is shown as a comment on the second line of the program.

Sun Drawing

May 13, 2020

Since spring is underway here in the Northern Hemisphere, we figure it's a good time to make a sun drawing, to pay homage to the primary engine of life here on Earth. Below is our Nell program for doing it.

; Draws a sun with wavy arms using cubic Bezier curves.
; nell sun04.nll START 3 | nellsvg 8.5 8.5 in 0.03 1 > sun04.svg;display sun04.svg
;
;*****ARMS section*****
n = 12;
a = 2*pi/n;
r1 = 2;
r2 = 4;
l = sqrt(r1^2+r2^2-2*r1*r2*cos(a/2));
phi = asin(r2*sin(a/2)/l);
ARMS : [M(r1) [T(phi) B(l,l/2,phi,-l/2,phi)] [T(-phi) B(l,l/2,phi,-l/2,phi)]] T(a);
;*****EYES section*****
EYES : P(3.5,5) E(0.5,0.25) P(5,5) E(0.5,0.25) P(4.0,5) L(0.5) P(5.5,5) T(pi/6) L(0.5) T(-pi/6) P(3.0,5) T(5*pi/6) L(0.5) T(-5*pi/6);
;*****SMILE section*****
b = 0.4;
l2 = 2.75;
SMILE1 : [Q(l2,(l2/2)*sqrt(b^2*l2^2+1),atan(-b*l2))] A(b,b/2);
SMILE : P(2.9,3.5) S(SMILE1,2);
;*****NOSE section*****
l3 = 0.8;
lc = 1.25;
ac = 0.22*pi;
NOSE : P(4.3,4.6) T(-pi/2) [Q(l3,lc,ac)] [Q(l3,lc,-ac)];
;*****MAIN section*****
START : P(4.25,4.25) C(r1) S(ARMS,n) S(EYES,1) S(SMILE,1) S(NOSE,1);

For ease of understanding, the program is separated into four anatomical sections: ARMS, EYES, SMILE, and NOSE. The ARMS section uses cubic Bezier curves. The SMILE and NOSE sections use quadratic Bezier curves. The SMILE is composed of two parabolas created just as in bezier2.nll and found in the book's chapter on Bezier curves.

The command line for generating the svg is shown as a comment on the second line of the program.

Making graph paper - triangular grid

May 6, 2020

Triangular grid graph paper with equilateral triangles is useful for organic chemistry, since the six triangles in common with every vertex form a hexagon.

organic molecule drawing on triangular grid graph paper
; Creates a triangular grid sheet of graph paper.
; nell gptri.nll START 3 | nellsvg 8.5 11 in 0.0025 1 > gptri.svg
W=8.5; paper width
H=11; paper height
d=0.5; width of triangle base
t=pi/3; triangle base angle
tt=tan(t);
ct=cos(t);
st=sin(t);
ht=d*tt/2; height of triangle
xm=H/tt;
n=int(xm/d)+1;
; L1 code strings draw the lines at angle t
L1A : A(h,x*tt) P(0,h) L(if(H-h < W*tt, (H-h)/st, W/ct)) A(x,x+d);
L1B : A(h,(W-x)*tt) P(x,0) L(if(h < H, (W-x)/ct, H/st)) A(x,x+d);
L1 : A(x,0) S(L1A,n) A(x,d) S(L1B,int(W/d));
; L2 code strings draw the lines at angle pi-2*t
L2A : A(h,x*tt) P(x,0) L(if(h < H, x/ct, H/st)) A(x,x+d);
L2B : A(h,(x-W)*tt) P(W,h) L(if(H-h < W*tt, (H-h)/st, W/ct)) A(x,x+d);
L2 : A(x,d) S(L2A,int(W/d)) S(L2B,n-1);
; HL draws the horizontal lines
HL : [T(-pi/2) L(W)] M(d*tt/2);
START : T(t) S(L1,1) T(pi-2*t) S(L2,1) P(0,0) D(pi/2) S(HL,int(H/ht)+1);

The above program does the job, with the line that starts with t=pi/3 being the key to making the triangles equilateral. To make the triangles bigger, we edit the line that starts with d=0.5, increasing the value. Another possibly useful angle is t=pi/4 which creates a triangular grid with square symmetry.

The command line for generating the svg is shown as a comment on the second line of the program. You can get pdf versions of the above mentioned graph paper below:

Here we have changed the default solid lines to dotted lines by opening up the svg output files in inkscape, selecting the grid, and choosing from the menu: Object | Fill and Stroke | Stroke Syle.

To make a version of the program for A4 paper size (210x297 mm), the command line would be:

nell gptri.nll START 3 | nellsvg 210 297 mm 0.254 1 > gptri.svg
where we would need to change the first 3 lines of the program to:
W=210; paper width
H=297; paper height
d=12.7; width of triangle base

Software Update

April 26, 2020

The following new math functions and operators have been added to the software. Download the software and recompile it to use them. Specifically, what's changed is calcfun.c and calcfun.h, so you'll need to recompile nell.c. It's not necessary to recompile nellsvg.c.

New Functions

New Operators

Making graph paper - log-linear grid

March 26, 2020

Log-linear grid graph paper is commonly used in math and engineering. Let's make some with the Nell language. Below is a Nell program that will do it.

; Creates a log-linear sheet of graph paper.
; nell gploglin1.nll START 3 | nellsvg 8.5 11 in 0.01 1 > gploglin1.svg
w=8.5; width
h=11; height
mt=0.5; margin at top
mb=0.5; margin at bottom
dw=0.5;
dh=2.0;
nx=w/dw-1;
ny=(h-mt-mb)/dh;
y=1;
dy=1;
H0 : P(0,mb+dh*log(y)/log(10.0)) L(w) A(y,y+dy);
HL : S(H0,9) A(dy,dy*10);
VL : [T(pi/2) M(mb) L(h-mt-mb)] M(dw);
START : [S(HL,ny) S(H0,1)] M(dw) S(VL,nx);

The above program creates a vertical log spacing versus a horizontal linear spacing grid on a letter size (8.5x11 inch) paper. There are 5 decades of log spacing, each decade taking 2 inches, and 17 steps of linear spacing, taking 1/2 inch each. Note that the thickness of the grid lines is set here as 0.01 inches. All of these parameters can be changed in the program or command line. The command line for generating the svg is shown as a comment on the second line of the program.

Below is a version of the program for an A4 paper size (210x297 mm).

; Creates a log-linear sheet of graph paper.
; nell gploglin2.nll START 3 | nellsvg 210 297 mm 0.254 1 > gploglin2.svg
w=210; width
h=297; height
mt=24; margin at top
mb=23; margin at bottom
dw=12;
dh=50;
nx=w/dw-1;
ny=(h-mt-mb)/dh;
y=1;
dy=1;
H0 : P(0,mb+dh*log(y)/log(10.0)) L(w) A(y,y+dy);
HL : S(H0,9) A(dy,dy*10);
VL : [T(pi/2) M(mb) L(h-mt-mb)] M(dw);
START : [S(HL,ny) S(H0,1)] M(dw) S(VL,nx);

You can get pdf versions of the above mentioned graph paper below:

Here we have changed the default solid lines to dotted lines by opening up the svg output files in inkscape, selecting the grid, and choosing from the menu: Object | Fill and Stroke | Stroke Syle.

Making graph paper - square grid

March 21, 2020

Square grid graph paper is commonly used in math and engineering. Let's make some with the Nell language. Below is a Nell program that will do it.

; Creates a linear-linear sheet of graph paper.
; nell gplinlin.nll START 3 | nellsvg 8.5 11 in 0.01 0 > gplinlin.svg
w=8.5; w = width of graph
h=11;  h = height of graph
d=0.25; d = distance between lines
HL : [T(-pi/2) L(w)] M(d);
VL : [T(pi/2) L(h)] M(d);
START : [T(pi/2) M(d) S(HL,h/d-1)] M(d) S(VL,w/d);

The above program creates a 1/4 inch square grid on a letter size (8.5x11 inch) paper. The command line for generating the svg is shown as a comment on the second line of the program. Note that the thickness of the grid lines is set here as 0.01 inches, which you can change to anything you like.

If you want to change the grid size from 1/4 inch to the more common 5 mm size, just replace the "d=0.25", on the fifth line of the program, with "d=5/25.4". For an A4 paper size (210x297 mm) with 5 mm grid size, the program below will work.

; Creates a linear-linear sheet of graph paper.
; nell gplinlin2.nll START 3 | nellsvg 210 297 mm 0.254 0 > gplinlin.svg
w=210; w = width of graph
h=297;  h = height of graph
d=5; d = distance between lines
HL : [T(-pi/2) L(w)] M(d);
VL : [T(pi/2) L(h)] M(d);
START : [T(pi/2) M(d) S(HL,h/d-1)] M(d) S(VL,w/d);

You can get pdf versions of the above mentioned graph paper below:

Here we have changed the default solid lines to dotted lines by opening up the svg output files in inkscape, selecting the grid, and choosing from the menu: Object | Fill and Stroke | Stroke Syle.

Drawing a convex lens

March 17, 2020

A staple of geometric optics is the convex lens. Let's draw a biconvex lens with the Nell language.

A biconvex lens can be drawn as two arcs. From the figure, the distance from the origin, o, defined as the point from which the first arc is drawn, to the center of the lens is:
rc=r*cos(a)
The distance from the origin to the point where the second arc is drawn is:
x=2*rc

Based on the above, we can write the Nell program shown below.

; Creates a biconvex lens.
; nell biconvex.nll START 1 | nellsvg 13.2 5.6 cm 0.04 1 > biconvex.svg
r = 7;    r = radius of arc of lens surface
a = pi/8; a = angle at drawing origin from x axis to top of lens
rc = r*cos(a); rc = distance from drawing origin to center of lens
x = 2*rc; x = point on x axis from which 2nd arc is drawn
NONLENS : P(0.1,2.8) C(0.05) [M(rc) C(0.05)] [L(2*rc) C(0.05)] [T(a) L(r)] [T(-a) L(r)];
LENS : R(r,r,-a,2*a) M(x) R(r,r,pi-a,2*a);
START : S(NONLENS,1) S(LENS,1);

The output is

Note: the 2nd line of the program gives the command for generating the output. The code labeled NONLENS are points and lines that are not part of the lens.

Encircling a circle with circles

March 14, 2020

The program circ3.nll in the book shows how to draw a circle that is completely encircled by circles. Here we want to show where the formulas for the distance from the center of the inner circle to the center of an outer circle, as well as the radius of the outer circles, comes from.

The isosceles triangle shown in the figure can be split into 2 identical right triangles with angles a/2 and b. From one of these triangles, we see that cos(b)=r/x where we define x=r0+r, giving r=x*cos(b), which is the radius of the outer circles. The distance from the center of the inner circle to the center of an outer circle is just x, which we can express as
x=r0+r
 =r0+x*cos(b)
Solving this for x gives
x=r0/(1-cos(b)).

The angle b can be written in terms of the number of circles encircling the inner circle, n, as follows:
a = 2π/n
a + 2b = π
=> b = (π-a)/2 = (π-2π/n)/2 = π(n-2)/(2n)

Circles inscribed and circumscribed on a regular polygon

March 12, 2020

The program circ4.nll in the book shows how to inscribe a circle in a regular n sided polygon. Here we want to show where the formulas for inscribing and circumscribing circles come from. If you draw lines from the center of a regular n sided polygon to each of the vertices, you will divide the polygon into n equal isosceles triangles. One of these triangles is shown in the figure below.

φ = 2π/n
h = radius of inscribed circle
d = radius of circumscribed circle
θ = (π-φ)/2

From these parameters and some simple trigonometry we get
h = x*tan(θ)/2 = x/(2*tan(φ/2))
d = x/(2*cos(θ)) = x/(2*sin(φ/2))

The following is a Nell program for drawing both an inscribed and circumscribed circle in a regular n sided polygon.

; Creates a circle inscribed/circumscribed in an n-sided polygon.
; nell inscribed.nll START 10 | nellsvg 2 2 in 0.02 1 > inscribed.svg
n = 5;
x = 1;
a = 2*pi/n;
b = (pi-a)/2;
h = x/(2*tan(a/2));
d = x/(2*sin(a/2));
T1 : L(x) T(a);
START : P(0.5,0.25) <S(T1,n-1) Z()> T(b) M(d) C(d) C(h);

The output is

Note: the 2nd line of the program gives the command for generating the output.


Send questions or comments to:
Richard Hollos (richard[AT]exstrom DOT com)
Stefan Hollos (stefan[AT]exstrom DOT com)
Copyright 2021 by Exstrom Laboratories LLC