How to get the distance to a CGPath for hit-testing?

橙三吉。 提交于 2021-02-18 12:47:14

问题


I have an open CGPath/UIBezierPath for which I want to detect if the user touches it, i.e. whether a point is within a certain distance from the path. The path is open (i.e. a line/curve, not a shape). It can contain both straight & curved elements. How do I get the distance to the path to hit-test it?


回答1:


It seems neither CGPath/UIBezierPath has a function to do this. EDIT: As per @nielsbot's suggestion, you could write a custom implementation using CGPathApply(…). Computing the distance to the curved parts is not so trivial though.

However I have found a neat way to achieve my original goal, hit-testing the path: CGPathCreateCopyByStrokingPath(…).

- (BOOL)isPoint:(CGPoint)p withinDistance:(CGFloat)distance ofPath:(CGPathRef)path
{
    CGPathRef hitPath = CGPathCreateCopyByStrokingPath(path, NULL, distance*2, kCGLineCapRound, kCGLineJoinRound, 0);
    BOOL isWithinDistance = CGPathContainsPoint(hitPath, NULL, p, false);
    CGPathRelease(hitPath);
    return isWithinDistance;
}

For better performance, you can cache hitPath. Could also be used for closed paths by adding the original path to hitPath using CGPathAddPath(…)




回答2:


for swift 3.0:

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
}

use:

let inside = self.isPoint(point: location, withinDistance: 4, ofPath: myPath!)
if inside{...

of course, as Patrick noted, is better to cache hitPath, instead of creating it every time. In case You have UIBezierPath, simply:

 let inside = self.isPoint(point: location, withinDistance: 4, ofPath: myUIPath.cgPath!)


来源:https://stackoverflow.com/questions/19463323/how-to-get-the-distance-to-a-cgpath-for-hit-testing

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!