[Math] converting an ellipse to circle

conic sections

I'm working on converting data that is represented as an ellipse into a unit circle. I currently have a least squares implementation of obtaining the offset xo and yo, angle, and major and minor axis as shown here.

I'm working on some equations for then converting that data back into a unit circle. Here is my code

def ellipse_to_unit_circle(x,y,gr=0):
    a = fitEllipse(x[gr:-gr],y[gr:-gr])
    center = ellipse_center(a)
    phi = ellipse_angle_of_rotation(a)
    axes = ellipse_axis_length(a)
    angles = np.arctan2(y,x)
    phi2 = ellipse_angle_of_rotation2(a)


    print(center)
    print(axes)

    denom_x = (-axes[0]*np.cos(angles)*np.cos(phi) + 
    axes[1]*np.sin(angles)*np.sin(phi))

    denom_y = (axes[0]*np.cos(angles)*np.sin(phi) + 
    axes[1]*np.sin(angles)*np.cos(phi))
    xx = (x-center[0])*np.cos(angles)/denom_x
    yy = (y-center[1])*np.sin(angles)/denom_y

    return [xx,yy]

I'll try my best to convert to a more readable form

for an ellipse with
$$major = a$$
$$minor = b$$
$$offset= x_0,y_0$$
$$angle=\theta$$
$$angle rotated =\phi$$

$$ x = a\cos(\theta)\cos(\phi)+ b\sin(\theta)\sin(\phi) + x_o $$
$$ y = -a\cos(\theta)\sin(\phi)+ b\sin(\theta)\cos(\phi) + x_o $$
thus to find a circle I would convert to as follows

$$ \frac{x_{measured} – x_0}{a\cos(\theta)\cos(\phi) + b\sin(\theta)\sin(\phi)} = 1$$
$$ \frac{y_{measured} – y_0}{-a\cos(\theta)\sin(\phi) + b\sin(\theta)\cos(\phi)} = 1$$

then multiply by cos(theta) for x, sin(theta) for y to obtain the unit circle
Additionally theta is calculated as arctan(y/x)

Here is the code to my example and a picture

if __name__ == '__main__':
    arc = 2
    R = np.arange(0,arc*np.pi, 0.01)
    xr = 2
    yr = 9
    x_offset = 2 + 1*np.random.rand(len(R))
    y_offset = 4 + 1*np.random.rand(len(R))

    phi_offset =0 #np.pi/4 
    x = xr*np.cos(R) 
    y = yr*np.sin(R)

    x = x*np.cos(phi_offset)+y*np.sin(phi_offset) + x_offset
    y = -x*np.sin(phi_offset)+y*np.cos(phi_offset) + y_offset

    xxx,yyy = ellipse_to_unit_circle(x,y)



    from pylab import *
    plot(x,y, color = 'purple', label='initial set')
    plot(xxx,yyy, color = 'green', label='converted to unit circle')

    legend(loc='upper left')
    show()

Picture!

First is there some problem mathematically from this conversion?

Second this equation creates singularities, is there an elegant way to deal with them?

Best Answer

I assume that the variables x and y in the program are arrays of numbers, because without that assumption it makes no sense to fit an ellipse to them. Then for each pair of values $(x_i,y_i)$ you compute $\theta_i = \mathrm{atan2}(y_i,x_i).$ This appears to be a fatal flaw, because the angle from the origin to an $(x,y)$ point after the circle has been distorted into an ellipse and translated away from the origin has very little to do with the parameter $\theta$ that you need in order to make the rest of your formulas work.

If you knew (or could reliably guess) the angle $\theta$ corresponding to a point on the circle before all the transformations that create the ellipse were applied, then I think you could use calculations like the ones you showed in order to convert the $(x,y)$ coordinates of the point on the ellipse to which your original point was mapped--but on the other hand if you know $\theta$ then you can plot the point on the circle without even looking at the coordinates on the ellipse.

I suggest trying a simple example, such as the ellipse generated by these parameterized equations: \begin{align} x &= 2\cos(\theta) + 5, \\ y &= \sin(\theta) + 2. \\ \end{align}

Plot these points for a few dozen equally-spaced of $\theta$ ranging from $0$ to $2\pi,$ confirm that you get an ellipse, then give these sets of coordinates to your function and see if it gives you back a circle. I will be surprised if the result makes any sense at all.


To do the algorithm correctly, as noted in a comment you just have to use the information from fitEllipse to create a matrix that scales the plane by a factor of $1/a$ parallel to the first axis of the ellipse and by a factor of $1/b$ parallel to the second axis of the ellipse. Translate all the points of the ellipse so that they are centered around the origin, then use the matrix to scale them onto a circle.