检测 CGPoint 是不是在多边形内

Posted

技术标签:

【中文标题】检测 CGPoint 是不是在多边形内【英文标题】:Detect if CGPoint within polygon检测 CGPoint 是否在多边形内 【发布时间】:2012-01-21 11:05:40 【问题描述】:

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

说,形状是三角形,而 CGPoint 是水平移动的,我如何检测它何时越过三角形线?

当形状是常规的 4 面形状时,我可以使用 CGRectContainsPoint,但我不知道如何处理奇怪的形状。

【问题讨论】:

【参考方案1】:

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

【讨论】:

谢谢!这正是我想要的!【参考方案2】:

为此,您需要编写一种方法来实现多边形内的点算法。

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

See this great answer on S.O.

【讨论】:

【参考方案3】:

这是 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
    

【讨论】:

【参考方案4】:

斯威夫特 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))
    

【讨论】:

以上是关于检测 CGPoint 是不是在多边形内的主要内容,如果未能解决你的问题,请参考以下文章

如何检查一个圆是不是位于凸多边形内

哪个是检查用户位置(android 应用程序)是不是在多边形内的更好方法

如何使用谷歌地图检测一个点在多边形内?

怎么判断一个点是不是在多边形区域内

检查点是不是在多边形内

确定给定点是不是在多边形内