Objective c 如何获得到命中测试CGPath的距离?
我有一个开放的CGPath/UIBezierPath,我想检测用户是否触摸它,即一个点是否在距离路径一定距离内。路径是开放的(即直线/曲线,而不是形状)。它可以包含直线图元和曲线图元。如何获取到路径的距离以点击测试它?似乎CGPath/UIBezierPath都没有这样做的功能。编辑:根据@nielsbot的建议,您可以使用Objective c 如何获得到命中测试CGPath的距离?,objective-c,core-graphics,cgpath,Objective C,Core Graphics,Cgpath,我有一个开放的CGPath/UIBezierPath,我想检测用户是否触摸它,即一个点是否在距离路径一定距离内。路径是开放的(即直线/曲线,而不是形状)。它可以包含直线图元和曲线图元。如何获取到路径的距离以点击测试它?似乎CGPath/UIBezierPath都没有这样做的功能。编辑:根据@nielsbot的建议,您可以使用cgpathpapply(…)编写自定义实现。计算到弯曲部分的距离并不是那么简单 然而,我找到了一个实现我最初目标的好方法,点击测试路径:CGPathCreateCopyBy
cgpathpapply(…)
编写自定义实现。计算到弯曲部分的距离并不是那么简单
然而,我找到了一个实现我最初目标的好方法,点击测试路径:CGPathCreateCopyByStrokingPath(…)
为了获得更好的性能,您可以缓存hitPath。也可以通过使用swift 3.0的CGPathAddPath(…)
将原始路径添加到hitPath来用于闭合路径:
final func isPoint(point: CGPoint, withinDistance distance: CGFloat, ofPath path: CGPath) -> Bool {
if let hitPath = CGPath( __byStroking: path,
transform: nil,
lineWidth: distance,
lineCap: CGLineCap.round,
lineJoin: CGLineJoin.miter,
miterLimit: 0) {
let isWithinDistance = hitPath.contains(point)
return isWithinDistance
}
return false
}
使用:
当然,正如Patrick所指出的,最好是缓存hitPath,而不是每次都创建hitPath。如果您有UIBezierPath,只需执行以下操作:
let inside = self.isPoint(point: location, withinDistance: 4, ofPath: myUIPath.cgPath!)
可以迭代路径中的所有绘制命令(移动、直线到、曲线到)。这不允许您实现自己的路径距离函数吗?看起来CGPathApply()可能正是您所需要的。@nielsbot:谢谢,这是一个有用的函数。但是,计算到曲线的距离有些复杂(需要数值迭代)。答案已更新。距离以米为单位吗?@sjoerdperf它是以原始路径的任何单位表示的(因为CGPath本身是无单位的),所以这取决于你从哪里得到它。
let inside = self.isPoint(point: location, withinDistance: 4, ofPath: myPath!)
if inside{...
let inside = self.isPoint(point: location, withinDistance: 4, ofPath: myUIPath.cgPath!)