Hebi
Hebi

Reputation: 97

Draw a circle with given curvature

I want to draw a circe with given curvature k.
I just need to know the y-coordinate for a given x-coordinate. So i.e. z = 1/k + sqrt(1/k^2 - x^2) is what I would normally use. The problem is that my k is allowed to become zero. Which means that my circle becomes a line. For a mathematican thats no problem. But for my computer it is. For example when k is minimum double value, y will be infinity, for k == 0 I receive nan for y.
Are there any ways to get this done?

Upvotes: 1

Views: 305

Answers (2)

Martin R
Martin R

Reputation: 539935

You gave the formula

y1 = 1/k + sqrt(1/k^2 - x^2)    // (1)

which describes the upper half of the circle with radius 1/k and center (0, 1/k). Now for small k these values become very large and will eventually be outside of your drawing are.

The lower half of the circle is given by

y2 = 1/k - sqrt(1/k^2 - x^2)    // (2)

For k approaching zero, these values "approach" the line y = 0. But for small values of k, (2) computes the difference of two large numbers. This causes a loss of precision and possible overflow.

But you can rewrite the formula (2) into the equivalent form

y2 = k * x^2 / (1 + sqrt(1 - k^2 * x^2))    // (2a)

Now you can compute the lower half of the circle for small values of k and even for k = 0 without any overflow or precision loss.

For the upper half you always have y1 >= 1/k. So if 1/k is larger than the boundary of your drawing area, you can ignore the upper value. Otherwise you can compute y1 via

y1 = 2/k - y2

Upvotes: 1

Eric J.
Eric J.

Reputation: 150138

Given such border cases, I would just test the input parameters to see if one of them applies and use separate logic to just draw a horizontal or vertical line as appropriate if a border case applies.

That is a fairly common approach and computationally quite efficient.

When testing for border cases, test k to ensure that: - k^2 will not overflow the data type in use - k is not so small that 1/k^2 will underflow the data type in use

In either case, use the appropriate border case logic. Thanks @Godeke for pointing that out.

Upvotes: 2

Related Questions