5
$\begingroup$

As part of an iOS app I’m making, I want to draw a decent approximation of an Archimedes spiral. The drawing library I’m using (CGPath in Quartz 2D, which is C-based) supports arcs as well as cubic and quadratic Bézier curves. What is a good method of approximating an Archimedes spiral using either of these path types? For example the wikipedia exemplar image says it was “drawn as a series of minimum-error Bézier segments.” How would one generate such segments?

My math background takes me through Calculus III plus some stuff I picked up from a classical mechanics class, but it’s been a couple of years so I’m rusty. What I have so far:

For a spiral r = a + b $\theta$, I used the information from this page to find that the cartesian slope at any point (r, $\theta$) is equal to

$$\frac{dy}{dx}=\frac{b\sin\theta\space+\space(a + b\theta)\cos\theta}{b\cos\theta\space-\space(a + b\theta)\sin\theta}$$

From here, I could use point-slope to find the equation of a tangent line at any point, but how do I go about finding the proper lengths of the handles (i.e. the positions of the middle two points) for the curve? Or would an approximation with circular arc segments be better/easier/faster?

If I can’t figure it out, I’ll just use a static image in the app, but it occurs to me that I don’t even know of a way to generate a high-quality image of an Archimedes spiral! The Spiral tool in Illustrator, for example, does only logarithmic spirals.

  • 0
    Your drawing library can't evaluate trigonometric functions?2012-08-05
  • 0
    You mean sin/cos/tan? I'm using C, so yes, I can. What are you getting at?2012-08-05
  • 1
    Then, why not just use the actual parametric equations for the Archimedean spiral instead of trying to draw a Bézier approximation?2012-08-05
  • 0
    @J.M. Most drawing libraries outside of specialized math software only allow drawing primitives like line segments, ellipses, and cubic Bézier curves, but not arbitrary parametric curves. I expect Zev can evaluate trigonometric functions to pick the parameters for these primitives, but cannot make the curve follow an arbitrary parametric path.2012-08-05
  • 0
    Right you are @RahulNarain. Wish I could do that!2012-08-05
  • 0
    This comment doesn't answer the question as stated, but if I were you, @Zev, I'd just evaluate positions along the curve at small increments of $\theta$ and connect them with a series of line segments.2012-08-05
  • 0
    You know, it didn't even occur to me to see if I could get it looking smooth using straight line segments. Now that I've got information from the answer below, I want to try that, but I'll try this version as well.2012-08-05
  • 0
    Drawing lots of straight-line segments is a bad idea; in many graphics libraries it can cause rendering errors (e.g. because of overlapping antialiasing or rounding issues). Quartz doesn’t suffer so much from that, but under Quartz performance will be hideous because in order to avoid the antialiasing problem it needs to compute self-intersections.2014-02-03
  • 0
    Just to add to my comment above, if you do need to decompose to line segments, it’s best to adaptively subdivide until the curve can be approximated by a straight line. This minimises rendering problems.2014-02-03

1 Answers 1

2

So it looks like the Wikipedia reference image uses 45 degree sections of these curves. You can use the equation for the spiral to give you the tangent line at the beginning and end of these curve sections. Evaluate the derivative at these two points to get the tangent line slope and then shift your line appropriately to hit the point used. The intersection Of these two lines should be your control point. Once you have found your control point you can put it in the function 'CGPathAddQuadCurveToPoint' for the cx, cy (I think) along with the point you want to go to (also from the spiral equation). For reference--check out the animation under 'quadratic curves' here

For extra speed, you only have to find 8 tangent lines max--just shift them out for the next cycle of the spiral and reuse them.

  • 0
    I think your Wikipedia link might work better if you use the syntax `[link text](URL goes here)`.2012-08-05
  • 0
    So, if I understand you, I use the intersection of adjacent tangent lines as the control points for my quad curves?2012-08-05
  • 0
    Your wikipedia link is from the mobile site, and the Stack Exchange link parser doesn't like it. Here's the desktop link: http://en.wikipedia.org/wiki/Bézier_curve#Constructing_B.C3.A9zier_curves2012-08-05
  • 1
    @Zav Eisenberg the lines on the animation on Wikipedia are tangent lines, the define the control point. So yes, that is the point you use.2012-08-05
  • 0
    Thanks for the link, I was typing on my phone so it's a little trickier.2012-08-05
  • 0
    That worked, and it looks really good. Here’s a comparison of line segments vs. quadratic. It’s subtle, but if you view at 100% you can see the difference: http://i.stack.imgur.com/sftCv.png I had some mishaps along the way, however: http://i.stack.imgur.com/d8UdB.png2012-08-05
  • 0
    I posted the code I ended up creating, in case anyone wants to use it: https://github.com/ZevEisenberg/ZESpiral2014-02-04