How to determine if a point is inside a 2D convex polygon?

后端 未结 8 1786
别那么骄傲
别那么骄傲 2020-11-27 12:58

I have a convex polygon (typically just a rotated square), and I know all of 4 points. How do I determine if a given point (yellow/green) is inside the polygon?

相关标签:
8条回答
  • 2020-11-27 13:49

    For those who would like to understand how the method written by Dean Povey above works, here is the explanation:

    The method looks at a "ray" that starts at the tested spot and extends to infinity to the right side of the X axis. For each polygon segment, it checks if the ray crosses it. If the total number of segment crossing is odd then the tested point is considered inside the polygon, otherwise - it is outside.

    To understand the way the crossing is calculated, consider the following figure:

                v2
                o
               /
              / c (intersection)
    o--------x----------------------> to infinity
    t       /
           /   
          /
         o
         v1
    

    For the intersection to occur, tested.y must be between the y values of the segment's vertices (v1 and v2). This is the first condition of the if statement in the method. If this is what happens, then the horizontal line must intersect the segment. It only remains to establish whether the intersection happens to the right of the tested point or to the left of it. This requires finding the x coordinate of the intersection point, which is:

                  t.y - v1.y
    c.x = v1.x + ----------- * (v2.x - v1.x)
                 v2.y - v1.y
    

    All that remains to be done is examining the subtleties:

    • If v1.y == v2.y then the ray goes along the segment and therefore the segment has no influence on the outcome. Indeed, the first part of the if statement returns false in that case.
    • The code first multiplies and only then divides. This is done to support very small differences between v1.x and v2.x, which might lead to a zero after the division, due to rounding.
    • Finally, the problem of crossing exactly on a vertex should be addressed. Consider the following two cases:
             o                    o
             |                     \     o
             | A1                C1 \   /
             |                       \ / C2  
    o--------x-----------x------------x--------> to infinity
            /           / \
        A2 /        B1 /   \ B2
          /           /     \ 
         o           /       o
                    o
    

    Now, to verify if it works, check for yourself what is returned for each of the 4 segments by the if condition in the method body. You should find that the segments above the ray (A1, C1, C2) receive a positive result, while those below it (A2, B1, B2) receive a negative one. This means that the A vertex contributes an odd number (1) to the crossing count, while B and C contribute an even number (0 and 2, respectively), which is exactly what is desired. A is indeed a real crossing of the polygon, while B and C are just two cases of "fly-by".

    0 讨论(0)
  • 2020-11-27 13:53

    Polygon's abscissas x_array: Array[Integer]

    Polygon's ordinates: y_array: Array[Integer]

    Point: x: Integer, y: Integer

    import java.awt.Polygon
    import java.awt.Point
    ...
    
    final boolean isInPolygon = 
        new Polygon(x_array,y_array,x_array.length).contains(new Point(x, y));
    

    In this example we create an object java.awt.Polygon and use the method contains to check if your coordinates are in the shape you designed.

    I use the object java.awt.Point to represent the coordinates to make the code elegant but that is optional, you can directly use .contains(x, y)

    0 讨论(0)
提交回复
热议问题