Scaling the X axis of a rotated ellipse - math

I have a scatter plot and I'm allowing points to be selected by drawing an ellipse like so:
In the above image the X axis and Y axis are scaled differently. I'm trying to implement functionality to allow the scale of each axis to be changed, but I'm having trouble scaling the ellipse shape with the axis. Changing the scale of the X axis to match the Y axis gives this:
I know I can scale the cx value of the ellipse with the X axis to get the new centre of the ellipse, but I don't know how to work out the new rx, ry and rotation angle. So my question is given a rotated ellipse with values cx, cy, rx, ry and rotation in radians, how do I calculate the new values for the ellipse given a scale value s for either the X axis or Y Axis? For clarity the rotation is done about the centre (cx, cy) of the ellipse.

I think I understand your problem. For an axis-aligned ellipse with points (x,y), the shape of (a*x,b*y) is still an ellipse with some arbitrary scaling factors a and b acting on the major and minor radii.
But for a rotated ellipse this is not true. In addition to the major and minor radii scaling differently, the rotation angle might differ also.
So mathematically the problem is as such: The parametric points of a rotated ellipse are
with θ the rotation angle r_1 and r_2 the original ellipse radii. The parameter t goes from 0 to 2π.
Now to find the modified parameters such that the ellipse matches a scaled version of the above
The above two are combined into one equation to be solved for r_1' and r_2' as well as θ' for all values of t.
Unfortunately, there is no solution that I can think of, because the combined 2×2 matrix on the RHS in front of the vector needs to be diagonalized by finding the appropriate rotation θ' to bring it down to this form
which is trivially solved for r_1' and r_2'.
But the rotation needs to satisfy two contradictory equations
tan(θ') = (a/b)*tan(θ) and tan(θ') = (b/a)*tan(θ)
which can only be solved if the two scaling factors are identical => a==b.
I suggest posting this problem into the [Mathematics.SE] as math problem, before trying to implement it as an algorithm. Maybe you will have better luck.

The computation is not that easy.
The equation of a rotated ellipse centered at the origin is
(c x + s y)² / a² + (s x - c y)² / b² = 1 = A x² + 2B xy + C y²
(c, s denote the cosine and sine of the rotation angle.) After development, the quadratic coefficients are
A = c² / a² + s² / b², 2B = 2 cs / a² - 2 sc / b², C = s² / a² + c² / b².
When you have the coefficients, you can retrieve 1/a², 1/b², c, s as the Eigenvalues and first Eigen vector of the 2x2 matrix
|A B|
|B C|
and the rotation angle is given by tan Θ = s / c.
Now let us stretch the abscissas by applying a coefficient r, giving
A' = r² A, B' = r B, C' = C.
The matrix becomes
|r²A rB|
|rB C|
and again, you will find the axis and cosine/sine of the angle by computing the Eigenvalues and first Eigenvector.
The Eigenvalues are roots of the polynomial
z² + (r²A + C) z + r²(AC - B²)
where A, B, C are computed as above, and the Eigenvector follows
(r²A - z) c + rB s = 0
from which you draw s/c.

Related

Fitting an ellipsoid given 2D contours

