Application Center - Maplesoft

App Preview:

Classic Curves - the Limaçon

You can switch back to the summary page by clicking here.

Learn about Maple
Download Application


 

Image 

Classic Curves - the Lima?on 

David A. Harrington
Chemistry Department, University of Victoria
Canada
dharr@uvic.ca, http://web.uvic.ca/~dharr 

Introduction 

The lima?on is a classic curve, named after its snail shape by Roberval. Also known as Pascal's lima?on after ?tienne Pascal, the father of Blaise Pascal, it was published, though not named, by D?rer in 1525. Special cases include the cardioid and the trisectrix. 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 used 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 (infinite length) s1 passing through p1 and p2
  intersection(inter,s1,c1)              cintersection points of line s1 with circle c1 - point or list of two points 

  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, 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 lima?on has two parameters, Typesetting:-mrow(Typesetting:-mi( and Typesetting:-mrow(Typesetting:-mi(. The base circle in some of the constructions below has radius Typesetting:-mrow(Typesetting:-mi(. The ratio Typesetting:-mrow(Typesetting:-mi( roughly determines how much of an internal loop there is. Here we choose values for the rest of the worksheet. Definite values need to be assigned for the plots to work. Special cases are:
Typesetting:-mrow(Typesetting:-mi(, the cardioid, and
 

Typesetting:-mrow(Typesetting:-mi(, the trisectrix. 

> a:=1;k:=1;
 

 

1
1 (2.1)
 

The draw command sometimes cuts off labels, so to force a larger viewing area, four white points around a rectangle a bit larger than the lima?on are defined here 

> border:=proc() local f;
         f:=1.1;
         point(sq1,-f*k,f*(a+k))(colour=white,printtext=false),
         point(sq2,f*(2*a+k),-f*(a+k))(colour=white,printtext=false),
         point(sq3,-f*k,-f*(a+k))(colour=white,printtext=false),
         point(sq4,f*(2*a+k),f*(a+k))(colour=white,printtext=false);
       end proc:
 

>
 

First construction 

The first construction uses a circle, the base circle, with its horizontal diameter of length Typesetting:-mrow(Typesetting:-mn( terminated in points named A and B. (We take the origin to be at A.) We choose a point Q on the circle (angle QAB = Typesetting:-mrow(Typesetting:-mi(, indicated in yellow), and construct a line segment in the direction AQ, extending a distance Typesetting:-mrow(Typesetting:-mi( either side of Q. Note from the right triangle QAB that the distance AQ is Typesetting:-mrow(Typesetting:-mn(. The endpoints of this line segment, P1 and P2 are on the lima?on. Change theta in the first line below to see other how other values look. 

> theta:=1;
point(A,0,0):point(B,2*a,0):
segment(horizontal,A,B):
circle(basecircle,[A,B],centername=O):
AQ:=2*a*cos(theta): # distance from A to Q
P1A:=AQ-k:          # distance from A to P1
P2A:=AQ+k:          # distance from A to P2
point(Q,AQ*cos(theta),AQ*sin(theta)):
point(P1,P1A*cos(theta),P1A*sin(theta)):
point(P2,P2A*cos(theta),P2A*sin(theta)):
segment(P1P2,P1,P2):
display(plottools[pieslice](coordinates(A),a,0..theta,colour=yellow),       
draw([border(),basecircle(colour=blue,printtext=false),horizontal(colour=blue),Q,P1P2(printtext=false,thickness=2),P1,P2],printtext=true,axes=none));
 

 

1
Plot_2d
 

Now we repeat for many points Q around the circle. We collect the information for a static plot of the lines, and also for an animated plot of the line moving and tracing out the curve with its ends. 

> n:=52: # number of points to use (frames in the animation)
point(A,0,0):point(B,2*a,0):
segment(horizontal,A,B):
circle(basecircle,[A,B]):
pics:=NULL: # collect the pictures in a sequence
picpts:=NULL: # collect the pictures and accumulated points
pts1:=[2*a-k,0]:pts2:=[2*a+k,0]:
for i from 0 to n do
  theta:=i*Pi/n;
  AQ:=2*a*cos(theta): # distance from A to Q
  P1A:=AQ-k:          # distance from A to P1
  P2A:=AQ+k:          # distance from A to P2
  point(P1||i,P1A*cos(theta),P1A*sin(theta)):
  point(P2||i,P2A*cos(theta),P2A*sin(theta)):
  segment(P1P2||i,P1||i,P2||i):
  pts1:=pts1,coordinates(P1||i):
  pts2:=pts2,coordinates(P2||i):
  dr:=draw([P1P2||i,basecircle(colour=blue)],axes=none):
  pics:=pics,dr;
  picpts:=picpts,display([pointplot([pts1],style=line),pointplot([pts2],style=line),dr]);
end do:
display([pics]);
 

Plot_2d
 

Now the animated version. Click on the plot and press play on the toolbar. 

> display([picpts],insequence=true,axes=none,scaling=constrained,view=[-k..2*a+k,-(a+k)..(a+k)]);
 

Plot_2d
 

>
 

Polar plot 

The lima?on in polar form is  Typesetting:-mrow(Typesetting:-mi(. To see this, just note that Typesetting:-mrow(Typesetting:-mi( is the distance A-P2 in the first construction method. 

> plot(k+2*cos('theta'),'theta'=0..2*Pi,coords=polar,scaling=constrained,axes=none);
 

Plot_2d
 

>
 

Parametric plot 

The lima?on can be plotted simply in parametric form, Typesetting:-mrow(Typesetting:-mi(. This can be found from the polar form Typesetting:-mrow(Typesetting:-mi( by noting that Typesetting:-mrow(Typesetting:-mi(, Typesetting:-mrow(Typesetting:-mi( and renaming Typesetting:-mrow(Typesetting:-mi( to Typesetting:-mrow(Typesetting:-mi(. Note however that the origin is now shifted Typesetting:-mrow(Typesetting:-mi( to the right. 

> combine(('k'+2*'a'*cos(t))*cos(t)); # x
combine(('k'+2*'a'*cos(t))*sin(t)); # y
plot([k*cos(t)+a*cos(2*t),k*sin(t)+a*sin(2*t),t=0..2*Pi],scaling=constrained,axes=none);
 

 

 

`+`(`*`(cos(t), `*`(k)), `*`(a, `*`(cos(`+`(`*`(2, `*`(t)))))), a)
`+`(`*`(sin(t), `*`(k)), `*`(a, `*`(sin(`+`(`*`(2, `*`(t)))))))
Plot_2d
 

>
 

Cartesian equation and implicitplot 

The cartesian equation of the lima?on can be derived starting from the polar form Typesetting:-mrow(Typesetting:-mi( Multiply each side by Typesetting:-mrow(Typesetting:-mi( (which introduces an additional point at the origin): Typesetting:-mrow(Typesetting:-mi(. Now square the whole thing and then simplify noting that Typesetting:-mrow(Typesetting:-mi( and Typesetting:-mrow(Typesetting:-mi(Typesetting:-mrow(Typesetting:-mi(We can use this in implicitplot, but it's not that nice unless we use a fine grid. 

> implicitplot((x^2+y^2-2*a*x)^2 = k^2*(x^2+y^2),x=-k..2*a+k,y=-(a+k)..(a+k),scaling=constrained,axes=none,grid=[100,100]);
 

Plot_2d
 

>
 

Construction as an epitrochoid 

An epitrochoid is the locus of a point carried round by one circle rolling around another, but not necessarily on the circumference. In this case the point is actually outside the circumference. This construction is based around a different base circle, centered at O, a distance Typesetting:-mrow(Typesetting:-mi( away from a fixed point A, and with radius Typesetting:-mrow(Typesetting:-mi( (blue circle). The rolling circle (red) has the same radius as the base circle, and has attached to it a point P a distance Typesetting:-mrow(Typesetting:-mi( away from its centre. We start with the rolling circle at the horizontal. 

> point(A,0,0):point(U,a-k/2,0):point(V,a+k/2,0):
circle(basecircle,[U,V],centername=O):
point(O2,a+k/2+k/2,0):
circle(c1,[O2,k/2]):
point(P,a+k/2+k/2+a,0):
segment(horizontal,A,P):
segment(O2P,O2,P):
draw([border(),basecircle(colour=blue),horizontal(colour=blue),c1,O2P(thickness=2)],printtext=true,axes=none);
 

Plot_2d
 

Now we roll the circle around until the line O-O2 has rotated an angle Typesetting:-mrow(Typesetting:-mi( (shaded yellow). If the circle slipped, O2-P would rotate Typesetting:-mrow(Typesetting:-mi(but without slippage it rotates another Typesetting:-mrow(Typesetting:-mi( The angle OAP is also Typesetting:-mrow(Typesetting:-mi(. The figure has mirror symmetry around the tangent line to the two circles (black dotted line).If we draw the old base circle of radius Typesetting:-mrow(Typesetting:-mi( (see first construction method) dotted, then A, Q and P are as before. To see this, note that O-Q-P-O2 is a parallelogram, so length Q-P = length O-O2 = Typesetting:-mrow(Typesetting:-mi(, and so P is a point on the lima?on as defined by the first construction method. 

> theta:=1/2;
point(A,0,0):point(B,2*a,0):
point(U,a-k/2,0):point(V,a+k/2,0):
circle(basecircle,[U,V],centername=O):
circle(oldbasecircle,[A,B]):
segment(horizontal,A,B):
point(OO2,a+k/2+k/2,0): # set up unrotated point O2
circle(c1,[OO2,k/2]):   # and unrotated circle c1
point(PP,a+k/2+k/2+a,0):  # and unrotated point P
rotation(rotc1,c1,theta,counterclockwise,O): # rotate circle around by theta
rotation(rotPP,PP,theta,counterclockwise,O): # and point PP
center(O2,rotc1): #rename centre of circle O2
rotation(P,rotPP,theta,counterclockwise,O2):# rotate PP further around O2 by theta
segment(O2P,O2,P):
segment(O2O,O,O2):
segment(AP,A,P):
segment(OQ,O,Q):
point(T,a+k/2*cos(theta),k/2*sin(theta)): # touch point of the two circles
tangentpc(tang,T,basecircle):
point(Q,2*a*cos(theta)^2,2*a*cos(theta)*sin(theta)):
display(plottools[pieslice](coordinates(O),k/2,0..theta,colour=yellow),
       plottools[pieslice](coordinates(A),k/2,0..theta,colour=yellow),
  draw([border(),basecircle(colour=blue),oldbasecircle(colour=blue,printtext=false,linestyle=3),horizontal(colour=blue),rotc1(printtext=false),Q(colour=black),O2O(colour=black),O2P(thickness=2),T,tang(colour=black,linestyle=3),AP(colour=black),OQ(colour=black)],printtext=true),axes=none);
 

 

`/`(1, 2)
Plot_2d
 

Now we repeat it many times, as the rolling circle goes around. The point P traces out the lima?on. Click on the plot and then on "play" on the toolbar to see the animation run. 

> n:=52: #number of circles to draw
point(A,0,0):point(B,2*a,0):
point(U,a-k/2,0):point(V,a+k/2,0):
circle(basecircle,[U,V],centername=O):
circle(oldbasecircle,[A,B]):
segment(horizontal,A,B):
point(OO2,a+k/2+k/2,0):
circle(c,[OO2,k/2]):
point(PP,a+k/2+k/2+a,0):
pics:=NULL:
pts:=NULL:
for i from 0 to n do
  theta:=i*2*Pi/n;   
  rotation(c||i,c,theta,counterclockwise,O):
  rotation(rotPP||i,PP,theta,counterclockwise,O):
  center(O2||i,c||i):
  rotation(P||i,rotPP||i,theta,counterclockwise,O2||i):
  segment(O2P||i,O2||i,P||i):
  pts:=pts,coordinates(P||i):
  pics:=pics,display([pointplot([pts],style=line),
                    draw([border(),basecircle(colour=blue),
                         c||i(printtext=false),O2P||i(thickness=2)])],axes=none);
end do:
display([pics],insequence=true);
 

Plot_2d
 

>
 

Envelope of circles around a base circle 

This construction uses the same base circle (blue) as for the epitrochoid method: centered at O, a distance Typesetting:-mrow(Typesetting:-mi( away from a fixed point A, and with radius Typesetting:-mrow(Typesetting:-mi(. A point T on the basecircle is chosen and a circle is drawn with centre T and radius AT. Typesetting:-mrow(Typesetting:-mi( is the angle TOV, shaded yellow. Change Typesetting:-mrow(Typesetting:-mi( to see different choices. (The origin is chosen at A.) To see why it works, note that in the epitrochoid method, length A-T = length T-P and so a circle with centre T through A has P on its circumference. Furthermore, T is the instantaneous centre of motion of P, and so a tangent of this circle at P is also a tangent of the lima?on. 

> theta:=1;
point(A,0,0):point(U,a-k/2,0):point(V,a+k/2,0):
circle(basecircle,[U,V],centername=O):
segment(horizontal,A,V):
point(T,a+k/2*cos(theta),k/2*sin(theta)):
circle(c1,[T,distance(A,T)]):
segment(AT,A,T):
display(plottools[pieslice](coordinates(O),k/2,0..theta,colour=yellow),
draw([border(),basecircle(colour=blue),horizontal(colour=blue),AT,T,c1],printtext=true),axes=none);
 

 

1
Plot_2d
 

Now we repeat it many times, for many circles around the base circle. The envelope of these circles is the lima?on. 

> n:=30: #number of circles to draw
point(A,0,0):point(U,a-k/2,0):point(V,a+k/2,0):
circle(basecircle,[U,V],centername=O):
segment(horizontal,A,V):
circles:=NULL: # collect the circles into a sequence
for i to n do
  theta:=i*2*Pi/n;
  point(T||i,a+k/2*cos(theta),k/2*sin(theta)):
  circle(c||i,[T||i,distance(A,T||i)]):
  circles:=circles,c||i;
end do:
draw([border(),basecircle(colour=blue),circles],axes=none);
 

Plot_2d
 

>
 

D?rer's method 

The circumference of a base circle of radius Typesetting:-mrow(Typesetting:-mi( is marked off at equal intervals, e.g., 10 degrees, and these points are numbered 0, 1, 2, ... . A line segment is constructed from Point 1 parallel to radius 2 of length Typesetting:-mrow(Typesetting:-mi(. Then from point 2 parallel to radius 4, ..., and in general from point Typesetting:-mrow(Typesetting:-mi( parallel to radius  Typesetting:-mrow(Typesetting:-mn(. The ends of these lines are on a lima?on. To see this, see the epitrochoid method and note that the radii and lines are O-O2 and O2-P.  

> point(top,0,k):point(bottom,0,-k):
circle(basecircle,[top,bottom],centername=O):
n:=20;
pts:=NULL:
for i from 0 to 6 do
  theta:=i*2*Pi/n;
  point(p||i,k*cos(theta),k*sin(theta));
  dsegment(r||i,O,p||i); # radius of length k
  pts:=pts,p||i,r||i;
end do:
pts2:=NULL:
for i from 0 to 3 do
  theta:=i*4*Pi/n; # angle steps twice as big
  point(a||i,a*cos(theta),a*sin(theta)):
  dsegment(s||i,O,a||i): # radius of length a
  translation(t||i,s||i,r||i): # and translate it to the end of r||i
  point(P||i,op(coordinates(DefinedAs(t||i)[2]))):
  pts2:=pts2,t||i,P||i:  
end do:
display(
draw([border(),basecircle(colour=blue),pts],printtext=true),
draw([pts2]),axes=none);
 

 

20
Plot_2d
 

Now the same thing more densely, showing only the lines and not the radii. 

> n:=100;
point(top,0,k):point(bottom,0,-k):
circle(basecircle,[top,bottom],centername=O):
pts:=NULL:
for i from 0 to 2*n do
  theta:=i*2*Pi/n;
  point(p||i,k*cos(theta),k*sin(theta));
  dsegment(r||i,O,p||i); # radius of length k
  pts:=pts,p||i,r||i;
end do:
pts2:=NULL:
for i from 0 to n do
  theta:=i*4*Pi/n; # angle steps twice as big
  point(a||i,a*cos(theta),a*sin(theta)):
  dsegment(s||i,O,a||i): # radius of length a
  translation(t||i,s||i,r||i): # and translate it to the end of r||i
  point(P||i,op(coordinates(DefinedAs(t||i)[2]))):
  pts2:=pts2,t||i,P||i:  
end do:
draw([border(),basecircle(colour=blue),pts2],axes=none);
 

 

100
Plot_2d
 

>
 

The lima?on as a pedal curve, and a second envelope of circles 

The base circle in this method is of radius Typesetting:-mrow(Typesetting:-mi(, with its centre a distance Typesetting:-mrow(Typesetting:-mn( from a fixed point A (blue). We choose a tangent on the circle and find the point P on it that is the foot of the perpendicular to A; P is on the lima?on. We take the origin at A. Thus the lima?on is the pedal curve of a circle (the base circle) with respect to the fixed point A. Since APT is a right triangle, P is on the circumference of a circle (red) with diameter AT, and an envelope of such circles also gives a lima?on.  

> theta:=1;
point(A,0,0):point(B,2*a,0):
segment(horizontal,A,B):
circle(basecircle,[B,k]):
point(T,2*a+k*cos(theta),k*sin(theta)): # point on the circle to find tangent at
tangentpc(t1,T,basecircle): # find tangent at T
PerpendicularLine(p1,A,t1): # find perpendicular from A
intersection(P,t1,p1):      # name the intersection point P
circle(cAT,[A,T]):
display(plottools[pieslice](coordinates(B),k,0..theta,colour=yellow),       
draw([border(),basecircle(colour=blue,printtext=false),horizontal(colour=blue),T,t1,p1,P,cAT(printtext=false)],printtext=true,axes=none));
 

 

1
Plot_2d
 

Now we repeat for many points T around the circle, drawing only the segments AP and PT 

> n:=52: # number of points to use
point(A,0,0):point(B,2*a,0):
segment(horizontal,A,B):
circle(basecircle,[B,k]):
pics:=NULL: # collect the pictures in a sequence
pics2:=NULL: # and the circles for the envelope method
picpts:=NULL: # collect the pictures and accumulated points
pts1:=NULL:
for i from 0 to n do
  theta:=i*2*Pi/n;
  point(T||i,2*a+k*cos(theta),k*sin(theta)):
  tangentpc(t||i,T||i,basecircle);
  PerpendicularLine(p||i,A,t||i);
  intersection(P||i,t||i,p||i):
  segment(AP||i,A,P||i):
  segment(PT||i,P||i,T||i):
  circle(cAT||i,[A,T||i]):
  dr:=draw([AP||i,PT||i,basecircle(colour=blue)],axes=none):
  dr2:=draw([cAT||i,basecircle(colour=blue)],axes=none):
  pts1:=pts1,coordinates(P||i):
  pics:=pics,dr;
  pics2:=pics2,dr2;
  picpts:=picpts,display([pointplot([pts1],style=line),dr]);
end do:
display([pics]);
 

Plot_2d
 

And the envelope of the circles 

> display([pics2]);
 

Plot_2d
 

Now the animated version of the pedal curve. Click on the plot and press play on the toolbar. 

> display([picpts],insequence=true,axes=none,scaling=constrained,view=[-k..2*a+k,-(a+k)..(a+k)]);
 

Plot_2d
 

>
 

Trisecting the angle with the trisectrix 

The trisectrix (lima?on with Typesetting:-mrow(Typesetting:-mi() can be used to trisect an angle. Following the first construction method, we have a base circle of radius Typesetting:-mrow(Typesetting:-mn(, with horizontal diameter AB. We choose some angle Typesetting:-mrow(Typesetting:-mi( and draw a line AR out from A at this angle, with length Typesetting:-mrow(Typesetting:-mi( (green angle). Join R to the centre of the circle, and where OR meets the trisectrix, draw point P1. The angle P1AO is one third of angle RAO. We construct the diagram by working backwards: starting with angle P1AO = Typesetting:-mrow(Typesetting:-mi( (yellow) and showing that angle RAO = Typesetting:-mrow(Typesetting:-mn(. Try different theta values.

The proof that the green angle is three times the yellow one is as follows: By the first construction method we have P1-Q = O-Q = A-O = Typesetting:-mrow(Typesetting:-mi(, so triangle OQP1 is isosceles. Let angle QAO = angle OQP1 = Typesetting:-mrow(Typesetting:-mi(, then angle P1OQ = 90 degrees - Typesetting:-mrow(Typesetting:-mi(. Now triangle OAQ is also isosceles so angle AOQ is 180 degrees -Typesetting:-mrow(Typesetting:-mn(. Therefore angle AOP1 = angle AOQ - angle P1OQ = 90 degrees -Typesetting:-mfrac(Typesetting:-mrow(Typesetting:-mn(. Now triangle OAR is also isosceles, so the green angle is 180 degrees - Typesetting:-mrow(Typesetting:-mn(.
 

> theta:=0.3;
point(A,0,0):point(B,2,0): # take k=a=1 without loss of generality
segment(horizontal,A,B):
circle(basecircle,[A,B],centername=O):
AQ:=2*cos(theta): # distance AQ
P1A:=AQ-1:        # distance A to P1 (on the trisectrix) by construction method 1
point(Q,AQ*cos(theta),AQ*sin(theta)):
point(P1,P1A*cos(theta),P1A*sin(theta)):
segment(QA,A,Q):
line(OP1,[O,P1]): # line O-P1 will meet at R
circle(c1,[A,1]): # circle on which R must lie
intersection('inter',OP1,c1): # R is at one intersection, O at the other
point(R,coordinates(inter[1])):
segment(AR,A,R):
segment(OR,O,R):
segment(OQ,O,Q):
line(ARline,[A,R]):
line(AOline,[A,O]):
alpha:=evalf(FindAngle(ARline,AOline));
display(plottools[pieslice](coordinates(A),1/2,0..3*theta,colour=green),
       plottools[pieslice](coordinates(A),3/2,0..theta,colour=yellow),
       plot(1+2*cos(t),t=0..2*Pi,coords=polar,scaling=constrained,axes=none),       
       draw([border(),basecircle(colour=blue),horizontal(colour=blue),
        AR(colour=black),OR(colour=black),OQ(colour=black),Q,QA,P1,R],
        printtext=true,axes=none));
 

 

 

.3
.9000000017
Plot_2d
 

>
 

References 

Lockwood, E.H. A Book of Curves, Cambridge University Press, London, 1961. Perhaps my favourite book. The drawing exercises in this book are time consuming compared to writing Maple code, but have a certain fascination. The cartesian equation is derived following Lawrence, J.D. A Catalog of Special Plane Curves, Dover, NY, 1972. 

Conclusions 

The lima?on can be generated in a variety of interesting and beautiful ways, which can be generated readily, though not trivially, with Maple. Some of these strategies can be useful to generate other curves as well. 

 

The geometry package is useful for the various constructions of the lima?on. Most of the calculations of where the points, circles etc should be have been done explicitly without using the deeper capabilities of the package; the use of "intersection" is the main place we have avoided explicit calculation. 

 

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.
 

Image