How can I determine whether a 2D Point is within a Polygon?

前端 未结 30 2084
醉梦人生
醉梦人生 2020-11-21 05:06

I\'m trying to create a fast 2D point inside polygon algorithm, for use in hit-testing (e.g. Polygon.contains(p:Point)). Suggestions for effective tech

30条回答
  •  轻奢々
    轻奢々 (楼主)
    2020-11-21 05:58

    VBA VERSION:

    Note: Remember that if your polygon is an area within a map that Latitude/Longitude are Y/X values as opposed to X/Y (Latitude = Y, Longitude = X) due to from what I understand are historical implications from way back when Longitude was not a measurement.

    CLASS MODULE: CPoint

    Private pXValue As Double
    Private pYValue As Double
    
    '''''X Value Property'''''
    
    Public Property Get X() As Double
        X = pXValue
    End Property
    
    Public Property Let X(Value As Double)
        pXValue = Value
    End Property
    
    '''''Y Value Property'''''
    
    Public Property Get Y() As Double
        Y = pYValue
    End Property
    
    Public Property Let Y(Value As Double)
        pYValue = Value
    End Property
    

    MODULE:

    Public Function isPointInPolygon(p As CPoint, polygon() As CPoint) As Boolean
    
        Dim i As Integer
        Dim j As Integer
        Dim q As Object
        Dim minX As Double
        Dim maxX As Double
        Dim minY As Double
        Dim maxY As Double
        minX = polygon(0).X
        maxX = polygon(0).X
        minY = polygon(0).Y
        maxY = polygon(0).Y
    
        For i = 1 To UBound(polygon)
            Set q = polygon(i)
            minX = vbMin(q.X, minX)
            maxX = vbMax(q.X, maxX)
            minY = vbMin(q.Y, minY)
            maxY = vbMax(q.Y, maxY)
        Next i
    
        If p.X < minX Or p.X > maxX Or p.Y < minY Or p.Y > maxY Then
            isPointInPolygon = False
            Exit Function
        End If
    
    
        ' SOURCE: http://www.ecse.rpi.edu/Homepages/wrf/Research/Short_Notes/pnpoly.html
    
        isPointInPolygon = False
        i = 0
        j = UBound(polygon)
    
        Do While i < UBound(polygon) + 1
            If (polygon(i).Y > p.Y) Then
                If (polygon(j).Y < p.Y) Then
                    If p.X < (polygon(j).X - polygon(i).X) * (p.Y - polygon(i).Y) / (polygon(j).Y - polygon(i).Y) + polygon(i).X Then
                        isPointInPolygon = True
                        Exit Function
                    End If
                End If
            ElseIf (polygon(i).Y < p.Y) Then
                If (polygon(j).Y > p.Y) Then
                    If p.X < (polygon(j).X - polygon(i).X) * (p.Y - polygon(i).Y) / (polygon(j).Y - polygon(i).Y) + polygon(i).X Then
                        isPointInPolygon = True
                        Exit Function
                    End If
                End If
            End If
            j = i
            i = i + 1
        Loop   
    End Function
    
    Function vbMax(n1, n2) As Double
        vbMax = IIf(n1 > n2, n1, n2)
    End Function
    
    Function vbMin(n1, n2) As Double
        vbMin = IIf(n1 > n2, n2, n1)
    End Function
    
    
    Sub TestPointInPolygon()
    
        Dim i As Integer
        Dim InPolygon As Boolean
    
    '   MARKER Object
        Dim p As CPoint
        Set p = New CPoint
        p.X = 
        p.Y = 
    
    '   POLYGON OBJECT
        Dim polygon() As CPoint
        ReDim polygon() 'Amount of vertices in polygon - 1
        For i = 0 To  'Same value as above
           Set polygon(i) = New CPoint
           polygon(i).X =  'Source a list of values that can be looped through
           polgyon(i).Y =  'Source a list of values that can be looped through
        Next i
    
        InPolygon = isPointInPolygon(p, polygon)
        MsgBox InPolygon
    
    End Sub
    

提交回复
热议问题