I have coordinates corresponding to a set of 2D contours, each corresponding to different heights. These contours do not draw out a perfect ellipsoid in 3D, and instead what I would like to do is to find the best fitting ellipsoid. I do not have any knowledge on the origin of this ellipsoid.
My first thought was to incorporate some type of least squares algorithm, where I find the ellipsoid parameters that minimize the distance between points. I imagine this would be quite expensive and not too far from a brute force approach. I am convinced there is a more elegant and efficient way of doing this. If there is an existing library that handles this (preferably in Python) that would be even better.
I have already seen a related question (Fitting an ellipsoid to 3D data points), but figured I would ask again as it has been over a decade since that post.
So you have a set of (x,y) values for each contour, which describe a portion of an ellipse (blue dots below).
The best fit ellipse is described by the general equation
A x^2 + B y^2 + 2C x y + 2D x + 2E y = 1
and once the coefficients (A,B,C,D,E) are found, the ellipse of fully described. See below in how to find the the curve coordinates (x,y) from the coefficients and a parameter t=0 .. 1.
To find the coefficients of the ellipse, form 5 vectors, each a column of a n×5 matrix Q
for i = 1 to n
Q(i,1) = x(i)^2
Q(i,2) = y(i)^2
Q(i,3) = 2*x(i)*y(i)
Q(i,4) = 2*x(i)
Q(i,5) = 2*y(i)
next i
and a vector K filled with 1 for the right-hand side
for i = 1 to n
K(i) = 1.0
next i
Find the coefficients using a least-squares fit with some linear algebra
[A,B,C,D,E] = inv(tr(Q)*Q)*tr(Q)*K
where tr(Q) is the transpose of Q and * is matrix/vector product
Now we need to extract the geometric properties of the ellipse from the coefficient. I want to have a the semi-major axis, b the semi-minor axis, φ the rotation angle, xc the x-axis center, yc the y-axis center.
xc = -(B*D-C*E)/(A*B-(C^2))
yc = -(A*E-C*D)/(A*B-(C^2))
φ = atan( 2*C/(A-B) )/2
a = SQRT(2*(A*(B+E^2)+B*D^2-C*(C+2*D*E))/((A*B-C^2)*(A+B-SQRT((A-B)^2+4*C^2))))
b = SQRT(2*(A*(B+E^2)+B*D^2-C*(C+2*D*E))/((A*B-C^2)*(A+B+SQRT((A-B)^2+4*C^2))))
Finally to plot the ellipse you need to generate a set of points (x,y) from the curve parameter t=0..1 using the above 5 coefficients.
Generate the centered aligned coordinates (u,v) with
u = a*cos(2*π*t)
v = b*sin(2*π*t)
Generate the centered rotated coordinates (x',y') with
x' = u*cos(φ) - v*sin(φ)
y' = u*sin(φ) + v*cos(φ)
Generate the ellipse coordinates (x,y) with
x = x' + xc
y = y' + yc
The result is observed above in the first picture.
Now for the total solution, each 2D slice would have its own ellipse. But all the slices would not generate an ellipsoid this way.
Extending the above into 3D coordinates (x,y,z) is doable, but the math is quite involved and I feel [SO] is not a good place to develop such an algorithm. You can hack it together, by finding the average center for each slice (weighted by the ellipse area π*a*b). Additionally, the rotation angle should be the same for all contours, and so another averaging is needed. Finally, the major and minor axis values would fall on an elliptical curve along the z-axis and it would require another least-fit solution. This one is driven by the equation
(x/a)^2 + (y/b)^2 + (z/c)^2 = 1
but rather in the aligned coordinates (u,v,w)
(u/a)^2 + (v/b)^2 + (w/c)^2 = 1

Standard form of ellipse

