Detect if CGPoint within polygon

断了今生、忘了曾经 提交于 2019-11-27 13:01:42

问题


I have a set of CGPoints which make up a polygon shape, how can I detect if a single CGPoint is inside or outside of the polygon?

Say, the shape was a triangle and the CGPoint was moving hoizontally, how could I detect when it crossed the triangle line?

I can use CGRectContainsPoint when the shape is a regular 4-sided shape but I can't see how I would do it with an odd shape.


回答1:


You can create a CG(Mutable)PathRef (or a UIBezierPath that wraps a CGPathRef) from your points and use the CGPathContainsPoint function to check if a point is inside that path. If you use UIBezierPath, you could also use the containsPoint: method.




回答2:


For that you need to write one method that implements a point inside polygon algorithm.

This method will take an array with N points (the polygon) as an argument and one specific point. It should return true if the point is inside the polygon and false if not.

See this great answer on S.O.




回答3:


Here is the implementation in 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
    }
}



回答4:


Swift 3

A simpler way using Swift 3, is using UIBezierPath contains method.

When creating an instance of CAShapeLayer, make sure to set the accessibilityPath

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

Checking if path contains touch location.

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


来源:https://stackoverflow.com/questions/8952476/detect-if-cgpoint-within-polygon

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!