iphone - guide - objective c documentation
Detectar si CGPoint dentro de polĂgono (4)
Tengo un conjunto de CGPoints que forman una forma poligonal, ¿cómo puedo detectar si un solo CGPoint está dentro o fuera del polígono?
Por ejemplo, la forma era un triángulo y el CGPoint se movía en forma horizontal, ¿cómo podía detectar cuándo cruzaba la línea del triángulo?
Puedo usar CGRectContainsPoint
cuando la forma es una forma regular de 4 lados pero no puedo ver cómo lo haría con una forma extraña.
Swift 3
Una forma más sencilla de usar Swift 3, es usar el método UIBezierPath
contains
.
Al crear una instancia de CAShapeLayer
, asegúrese de establecer la accessibilityPath
shapeLayer.path = bazierPath.cgPath
shapeLayer.accessibilityPath = bazierPath
Comprobando si la ruta contiene la ubicación táctil.
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))
}
}
Aquí está la implementación en 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
}
}
Para eso necesitas escribir un método que implemente un punto dentro del algoritmo de polígono.
Este método tomará una matriz con N puntos (el polígono) como un argumento y un punto específico. Debería devolver true si el punto está dentro del polígono y false si no lo está.
Puede crear un CG(Mutable)PathRef
(o un UIBezierPath
que envuelve un CGPathRef
) a partir de sus puntos y usar la función CGPathContainsPoint
para verificar si un punto está dentro de esa ruta. Si usas UIBezierPath
, también podrías usar el método UIBezierPath
containsPoint:
.