I'm getting ellipses as level curves of a fit dataset. After selecting a particular ellipse, I would like to report it as a center point, semi-major and minor axes lengths, and a rotation angle. In other words, I would like to transform (using mathematica) my ellipse equation from the form:
Ax^2 + By^2 + Cx + Dy + Exy + F = 0
to a more standard form:
((xCos[alpha] - ySin[alpha] - h)^2)/(r^2) + ((xSin[alpha] + yCos[alpha] - k)^2)/(s^2) = 1
where (h,k) is the center, alpha is the rotation angle, and r and s are the semi-axes
The actual equation I'm attempting to transform is
1.68052 x - 9.83173 x^2 + 4.89519 y - 1.19133 x y - 9.70891 y^2 + 6.09234 = 0
I know the center point is the fitted maximum, which is:
{0.0704526, 0.247775}
I posted a version of this answer on Math SE since it benefits a lot from proper mathematical typesetting. The example there is simpler as well, and there are some extra details.
The following description follows the German Wikipedia article Hauptachsentransformation. Its English counterpart, according to inter-wiki links, is principal component analysis. I find the former article a lot more geometric than the latter. The latter has a strong focus on statistical data, though, so it might be useful for you nevertheless.
Rotation
Your ellipse is described as
[A E/2] [x] [x]
[x y] * [E/2 B] * [y] + [C D] * [y] + F = 0
First you identify the rotation. You do this by identifying the eigenvalues and eigenvectors of this 2×2 matrix. These eigenvectors will form an orthogonal matrix describing your rotation: its entries are the Sin[alpha] and Cos[alpha] from your formula.
With your numbers, you get
[A E/2] [-0.74248 0.66987] [-10.369 0 ] [-0.74248 -0.66987]
[E/2 B] = [-0.66987 -0.74248] * [ 0 -9.1715] * [ 0.66987 -0.74248]
The first of the three factors is the matrix formed by the eigenvectors, each normalized to unit length. The central matrix has the eigenvalues on the diagonal, and the last one is the transpose of the first. If you multiply the vector (x,y) with that last matrix, then you will change the coordinate system in such a way that the mixed term vanishes, i.e. the x and y axes are parallel to the main axes of your ellipse. This is just what happens in your desired formula, so now you know that
Cos[alpha] = -0.74248 (-0.742479398678 with more accuracy)
Sin[alpha] = 0.66987 ( 0.669868899516)
Translation
If you multiply the row vector [C D] in the above formula with the first of the three matrices, then this effect will exactly cancel the multiplication of (x, y) by the third matrix. Therefore in that changed coordinate system, you use the central diagonal matrix for the quadratic term, and this product for the linear term.
[-0.74248 0.66987]
[1.68052, 4.89519] * [-0.66987 -0.74248] = [-4.5269 -2.5089]
Now you have to complete the square independently for x and y, and you end up with a form from which you can read the center coordinates.
-10.369x² -4.5269x = -10.369(x + 0.21829)² + 0.49408
-9.1715y² -2.5089y = -9.1715(y + 0.13677)² + 0.17157
h = -0.21829 (-0.218286476695)
k = -0.13677 (-0.136774259156)
Note that h and k describe the center in the already rotated coordinate system; to obtain the original center you'd multiply again with the first matrix:
[-0.74248 0.66987] [-0.21829] [0.07045]
[-0.66987 -0.74248] * [-0.13677] = [0.24778]
which fits your description.
Scaling
The completed squares above contributed some more terms to the constant factor F:
6.09234 + 0.49408 + 0.17157 = 6.7580
Now you move this to the right side of the equation, then divide the whole equation by this number so that you get the = 1 from your desired form. Then you can deduce the radii.
1 -10.369
-- = ------- = 1.5344
r² -6.7580
1 -9.1715
-- = ------- = 1.3571
s² -6.7580
r = 0.80730 (0.807304599162099)
s = 0.85840 (0.858398019487315)
Verifying the result
Now let's check that we didn't make any mistakes. With the parameters we found, you can piece together the equation
((-0.74248*x - 0.66987*y + 0.21829)^2)/(0.80730^2)
+ (( 0.66987*x - 0.74248*y + 0.13677)^2)/(0.85840^2) = 1
Move the 1 to the left side, and multiply by -6.7580, and you should end up with the original equation. Expanding that (with the extra precision versions printed in parentheses), you'll get
-9.8317300000 x^2
-1.1913300000 x y
+1.6805200000 x
-9.7089100000 y^2
+4.8951900000 y
+6.0923400000
which is a perfect match for your input.
If you have h and k, you can use Lagrange Multipliers to maximize / minimize the function (x-h)^2+(y-k)^2 subject to the constraint of being on the ellipse. The maximum distance will be the major radius, the minimum distance the minor radius, and alpha will be how much they are rotated from horizontal.

Transform 3D points to 2D

