我正在尝试采用贝塞尔曲线(Core Graphics 中的任意曲线)并在给定另外两个端点的情况下按比例缩小(或扩展)它。我有一种可行的方法,但它最终会“拉平”曲线,而不是完全保持形状。也许我搞砸了代码或逻辑,但我有两个原始点以及控制点。给定另一组端点,我想计算适当的控制点以在新端点之间产生相同的形状。
这是计算 1 个控制点的主要代码:
CGPoint (^ScaledCtrlPoint)(CGPoint, CGPoint, CGPoint, CGPoint, CGPoint) = ^CGPoint (CGPoint refPoint1, CGPoint refPoint2, CGPoint bevPoint1, CGPoint bevPoint2, CGPoint ctrlPoint){
//Normalize points to refPoint1
refPoint2.x -= refPoint1.x; refPoint2.y -= refPoint1.y;
ctrlPoint.x -= refPoint1.x; ctrlPoint.y -= refPoint1.y;
//Normalize bevPoints to bevPoint1
bevPoint2.x -= bevPoint1.x; bevPoint2.y -= bevPoint1.y;
//Calculate control point angle
CGFloat theta = PointTheta(refPoint2);
CGFloat refHyp = (refPoint2.y != 0.0f) ? refPoint2.y / sinf(theta) : refPoint2.x / cosf(theta);
theta = PointTheta(bevPoint2);
CGFloat bevHyp = (bevPoint2.y != 0.0f) ? bevPoint2.y / sinf(theta) : bevPoint2.x / cosf(theta);
theta = PointTheta(ctrlPoint);
CGFloat ctrlHyp = (ctrlPoint.y != 0.0f) ? ctrlPoint.y / sinf(theta) : ctrlPoint.x / cosf(theta);
ctrlHyp *= (bevHyp / refHyp);
return CGPointMake(bevPoint1.x + cosf(theta) * ctrlHyp, bevPoint1.y + sinf(theta) * ctrlHyp);
};
这些bevPoints
是我用来计算新控制点的新点。refPoints
和ctrlPoint
是贝塞尔曲线的原点。如您所见,我正在尝试按与原始端点与新端点相同的比例缩小 ctrlPoint(也可以放大)。
我还使用了另一个函数,用于计算入射角。这很简单:
CGFloat PointTheta(CGPoint point){
//This assumes an origin of {0, 0} and returns a theta for the given point
CGFloat theta = atanf(point.y / point.x);
//Using arc tan requires some adjustment depending on the point quadrant
if (point.x == 0.0f) theta = (point.y >= 0.0f) ? M_PI_2 : M_PI + M_PI_2;
else if (point.x < 0.0f) theta += M_PI;
else if (point.x > 0.0f && point.y < 0.0f) theta += (M_PI * 2);
return theta;
}