Reputation: 21512
I asked a quick question Bezier curve algorithm in objective-c that seemed to solve my issues. I'm asking this new question as I think its different enough rather than repurposing the old one.
I have what seems like a working Bezier Curve algorithm but when compared to built in NSBezierPath
version there are some major issues. It looks as though certain types of curves are very much distorted.
You can see from the above image the differences, the red line is my function and the lighter color is the built in version. I am not expecting and exat match, pixel for pixel, but as you can see the red lines go way off course at times.
The first method I'm listing is what calls the 2 Bezier methods, it shows that the inputs are the same to both versions.
- (void)MakeBezier
{
int x1 = [self getMegaNumber:2];
int y1 = self.frame.size.height - [self getMegaNumber:2];
int x2 = [self getMegaNumber:2];
int y2 = self.frame.size.height - [self getMegaNumber:2];
int x3 = [self getMegaNumber:2];
int y3 = self.frame.size.height - [self getMegaNumber:2];
int x4 = [self getMegaNumber:2];
int y4 = self.frame.size.height - [self getMegaNumber:2];
int cnt = [self getMegaNumber:2];
NSBezierPath *bezierPath = [[NSBezierPath alloc] init];
[bezierPath setLineWidth:1.0f];
[bezierPath moveToPoint:NSMakePoint(x1, y1)];
[bezierPath curveToPoint:NSMakePoint(x4, y4) controlPoint1:NSMakePoint(x2, y2) controlPoint2:NSMakePoint(x3, y3)];
// Draw path to image with build in NSBezierPath
[self drawPath:bezierPath fill:NO];
// Draw path with custom algorithm
[self drawBezierFrom:NSMakePoint(x1, y1) to:NSMakePoint(x4, y4) controlA:NSMakePoint(x2, y2) controlB:NSMakePoint(x3, y3) sections:cnt color:4];
}
This next method is the custom algorithm thats used to draw the red lines in the sample image.
- (void)drawBezierFrom:(NSPoint)from to:(NSPoint)to controlA:(NSPoint)a controlB:(NSPoint)b sections:(NSUInteger)cnt color:(NSUInteger)color
{
float qx, qy;
float q1, q2, q3, q4;
int lastx = - 1, lasty;
int plotx, ploty;
float t = 0.0;
while (t <= 1)
{
q1 = t*t*t*-1 + t*t*3 + t*-3 + 1;
q2 = t*t*t*3 + t*t*-6 + t*3;
q3 = t*t*t*-3 + t*t*3;
q4 = t*t*t;
qx = q1*from.x + q2*a.x + q3*to.x + q4*b.x;
qy = q1*from.y + q2*a.y + q3*to.y + q4*b.y;
plotx = round(qx);
ploty = round(qy);
if (lastx != -1)
[self drawLineFrom:NSMakePoint(lastx, lasty) to:NSMakePoint(plotx, ploty) color:color];
else
[self drawLineFrom:NSMakePoint(from.x, from.y) to:NSMakePoint(plotx, ploty) color:color];
lastx = plotx;
lasty = ploty;
t = t + (1.0/(cnt + 0.0f));
}
[self drawLineFrom:NSMakePoint(lastx, lasty) to:NSMakePoint(to.x, to.y) color:color];
}
So my question is; is the custom algorithm way off or is it just missing an edge case for specific kinds of lines, or something else? Either way any help in fixing the algorithm would be very appreciated. To reiterate, I am not looking for a pixel perfect match, but I am expecting the curves to lineup together.
Upvotes: 3
Views: 2115
Reputation: 26353
Looking at the Wikipedia page here it seems that your coefficients for the q1-q4 are incorrect. Shouldn't they be symmetric?
It also seems that to.x and b.x should be swapped:
qx = q1*from.x + q2*a.x + q3*to.x + q4*b.x;
qy = ...
Upvotes: 4