I have a path like this (red middle line), which is created from
func drawALine(point1:CGPoint,point2:CGPoint)->CAShapeLayer{
let path = UIBezierPath()
path.move(to: point1)
path.addLine(to: point2)
let shapeLayer = CAShapeLayer()
shapeLayer.path = path.cgPath
shapeLayer.strokeColor = UIColor.red.cgColor
shapeLayer.lineWidth = 10
self.layer.addSublayer(shapeLayer)
return shapeLayer
}
Because I have multiple Lines so I have to detect which one I'm touching with this
for each in RulerModelArray{
if (!(each.midPath.path?.contains(touchPoint))!) {
print("not contain")
} else {
print("contained",each.ID)
}
}
Problem is if my point1
/point2
y is 450, and my touchPoint.y is 450.00001 then it won't be detected. There is only like 1% that I can't tap on the perfect spot.
Tested with this:
let testPoint:CGPoint = CGPoint(x: touchPoint.x, y: touchPoint.y + 0.0001 )
for each in RulerModelArray{
if (!(each.midPath.contains(testPoint))) {
print("not contain")
} else {
print("contained",each.ID)
}
}
///always return not contain
Is there anyway that I can detect the path within shapeLayer.lineWidth = 10
?
this is more universal way
works for any kinds of straight line,
by calculating the distance from touch point to the destination line
extension CGPoint{
// tolerance, should by the lineWidth of a UIBezierPath
func contained(byStraightLine start: CGPoint,to end: CGPoint, tolerance width: CGFloat) -> Bool{
return distance(fromLine: start, to: end) <= width * 0.5
}
func distance(fromLine start: CGPoint,to end: CGPoint) -> CGFloat{
let a = end.y - start.y
let b = start.x - end.x
let c = (start.y - end.y) * start.x + ( end.x - start.x ) * start.y
return abs(a * x + b * y + c)/sqrt(a*a + b*b)
}
}