检测CGPoint是否在多边形内部

21

我有一组构成多边形的 CGPoints,如何检测一个单独的 CGPoint 是否在多边形内或外?

比如,假设该多边形是一个三角形,而这个 CGPoint 是在水平移动,我该如何检测它何时穿过三角形的边界线?

当形状为常规的四边形时,我可以使用 CGRectContainsPoint 进行判断,但对于奇异形状,我不知道应该如何实现。

4个回答

30
您可以使用您的点创建一个 CG(Mutable)PathRef (或包装了CGPathRefUIBezierPath),并使用CGPathContainsPoint函数检查一个点是否在该路径内。如果使用UIBezierPath,还可以使用containsPoint:方法。

2

你需要编写一个实现点在多边形内算法的方法。

该方法将接受一个包含N个点(即多边形)的数组作为参数和一个特定点。如果该点在多边形内部则返回true,否则返回false。

查看S.O.上的优秀答案。


1

以下是用Swift编写的实现:

extension CGPoint {
    
    func isInsidePolygon(vertices: [CGPoint]) -> Bool {
        guard vertices.count > 0 else { return false }
        var i = 0, j = vertices.count - 1, c = false, vi: CGPoint, vj: CGPoint
        while true {
            guard i < vertices.count else { break }
            vi = vertices[i]
            vj = vertices[j]
            if (vi.y > y) != (vj.y > y) &&
                x < (vj.x - vi.x) * (y - vi.y) / (vj.y - vi.y) + vi.x {
                c = !c
            }
            j = i
            i += 1
        }
        return c
    }
}

0

Swift 3

使用 Swift 3 更简单的方法是使用 UIBezierPathcontains 方法。

创建 CAShapeLayer 实例时,请确保设置 accessibilityPath

shapeLayer.path = bazierPath.cgPath
shapeLayer.accessibilityPath = bazierPath

检查路径是否包含触摸位置。

override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
    guard let point = touches.first?.location(in: self) else { return }

    for shape in layer.sublayers ?? [] where shape is CAShapeLayer {
        guard let layer = shape as? CAShapeLayer,
            let bazier = layer.accessibilityPath else { continue }

        // Handle touch
        print(bazier.contains(point))
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接