How can Javascript be used to divide a circle equally so that it's correct to 1,000,000,000% zoom?

佐手、 提交于 2019-12-12 06:11:51

问题


Split off from: https://stackoverflow.com/questions/31076846/is-it-possible-to-use-javascript-to-draw-an-svg-that-is-precise-to-1-000-000-000

Using floating point precision, there are rounding errors when calculating the position of points on a circle.

Example:

function pointsOnACircle (whichpoint, numberOfPoints, cx, cy, radius) {
    //Returns a point along the outside of a circle, starting at (whichpoint=1) = 0 degrees

    eachpoint = whichpoint * 2 * Math.PI /numberOfPoints;
    var thiscx = cx + (radius * Math.sin(eachpoint));
    var thiscy = cy - (radius * Math.cos(eachpoint));

    thisPoint = [ thiscx, thiscy ];

    return thisPoint;
}

If the function is run as fourthPointofSix = pointsOnACircle (4, 6, 126, 126, 63); then the points returned are

0: 71.44039956158039 1: 157.50000000000003

Calculating them with the calculator at http://www.ttmath.org/online_calculator, the numbers should be:

0: 71.440399561580365.. 1: 157.5

Similarly, if we run fifthPointofSix = pointsOnACircle (5, 6, 126, 126, 63); then the points returned are:

0: 71.44039956158034 1: 94.50000000000004

They should be:

0: 71.440399561580365... 1: 94.5

Note: the x of both points 4 and 5 should be the same, but they come back different

Is there a standard solution for solving these kinds of precise circle-based calculations?


回答1:


Its quite possible that very large zooms might be needed. One example of these are the interactive fractal plots. For this sort of application you don't want to scale a static object you want a dynamic solution where the object is recalculated so that the precision is appropriate to the scale factor. For example in this program Scalable circle you can zoom to any level you want. This solution uses an implicit version of the equation of a circle (x-1)^2 + y^2 = 1.

If we look at the the precision of numbers IEEE floating point double gives us 15-16 decimal digits of floating point accuracy. This should be fine for 1e7 = 1,000,000,000% zoom. The Math.sin() and Math.cos() are accurate to the last binary digit.

Taking the values in the question and subtract the actual values 71.44039956158039 - 71.440399561580365 = 2.842170943040401e-14 now multiply this by the scale factor 1e7 gives 2.842170943040401e-7 the error is less that one millionth of a pixel. (I've uses chromes javascript console to do the calculations).

We might start to get problems if the scale factor is 1e14 here the error is 2.8421709430404007 a couple of pixels. For that level of zoom you would want a different algorithm. The good news is that at this level of zoom a circle will be indistinguishable from a straight line. So we could just use y=m x+c. The harder bit would be finding whether a point on the circle lies in our viewing area. We start to get problems with the accuracy of specifying the radius of the circle.




回答2:


There are three short answers:

  1. By using an external library that supports math to that precision (then effectively using it)
  2. By doing calculations as integers (for example, multiply by 1,000,000,000, do the calculations, then divide by the same amount)
  3. By building the zoom function in to the code and re-drawing the display when zoomed

Note: From what I could find, only #3 will allow a mathematically accurate representation of a circle to be shown on screen. In all cases, Bézier curves are used to make a very close approximation of a circle, but in the first two cases 1,000,000,000% zoom is more than enough to show that the Bézier curves are not a correct circle, whereas in the third the curve is generated for the viewport.



来源:https://stackoverflow.com/questions/31079577/how-can-javascript-be-used-to-divide-a-circle-equally-so-that-its-correct-to-1

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!