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

后端 未结 8 720
青春惊慌失措
青春惊慌失措 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

    fortran's answer almost worked for me except I found I had to translate the polygon so that the point you're testing is the same as the origin. Here is the JavaScript that I wrote to make this work:

    function Vec2(x, y) {
      return [x, y]
    }
    Vec2.nsub = function (v1, v2) {
      return Vec2(v1[0]-v2[0], v1[1]-v2[1])
    }
    // aka the "scalar cross product"
    Vec2.perpdot = function (v1, v2) {
      return v1[0]*v2[1] - v1[1]*v2[0]
    }
    
    // Determine if a point is inside a polygon.
    //
    // point     - A Vec2 (2-element Array).
    // polyVerts - Array of Vec2's (2-element Arrays). The vertices that make
    //             up the polygon, in clockwise order around the polygon.
    //
    function coordsAreInside(point, polyVerts) {
      var i, len, v1, v2, edge, x
      // First translate the polygon so that `point` is the origin. Then, for each
      // edge, get the angle between two vectors: 1) the edge vector and 2) the
      // vector of the first vertex of the edge. If all of the angles are the same
      // sign (which is negative since they will be counter-clockwise) then the
      // point is inside the polygon; otherwise, the point is outside.
      for (i = 0, len = polyVerts.length; i < len; i++) {
        v1 = Vec2.nsub(polyVerts[i], point)
        v2 = Vec2.nsub(polyVerts[i+1 > len-1 ? 0 : i+1], point)
        edge = Vec2.nsub(v1, v2)
        // Note that we could also do this by using the normal + dot product
        x = Vec2.perpdot(edge, v1)
        // If the point lies directly on an edge then count it as in the polygon
        if (x < 0) { return false }
      }
      return true
    }
    

提交回复
热议问题