Index Books FAQ Contact About Rod

Title: Draw a hyperbolic spiral in C#

A hyperbolic spiral, which is also called an reciprocal spiral, is the inverse of an Archimedes spiral. It uses the equation r = A / θ to generate points on a spiral.

This spiral has a couple of interesting properties. First, it is drawn backwards (in some sense). Points on the Archimedes spiral and logarithmic spiral move farther from the spiral's center as θ in increases. Points on a hyperbolic spiral move closer to the center as θ in increases.

Like a logarithmic spiral, the hyperbolic spiral doesn't reach the spiral's center when θ is 0. In fact, this spiral isn't defined when θ is 0 because calculating r for that value would force you to divide by zero.

Earlier examples calculated values for r until they were larger than the distance to the farthest corner of the drawing area. We can still use that technique but with two caveats. First, in this program θ must decrease instead of increasing to produce increasingly larger values of r. Second, the program should beware of setting θ equal to 0. The example program doesn't worry about that because r grows big enough to stop the program's loop before that happens, but you should be aware of this issue in case you encounter it in some other program.

The earlier logarithmic spiral example calculated a maximum value for θ to make the spiral begin at (or at least very close to) the spiral's center. This example can make a similar calculation.

This time, suppose we want generate a minimum r value of 2 so the spiral begins 2 pixels away from the center. (This spiral becomes increasingly dense as it approaches its center, so I want to leave a small hole in the middle so whole things isn't a big blob of solid color. Setting r = 2, the spiral's equation becomes 2 = A / &theta'. Solving for θ gives max_theta = A / 2.

The following code fragment shows how this example generates a spiral's points.

// Return points that define a spiral. private List<PointF> GetSpiralPoints( float dtheta, PointF center, float A, float angle_offset, float max_r) { // Get the points. float max_theta = A / 2f; List<PointF> points = new List<PointF>(); for (float theta = max_theta; ; theta -= dtheta) { // Calculate r. float r = A / theta; // Convert to Cartesian coordinates. float x, y; PolarToCartesian(r, theta + angle_offset, out x, out y); // Center. x += center.X; y += center.Y; // Create the point. points.Add(new PointF((float)x, (float)y)); // If we have gone far enough, stop. if (r > max_r) break; } return points; }

This method calculates max_theta as described above and makes a list to hold the spiral's points. It then enters a loop where variable theta runs downward from max_theta. Inside the loop, the code calculates the value r, converts the result into Cartesian coordinates, and adds the point to the points list.

When r is larger than the distance to the farthest corner of the drawing area, the method breaks out of its loop and returns the spiral's points.