2012-01-21 38 views
16

Tôi có một tập hợp các điểm CGPoint tạo thành một hình đa giác, làm cách nào tôi có thể phát hiện xem một CGPoint đơn có nằm trong hoặc ngoài đa giác không?Phát hiện nếu CGPoint trong đa giác

Giả sử hình dạng là hình tam giác và CGPoint đang di chuyển hoizontally, làm thế nào tôi có thể phát hiện khi nó vượt qua đường tam giác?

Tôi có thể sử dụng CGRectContainsPoint khi hình dạng là hình dạng 4 mặt thông thường nhưng tôi không thể thấy cách tôi sẽ làm điều đó với hình dạng kỳ lạ.

Trả lời

27

Bạn có thể tạo CG(Mutable)PathRef (hoặc UIBezierPath kết thúc tốt đẹp CGPathRef) từ các điểm của bạn và sử dụng chức năng CGPathContainsPoint để kiểm tra xem một điểm có nằm trong đường dẫn đó hay không. Nếu bạn sử dụng UIBezierPath, bạn cũng có thể sử dụng phương thức containsPoint:.

+0

Cảm ơn! Đó chính xác là những gì tôi đang tìm kiếm! – JWood

2

Đối với điều đó, bạn cần phải viết một phương pháp thực hiện một điểm bên trong thuật toán đa giác.

Phương pháp này sẽ lấy một mảng có N điểm (đa giác) làm đối số và một điểm cụ thể. Nó sẽ trả về true nếu điểm nằm trong đa giác và false nếu không.

See this great answer on S.O.

0

Đây là việc thực hiện ở 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

Một cách đơn giản sử dụng Swift 3, đang sử dụng UIBezierPathcontains phương pháp.

Khi tạo một thể hiện của CAShapeLayer, hãy chắc chắn để thiết lập accessibilityPath

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

Kiểm tra nếu đường dẫn chứa vị trí cảm ứng.

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)) 
    } 
} 
Các vấn đề liên quan