views:

326

answers:

1

Just to clarify; the code below works, but I don't understand where the formula for the variable "controlRadius" comes from. I wrote this function by dissecting an example I found elsewhere, but I can't find any explanation and the original code comments were not able to be translated.

Thanks in advance


//returns an array of quadratic Bezier segments
    public static function generateCircularQuadraticBezierSegments(radius:Number, numControlPoints:uint, centerX:Number, centerY:Number):Array
    {
        var segments:Array = [];

        var arcLength:Number = 2 * Math.PI / numControlPoints;

        var controlRadius:Number;

        var segment:QuadraticBezierSegment;

        for (var i:int = 0; i < numControlPoints; i++) {

            var startX:Number = centerX + radius * Math.cos(arcLength * i);
            var startY:Number = centerY + radius * Math.sin(arcLength * i);

            //control radius formula
            //where does it come from, why does it work?
            controlRadius = radius / Math.cos(arcLength * .5);

            //the control point is plotted halfway between the arcLength and uses the control radius
            var controlX:Number = centerX + controlRadius * Math.cos(arcLength * (i + 1) - arcLength * .5);
            var controlY:Number = centerY + controlRadius * Math.sin(arcLength * (i + 1) - arcLength * .5);

            var endX:Number = centerX + radius * Math.cos(arcLength * (i + 1));
            var endY:Number = centerY + radius * Math.sin(arcLength * (i + 1));

            segment = new QuadraticBezierSegment(new Point(startX, startY), new Point(controlX, controlY), new Point(endX, endY));

            segments.push(segment);
        }

        return segments;
    }
+3  A: 

The following should make it clear. It is for numControlPoints = 4, which will not yield good results, since quadratic beziers can only approximate conic sections (circles being conic sections). However I needed a bigger angle for things to be clearer. :)

alt text

the "inner" (partially red, partially dotted) circle is the circle we want to draw, one segment of angle arclength being shown, with its control point. the control point's angle lies in the center of the segment's, with a distance of controlRadius. Now if we draw the circle segment with radius controlRadius (grey circle), we see that radius = cos(argclength/2)*controlRadius, which after solving for controlRadius yields the formula above.
Note: this is not just because I chose a segment of a right angle. It is always the case, since the control point is the intersection of the tangents of the start and endpoint of the segment to be drawn. Thus you always obtain a right angle between the radius and the line between start and control point

hope that helps

greetz
back2dos

back2dos
Thanks for the detailed answer and graphic. If I understand correctly, r/cos(arcLength/2) is the intersection of the tangents of the start and end points which is the same as the length of the hypotenuse of a right triangle formed with theta equal to arcLength/2 and adjacent length equal to the circle's radius, ie: cos(theta) = adjacent/hypotenuse --> cos(arcLength/2) = radius/controlRadius -->controlRadius = radius/cos(arcLength/2), Cool. Guess I should have done a better job befriending Chief Sohcahtoa so I could recognize the relationship :(
Casey