I drew the above BezierPath by doing: // location is where the user touches screen. // location will be the maximum of the graph CGPoint origin = CGPointMake(xStart, 620.0); CGPoint endpt = CGPointMake(xEnd, 620.0); CGPoint midpt1 = midPointForPoints(origin, location); CGPoint midpt2 = midPointForPoints(location, endpt);
UIBezierPath *path = [UIBezierPath bezierPath];
[path moveToPoint:origin];
[path addQuadCurveToPoint:location controlPoint:CGPointMake(midpt1.x, midpt1.y+50)];
[path addQuadCurveToPoint:endpt controlPoint:CGPointMake(midpt2.x, midpt2.y+50)];
[shapeLayer setPath:path.CGPath];
Now, I want to retrieve y-coordinates for certain x-coordinates that lie on the path. For example, given x = 0.0, I want to get y = 0.0, or given x = 300.0, y = 50.0.
I looked at some references like this question and sample code I am still not sure.
Update: basically, I want to do something like this.
Update: Following @Fang's advice:
Given the equation
X = (1-t)^2*X0 + 2*t*(1-t)*X1 + t^2 *X2
I solve for t
t = ((2.0 * x0 - x1) + sqrt(((-2.0 * x0 + x1) ** 2.0)
- ((4 * (x0 - 2.0 * x1 + x2)) * (x0 - x)))) / (2.0 * (x0 - 2.0 * x1 + x2))
or
t = ((2.0 * x0 - x1) - sqrt(((-2.0 * x0 + x1) ** 2.0)
- ((4 * (x0 - 2.0 * x1 + x2)) * (x0 - x)))) / (2.0 * (x0 - 2.0 * x1 + x2))
Using this value, find Y that corresponds to X (we used X to find the above t value)
Y = (1-t)^2*Y0 + 2*t*(1-t)*Y1 + t^2 *Y2
Following the above equation, I am supposed to get the y-value of the point that lies on the Bezier curve but I get a point that's far from the right one. Any further help will be very much appreciated..
Concern: I think one possible problem is that I am calling addQuadCurveToPoint()
twice with two control points instead of once with two control points. Does it mean I draw two Bezier paths and combine them? I am also looking at this to see what's wrong with my computation and the only difference seems to be that he uses two control points when calling addQuadCurveToPoint()
.
Update after Fang's intense consulting:
- (float)getYFromBezierPath:(float)x location:(CGPoint)location ctrlpt1:(CGPoint)ctrlpt1 ctrlpt2:(CGPoint)ctrlpt2 endpt:(CGPoint)endpt {
float yVal;
float tVal;
if (x <= location.x) {
tVal = [self getTvalFromBezierPath:x x0Val:0.0 x1Val:ctrlpt1.x x2Val:location.x];
yVal = [self getCoordFromBezierPath:tVal origin:0.0 p1Val:ctrlpt1.y p2Val:location.y];
} else {
// THIS PART IS THE PROBLEM //
tVal = [self getTvalFromBezierPath:x x0Val:location.x x1Val:ctrlpt2.x x2Val:endpt.x];
yVal = [self getCoordFromBezierPath:tVal origin:location.y p1Val:ctrlpt2.y p2Val:endpt.y];
}
return yVal;
}
- (float)getTvalFromBezierPath:(float)x x0Val:(float)x0 x1Val:(float)x1 x2Val:(float)x2 {
float tVal = (x-x0)/(2*(x1-x0));
return tVal;
}
- (float)getCoordFromBezierPath:(float)t origin: (float)origin p1Val: (float)p1 p2Val: (float)p2 {
// tVal = (sqrt((-2.0 * x * x1) + (x * x0) + (x * x2) + pow(x1, 2) - (x0 * x2)) + x0 - x1) / (x0 - (2.0 * x1) + x2);
return (pow((1-t),2) * origin) + (2 * t * (1-t) * p1) + (pow(t,2) * p2);
}
Last question: for the second Bezeir path, y-value should decrease as t-value increases. Right now, y-value keeps increasing. How should I fix this? After intensive debugging I haven't found why this is happening because everything conforms to the document.