2012-01-21 13 views
16

Ho una serie di punti CGP che formano una forma poligonale, come posso rilevare se un singolo CGPoint è all'interno o all'esterno del poligono?Rileva se CGPoint all'interno del poligono

Supponiamo che la forma fosse un triangolo e che il CGPoint si muovesse orizzontalmente, come avrei potuto rilevare quando ha attraversato la linea del triangolo?

Posso usare CGRectContainsPoint quando la forma è una normale forma a 4 lati, ma non riesco a vedere come lo farei con una forma strana.

risposta

27

È possibile creare un CG(Mutable)PathRef (o un UIBezierPath che avvolge una CGPathRef) dai punti e utilizzare la funzione CGPathContainsPoint per verificare se un punto è all'interno di quel percorso. Se si utilizza UIBezierPath, è anche possibile utilizzare il metodo containsPoint:.

+0

Grazie! Era esattamente quello che stavo cercando! – JWood

2

Per questo è necessario scrivere un metodo che implementa un punto all'interno dell'algoritmo poligono.

Questo metodo richiederà un array con N punti (il poligono) come argomento e un punto specifico. Dovrebbe restituire true se il punto è all'interno del poligono e falso se non lo è.

See this great answer on S.O.

0

Qui è l'implementazione a 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 
    } 
} 
0

Swift 3

Un modo più semplice usando Swift 3, sta utilizzando UIBezierPathcontains metodo.

Quando si crea un'istanza di CAShapeLayer, assicurarsi di impostare il accessibilityPath

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

Verificando percorso contiene posizione tocco.

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