1

[enter image description here][1]I have a bezierpath for an unclosed structure. I want to detect tap only when clicked on the path, and not for taps on the area enclosed by the path.If I use path.contains, it giving me true even for taps enclosed by path.

bezier.contains(touchPoint)

The Path Image has grey path which is created using code below, I would like to detect the clicks on gray portions only and not inside the area surrounded by gray portion.

let color:UIColor = getColor(structure.category)
let bpath:UIBezierPath = UIBezierPath()
beziers.append(bpath);
bpath.move(to: structure.points[0].fromPoint)
for point in structure.points {
    bpath.addCurve(to: point.toPoint, controlPoint1:point.controlPointOne, controlPoint2: point.controlPointTwo)
}
bpath.lineWidth = 5.0
color.set()
bpath.stroke()
Xin
  • 1,300
  • 2
  • 14
  • 27
  • I was about to answer something when I realized I simply do not understand the question given what you've said. How can an *unclosed* path detect taps *enclosed* by the path? Any chance you could give use more code? I could probably help you if you do. –  Feb 28 '17 at 16:29
  • Edited the question above – vishal jain Feb 28 '17 at 17:06
  • The path looks think enough to create a CAShapeLayer (with both stroke and fill) of. If you do that, you could have something to run a *hitTest()* of. Yes, the path is so small that fat fingers (30-44 points) *will* detect a tap, but I think that's about the best such a shape will get for tap detection. –  Feb 28 '17 at 17:12

3 Answers3

2

Turn your strokes to a closed path by taking the UIBezierPath's path property, which is a CGPath, and calling copy(strokingWithWidth:) on that CGPath. Now you have a closed path (or more than one closed path) and you can use the CGPath contains method successfully.

matt
  • 515,959
  • 87
  • 875
  • 1,141
  • Did you mean to say I should check for "contains" in this modified path instead of the original bezierpath . Also Once I have the copy for original path, How do I set this new path as path for my bezier. – vishal jain Feb 28 '17 at 18:16
  • You don't. It's just a way of performing the `contains` calculation successfully. – matt Feb 28 '17 at 18:17
0

It's not easy to detect whether a point lies on any bezierPath but I have a trick for you.

To detect whether a point lies on any shape, render it in a colour C to a bitmap, get the pixel corresponding to your coordinate and check colour of that pixel. If it's C then the point lies on your shape, otherwise it doesn't.

kkodev
  • 2,557
  • 23
  • 23
0

@matt's solution below is a good way to determine if a point near the original path. It's similar to the solution in this question that uses CGPathCreateCopyByStrokingPath.

An alternative option would be to use the ClippingBezier library I wrote, which contains a closestPointOnPathTo: method. You could then, in pseudocode:

CGPoint pointOnPath = [myBezierPath closestPointOnPathTo:touchPoint];
CGFloat distToPath = distanceBetweenPoints(pointOnPath, touchPoint);
if(distToPath < 5) ...

This may be overkill depending on what you need, or might give some additional useful bezier tools depending on what else you'll do with your paths.

Community
  • 1
  • 1
adam.wulf
  • 2,149
  • 20
  • 27