Egg shape and camshaft


For some tinkering, I wanted to be able to draw a standard, egg-shaped cam and compute the displacement it was generating.

I thought this was a trivial problem, but I couldn’t find anything, so I’ll describe the path I used. As a side note, the end-goal was to generate some 3D animation with persistence of vision, so I was somehow constrained by what as doable with this software (knowing that I don’t generate anything and just use the software, so no real way of numerical solution and such)

The approach I followed seems to have been used for centuries by architect to create egg-shaped curves.

It uses 2 parameters, that I named r and h. I’ll describe the geometrical construction and then go to the calculus phase.

As a side note, I had great fun finding all of these and coining it into an article, hope you’ll like reading it as much as I had writing it 🙂 Some other may follow on related subjects, depending on interest / time.


  • Choose a point (O), this will be your center of rotation for your cam.Screen Shot 2016-01-25 at 6.14.54 PM
  • Draw a circle S1 (black one) , centered on O and radius r
  • Draw a diameter, creating points A and B on circle intersection.
  • Draw a perpendicular diameter and pick a new point C so that OC = h
  • From now, the construction is symmetrical, I’ll focus on one side.
  • Draw a circle S2 (red one) centered on A and going through B (hence, radius = 2r )
  • let D be the intersection of S2 and OC
  • Draw a circle S3 (green one) center on C and going through D
  • Your egg-shape is now, starting from bottom : S1 to B, then S2 to D then S3



Diameter of green circle

By definition,AD = 2r

Using pythagore on ACO, AC = sqrt{r^{2}+h^{2}}

Then CD = rho = 2r-sqrt{r^{2}+h^{2}}

BOD Angle

If you project D on AB to have a new H point, then you have widehat{HOD} = widehat{BOD} = beta and tan (beta) = frac{DH}{OH}

tan (widehat{OAC}) = frac{OC}{AO} = frac{h}{r} then widehat{OAC} = alpha = tan^{-1}{frac{h}{r}}

AH = 2r.cos(alpha) and DH = 2r.sin(alpha)

 OH = AH - OA = 2r.cos(alpha) - r = r(2.cos(alpha)-1)

Finally : tan(beta) = frac{2r.sin(alpha)}{r(2.cos(alpha)-1)} = frac{2.sin(tan^{-1}{frac{h}{r}})}{2.cos(tan^{-1}{frac{h}{r}})-1}

Polar coordinates

Let’s continue the fun, the end-goal is to have the polar coordinates of the cam…

We’ll use theta as parameter and assume it’s value is 0 on AB axis. Function will have nice properties:

  • f(theta+2pi)=f(theta)
  • f(frac{3pi}{2}-theta)=f(theta)

Meaning that we can focus on [-frac{pi}{2},frac{pi}{2}]

On [-frac{pi}{2},0], solution is trivial : f(theta)=r

On [0,beta], solution is circle center on (-r,0) radius 2r, which has implicit equation

 (x+r)^{2}+y^{2} = (2r)^2

Using standard polar replacements:

 (f(theta)cos(theta)+r)^{2}+f^{2}(theta)sin^{2}(theta) = (2r)^2

The interesting function is now a second order equation, that can be trivially solved:


On [beta,frac{pi}{2}], solution is circle center on (0,h) radius ρ, which has implicit equation

 x^{2}+(y-h)^{2} = rho^2

or  f(theta)^{2}cos^{2}(theta)+(f(theta)sin(theta)-h)^{2} = (2r-sqrt{r^{2}+h^{2}})^2

Again, the interesting function is now a second order equation, which can be (not so) trivially solved:

f(theta)= h.sin(theta)+sqrt{h^{2}sin^{2}(theta) +5r^{2} -4rsqrt{r^2+h^2} }

Limits on parameter

Due to the way the cam is built, h must be positive.

In addition, the worst case is having D aligned with O and C (actually C = D), and then, using pythagore:

 h in [0,sqrt{3}]

Realization with Pov-Ray

Now that we’re done with the maths, it’s time to do the actual stuff. Real implementation can be found on my POV repository, core is in an include file and there is a reference example file.

The cam itself is generated using CSG : intersection of cylinder and plan, the exact same way I’ve explained before. I encapsulated it into a macro with 2 parameters, h and r. With these explanations, reading the file is really straightforward.

The polar function is implemented using a bunch of functions within POV. There are a few caveats:

  • it seems recursion is not well supported and maybe using a modulo would be smarter
  • using an horizontal egg instead of a vertical one (i.e. changing the theta reference) would allow to have a symmetrical function (the current one has a pi/2 offset)
  • POV function do not allow to use #if statement (seems to be limited to global variable). Using select is a ice workaround but is really killing readability

To have an idea of how h parameter influences the result, quick matrix of rendering with r=1 and h variable:


Free bonus, script used for the rendering, with some image magick in it:


find $OUTPUT -iname "$BASE*.tga" -delete
for a in `seq 0.1 0.1 1.6`; do 
 povray -W200 -H200 +k0.1 -Iscene/$BASE.pov -O${OUT} Declare=h_parameter=$a
 convert ${OUT} -fill white -stroke red -pointsize 40 -gravity south -annotate 0 "h:$a" ${OUT2}

montage ${TOTAL} -geometry +2+2 result.jpeg

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s