点在多边形内的c代码

来源:互联网 发布:海龙设计软件视频 编辑:程序博客网 时间:2024/04/30 14:35
//#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)

原创粉丝点击