I have a set of points (x1, x2,..xn) that lie on the plane define by Ax+ By+Cz+d=0.
I would like to find the transformation matrix to translate and rotate to XY plane. So, the new point coordinate will be x1'=(xnew, ynew,0).
A lot of answer give quaternion, dot or cross product matrix. I am not sure which one is the correct way.
Thank you
First of all, unless in your plane equation, d=0, there is no linear transformation you can apply. You need to instead perform an affine transformation.
One way to do this is to determine an angle and vector about which to rotate to make your pointset lie in a plane parallel to the XY plane (ie. the Z component of your transformed pointset to all have the same values). Then you simply drop the Z component.
For this, let V be the normalized plane normal for the plane containing your points. For convenience define from your plane equation above Ax+By+Cz+d=0:
V = (A, B, C)
V' = V / ||V|| = (A', B', C')
Z = (0, 0, 1)
where
A' = A / ||V||
B' = B / ||V||
C' = C / ||V||
||V|| = (A2+B2+C2)1/2
The angle will simply be:
θ = cos-1(Z∙V / ||V||)
= cos-1(Z∙V')
= cos-1(C')
The axis R about which to rotate is just the cross product of the normalized plane normal V' and Z. That is
R = V'×Z
= (B', -A', 0)
You can now use this angle / axis pair to build the quaternion rotation needed to rotate all of the points in your dataset to a plane parallel to the XY plane. Then, a I said earlier, just drop the Z component to perform an orthogonal projection onto the XY plane.
Update: antonakos makes a good point about normalizing the R before using an API taking axis / angle pairs.

Finding points of intersection when two spheres intersect

I have the center (xyz - in 3 dimensional space) and the radius of two spheres A and B.
Now I have to figure out a point or more than 1 point where these spheres meet. It is fairly easy to figure out if the two spheres collide or not, but how do I find out the points of intersection of 2 spheres?
Any help would be greatly appreciated.
The curve where they intersect is a circle. The equation for the radius of the circle is a bit complicated, but is shown here, in eqn. 8, and this distance of the circle from the center of one of the spheres is shown in eqn. 5.
If the radius of the smaller sphere is A, and the bigger is B, and their centers are D units apart, then the points of intersection are on a circle of radius r centered on a point directly between the centers of the two spheres, which is y units from the center of the bigger sphere, and x units from the center of the other, where
y = 1/2 (D + (B^2 - A^2)/D)
and
x = 1/2 (D - (B^2 - A^2)/D)
with radius
r = B^2 - x^2 = A^2 - y^2
If you need the equation for this circle the best way is to represent it as a set of three parameterized equations, where the x, y, and z coordinates are each expressed a a function of some t, which represents the radius vector trraveling around the circle once, from zero to 2PI...
To construct these equations, think about expressing the point which is the radius r from the center, on the 2D plane which is normal to the line between the two spheres.
Check out this link for some iedas on how to do this..
Derivation is as follows: draw a line between the centers of the two spheres. Label it as D
Designate a point on this line as the center of the final solution circle label it as point O
Label the smaller portion of D as x, and the large portion as y
draw a line from O perpindicular to D, for some distance r to represent the radius of the solution circle
Label the end of this radius as Q
Now draw B between the center of the larger sphere to Q and A from the center of smaller sphere and Q
From Pythagoras:
B^2 = y^2 + r^2 and A^2 = x^2 + r^2
so, after eliminating r and a bit of algebra,
y-x = (B^2 - A*2) / (x+y)
But x+y = D so,
y-x = (B^2 - A*2) / D
Adding the equation x+y=D to the above eliminates the x, giving
2y = D + (B^2 - A*2) / D
or,
y = 1/2 ( D + (B^2 - A*2) / D )

Hexagonal Grid Coordinates To Pixel Coordinates

I am working with a hexagonal grid. I have chosen to use this coordinate system because it is quite elegant.
This question talks about generating the coordinates themselves, and is quite useful. My issue now is in converting these coordinates to and from actual pixel coordinates. I am looking for a simple way to find the center of a hexagon with coordinates x,y,z. Assume (0,0) in pixel coordinates is at (0,0,0) in hex coords, and that each hexagon has an edge of length s. It seems to me like x,y, and z should each move my coordinate a certain distance along an axis, but they are interrelated in an odd way I can't quite wrap my head around it.
Bonus points if you can go the other direction and convert any (x,y) point in pixel coordinates to the hex that point belongs in.
For clarity, let the "hexagonal" coordinates be (r,g,b) where r, g, and b are the red, green, and blue coordinates, respectively. The coordinates (r,g,b) and (x,y) are related by the following:
y = 3/2 * s * b
b = 2/3 * y / s
x = sqrt(3) * s * ( b/2 + r)
x = - sqrt(3) * s * ( b/2 + g )
r = (sqrt(3)/3 * x - y/3 ) / s
g = -(sqrt(3)/3 * x + y/3 ) / s
r + b + g = 0
Derivation:
I first noticed that any horizontal row of hexagons (which should have a constant y-coordinate) had a constant b coordinate, so y depended only on b. Each hexagon can be broken into six equilateral triangles with sides of length s; the centers of the hexagons in one row are one and a half side-lengths above/below the centers in the next row (or, perhaps easier to see, the centers in one row are 3 side lengths above/below the centers two rows away), so for each change of 1 in b, y changes 3/2 * s, giving the first formula. Solving for b in terms of y gives the second formula.
The hexagons with a given r coordinate all have centers on a line perpendicular to the r axis at the point on the r axis that is 3/2 * s from the origin (similar to the above derivation of y in terms of b). The r axis has slope -sqrt(3)/3, so a line perpendicular to it has slope sqrt(3); the point on the r axis and on the line has coordinates (3sqrt(3)/4 * s * r, -3/4 * s * r); so an equation in x and y for the line containing the centers of the hexagons with r-coordinate r is y + 3/4 * s * r = sqrt(3) * (x - 3sqrt(3)/4 * s * r). Substituting for y using the first formula and solving for x gives the second formula. (This is not how I actually derived this one, but my derivation was graphical with lots of trial and error and this algebraic method is more concise.)
The set of hexagons with a given r coordinate is the horizontal reflection of the set of hexagons with that g coordinate, so whatever the formula is for the x coordinate in terms of r and b, the x coordinate for that formula with g in place of r will be the opposite. This gives the third formula.
The fourth and fifth formulas come from substituting the second formula for b and solving for r or g in terms of x and y.
The final formula came from observation, verified by algebra with the earlier formulas.

Resources