检测多边形内是否有CGPoint

时间:2012-01-21 11:05:40

标签: iphone objective-c ios cocoa quartz-graphics

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

说,形状是一个三角形,CGPoint正在向右移动,我怎么能检测到它何时越过三角线?

当形状是常规的4面形状时,我可以使用CGRectContainsPoint,但我看不出我会用奇怪的形状做到这一点。

4 个答案:

答案 0 :(得分:27)

您可以从积分中创建CG(Mutable)PathRef(或UIBezierPath包裹CGPathRef)并使用CGPathContainsPoint函数检查点是否在该路径内。如果您使用UIBezierPath,则还可以使用containsPoint:方法。

答案 1 :(得分:2)

为此,您需要编写一个在多边形算法中实现点的方法。

此方法将采用具有N个点(多边形)作为参数和一个特定点的数组。如果该点在多边形内部,则应返回true,否则返回false。

See this great answer on S.O.

答案 2 :(得分:0)

以下是Swift中的实现:

extension CGPoint {
    func isInsidePolygon(vertices:[CGPoint]) -> Bool {
        var i = 0, j = 0, c = false, vi:CGPoint, vj:CGPoint
        for (i = 0, j = vertices.count-1; i < vertices.count; j = i++) {
            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;
            }
        }
        return c
    }
}

答案 3 :(得分:0)

  

Swift 3

使用Swift 3的一种更简单的方法是使用UIBezierPath contains方法。

创建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))
    }
}