问题
I have used the Parametric Expression of a Bezier Curve to locate a point along my curve and it's working as it should. The problem is I'm setting my t
value as the percentage of the y axis and unfortunately (and obviously) it doesn't correlate because my curve is longer than my Y axis. So in this program if I set my Y Value to 75 I want to return the point on my line that sits at the Y value of 25 (the inverse because in iOS the (0, 0) sits at the top left instead of the bottom left as my graph reads). Currently setting my Y value retunes the point on my curve at 75% which has a Y of 15.62.
Anyone have a recommendation of how to get the point on my curve at Y instead of at 75%?
This is a follow-up question to a previous question, finding a point on a path, but I felt it was different enough to warrant its own thread.
#import "GraphView.h"
@interface GraphView ()
{
float yVal;
}
@end
@implementation GraphView
@synthesize myLabel, yValue;
- (id)initWithCoder:(NSCoder *)aDecoder
{
self = [super initWithCoder:aDecoder];
if (self) {
yVal = 50;
}
return self;
}
- (IBAction)yValueTextField:(id)sender
{
yVal = yValue.text.intValue;
[self resignFirstResponder];
[self setNeedsDisplay];
}
- (void)drawRect:(CGRect)rect
{
float t = yVal / 100;
// Starting point
float p1x = 0;
float p1y = 100;
// Control point 1
float c1x = 50;
float c1y = 100;
// Control point 2
float c2x = 50;
float c2y = 0;
// End Point
float p2x = 100;
float p2y = 0;
CGPoint p1 = CGPointMake(p1x, p1y);
CGPoint c1 = CGPointMake(c1x, c1y);
CGPoint c2 = CGPointMake(c2x, c2y);
CGPoint p2 = CGPointMake(p2x, p2y);
// Cubic Bezier Curver Parmetic Expression
float X = pow((1 - t), 3) * p1x + 3 * pow((1 - t), 2) * t * c1x + 3 * (1 - t) * pow(t, 2) * c2x + pow(t, 3) * p2x;
float Y = pow((1 - t), 3) * p1y + 3 * pow((1 - t), 2) * t * c1y + 3 * (1 - t) * pow(t, 2) * c2y + pow(t, 3) * p2y;
myLabel.text = [NSString stringWithFormat:@"Coord = %.2f, %.2f", X, Y];
UIBezierPath *circle = [UIBezierPath bezierPathWithOvalInRect:CGRectMake((X - 2), (Y - 2), 4, 4)];
[[UIColor blackColor] setFill];
[circle fill];
UIBezierPath *curve = [[UIBezierPath alloc] init];
[curve moveToPoint:p1];
[curve addCurveToPoint:p2 controlPoint1:c1 controlPoint2:c2];
[curve setLineWidth:1];
[[UIColor blueColor] setStroke];
[curve stroke];
}
@end
回答1:
Here is my solution to finding my point on my bezier curve. For more background regarding this see another related post of mine --> finding a point on a path
#import "Calculation.h"
@implementation Calculation
@synthesize a, b, c, d, xy;
- (float) calc
{
float squareRootCalc =
sqrt(
6*pow(xy,2)*b*d
+4*a*pow(c,3)
-3*pow(b,2)*pow(c,2)
+9*pow(xy,2)*pow(c,2)
-6*a*c*b*d
+6*a*xy*c*b
-18*pow(xy,2)*b*c
+6*a*pow(xy,2)*c
-12*a*xy*pow(c,2)
-2*pow(a,2)*xy*d
+pow(a,2)*pow(d,2)
+4*pow(b,3)*d
+pow(xy,2)*pow(d,2)
-4*pow(b,3)*xy
-4*pow(c,3)*xy
+pow(a,2)*pow(xy,2)
+6*c*b*d*xy
+6*a*c*d*xy
+6*a*b*d*xy
-12*pow(b,2)*d*xy
+6*xy*c*pow(b,2)
+6*xy*b*pow(c,2)
-2*a*pow(xy,2)*d
-2*a*xy*pow(d,2)
-6*c*d*pow(xy,2)
+9*pow(xy,2)*pow(b,2)
-6*a*pow(xy,2)*b)
;
float aCalc = 24*c*d*xy + 24*a*pow(c,2) - 36*xy*pow(c,2) + 4 * squareRootCalc * a;
float bCalc = -12 * squareRootCalc * b;
float cCalc = 12 * squareRootCalc * c;
float dCalc = -4 * squareRootCalc * d;
float xyCalc =
24*xy*a*b
-24*xy*b*d
-12*b*a*d
-12*c*a*d
-12*c*b*d
+8*xy*a*d
+8*pow(b,3)
+8*pow(c,3)
+4*pow(a,2)*d
+24*pow(b,2)*d
-4*xy*pow(a,2)
-4*xy*pow(d,2)
+4*a*pow(d,2)
-12*c*pow(b,2)
-12*b*pow(c,2)
-12*a*b*c
-24*xy*a*c
+72*xy*c*b
-36*xy*pow(b,2)
;
float cubeRootCalc = cbrt(aCalc + bCalc + cCalc + dCalc + xyCalc);
float denomCalc = (a-3*b+3*c-d);
float secOneCalc = 0.5 * cubeRootCalc / denomCalc;
float secTwoCalc = -2 * ((a*c - a*d - pow(b,2) + c*b + b*d - pow(c,2)) / (denomCalc * cubeRootCalc));
float secThreeCalc = (a - 2*b + c) / denomCalc;
return secOneCalc + secTwoCalc + secThreeCalc;
}
- (Calculation *) initWithA:(float)p0 andB:(float)p1 andC:(float)p2 andD:(float)p3 andXy:(float)xyValue
{
self = [super init];
if (self) {
[self setA:p0];
[self setB:p1];
[self setC:p2];
[self setD:p3];
[self setXy:xyValue];
}
return self;
}
- (void) setA:(float)p0 andB:(float)p1 andC:(float)p2 andD:(float)p3 andXy:(float)xyValue
{
[self setA:p0];
[self setB:p1];
[self setC:p2];
[self setD:p3];
[self setXy:xyValue];
}
@end
来源:https://stackoverflow.com/questions/16779924/parametric-expression-of-a-bezier-curve