Обнаружить, если CGPoint в полигоне - программирование
Подтвердить что ты не робот

Обнаружить, если CGPoint в полигоне

У меня есть набор CGPoints, которые составляют форму многоугольника, как я могу определить, находится ли один CGPoint внутри или вне многоугольника?

Скажем, форма была треугольником, а CGPoint двигался горизонтально, как я мог обнаружить, когда она пересекла линию треугольника?

Я могу использовать CGRectContainsPoint, когда форма является обычной 4-сторонней формой, но я не вижу, как бы я сделал это с нечетной формой.

4b9b3361

Ответ 1

Вы можете создать CG(Mutable)PathRef (или UIBezierPath, который обертывает CGPathRef) из ваших точек, и использовать CGPathContainsPoint, чтобы проверить, находится ли точка внутри этого пути. Если вы используете UIBezierPath, вы также можете использовать метод containsPoint:.

Ответ 2

Для этого вам нужно написать один метод, реализующий точку внутри алгоритма многоугольника.

Этот метод будет принимать массив с N точками (полигон) в качестве аргумента и одной конкретной точки. Он должен возвращать true, если точка находится внутри полигона, а false, если нет.

Посмотрите на этот отличный ответ на S.O.

Ответ 3

Вот реализация в 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

Простейший способ использования 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))
    }
}