2

This question is an extension of How to find the center of an ellipse?.

The solution there works well, but in Javascript the floating point calculations are not that accurate. The workaround is to "scale up" all the values so that many of the digits are before the decimal point. To do this I modified the algo mentioned below, but it is not working. It works if I set $multiplier$ to $1$. $multiplier$ is the factor which decides by how much I will be scaling up the values. In my tests I have set it to 300.

  1. Given points $P_0$, $P_1$ on the ellipse of radii $r_x$ and $r_y$. The major-axis of the ellipse makes $\alpha$ angle on x-axis. I now need to find the centers ($C_1$, $C_2$) of this ellipse (there can be two ellipses).
  2. I apply rotation transform of $-\alpha$.
  3. I then scale it by $multiplier/r_x$ (along x-axis) and $multiplier/r_y$ (along y-axis).
  4. The above transforms give a circle of radius $multiplier$.
  5. Now I find the new values of $P_0$ and $P_1$ after all these transforms. Let's call them $R_0$ and $R_1$.
  6. Both these points form a chord on the circle we got on step 4. The perpendicular bisector of that chord will pass through the circle's center. This is the point I seek.
  7. Let $c$ represent half of the length of the chord. Let $s$ be the length of the perpendicular from circle's center to the chord's mid-point. So, the relation will be $s = \sqrt{multiplier^2 - c^2}$. For brevity, let's ignore the cases where $c>=multiplier$.
  8. I now translate the chord's midpoint to origin by translating the circle by $[-(R_0+R_1)/2]$.
  9. After this I rotate the circle by $\pi/2$. This will align $R_0$ with the center of the circle when we were in step 8.
  10. Now I can get the circle's center if scale in such a way that $R_0$ coincides with that location. For this I need to scale chord's half-length from $c$ to $s$. For this I apply scaling transform of $s/c$.
  11. Now let us call $S_0$ the new value of $R_0$.
  12. When I "un-transform" $S_0$'s value then we get the ellipse's center. To "un-transform" it I use combined transform matrix till step 3 and find its inverse.

Note: I have left out the part to find the second ellipse's center.

AppleGrew
  • 257
  • "too many steps" + "not enough precision" = "loss of accuracy" – J. M. ain't a mathematician Aug 04 '11 at 17:14
  • Also: there are ways to evaluate expressions that are less numerically sound than others. Sometimes, what you think is an "optimization" may well be an inaccurate way of computing an intermediate quantity, whose error will eventually swamp your end result. – J. M. ain't a mathematician Aug 04 '11 at 17:16
  • I'm going to ask a side question here: what problem are you trying to solve? The specific data that you're working with (two points on the ellipse and an angle) seems so unusual that I'm wondering what its providence is, and whether there's an easier answer to your problem lurking somewhere in the background. – Steven Stadnicki Aug 04 '11 at 17:17
  • Also, as another note: how are you performing your rotation by α? That would seem to require either floating point itself (in which case, why bother scaling and doing the rest as integers?), or another scaling step that you're omitting here. Either way, it feels like while this problem is potentially solvable, the clunkiness suggests that the whole approach is off somewhere. – Steven Stadnicki Aug 04 '11 at 17:19
  • Particularly: if you look at whuber's solution in the answer to your previous question, he computes the quantity $\sqrt{1-c^2}$; that form would be inaccurate if $c\approx 1$. I'll try to think of a way to mitigate that... – J. M. ain't a mathematician Aug 04 '11 at 17:21
  • Oohh.. It's seems I have been banging my head against this problem for too long. JS is not the problem it seems. Thanks J.M. for knocking me into senses. :P – AppleGrew Aug 04 '11 at 17:28
  • @J.M. Why that would be inaccurate? I didn't get you. Maybe whatever you are referring to could be the source of my grief and I drove offcourse. – AppleGrew Aug 04 '11 at 17:30
  • If $c$ is near 1, $c^2$ would also be near 1. One minus that would be near zero, and you potentially lose a lot of significant figures there. For now, try computing that as Math.sqrt((1-c)*(1+c)) (skip the scaling for now!) and report back. – J. M. ain't a mathematician Aug 04 '11 at 17:50
  • I can't find any mistake in the steps. I also don't see why $\sqrt{1-c^2}$ should cause a precision problem for multipliers other than $1$ but not for $1$. I suspect that the problem might be a bug in the code; perhaps you could post one of those jsfiddle links like in the other thread? – joriki Aug 04 '11 at 17:51
  • @J.M.: Are you proposing this as an alternative solution to the precision problem, instead of the multiplier, or as an explanation why the version with the multiplier isn't working? I think the former might make sense, but the latter wouldn't. – joriki Aug 04 '11 at 17:53
  • @joriki, @ J.M. I have finally understood the source of problem. The problem is in the computers all rationals are approximated. So if I say $P_0$ is at $(0, 1.3)$ then computer may not store the exact value of $1.3$. In this the approximation may make it $1.299999998$. That's an error. When I scale this value by (say) 300 then this error too blows up and becomes obviously clear. So to fix this I can multiply all input variables by (say) a 500 and later divide the computer coords by this to get the ans. – AppleGrew Aug 04 '11 at 18:36
  • But the problem of error at $\sqrt{1-c^2}$ remains the same. Maybe refactoring that to $\sqrt{1-c}\sqrt{1+c}$ may help. Not sure. Any advice? – AppleGrew Aug 04 '11 at 18:39
  • @joriki and Apple: I can't see the JS so I just as well may be grasping at straws here. I'm asking that Apple try it out since that looks to be the potentially numerically unstable portion for me at first glance, but I certainly haven't done a thorough analysis of the algorithm. Maybe after I sleep... – J. M. ain't a mathematician Aug 04 '11 at 18:48
  • For that matter, why not instead compute $s/c$ as $\sqrt{1/c-1}$? That looks to me to be the actual working quantity and not either of $s$ or $c$... – J. M. ain't a mathematician Aug 04 '11 at 18:51
  • @J.M. Yes this is much better, but there is still one value for which I see a spike in error. It is - $P_0=(1.15,0)$, $P_1=(1.1,0.355)$, $\alpha=0$, $r_x=r_y=1$. In this I get $c=0.1792519177024335$, $C_1=(1.5048143686806574,-2.2273133985451077)$ and $C_2=(0.7459452600567043,2.5824203885081163)$. The y value seems to be larger than expected. Instead of using your above tip if I use the old method of calculating $s$ first then dividing then the values of y calculates to $-5.990619417072389$ and $6.34589383623051$! And yes x value too changes. All for the same inputs! – AppleGrew Aug 04 '11 at 19:51
  • @AppleGrew: I'd still love to know where your original data is coming from and what specific problem you're trying to solve, because there's a very non-zero chance that this approach to the problem is more prone to round-off errors than other ones might be. – Steven Stadnicki Aug 04 '11 at 20:47
  • @Steven The input data come from users. These info are used to draw an elliptical curve between $P_0$ $P_1$. The drawn curve is scaled up by 300, otherwise it will be too small. You can know more about this at http://cink.applegrew.com – AppleGrew Aug 05 '11 at 03:34
  • As a note: if the two points determining your ellipse are "too close" such that the two possible ellipses are nearly tangent to each other, no amount of arithmetical trickery will save you from the expected precision loss. – J. M. ain't a mathematician Aug 05 '11 at 05:11
  • @J.M. Can you please explain this? Maybe you can put it as an answer. – AppleGrew Aug 05 '11 at 09:19

0 Answers0