xeravim xeravim - 1 month ago 26
Objective-C Question

Create Bezier Curve in Objective C using Paul de Casteljau algorithm

I am trying to use Paul de Casteljau algorithm to draw Bezier Curve for my homework, but it seems it is not perfect, here are the codes



- (void)recursive_bezier :(double)x1 :(double)y1
:(double)x2 :(double)y2
:(double)x3 :(double)y3
:(double)x4 :(double)y4
{

count = count+1;
// Calculate all the mid-points of the line segments
//----------------------
double x12 = (x1 + x2) / 2;
double y12 = (y1 + y2) / 2;
double x23 = (x2 + x3) / 2;
double y23 = (y2 + y3) / 2;
double x34 = (x3 + x4) / 2;
double y34 = (y3 + y4) / 2;
double x123 = (x12 + x23) / 2;
double y123 = (y12 + y23) / 2;
double x234 = (x23 + x34) / 2;
double y234 = (y23 + y34) / 2;
double x1234 = (x123 + x234) / 2;
double y1234 = (y123 + y234) / 2;


if(isFlat)
{
// // Draw and stop
// //----------------------
[self drawLine:x1 :y1 :x4 :y4];

}
else
{
// Continue subdivision
//----------------------
if (count == 5) {
isFlat=true;
}

[self recursive_bezier:x1 :y1 :x12 :y12 :x123 :y123 :x1234 :y1234];
[self recursive_bezier:x1234 :y1234 :x234 :y234 :x34 :y34 :x4 :y4];


}
}

- (void)drawLine :(double)x1 :(double)y1
:(double)x4 :(double)y4{
countDraw = countDraw+1;
NSLog(@"============%d============",countDraw);
NSLog(@"x1 = %f y1 = %f",x1, y1);
NSLog(@"x4 = %f y4 = %f",x4, y4);

UIBezierPath *path = [UIBezierPath bezierPath];
[path moveToPoint:CGPointMake(x1, y1)];

[path addLineToPoint:CGPointMake(x4, y4)];

CAShapeLayer *shapeLayer = [CAShapeLayer layer];
shapeLayer.path = [path CGPath];
shapeLayer.strokeColor = [[UIColor blueColor] CGColor];
shapeLayer.lineWidth = 2.0;
shapeLayer.fillColor = [[UIColor clearColor] CGColor];

[self.view.layer addSublayer:shapeLayer];

}





enter image description here

Can anyone help me why the right side not calculated and how to make the curve smooth?

ps : i got the algorithm on Bezier Curve Algorithm

Answer

The problem is that once isFlat is set to true, any further segments won't be subdivided properly, even at the top level. This is because it is information related to a specific level of the recursive calls and not something global to the whole thing. If you step through the execution of the code this should be more clear.

A better way to do it is to declare count as an int parameter to recursive_bezier and pass 0 at the top level when you call it, and pass count + 1 when you call it recursively. You can get rid of the isFlat variable and just test for count >= 5.