如何在Swift中获取UIBezierPath上的每个CGPoint

时间:2017-09-13 10:17:56

标签: swift uibezierpath cgpoint

image

Problem Image

我想找出UIBezierPath路径下的所有cgpoints,因为我有3个点可以创建UIBezier路径。我尝试了下面的代码,但它没有提供准确的结果。请查看附图。任何人都可以帮我解决这个问题。

提前致谢:)

  func getPathElementsPointsAndTypes() -> ([CGPoint],[CGPathElementType]) {
    var arrayPoints : [CGPoint]! = [CGPoint]()
    var arrayTypes : [CGPathElementType]! = [CGPathElementType]()
    self.forEach { element in
        switch (element.type) {
        case CGPathElementType.moveToPoint:
            arrayPoints.append(element.points[0])
            arrayTypes.append(element.type)
        case .addLineToPoint:
            arrayPoints.append(element.points[0])
            arrayTypes.append(element.type)
        case .addQuadCurveToPoint:
            arrayPoints.append(element.points[0])
            arrayPoints.append(element.points[1])
            arrayTypes.append(element.type)
            arrayTypes.append(element.type)
        case .addCurveToPoint:
            arrayPoints.append(element.points[0])
            arrayPoints.append(element.points[1])
            arrayPoints.append(element.points[2])
            arrayTypes.append(element.type)
            arrayTypes.append(element.type)
            arrayTypes.append(element.type)
        default: break
        }
    }
    return (arrayPoints,arrayTypes)
}

1 个答案:

答案 0 :(得分:0)

让我们退后一会儿。为什么要所有这些点?是否可以查看是否有人在摸索路径的轮廓?如果是这样,请使用CGPathCreateCopyByStrokingPath创建一个新路径,该路径将填充原始位置,然后使用新路径的containsPoint方法。容易。

如果您真的想要“所有”这些点,则必须接受数学上的观点,即直线和曲线上存在无限数量的点,因此无法全部获得它们。在点是CGFloat对的iOS中,仍然有太多点无法实际拥有“所有”点。但是,您可以在曲线的任何部分上获得尽可能多的点,因此,如果说“路径上的100个点”或“路径上的1000个点”(或几乎任何您喜欢的整数)将解决您的问题那么这仍然是一个可以解决的问题。

遍历每个路径元素都是一个好的开始。

对于每条线,您都需要生成线上的“所有”点,这是非常简单的几何:计算从起点到终点的向量。从0.0到1.0进行迭代,步长尽可能小。将矢量乘以该分数,然后将其添加到起点即可。

对于每条曲线,您需要一个更复杂的方程式,这里有一些伪代码:

function computeCurve(points[], t):
  if(points.length==1):
    recordPoint(points[0])
  else:
    newpoints=array(points.size-1)
    for(i=0; i<newpoints.length; i++):
      newpoints[i] = (1-t) * points[i] + t * points[i+1]
    computeCurve(newpoints, t)

要认真了解贝塞尔曲线如何“真正起作用”,请查看https://pomax.github.io/bezierinfo/(它具有伪代码-基本上包括我上面提到的那部分,但是您无法在Swift中直接执行任何操作)。

对于已经在iOS上执行此操作的代码,请查看:

https://github.com/CodingMeSwiftly/UIBezierPath-Superpowers

对于macOS,我做了一个相当小的分支,以支持macOS上略有不同的原语集:

https://github.com/stripes/UIBezierPath-Superpowers

他们将为您提供UIBezierPath(或NSBezierPath)mx_point(按小数:CGFloat)的新方法,该方法可将其赋予0到1的值并获得您感兴趣的点。它也提供了一种方法路径的总长度,因此,如果您不需要“路径上的100个点”,而是“路径上的点之间的距离不超过3个像素”,则可以使用它来估算步数分数。这只是一个猜测,因为弧的某些部分将比其他部分“移动”得更快。因此,您将需要生成每个点,如果它们相距太远而无法使用,请后退一点。

祝你好运!