Search code examples
objective-ccore-graphicscgpath

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


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?


Solution

  • 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(…)