Classic Curves - the Nephroid
David A Harrington
Chemistry Department, University of Victoria
Canada
dharr@uvic.ca, http://web.uvic.ca/~dharr
Introduction
The nephroid is a classic curve, named after its kidney shape by Procter in 1878. In this worksheet, I show how to generate it via several different construction methods.
Most of the geometric construction commands are from the geometry package, see ?geometry. (An alternative would have been to use commands from the plottools package.) The common ones we use are reviewed here. For most of the construction commands the first argument is the name of the object being constructed.
point(p1,x,y) construct point p1 with coordinates (x,y)
circle(c1,top,bottom) construct circle c1 with diameter between points top and bottom
circle(c1,[centre,radius]) construct circle c1 with center point "centre" and radius of length "radius"
segment(s1,p1,p2) construct line segment s1 between points p1 and p2
line(s1,[p1,p2]) construct line s1 of infinite extent through points p1 and p2
rotation(r2,q1,theta,clockwise,centre) make object r2 by rotating object q1 clockwise by angle theta around point "centre"
coordinates(p1) returns coordinates [x,y] of point p1
DefinedAs(s1) returns [p1,p2], the names of the two points at the end of line segment s1
As the package requires all objects to be named, and so within loops with index i the concatenation operator "||" is used to generate new names, e.g., point(p||i,...) generates points p1, p2, p3,... as the index i goes 1,2,3,...
Initialization
After running this initialization section, any of the sections below may be run independently of each other.
> |
restart;with(geometry):with(plots): |
The nephroid has one parameter,
, that determines its size. The base circle in some of the constructions below has radius
, in others
. Here we choose a value for the purposes of the plots.
 |
