我正在尝试绘制贝塞尔曲线(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;
}
最佳答案
我会用参数计算CGAffineTransform
(a, b, -b, a, tx, ty)
(即无偏斜的变换),将旧端点映射到新端点,然后将此变换应用于旧控制点以获取新控制点。
将2个旧端点映射到2个新端点的条件给出了a,b,tx,ty的4个方程,这些方程甚至可以在没有三角函数的情况下求解。
关于ios - 按比例缩放贝塞尔曲线-计算控制点,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/12264741/