## Introduction

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.

## Construction

- Choose a point (
*O*), this will be your center of rotation for your cam.
- 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*

## Calculus

#### 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+2\pi)=f(\theta)\)
- \(f(\frac{3\pi}{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:

\(f(\theta)=r.(\sqrt{cos^{2}(\theta)+3}-cos(\theta))\)

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} -4r\sqrt{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:

#/bin/bash
BASE="came"
OUTPUT=output
find $OUTPUT -iname "$BASE*.tga" -delete
TOTAL=""
for a in `seq 0.1 0.1 1.6`; do
OUT=$OUTPUT/${BASE}_${a}.tga
OUT2=${OUTPUT}/${BASE}_${a}.jpg
TOTAL="${TOTAL} ${OUT2}"
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}
done
montage ${TOTAL} -geometry +2+2 result.jpeg