Swift UIBelzierpath-path.contains(userTouchPoint)只能检测userTouchPoint.y是否正好位于路径y的位置

Swift UIBelzierpath-path.contains(userTouchPoint)只能检测userTouchPoint.y是否正好位于路径y的位置,swift,uibezierpath,Swift,Uibezierpath,我有这样一条路径(红色中间线),它是从 func drawALine(point1:CGPoint,point2:CGPoint)->CAShapeLayer{ let path = UIBezierPath() path.move(to: point1) path.addLine(to: point2) let shapeLayer = CAShapeLayer() shapeLayer.path =

我有这样一条路径(红色中间线),它是从

   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)
            }
        }
问题是如果我的
点1
/
点2
y是450,而我的接触点.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
中是否有我可以检测到的路径?

您可以使用此选项

检查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
        }
    }
    
}
扩展UIBezierPath{ func HASFORHORIONTALLINE(pt点:CGPoint)->Bool{ 设bezierRect=边界 让origin=bezierrrect.origin let size=bezierrrect.size 如果origin.x=point.x,origin.y-线宽*0.5=point.y{ 返回真值 } 否则{ 返回错误 } } }
这是一种更通用的方法

适用于任何类型的直线

通过计算从接触点到目标线的距离

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)
    }
    
}
扩展点{
//公差,应为UIBezierPath的线宽
包含func(铁路线起点:CGPoint,终点:CGPoint,公差宽度:CGFloat)->Bool{
返回距离(从行:开始,到:结束)CGFloat{
设a=end.y-start.y
设b=start.x-end.x
设c=(start.y-end.y)*start.x+(end.x-start.x)*start.y
返回abs(a*x+b*y+c)/sqrt(a*a+b*b)
}
}

each.midPath.path?
是一个CGPath,似乎我不能将
边界
与CGPath一起使用。而我的
midPath
是一个CAShapeLayer,它总是将所有内容返回0给我