亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 學院 > 開發設計 > 正文

Determiningifapointliesontheinteriorofapolygon

2019-11-14 13:41:17
字體:
來源:轉載
供稿:網友

Determining if a point lies on the interior of a polygon

Written by Paul Bourke  November 1987

Solution 1 (2D)

The following is a simple solution to the PRoblem often encountered in computer graphics, determining whether or not a point (x,y) lies inside or outside a 2D polygonally bounded plane. This is necessary for example in applications such as polygon filling on raster devices, hatching in drafting software, and determining the intersection of multiple polygons.

Consider a polygon made up of N vertices (xi,yi) where i ranges from 0 to N-1. The last vertex (xN,yN) is assumed to be the same as the first vertex (x0,y0), that is, the polygon is closed. To determine the status of a point (xp,yp) consider a horizontal ray emanating from (xp,yp) and to the right. If the number of times this ray intersects the line segments making up the polygon is even then the point is outside the polygon. Whereas if the number of intersections is odd then the point (xp,yp) lies inside the polygon. The following shows the ray for some sample points and should make the technique clear.

 

Note: for the purposes of this discussion 0 will be considered even, the test for even or odd will be based on modulus 2, that is, if the number of intersections modulus 2 is 0 then the number is even, if it is 1 then it is odd.

The only trick is what happens in the special cases when an edge or vertex of the polygon lies on the ray from (xp,yp). The possible situations are illustrated below.

 

The thick lines above are not considered as valid intersections, the thin lines do count as intersections. Ignoring the case of an edge lying along the ray or an edge ending on the ray ensures that the endpoints are only counted once.

Note that this algorithm also works for polygons with holes as illustrated below

 

The following C function returns INSIDE or OUTSIDE indicating the status of a point P with respect to a polygon with N points.

#define MIN(x,y) (x < y ? x : y)#define MAX(x,y) (x > y ? x : y)#define INSIDE 0#define OUTSIDE 1typedef struct {   double x,y;} Point;int InsidePolygon(Point *polygon,int N,Point p){  int counter = 0;  int i;  double xinters;  Point p1,p2;  p1 = polygon[0];  for (i=1;i<=N;i++) {    p2 = polygon[i % N];    if (p.y > MIN(p1.y,p2.y)) {      if (p.y <= MAX(p1.y,p2.y)) {        if (p.x <= MAX(p1.x,p2.x)) {          if (p1.y != p2.y) {            xinters = (p.y-p1.y)*(p2.x-p1.x)/(p2.y-p1.y)+p1.x;            if (p1.x == p2.x || p.x <= xinters)              counter++;          }        }      }    }    p1 = p2;  }  if (counter % 2 == 0)    return(OUTSIDE);  else    return(INSIDE);}

The following code is by Randolph Franklin, it returns 1 for interior points and 0 for exterior points.

    int pnpoly(int npol, float *xp, float *yp, float x, float y)    {      int i, j, c = 0;      for (i = 0, j = npol-1; i < npol; j = i++) {        if ((((yp[i] <= y) && (y < yp[j])) ||             ((yp[j] <= y) && (y < yp[i]))) &&            (x < (xp[j] - xp[i]) * (y - yp[i]) / (yp[j] - yp[i]) + xp[i]))          c = !c;      }      return c;    }

Contribution by Alexander Motrichuk: 

