问题描述
我有一条类似的路径(红色中间线),是从
创建的 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
}
因为我有多条线,所以我必须检测我正在用哪条线
for each in RulerModelArray{
if (!(each.midpath.path?.contains(touchPoint))!) {
print("not contain")
} else {
print("contained",each.ID)
}
}
问题是如果我的point1
/ point2
y是450,而我的touchPoint.y是450.00001,那么就不会检测到它。只有1%的人无法选择最合适的位置。
经过测试:
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
我是否可以检测到shapeLayer.linewidth = 10
中的路径?
解决方法
这是更通用的方式
适用于任何类型的直线,
通过计算触摸点到目标线的距离
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)
}
}
,
您可以使用此
检查CGPoint是否在UIBezierPath的范围内
适用于水平线,因为水平线的高度为0
extension UIBezierPath{
func hasForHorizontalLine(pt point: CGPoint) -> Bool{
let bezierRect = bounds
let origin = bezierRect.origin
let size = bezierRect.size
if origin.x <= point.x,origin.x + size.width >= point.x,origin.y - lineWidth * 0.5 <= point.y,origin.y + lineWidth * 0.5 >= point.y{
return true
}
else{
return false
}
}
}