0
$\begingroup$

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?

$\endgroup$
  • $\begingroup$ No time to parse your code, so a comment not an answer. If you know the major and minor axes, the angle the major axis makes with the $x$-axis and the center you can map the ellipse to the standard unit circle by translating the center to the origin, then multiplying by the matrix with eigenvectors the two axes and eigenvalues the reciprocals of the axis lengths. There should be no singularities. $\endgroup$ – Ethan Bolker Nov 15 '17 at 1:05
  • $\begingroup$ Using some MathJax would help in understanding your question. $\endgroup$ – Stephen Meskin Nov 15 '17 at 1:24
  • $\begingroup$ @EthanBolker I'm trying to visualize what you are suggesting but not really getting it. how do I determine the eigenvectors of the two axis? Is that merely the eigenvector calculated in the optimization, and scaling the x only portion by 1/a and the y portion by 1/b? $\endgroup$ – Legen Diary Nov 15 '17 at 18:10
0
$\begingroup$

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.

$\endgroup$
  • $\begingroup$ you should look again, because you are missing things. I think the bigger issue is that you are not being clear about your complaint (angles is represented by R in the test code, your issue with graph case being different from function is not true, with no randomization it returns a unit circle, issues only appear with randomization, your argument of atan2 being unreliable is compelling) and additionally it is tangential to the issue at hand. the eigenvector is a more compelling path forward. Do I just use the eigenvector, scale the x and y portions of the vector by 1/a and 1/b respectively? $\endgroup$ – Legen Diary Nov 15 '17 at 19:15
  • $\begingroup$ For the eigenvector method, you have the right scaling factors, just make sure that they act in the directions of the rotated axes of the ellipse and not in the x and y directions of your world coordinates. $\endgroup$ – David K Nov 15 '17 at 19:29
  • $\begingroup$ do you have any suggestions for generating those vectors? the eigenvector generated by the optimization is of the form (x^2,xy,y^2,x,y,const). I'm having trouble thinking of how to convert that into a 2x2 matrix of form [[xx,xy],[yx,yy]] (how much of x goes to x....), unless that is merely taking the first three fields, and repeating xy twice (though that doesn't seem right because it is x squared not x into x.... $\endgroup$ – Legen Diary Nov 15 '17 at 19:54
  • $\begingroup$ I believe you compute the values of phi and phi2 correctly. One of those should be the angular direction of one of the axes (probably the a axis, I think). A typical way to get such a matrix is you take the matrix for rotation by $-\phi,$ multiply on the left by the matrix to multiply the $x$ coordinate by $1/a,$ then multiply on the left by the matrix for rotation by $\phi.$ $\endgroup$ – David K Nov 15 '17 at 20:08
  • $\begingroup$ BTW it looks like phi2 gives you the direction of the longer axis, so if $b>a$ it gives you the direction the "$y$-axis" of the ellipse was rotated to. $\endgroup$ – David K Nov 15 '17 at 20:36

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.