【问题标题】:How to Get every CGPoint on UIBezierPath in Swift如何在 Swift 中获取 UIBezierPath 上的每个 CGPoint
【发布时间】:2019-07-19 00:41:14
【问题描述】:

我想找出 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)
}

【问题讨论】:

  • 我需要该路径下的每个坐标(CGPoint)。
  • 没有附加图片。
  • i.stack.imgur.com/3ZWDe.png 请检查一下
  • 贝塞尔路径是一条连续的曲线,上面有无数个点。
  • 我想在贝塞尔路径上绘制一些在贝塞尔路径之外但靠近贝塞尔路径的点,因此我需要一些坐标,通过它可以将它们与最近的点进行比较

标签: swift uibezierpath cgpoint


【解决方案1】:

让我们退后一步。为什么你想要所有这些分数?是看有没有人在摸路径的轮廓吗?如果是这样,请使用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(at fraction: CGFloat) 的新方法,可让您为其赋值 0 到 1 并获得您感兴趣的点。它还有一种方法可以为您提供路径的总长度,因此如果您不需要“路径上的 100 个点”但“路径上的点相距不超过 3 个像素”,您可以使用它来估计步进的速度分数。这只是一个猜测,因为弧的某些部分会比其他部分“移动”得更快。因此,您将需要生成每个点,如果它们相距太远而无法使用,请退后一点。

祝你好运!

【讨论】:

    猜你喜欢
    • 2018-08-27
    • 2017-06-11
    • 1970-01-01
    • 2016-12-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-10-11
    • 1970-01-01
    相关资源
    最近更新 更多