Detect if a set of points in an array that are the vertices of a complex polygon were defined in a clockwise or counterclockwise order?

前端 未结 5 1004
说谎
说谎 2021-02-07 05:57

EDIT: I updated the program with the answer and it works great!

I am making a program (feel free to try it out) that lets users draw polygons which it then triangulates.

相关标签:
5条回答
  • 2021-02-07 06:33

    A general idea would be to take a look at the convex hull of your polygone and guess the orientation from there. However, I think that you do not need to build the whole hull to find the orientation, but just one segment belonging to it.

    So:

    • Find two points of your polygones so that all the other points are on one side of this line.
    • If all the points are on the left (just check one of the points), it's counterclockwise. If they are on the right, it's clockwise.

    Example:

    On the top figure: 4-5 let the figure on the right, 5-11 let the figure on the right, ... On the bottom figure: 6-7 let the figure on the left, 7-14 let the figure on the left, ...

    Warning: While "walking" on your polygon, do not restart the numeration, otherwise it will be wrong. On the top figure, 4-(n-1) let the figure on the left!

    0 讨论(0)
  • 2021-02-07 06:33

    Your intuitive definition of clockwisedness is not well defined. For example, If I draw a horseshoe:

       /---a-b--\
      /   _d_c_  \
     /  /       \ \
     | |        | |
     | |        | |
      \ \       / /
       \ \     / /
        --     --
    

    If 0 = a < b < b < d and I look at a and b I would conclude from your description that the shape has been drawn clockwise, but if 0 = c < d < a < b I would conclude that the shape has been drawn anticlockwise. Since both of these scenarios involve the same direction in which the points were drawn, just from different starting points, I can only conclude that your definition is lacking.

    The horseshoe I drew isn't the best; the idea is that it is almost a circle with just a small hole at the bottom, to allow the other side to be drawn in the opposite direction.

    If you are interested in defining things more strictly, then I suggest something along the following lines:

    Considering any finite simple polygon as separating the plane into two distinct areas (one finite and one infinite), we can always consider the finite area to be the interior of the polygon. In such a scenario we define a vertex ordering to be clockwise iff the order of the points runs with the exterior along its right-hand side. This is called curve orientation.

    Once you have this more solid definition, implementation can be as simple as counting the winding number. Take the midpoint of any ordered pair, say 0 and 1, take a line segment to the right of the ordered pair (at any angle, say perpendicular), and count how many intersections it has with other line segments: The curve is clockwise iff the number is odd.

    This is simple to implement, linear in time O(n), and adds constant space O(1).

    0 讨论(0)
  • In case someone is using three.js the ShapeUtils comes with an inbuilt isClockWise method which internally uses the area method to determine the sign of the calculated area.

    isClockWise: function ( pts ) {
    
        return ShapeUtils.area( pts ) < 0;
    
    }
    

    The ShapeUtils.isClockWise Method can be found here.

    area: function ( contour ) {
    
        var n = contour.length;
        var a = 0.0;
    
        for ( var p = n - 1, q = 0; q < n; p = q ++ ) {
    
            a += contour[ p ].x * contour[ q ].y - contour[ q ].x * contour[ p ].y;
    
        }
    
        return a * 0.5;
    
    },
    

    The ShapeUtils.area Method can be found here.

    0 讨论(0)
  • 2021-02-07 06:38

    Compute the polygon area using the shoelace formula, but without the absolute value sign. If the result is positive, the points are ordered counterclockwise, and if negative - clockwise.

    function polygonArea() { 
        var area = 0;
        for (var i = 0; i < vertices.length; i++) {
            j = (i + 1) % vertices.length;
            area += vertices[i].x * vertices[j].y;
            area -= vertices[j].x * vertices[i].y;
        }
        return area / 2;
    }
    var clockwise = polygonArea() > 0;
    
    0 讨论(0)
  • 2021-02-07 06:46

    This a function function that specialized for OpenLayers. As You Can See The Condition Of Clockwise Polygon Is area<0 This Reference Confirm It.

    function IsClockwise(feature)
    {
    if(feature.geometry==null)return -1;
    var vertices=feature.geometry.getVertices();
    var area=0;
    for (var i = 0; i < (vertices.length); i++) 
        {
        j = (i + 1) % vertices.length;
        area += vertices[i].x * vertices[j].y;
        area -= vertices[j].x * vertices[i].y;
        // console.log(area);
        }
    return (area < 0);
    }
    
    0 讨论(0)
提交回复
热议问题