//SOLUTION #1 (2D) - Redesigned#define MIN(x,y) (x < y ? x : y)#define MAX(x,y) (x > y ? x : y)#define INSIDE    1#define OUTSIDE   0struct Point{    Point() : x(.0), y(.0) {};    Point(double x1, double y1) : x(x1), y(y1) {};    bool Operator==(const Point& _right)    {        return x == _right.x && y == _right.y;    };    double x, y;};//horizintal left cross over direction algorithm//-----------------------------------------------//  bound   |   value that will be returned only if (p) lies on the bound or vertexint InsidePolygon(Point* polygon, int N, Point p, int bound){    //cross points count of x    int __count = 0;    //neighbour bound vertices    Point p1, p2;    //left vertex    p1 = polygon[0];    //check all rays    for(int i = 1; i <= N; ++i)    {        //point is an vertex        if(p == p1) return bound;        //right vertex        p2 = polygon[i % N];        //ray is outside of our interests        if(p.y < MIN(p1.y, p2.y) || p.y > MAX(p1.y, p2.y))        {            //next ray left point            p1 = p2; continue;        }        //ray is crossing over by the algorithm (common part of)        if(p.y > MIN(p1.y, p2.y) && p.y < MAX(p1.y, p2.y))        {            //x is before of ray            if(p.x <= MAX(p1.x, p2.x))            {                //overlies on a horizontal ray                if(p1.y == p2.y && p.x >= MIN(p1.x, p2.x)) return bound;                //ray is vertical                if(p1.x == p2.x)                {                    //overlies on a ray                    if(p1.x == p.x) return bound;                    //before ray                    else ++__count;                }                //cross point on the left side                else                {                    //cross point of x                    double xinters = (p.y - p1.y) * (p2.x - p1.x) / (p2.y - p1.y) + p1.x;                    //overlies on a ray                    if(fabs(p.x - xinters) < __DBL_EPSILON__) return bound;                    //before ray                    if(p.x < xinters) ++__count;                }            }        }        //special case when ray is crossing through the vertex        else        {            //p crossing over p2            if(p.y == p2.y && p.x <= p2.x)            {                //next vertex                const Point& p3 = polygon[(i+1) % N];                //p.y lies between p1.y & p3.y                if(p.y >= MIN(p1.y, p3.y) && p.y <= MAX(p1.y, p3.y))                {                    ++__count;                }                else                {                    __count += 2;                }            }        }        //next ray left point        p1 = p2;    }    //EVEN    if(__count % 2 == 0) return(OUTSIDE);    //ODD    else return(INSIDE);}
View Code

 

Quote: "For most of the algorithms above there is a pathological case if the point being queried lies exactly on a vertex. The easiest way to cope with this is to test that as a separate process and make your own decision as to whether you want to consider them inside or outside."

Contribution in VBA by Giuseppe Iaria: 

