點在多邊形內的c代碼

//#define DEBUG

#i nclude <iostream>
#i nclude <cmath>
#ifdef DEBUG
#i nclude <fstream>
#endif

using namespace std;

const double INFINITY  = 1e10;
const double ESP = 1e-5;
const int MAX_N     = 1000;


struct Point {
 double x, y;
};

struct LineSegment {
 Point pt1, pt2;
};


int n, m, count;
Point polygon[MAX_N];
Point P;

#ifdef DEBUG
ifstream fin("1081.in");
istream& in  = fin;
ostream& out = cout;
#else
istream& in  = cin;
ostream& out = cout;
#endif


inline double max(double x, double y)
{
 return (x > y ? x : y);
}

inline double min(double x, double y)
{
 return (x < y ? x : y);
}

// 計算叉乘 |P1P0| × |P2P0|
double Multiply(Point p1, Point p2, Point p0)
{
 return ( (p1.x - p0.x) * (p2.y - p0.y) - (p2.x - p0.x) * (p1.y - p0.y) );
}

// 判斷線段是否包含點point
bool IsOnline(Point point, LineSegment line)
{
 return( ( fabs(Multiply(line.pt1, line.pt2, point)) < ESP ) &&
  ( ( point.x - line.pt1.x ) * ( point.x - line.pt2.x ) <= 0 ) &&
  ( ( point.y - line.pt1.y ) * ( point.y - line.pt2.y ) <= 0 ) );
}

// 判斷線段相交
bool Intersect(LineSegment L1, LineSegment L2)
{
 return( (max(L1.pt1.x, L1.pt2.x) >= min(L2.pt1.x, L2.pt2.x)) &&
  (max(L2.pt1.x, L2.pt2.x) >= min(L1.pt1.x, L1.pt2.x)) &&
  (max(L1.pt1.y, L1.pt2.y) >= min(L2.pt1.y, L2.pt2.y)) &&
  (max(L2.pt1.y, L2.pt2.y) >= min(L1.pt1.y, L1.pt2.y)) &&
  (Multiply(L2.pt1, L1.pt2, L1.pt1) * Multiply(L1.pt2, L2.pt2, L1.pt1) >= 0) &&
  (Multiply(L1.pt1, L2.pt2, L2.pt1) * Multiply(L2.pt2, L1.pt2, L2.pt1) >= 0)
  );
}


// 判斷點在多邊形內
bool InPolygon(Point polygon[], int n, Point point)
{
    if (n == 1)
 {
  return ( (fabs(polygon[0].x - point.x) < ESP) && (fabs(polygon[0].y - point.y) < ESP) );
 } else if (n == 2) {
  LineSegment side;
  side.pt1 = polygon[0];
  side.pt2 = polygon[1];
  return IsOnline(point, side);
 }
 
 int count = 0;
 LineSegment line;
 line.pt1 = point;
 line.pt2.y = point.y;
 line.pt2.x = - INFINITY;
 
 for( int i = 0; i < n; i++ ) {
  // 得到多邊形的一條邊
  LineSegment side;
  side.pt1 = polygon[i];
  side.pt2 = polygon[(i + 1) % n];
  
  if( IsOnline(point, side) ) {
   return true;
  }
  
  // 如果side平行x軸則不作考慮
  if( fabs(side.pt1.y - side.pt2.y) < ESP ) {
   continue;
  }
  
  if( IsOnline(side.pt1, line) ) {
   if( side.pt1.y > side.pt2.y ) count++;
        } else if( IsOnline(side.pt2, line) ) {
            if( side.pt2.y > side.pt1.y ) count++;
        } else if( Intersect(line, side) ) {
            count++;
        }
    }
 
    return ( count % 2 == 1 );
}


int main()
{
 count = 0;
 in >> n;
 while (n > 0) {
  count++;
  if (count > 1) out << endl;
  out << "Problem " << count << ":" << endl;
  
  in >> m;
  
  for (int i = 0; i < n; i++) {
   in >> polygon[i].x >> polygon[i].y;
  }
  
  for ( i = 0; i < m; i++) {
   in >> P.x >> P.y;
   if (InPolygon(polygon, n, P)) {
    out << "Within" << endl;
   } else {
    out << "Outside" << endl;
   }
  }
  
  n = 0;
  in >> n;
 }
 return 0;
}

 

 

需要指出的是,這裏的多邊形是凸多邊形

1.判斷點在形內形外
從該點向右做一條射線,對於多邊形(A1,A2,...,An):

點在多邊形內:邊和射線的交點個數是奇數;

點在多邊形外:邊和射線的交點個數是偶數;

對於每條線段,只要一個端點高於射線,另一端點不低於射線,且交點在射線右側,就算作線段和射線相交。

2.多邊形的面積
已原點爲三角形的一點,多邊形的一邊構成三角形,按多邊形的邊順序進行三角形剖分,
計算各三角形的有向面積,多邊形面積爲所有三角形的和
多邊形面積A=∑(xiyi+1-xi+1yi)/2

3.多邊形的重心
多邊形三角剖分,計算每個三角形的重心和麪積,然後以面積爲權求所有三角形的加權平均
x=∑((xi+xi+1)(xiyi+1-xi+1yi))/(6A)

發佈了12 篇原創文章 · 獲贊 1 · 訪問量 15萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章