1

我正在尝试采用贝塞尔曲线(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是我用来计算新控制点的新点。refPointsctrlPoint是贝塞尔曲线的原点。如您所见,我正在尝试按与原始端点与新端点相同的比例缩小 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;
}
4

1 回答 1

2

我会CGAffineTransform用参数计算

(a, b, -b, a, tx, ty)

(即没有倾斜的变换)将旧端点映射到新端点,然后将此变换应用于旧控制点以获得新控制点。

将 2 个旧端点映射到 2 个新端点的条件给出了 a、b、tx、ty 的 4 个方程,这些方程甚至可以在没有三角函数的情况下求解。

于 2012-09-04T14:19:02.973 回答