'---------------------------------------------------------------------------------------------------------'************************************ Function InsidePolygon *************************************'---------------------------------------------------------------------------------------------------------'VBA implementation of the theory provided by Paul Bourke (http://paulbourke.net/geometry/polygonmesh/)'author: ing. Giuseppe Iaria - rev. 20/08/2014'---------------------------------------------------------------------------------------------------------'The function is based on Solution 1 (2D)'The function determines if a point P lies inside or outside a Polygon, returning "True" or "False"'The points are defined through the user-defined type "Point"'The Polygon is an array of points, each being a user-defined type "Point"'The Polygon is implemented assuming a "Base 1" condition, so the "Option Base 1" statement is required'The optional argument "OnPolygonBorder" deals with these special cases:' - P lies on a vertex of the Polygon' - P lies on a line segment of the Polygon'If omitted or passed as "False", and a special case occurs, then the function returns "False"'If passed as "True", and a special case occurs, then the function returns "True"'Auxiliary functions used:' - DistancePointSegment: determines the distance between a point and a line segment' - Distance2Point: determines the distance between two points'Both the auxiliary functions have been developed on:' - the theory by Paul Bourke (http://paulbourke.net/geometry/pointlineplane/)' - an original VBA code by Brandon Crosby (http://paulbourke.net/geometry/pointlineplane/source.vba)'---------------------------------------------------------------------------------------------------------Option Base 1Public Type Point    x As Double    y As DoubleEnd TypePublic Function InsidePolygon(Polygon() As Point, P As Point, Optional ByVal OnPolygonBorder As Boolean) As BooleanDim counter As Integer, i As Integer, ip1 As IntegerDim xInters As Double, dist As DoubleConst EPS As Single = 0.0001'Check if the point lies on a polygon's vertex or line segmentFor i = 1 To UBound(Polygon)    ip1 = i Mod UBound(Polygon) + 1    dist = DistancePointSegment(P, Polygon(i), Polygon(ip1))    If dist < EPS Then        If OnPolygonBorder Then            InsidePolygon = True            Else            InsidePolygon = False        End If        Exit Function    End If    Next i'Determine the numbers of intersection between the orizzontal ray from point and polygonFor i = 1 To UBound(Polygon)    ip1 = i Mod UBound(Polygon) + 1    If P.y > IIf(Polygon(i).y < Polygon(ip1).y, Polygon(i).y, Polygon(ip1).y) Then        If P.y <= IIf(Polygon(i).y > Polygon(ip1).y, Polygon(i).y, Polygon(ip1).y) Then            If P.x <= IIf(Polygon(i).x > Polygon(ip1).x, Polygon(i).x, Polygon(ip1).x) Then                If Polygon(i).y <> Polygon(ip1).y Then                    xInters = Polygon(i).x + (Polygon(ip1).x - Polygon(i).x) * (P.y - Polygon(i).y) / (Polygon(ip1).y - Polygon(i).y)                    If (Polygon(i).x = Polygon(ip1).x) Or (P.x <= xInters) Then counter = counter + 1                End If            End If        End If    End If    Next iIf counter Mod 2 = 0 Then InsidePolygon = False Else InsidePolygon = TrueEnd FunctionPrivate Function DistancePointSegment(P As Point, P1 As Point, P2 As Point) As DoubleDim LineMag As Double, u As DoubleDim d1 As Double, d2 As DoubleDim Pint As PointConst EPS As Single = 0.0001LineMag = Distance2Point(P1, P2)If LineMag < EPS Then Exit Functionu = (((P.x - P1.x) * (P2.x - P1.x)) + ((P.y - P1.y) * (P2.y - P1.y))) / LineMag ^ 2If u < 0 Or u > 1 Then    d1 = Distance2Point(P, P1)    d2 = Distance2Point(P, P2)    If d1 > d2 Then DistancePointSegment = d2 Else DistancePointSegment = d1    Else    Pint.x = P1.x + u * (P2.x - P1.x)    Pint.y = P1.y + u * (P2.y - P1.y)    DistancePointSegment = Distance2Point(P, Pint)End IfEnd FunctionPrivate Function Distance2Point(P1 As Point, P2 As Point) As DoubleDistance2Point = Sqr((P2.x - P1.x) ^ 2 + (P2.y - P1.y) ^ 2)End Function
View Code

 

Contribution written in c# by Jerry Knauss: 

public static bool Contains( Point[] points, Point p ) {   bool result = false;   for( int i = 0; i < points.Length - 1; i++ )   {      if( ( ( ( points[ i + 1 ].Y <= p.Y ) && ( p.Y < points[ i ].Y ) ) || ( ( points[ i ].Y <= p.Y ) && ( p.Y < points[ i + 1 ].Y ) ) ) && ( p.X < ( points[ i ].X - points[ i + 1 ].X ) * ( p.Y - points[ i + 1 ].Y ) / ( points[ i ].Y - points[ i + 1 ].Y ) + points[ i + 1 ].X ) )      {         result = !result;      }   }   return result;}
View Code

 

Solution 2 (2D)

Another solution forwarded by Philippe Reverdy is to compute the sum of the angles made between the test point and each pair of points making up the polygon. If this sum is 2pi then the point is an interior point, if 0 then the point is an exterior point. This also works for polygons with holes given the polygon is defined with a path made up of coincident edges into and out of the hole as is common practice in many CAD packages.

The inside/outside test might then be defined in C as

typedef struct {   int h,v;} Point;int InsidePolygon(Point *polygon,int n,Point p){   int i;   double angle=0;   Point p1,p2;   for (i=0;i<n;i++) {      p1.h = polygon[i].h - p.h;      p1.v = polygon[i].v - p.v;      p2.h = polygon[(i+1)%n].h - p.h;      p2.v = polygon[(i+1)%n].v - p.v;      angle += Angle2D(p1.h,p1.v,p2.h,p2.v);   }   if (ABS(angle) < PI)      return(FALSE);   else      return(TRUE);}/*   Return the angle between two vectors on a plane   The angle is from vector 1 to vector 2, positive anticlockwise   The result is between -pi -> pi*/double Angle2D(double x1, double y1, double x2, double y2){   double dtheta,theta1,theta2;   theta1 = atan2(y1,x1);   theta2 = atan2(y2,x2);   dtheta = theta2 - theta1;   while (dtheta > PI)      dtheta -= TWOPI;   while (dtheta < -PI)      dtheta += TWOPI;   return(dtheta);}

Solution 3 (2D)

There are other solutions to this problem for polygons with special attributes. If the polygon is convex then one can consider the polygon as a "path" from the first vertex. A point is on the interior of this polygons if it is always on the same side of all the line segments making up the path.

Given a line segment between P0 (x0,y0) and P1 (x1,y1), another point P (x,y) has the following relationship to the line segment.

Compute 

(y - y0) (x1 - x0) - (x - x0) (y1 - y0)

 

if it is less than 0 then P is to the right of the line segment, if greater than 0 it is to the left, if equal to 0 then it lies on the line segment.

Solution 4 (3D)

This solution was motivated by solution 2 and correspondence with Reinier van Vliet and Remco Lam. To determine whether a point is on the interior of a convex polygon in 3D one might be tempted to first determine whether the point is on the plane, then determine it's interior status. Both of these can be accomplished at once by computing the sum of the angles between the test point (q below) and every pair of edge points p[i]->p[i+1]. This sum will only be 2pi if both the point is on the plane of the polygon AND on the interior. The angle sum will tend to 0 the further away from the polygon point q becomes.

The following code snippet returns the angle sum between the test point q and all the vertex pairs. Note that the angle sum is returned in radians.

typedef struct {   double x,y,z;} XYZ;#define EPSILON  0.0000001#define MODULUS(p) (sqrt(p.x*p.x + p.y*p.y + p.z*p.z))#define TWOPI 6.283185307179586476925287#define RTOD 57.2957795double CalcAngleSum(XYZ q,XYZ *p,int n){   int i;   double m1,m2;   double anglesum=0,costheta;   XYZ p1,p2;   for (i=0;i<n;i++) {      p1.x = p[i].x - q.x;      p1.y = p[i].y - q.y;      p1.z = p[i].z - q.z;      p2.x = p[(i+1)%n].x - q.x;      p2.y = p[(i+1)%n].y - q.y;      p2.z = p[(i+1)%n].z - q.z;      m1 = MODULUS(p1);      m2 = MODULUS(p2);      if (m1*m2 <= EPSILON)         return(TWOPI); /* We are on a node, consider this inside */      else         costheta = (p1.x*p2.x + p1.y*p2.y + p1.z*p2.z) / (m1*m2);      anglesum += acos(costheta);   }   return(anglesum);}

Note

For most of the algorithms above there is a pathological case if the point being queries lies exactly on a vertex. The easiest way to cope with this is to test that as a separate process and make your own decision as to whether you want to consider them inside or outside.


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
亚洲欧美激情在线视频| 在线播放日韩av| 黄网站色欧美视频| 欧美一区深夜视频| 高清欧美性猛交xxxx黑人猛交| www.美女亚洲精品| 午夜精品一区二区三区在线| 91九色蝌蚪国产| 97久久久免费福利网址| 国产精品久久久久久久9999| 91在线观看免费网站| yw.139尤物在线精品视频| 国产精品久久一区| 美女性感视频久久久| 欧美男插女视频| 色综合久综合久久综合久鬼88| 亚洲精品国偷自产在线99热| 91麻豆国产语对白在线观看| 欧美性开放视频| 国产精品福利网站| 亚洲精品中文字| 欧美大人香蕉在线| 欧美午夜片欧美片在线观看| 中文字幕欧美在线| 亚洲人成电影网站色| 国产视频精品在线| 久久久精品国产网站| 欧美激情奇米色| 亚洲一区二区在线播放| 精品国产欧美成人夜夜嗨| 久久精品国产亚洲一区二区| 2018日韩中文字幕| 亚洲白虎美女被爆操| 日韩精品有码在线观看| 久久亚洲国产精品成人av秋霞| 欧美成年人视频| 色综合视频一区中文字幕| 欧美亚洲国产视频小说| 欧美裸体视频网站| 国产suv精品一区二区| 久久久www成人免费精品| 国产午夜一区二区| 97精品国产97久久久久久春色| 亚洲一二在线观看| 日韩av片电影专区| 欧美激情视频免费观看| 欧美一级淫片播放口| 日韩国产一区三区| 亚洲天堂男人天堂女人天堂| 日韩经典第一页| 日韩免费不卡av| 国产视频自拍一区| 亚洲级视频在线观看免费1级| 麻豆国产精品va在线观看不卡| 日韩在线播放视频| 欧美日韩综合视频网址| 538国产精品一区二区免费视频| 成人h猎奇视频网站| 国内精品小视频在线观看| 精品久久久精品| 欧美日韩在线视频一区二区| 日韩欧美大尺度| 欧美丰满少妇xxxxx做受| 亚洲综合色激情五月| 欧美成人久久久| 91成人免费观看网站| 在线观看国产精品日韩av| 亚洲成人久久久| 欧美大尺度电影在线观看| 亚洲黄色在线观看| 日韩精品极品在线观看播放免费视频| 日韩精品在线第一页| 欧美激情伊人电影| 日韩在线视频网站| 欧美日韩国产一中文字不卡| 国产精品18久久久久久麻辣| 欧美日韩在线影院| 国产精品www色诱视频| 狠狠色狠狠色综合日日五| 亚洲一区二区三区视频播放| 国产成人在线亚洲欧美| 久久久免费观看| 国产一区欧美二区三区| 国产成人欧美在线观看| 大荫蒂欧美视频另类xxxx| 欧美成人中文字幕| 精品成人国产在线观看男人呻吟| 久久久久久国产精品| 日韩电影大片中文字幕| 精品视频久久久久久| 日韩精品免费综合视频在线播放| 午夜精品久久17c| 日韩免费在线视频| 粉嫩av一区二区三区免费野| 欧美日韩国产精品| 日韩中文字幕免费看| 欧美电影免费观看高清| 亚洲天堂第二页| 色悠悠国产精品| 91在线视频免费| 亚洲跨种族黑人xxx| 国产美女91呻吟求| 亚洲第一网站男人都懂| 亚洲第一av网站| 久久综合五月天| 久久免费少妇高潮久久精品99| 亚洲视频网站在线观看| 日韩精品视频在线播放| 永久免费毛片在线播放不卡| 亚洲理论在线a中文字幕| 国产在线观看精品一区二区三区| 久久久免费电影| 久热爱精品视频线路一| 亚洲欧美视频在线| 日韩乱码在线视频| 在线丨暗呦小u女国产精品| 久久夜色精品国产| 久久人体大胆视频| 国产极品精品在线观看| 亚洲成av人影院在线观看| 欧美激情国内偷拍| 九九精品视频在线观看| 国产精品极品美女粉嫩高清在线| 欧美激情视频一区二区三区不卡| 久久99久久99精品免观看粉嫩| 亚洲аv电影天堂网| 欧美大尺度在线观看| 国产视频综合在线| 国产福利视频一区| 欧美日韩国产综合视频在线观看中文| 久久躁日日躁aaaaxxxx| 青青草一区二区| 国产精品久久久久久久久久东京| 亚洲精品视频中文字幕| 成人国产在线激情| 成人在线激情视频| 91精品在线国产| 中文字幕亚洲欧美日韩2019| 久久91精品国产91久久久| 精品电影在线观看| 一区二区欧美亚洲| 亚洲视频自拍偷拍| 久久五月情影视| 8x拔播拔播x8国产精品| 色综合色综合久久综合频道88| 精品一区精品二区| 色系列之999| 国产欧美精品在线播放| 日本三级久久久| 亚洲第一级黄色片| 最新69国产成人精品视频免费| 久久69精品久久久久久国产越南| 一区二区三区 在线观看视| 日韩av在线一区二区| 亚洲欧美国产高清va在线播| 国模精品一区二区三区色天香| 久久福利视频导航| 一个色综合导航| 国产免费一区二区三区香蕉精| 精品久久久精品| 欧美激情一区二区三区高清视频| 一区三区二区视频| 亚洲精品电影久久久| 日韩激情在线视频|