brutfood

09-13-2002, 09:16 AM

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?

Dickee

09-13-2002, 02:01 PM

Hey brutfood!

I made an example based on 4 prototypes found here:

http://chattyfig.figleaf.com/flashcoders-wiki/index.php?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

brutfood

09-13-2002, 10:23 PM

Thanks Richard,

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

Dickee

09-14-2002, 03:00 AM

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]

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/FM101_unitCircle8.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 (http://board.flashkit.com/board/showthread.php?threadid=355601bezier) 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]

brutfood

09-14-2002, 05:17 AM

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.

Dickee

09-19-2002, 02:45 AM

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 (http://www.whizkidtech.net/bezier/circle) 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 (http://members.shaw.ca/flashmath101/quad-cubicBezierCircle.swf) .zip (http://members.shaw.ca/flashmath101/quad-cubicBezierCircle.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