How to test if a point is inside of a convex polygon in 2D integer coordinates?

后端 未结 8 717
青春惊慌失措
青春惊慌失措 2020-11-30 04:05

The polygon is given as a list of Vector2I objects (2 dimensional, integer coordinates). How can i test if a given point is inside? All implementations i found on the web fa

8条回答
  •  感情败类
    2020-11-30 04:33

    You have to check that the point to test maintains it's orientation relative to all segments of the convex polygon. If so, it's inside. To do this for each segment check if the determinant of the segment vector say AB and the point's vector say AP preserves it's sign. If the determinant is zero than the point is on the segment.

    To expose this in C# code,

      public bool IsPointInConvexPolygon(...)
      {
         Point pointToTest = new Point(...);
         Point pointA = new Point(...);
         ....
    
         var polygon = new List { pointA, pointB, pointC, pointD ... };
         double prevPosition = 0;
         // assuming polygon is convex.
         for (var i = 0; i < polygon.Count; i++)
         {
            var startPointSegment = polygon[i];
            // end point is first point if the start point is the last point in the list
            // (closing the polygon)
            var endPointSegment = polygon[i < polygon.Count - 1 ? i + 1 : 0];
            if (pointToTest.HasEqualCoordValues(startPointSegment) ||
                pointToTest.HasEqualCoordValues(endPointSegment))
              return true;
    
            var position = GetPositionRelativeToSegment(pointToTest, startPointSegment, endPointSegment);
            if (position == 0) // point position is zero so we are on the segment, we're on the polygon.
               return true;
    
            // after we checked the test point's position relative to the first segment, the position of the point 
            // relative to all other segments must be the same as the first position. If not it means the point 
            // is not inside the convex polygon.
            if (i > 0 && prevPosition != position)
               return false;
    
            prevPosition = position;
         }
         return true; 
      }
    

    The determinant calculus,

      public double GetPositionRelativeToSegment(Point pointToTest, Point segmentStart, Point segmentEnd)
      {
         return Math.Sign((pointToTest.X - segmentStart.X) * (segmentEnd.Y - segmentStart.Y) -
                    (pointToTest.Y - segmentStart.Y) * (segmentEnd.X - segmentStart.X));
      }
    

提交回复
热议问题