(2.1) |
The draw command sometimes cuts off labels, so to force a larger viewing area, a white square border with sides of length s is defined
> |
border:=proc(s);
square(sq,[point(sq1,-s/2,s/2),point(sq2,s/2,s/2),
point(sq3,s/2,-s/2),point(sq4,-s/2,-s/2)]);
sq(colour=white,printtext=false);
end proc: |
Parametric plot
The nephroid can be plotted simply in parametric form,
.
> |
plot([3*a*cos(t)+a*cos(3*t),3*a*sin(t)+a*sin(3*t),t=0..2*Pi],scaling=constrained,axes=none); |
Envelope of circles around a base circle
The first construction is based around a circle, the base circle, centered at the origin O with radius
. This is easiest to define via its vertical diameter, which is terminated in points named "top" and "bottom".
> |
point(top,0,2*a):point(bottom,0,-2*a):
circle(basecircle,[top,bottom],centername=O):
segment(vertical,top,bottom):
draw([border(5*a),basecircle(colour=blue),vertical(colour=blue)],printtext=true,axes=none); |
We now construct a circle c1 with its centre on the base circle. Choose an angle
clockwise around the base circle from 12 o'clock (the yellow region). The point p1 at the end of the radius at this angle has coordinates
and is the centre of the circle c1. The circle also touches the vertical line at p2, so that the horizontal distance between p1 and the vertical is
. So this circle is defined with centre at p1 and radius
Try changing theta in the line below to see other possible circles.
> |
theta:=1.2;
point(p1,2*a*sin(theta),2*a*cos(theta)):
circle(c1,[p1,abs(2*a*sin(theta))]):
segment(s1,p1,point(p2,0,2*a*cos(theta))):
display(plottools[pieslice]([0,0],2*a,Pi/2..Pi/2-theta,colour=yellow),
draw([border(5*a),basecircle(colour=blue),vertical(colour=blue),p1,c1,s1],
printtext=true),
axes=none); |
Now we do it many times, for many circles around the base circle. Note that negative and zero radii generate an error, so we take the absolute value of the x coordinate of p1 when defining the circle, and avoid circles at
or
The envelope of these circles is the nephroid.
> |
n:=30: #number of circles to draw
circles:=NULL:
for i to n-1 do
theta:=i*2*Pi/n;
if theta=Pi then next end if;
point(p||i,2*a*sin(theta),2*a*cos(theta));
circle(c||i,[p||i,abs(2*a*sin(theta))]);
circles:=circles,c||i; # collect the circles in a sequence
end do:
draw([basecircle(colour=blue),vertical(colour=blue),circles],axes=none); |
Epicycloid
The nephroid is also an epicycloid, i.e., the locus of a point on the circumference of a circle that rolls around another circle. If the radius of the base circle is
, then the locus of a point on a circle of radius
rolling around the base circle is a nephroid. We start with the circle at the top:
> |
point(top,0,2*a):point(bottom,0,-2*a):
circle(basecircle,[top,bottom],centername=O):
point(centre,0,3*a): #centre of rolling circle
circle(c1,[centre,a]): #rolling circle
point(b1,0,2*a): #bottom of circle
segment(s1,centre,b1): #vert. down radius of circle
draw([basecircle(colour=blue),b1,s1,c1],printtext=true,axes=none); |
At an angle theta around the base circle, we have traversed a distance
around the circumference of the base circle (yellow region). So the rolling circle has rotated by the same circumference, or by an angle
(green region). This angle is added to
to give the angle from the downward vertical of the radius that ends at b2 . Point b2 is on the nephroid. Try changing theta to see the rolling circle at different points around its travel.
> |
theta:=0.2;
point(centre,3*a*sin(theta),3*a*cos(theta)): #centre of rolling circle
circle(c2,[centre,a]): #rolling circle
point(bb2,3*a*sin(theta),3*a*cos(theta)-a): #bottom of rolling circle
segment(ss2,centre,bb2): #vert. down radius of circle
phi:=theta*2: #angle to rotate above segment by
rotation(sss2,ss2,phi+theta,clockwise,centre): #rotate it
point(b2,coordinates(DefinedAs(sss2)[2])): #point at end of rotated segment
segment(s2,centre,b2): #redefine segment to get nice endpoint names
display(plottools[pieslice]([0,0],2*a,Pi/2..Pi/2-theta,colour=yellow),
plottools[pieslice](coordinates(centre),a,3*Pi/2..3*Pi/2-theta,colour=yellow),
plottools[pieslice](coordinates(centre),a,3*Pi/2-theta-phi..3*Pi/2-theta,
colour=green),
draw([basecircle(colour=blue),b2,s2,c2],printtext=true),
axes=none);
|
Now put this in a loop and animate the sequence of drawings formed. Accumulate the points into a curve. To see the animation, click on the plot and choose play on the toolbar.
> |
n:=52: #number of pictures to draw
pics:=NULL:pts:=[0,2*a]:
for i from 0 to n do
theta:=i*2*Pi/n;
point(centre,3*a*sin(theta),3*a*cos(theta)):
circle(c||i,[centre,a]):
point(bb||i,3*a*sin(theta),3*a*cos(theta)-a):
segment(ss||i,centre,bb||i):
phi:=theta*2:
rotation(s||i,ss||i,phi+theta,clockwise,centre):
b||i:=DefinedAs(s||i)[2]:
pts:=pts,coordinates(b||i):
pics:=pics,display(pointplot([pts],style=line),
draw([border(5*a),basecircle(colour=blue),b||i,s||i,c||i])):
end do:
display([pics],insequence=true,axes=none,scaling=constrained,view=[-4*a..4*a,-4*a..4*a]); |
Epicycloid, second form
The nephroid is also an epicycloid in a second sense. This time the rolling circle is radius
, larger than the base circle and the "inside" of the rolling circle rolls around the base circle.We start with the rolling circle touching at the top.
> |
point(top,0,2*a):point(bottom,0,-2*a):
circle(basecircle,[top,bottom],centername=O):
point(touch,0,2*a): #rolling circle touches base circle
segment(baseradius,O,touch): #radius of base circle
expansion(rr1,baseradius,3/2,touch): #stretch radius to make rolling circle radius
point(centre,coordinates(DefinedAs(rr1)[1])): #centre of rolling circle
segment(r1,centre,touch): #redo stretch radius with nice endpoint names
circle(c1,[centre,3*a]): #rolling circle
draw([basecircle(colour=blue),r1,c1],printtext=true,axes=none); |
 |
