xeravim - 11 months ago 93

Objective-C Question

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];

}

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 Source

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`

.