A Flash Developer Resource Site

Results 1 to 6 of 6

Thread: Draw a circle with quadratic bezier curves

  1. #1
    madskool.wordpress.com brutfood's Avatar
    Join Date
    Apr 2002
    Posts
    469
    Here's a nice little problem. How do I draw an approximation for a circle using curveTo.

    Not in the way that the flash MX documentation states - that's for sure!

    I need a good value for the control point of each quarter segment. I could use trial and error to find an appoximation - but I want a mathematically derived value.

    This is what I tried to do to find an answer. But it didn't work out:-

    Consider the first segment of a unit circle. The problem is to find a control point (q,q) to that the quadratic bezier approimates:-

    x1(t)=cos(t*PI/2)
    y1(t)=sin(t*PI/2)
    0<=t<=1

    I assume the equations of the curve that curveTo draws in this case are:-

    x2(t,q)=q*t*(1-t)+(1-t)^2
    y2(t,q)=q*t*(1-t)+t^2
    0<=t<=1

    (Please correct this assumption if wrong)

    So I assumed:

    error=sqrt((x1(t)-x2(t,q))^2+(y1(t)-y2(t,q))^2)

    I differentiated (d error / d q). Unfortunately, this didn't lead to a valid answer.

    Any suggestions?

  2. #2
    Senior Member
    Join Date
    Mar 2000
    Posts
    472
    Hey brutfood!

    I made an example based on 4 prototypes found here:

    http://chattyfig.figleaf.com/flashco...CodeOnlyCircle

    The first 3 are using 'curveTo', drawn in 45 degree increments ... all basically the same, with the first 2 by Casper Schuirink ... #2(CW) is the mirror of #1(CCW), used for masking purposes. The 3rd by Ralf Bokelberg is the same as #1, but he creates variables for use in the multiple 'curveTo' functions.The 4th by Tatsuo Kato uses 'lineTo' instead, with .01 increments through 2PI of the polar to Cartesian equation.

    http://members.shaw.ca/flashmath101/bezierCircle.swf
    http://members.shaw.ca/flashmath101/bezierCircle.fla

    Richard

  3. #3
    madskool.wordpress.com brutfood's Avatar
    Join Date
    Apr 2002
    Posts
    469

    Thanks

    Thanks Richard,

    FlashCoders looks an interesting community too. Any idea how Casper Schuirink arrived at his solution?

  4. #4
    Senior Member
    Join Date
    Mar 2000
    Posts
    472
    Here you go ... I hope you can follow the logic:

    // circle quadrants... 1:NE, 2:NW, 3:SW, 4:SE

    // anchor points use sin and cos: both values range from -1to1
    // sin...quadrants 1 and 2 positive values, 3 and 4 negative values
    // cos...quadrants 1 and 4 positive values, 2 and 3 negative values
    // -0.7071 and 0.7071 are sin and cos values for pi/4 radians or 45 degrees, +/- depends on quadrant

    // control points use tan and cot...quadrants 1 and 3 positive values, 2 and 4 negative values
    // -0.4142 and 0.4142 are tan and cot values for pi/8 or 22.5 degrees, half-way through each 45 degree bezier angle
    // tan used for x-axis +/- pi/8, cot used for y-axis +/- pi/8
    // tan=sin/cos, cot=cos/sin
    // note: there is no Flash Math.method for cotangent

    // control points for 8 quadratic beziers of the circle are located at radius+ x or y offset and the complementary cos or sin value[/b]

    Code:
    MovieClip.prototype.drawCircle = function(r, x, y) { 
                // r=circle radius, x,y=offset circle center coordinates within mcClip
        this.moveTo(x+r, y); 
                // start drawing circle CCW at positive x-axis, at distance r from center(x+r)
                // 1st anchor point...x:(x+r), y:y
        this.curveTo(r+x,-0.4142*r+y,0.7071*r+x,-0.7071*r+y);
                // control point...x:radius+x offset, y:tan(pi/8)*radius+y offset 
                // 2nd anchor point...x:cos(pi/4)*radius+x offset, y:sin(pi/4)*radius+y offset
                // becomes 1st anchor point for next curveTo
        this.curveTo(0.4142*r+x,-r+y,x,-r+y);
                // control point...x:cot(3pi/8)*radius+x offset, y:-radius+ y offset
                // 2nd anchor point...x:x offset,y:-radius+y offset
                // etc...
        this.curveTo(-0.4142*r+x,-r+y,-0.7071*r+x,-0.7071*r+y);
        this.curveTo(-r+x,-0.4142*r+y,-r+x, y);
        this.curveTo(-r+x,0.4142*r+y,-0.7071*r+x,0.7071*r+y);
        this.curveTo(-0.4142*r+x,r+y,x,r+y);
        this.curveTo(0.4142*r+x,r+y,0.7071*r+x,0.7071*r+y);
        this.curveTo(r+x,0.4142*r+y,r+x,y);
    }// Casper Schuirink
    http://members.shaw.ca/flashmath101/...nitCircle8.swf

    BTW ... this isn't a perfect circle either, but it certainly is an improvement over the 90 degree quadratics used in the Flash help example. That's why using the cubic Bezier approximation algorithms of the beziers thread is such a good thing!

    --edit--

    I had the wrong version of unit circle up, which didn't show CCW degrees, nor unit circle radian equations. v8 isn't complete either (I never did get the trig graphing and angle functions finished...I must convert this all to Flash MX soon!), however degree values are now correct.

    Richard
    [Edited by Dickee on 09-14-2002 at 07:22 PM]

  5. #5
    madskool.wordpress.com brutfood's Avatar
    Join Date
    Apr 2002
    Posts
    469

    Doh!

    Doh!

    What obvious logic. Apologies for my stupid question. And for not recognising 0.707 as PI/4 - I should be shot by my old maths teacher.

    I was looking for better control points to make 4 curveTos look better - when I should just have increased the number of curvesTos to 8.

    I like the FlashCoders solution also to drawing an elipse also - very useful.

  6. #6
    Senior Member
    Join Date
    Mar 2000
    Posts
    472

    Unexpected results

    Hmmmm ... I made a file to compare the 8-45 degree segment quadBezier Circle from the post above with Timothee Groleau's 'drawCubicBezier' algorithm, in which I used 4-90 degree 'cubicBezier' segments to form the circle. Each 'cubicBezier' segment is produced by recursively drawing quadratic bezier 'curveTos' (default is 4 ... adjustable to 10), which produces a total of 16-40 'curveTos' for the entire circle.

    Now, assuming that the algorithm for 'kappa' by G. Adam Stanislav that I found here is correct, I expected the 'cubicBezier' algo (blue circle) to be more accurate than the 'quadBezier' algo (red circle). However, after about 5 right-click 'zoom-ins', viewing the circle graphic (button-press 'n hold within the circle) at the perimeter reveals the 'quadBezier' algo to be more accurate, no matter what the 'cubicBezier's recurse' value is set to ... who knew!

    quad-cubicBezierCircle: .swf .zip

    There is a very interesting thread called: 'Circle from Bezier Curve' at the [comp.graphics.algorithms] newsgroup which deals with this subject in detail.

    In summation, circle precision relies more on the number of control points/segments than on the number of 'curveTos'. The 'cubicBezier' algo is still very useful, however, for drawing self-intersecting bezier curves, which can't be accomplished with a single quadratic bezier line.

    Richard

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  




Click Here to Expand Forum to Full Width

HTML5 Development Center