|
At an angle
around the base circle, the rolling circle touches at the end of the radius at angle theta (yellow slice). Expand this radius by 3/2 (back from the touch point) to get the rolling circle radius. We have traversed a distance
around the circumference of the base circle. So the rolling circle has rolled by the same circumference, or by an angle
(green region). This angle is subtracted from
to find the point p2 on the nephroid. Try different values of theta to see the rolling circle at different possible positions.
> |
theta:=1;
point(touch,2*a*sin(theta),2*a*cos(theta)): #rolling circle touches base circle
segment(baseradius,O,touch): #radius of base circle at angle theta
expansion(rr2,baseradius,3/2,touch): #stretch radius to make rolling circle radius
point(centre,coordinates(DefinedAs(rr2)[1])): #centre of rolling circle
segment(r2,centre,touch): #redo stretch radius with nice endpoint names
circle(c2,[centre,3*a]): #rolling circle
phi:=theta*2/3;
rotation(s2,rr2,phi,counterclockwise,centre): #rotate the stretched radius by phi
point(p2,coordinates(DefinedAs(s2)[2])): #here is its endpoint
display(draw([basecircle(colour=blue),touch,c2,r2,p2],printtext=true,axes=none),
plottools[pieslice]([0,0],2*a,Pi/2..Pi/2-theta,colour=yellow),
plottools[pieslice](coordinates(centre),3*a,Pi/2-theta..Pi/2-theta+phi,colour=green), view=[-4*a..4*a,-4*a..4*a]);
|
Now put this in a loop and animate the sequence of drawings formed. We need to go to
to get the full curve, as shown by the red radius. To see the animation, click on the plot and choose play on the toolbar.
The green radius of the rolling circle points to the point on the circumference tracing out the nephroid.
> |
n:=52: #number of pictures to draw
pics:=NULL:pts:=[0,2*a]:
for i from 0 to n-1 do
theta:=i*6*Pi/n;
point(touch||i,2*a*sin(theta),2*a*cos(theta)):
segment(baseradius||i,O,touch||i):
expansion(rr||i,baseradius||i,3/2,touch||i):
point(centre||i,coordinates(DefinedAs(rr||i)[1])):
segment(r||i,centre||i,touch||i):
circle(c||i,[centre||i,3*a]):
phi:=theta*2/3;
rotation(ss||i,rr||i,phi,counterclockwise,centre||i):
point(p||i,coordinates(DefinedAs(ss||i)[2])):
segment(s||i,p||i,centre||i):
pts:=pts,coordinates(p||i):
pics:=pics,display(pointplot([pts],style=line),
draw([border(5*a),basecircle(colour=blue),O(colour=blue),centre||i,
c||i,r||i,p||i,s||i(colour=green)]));
end do:
display([pics],insequence=true,axes=none,scaling=constrained,view=[-4*a..4*a,-4*a..4*a]); |
Envelope of tangents
This construction is based around a base circle centered at the origin O, with a vertical diameter, as before except that this time the radius is
. We choose a point R on the vertical diameter, and construct a circle with R as centre that passes through the origin. We then find the points T1 and T2 where this circle intersects the base circle, and construct the line segments R-T1 and R-T2
Note that there will be no intersection if R is closer to the origin than it is to the top point. On the other hand, it is possible to have R outside the base circle on an extension of the vertical diameter. The intersection command below returns the two points of intersection between the circles "c1" and "basecircle" and names them "T1" and "T2".
> |
point(top,0,4*a):point(bottom,0,-4*a):
circle(basecircle,[top,bottom],centername=O):
segment(vertical,top,bottom):
h:=2.4*a; # height of point R
point(R,0,h):
circle(c1,[R,h]):
intersection('T1T2',c1,basecircle,['T1','T2']):
segment(RT1,R,T1):
segment(RT2,R,T2):
draw([basecircle(colour=blue),vertical(colour=blue),c1,RT1,RT2],printtext=true,axes=none); |
Now we draw the line segments R-T1 and R-T2 for many points R along the top and bottom quarters of the vertical diameter and and also on the extension of the vertical diameter outside the base circle. The envelope of these lines is the nephroid. The picture looks better if the R's are more closely spaced near
than further out, hence the use of
in the calculation of
, the distance of R above the origin. The value of
is taken as positive; the top R-T1 and R-T2 are then calculated from
and the bottom ones are calculated using
.
> |
n:=25: #number of points along the vertical diameter
segments:=NULL:i:=0:
for i to n do
h:=radius(basecircle)/2+(i/n)^2*30*radius(basecircle)/n;
point(Rtop||i,0,h);
circle(ctop||i,[Rtop||i,h]);
intersection('T1T2',ctop||i,basecircle,[T1top||i,T2top||i]);
segments:=segments,segment(RT1top||i,Rtop||i,T1top||i),segment(RT2top||i,Rtop||i,T2top||i):
point(Rbot||i,0,-h);
circle(cbot||i,[Rbot||i,h]);
intersection('T1T2',cbot||i,basecircle,[T1bot||i,T2bot||i]);
segments:=segments,segment(RT1bot||i,Rbot||i,T1bot||i),segment(RT2bot||i,Rbot||i,T2bot||i):
end do:
draw([basecircle(colour=blue),segments],axes=none); |
Envelope of tangents, second form
This construction is based around a base circle, centered at the origin O with radius
. The circumference is marked off at equal intervals, e.g., 10 degrees, and these points are numbered 0, 1, 2, ... . Point 1 is joined to point 3, points 2 to 6, points 3 to 9, and in general point
to
. The envelope of these lines is the nephroid.
> |
point(top,0,4*a):point(bottom,0,-4*a):
circle(basecircle,[top,bottom],centername=O):
n:=36;
pts:=NULL:
for i to 9 do
theta:=i*2*Pi/n;
point(p||i,4*a*cos(theta),4*a*sin(theta));
pts:=pts,p||i;
end do:
segment(s13,p1,p3):
segment(s26,p2,p6):
segment(s39,p3,p9):
draw([border(9*a),basecircle(colour=blue),pts,s13(printtext=false),
s26(printtext=false),s39(printtext=false)],printtext=true,axes=none);
|
Now do it many times. The intial points need only go a quarter of the way around the circle. For symmetry, we run both clockwise and anticlockwise. The left half of the nephroid is obscured by the lines and so we do not generate its envelope.
> |
n:=100;
segments:=NULL:
for i from 1 to 3*n/4 do # make the points
theta:=i*2*Pi/n;
point(p||i,4*a*cos(theta),4*a*sin(theta)); # going counter clockwise
point(m||i,4*a*cos(-theta),4*a*sin(-theta)); # clockwise
end do:
for i from 1 to n/4 do
j:=3*i;
segment(sp||i,p||i,p||j);
segment(sm||i,m||i,m||j);
segments:=segments,sp||i,sm||i;
end do:
display(draw([basecircle(colour=blue),segments],axes=none),view=[-6*a..6*a,-6*a..6*a]); |
Reflection of parallel rays by a circle
If parallel rays hit a circle and are reflected (angle of incidence = angle of reflection), then the envelope of the reflected rays is a nephroid. In technical language, the nephroid is the caustic of a circle with radiant point at infinity. A ray entering from the top (black) hits at point P and is reflected (red). Note the ease of programming this using the reflection command, where "ref" is the result of "ray" reflected in the line "rad".
> |
h:=2.1*a: # horizontal location of incoming ray
point(top,0,4*a):point(bottom,0,-4*a):
circle(basecircle,[top,bottom],centername=O):
point(inh,h,8*a): # ray comes in from this point
point(P,h,-sqrt((4*a)^2-h^2)): # point where hits circle
segment(ray,inh,P):
line(rad,[O,P]): # radius O-P
reflection(ref,ray,rad):
draw([border(9*a),basecircle(colour=blue),P,ray(colour=black,printtext=false),ref(printtext=false)],printtext=true,axes=none);
|
Now do it many times.
> |
n:=15;
point(top,0,4*a):point(bottom,0,-4*a):
circle(basecircle,[top,bottom],centername=O):
rays:=NULL:
for i from -n to n do
h:=i*4*a/n;
point(inh||i,h,8*a): # ray comes in from this point
point(P||i,h,-sqrt((4*a)^2-h^2)): # point where hits circle
segment(ray||i,inh||i,P||i):
line(rad||i,[O,P||i]): # radius O-P
reflection(ref||i,ray||i,rad||i);
rays:=rays,ray||i,ref||i;
end do:
draw([border(9*a),rays,basecircle(colour=blue)],axes=none); |
This reflection can be seen in diluted milk in a cooking pot on the floor, with the sun coming in a window, as in the image below.
Polar and cartesian equations and plots
The polar equation can be written in several forms. Simplest is perhaps
Another form is
, which needs to run to
to produce the whole closed curve.
> |
plot(2^(1/2)*a*((1+sin('theta'))^(1/3)+(1-sin('theta'))^(1/3))^(3/2),'theta'=0..2*Pi,coords=polar,scaling=constrained,axes=none);
plot(2*a*(sin('theta'/2+Pi/4)^(2/3)+cos('theta'/2+Pi/4)^(2/3))^(3/2),'theta'=0..4*Pi,coords=polar,scaling=constrained,axes=none); |
And the cartesion equation is
, which can be plotted using implicitplot.
> |
implicitplot((x^2+y^2-4*a^2)^3=108*a^4*x^2,x=-4..4,y=-3..3,grid=[100,100],scaling=constrained,axes=none); |
References
Lockwood, E.H. A Book of Curves, Cambridge University Press, London, 1961. Instructions for the drawing exercises include dimensions for getting nice looking results. In some cases several Maple commands replicate a simple drawing action, but sometimes the Maple is very simple, for example, the reflection command in generating the caustic. The Cartesian equation and one of the polar forms are found in Lawrence, J.D. A Catalog of Special Plane Curves, Dover, NY, 1972, though they are rotated 90 degrees from those given here.
Conclusions
The nephroid can be generated in a variety of interesting and beautiful ways, which can be implemented in Maple using the geometry package. The analytical capabilities of Maple allow the curve to be plotted and analysed for things that we have not attempted here, e.g., for deriving the arc length, but it is interesting to generate the curves using envelopes of circles and lines, as was done historically.
Legal Notice: The copyright for this application is owned by the author(s). Neither Maplesoft nor the author are responsible for any errors contained within and are not liable for any damages resulting from the use of this material. This application is intended for non-commercial, non-profit use only. Contact the author for permission if you wish to use this application in for-profit activities.