【问题标题】:Get CGPath total length获取CGPath总长度
【发布时间】:2012-08-19 06:24:45
【问题描述】:

我有许多 UIBezierPath,我正在使用 CALyerAnimation @"StrokeStart" 和 @"strokeEnd" 制作动画。

我希望动画对所有路径都具有相同的速度,所以我想我可以使用路径的长度:

距离/时间 = 速度

有没有办法计算路径“长度”?

谢谢

沙尼

【问题讨论】:

标签: ios uibezierpath cgpath


【解决方案1】:

虽然您可以通过数值积分来计算贝塞尔路径的长度,但通过将路径划分为线性段可以更容易地完成。如果片段足够小,则近似误差应该可以忽略不计,尤其是您只是想对其进行动画处理。

我将向您展示四次曲线的函数,但您也可以轻松地合并三次曲线的解决方案:

- (float) bezierCurveLengthFromStartPoint: (CGPoint) start toEndPoint: (CGPoint) end withControlPoint: (CGPoint) control
{
    const int kSubdivisions = 50;
    const float step = 1.0f/(float)kSubdivisions;

    float totalLength = 0.0f;
    CGPoint prevPoint = start;

    // starting from i = 1, since for i = 0 calulated point is equal to start point
    for (int i = 1; i <= kSubdivisions; i++)
    {
        float t = i*step;

        float x = (1.0 - t)*(1.0 - t)*start.x + 2.0*(1.0 - t)*t*control.x + t*t*end.x;
        float y = (1.0 - t)*(1.0 - t)*start.y + 2.0*(1.0 - t)*t*control.y + t*t*end.y;

        CGPoint diff = CGPointMake(x - prevPoint.x, y - prevPoint.y);

        totalLength += sqrtf(diff.x*diff.x + diff.y*diff.y); // Pythagorean

        prevPoint = CGPointMake(x, y);
    }

    return totalLength;
}

编辑

如果您无法访问路径控制点(例如您使用弧创建路径),您始终可以使用 CGPathApply 函数访问底层贝塞尔曲线:

- (void) testPath
{
    UIBezierPath *path = [UIBezierPath bezierPath];
    [path moveToPoint:CGPointZero];
    [path addQuadCurveToPoint:CGPointMake(1, 1) controlPoint:CGPointMake(-2, 2)];

    CGPathRef p = path.CGPath;

    CGPathApply(p, nil, pathFunction);
}

void pathFunction(void *info, const CGPathElement *element)
{
    if (element->type == kCGPathElementAddQuadCurveToPoint)
    {
        CGPoint p;
        p = element->points[0]; // control point
        NSLog(@"%lg %lg", p.x, p.y);

        p = element->points[1]; // end point
        NSLog(@"%lg %lg", p.x, p.y);
    }
    // check other cases as well!
}

请注意,它不提供路径的起点,但您可以轻松跟踪它。

【讨论】:

  • 谢谢,我会根据我的需要更改它现在我无法弄清楚如何获得起点和终点。创建路径时是否必须存储它们?我在参考中没有看到任何属性。
  • 您可以在创建路径时跟踪它,或者我刚刚编辑了我的答案,显示如何查询 CGPathRef 以获取此详细信息
  • @BartoszCiechanowski 嗨,Bartosz。干得好。快速提问:我有一个在element-&gt;type 中不存在的CGPathAddArcToPoint,还有其他方法吗?提前致谢。问候。
  • @Unheilig 据我记得,圆弧实际上是作为曲线添加的,所以它们应该属于kCGPathElementAddCurveToPoint case
  • @BartoszCiechanowski 我试过了,没用。如果您有更多关于它的信息或将来有其他方法来解决它,请随时回帖。 Dziekuje。
猜你喜欢
  • 2014-04-16
  • 1970-01-01
  • 2021-07-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多