找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
热搜: 活动 交友 discuz
查看: 175|回复: 0

判断点在多边形内算法的C++实现

[复制链接]

1

主题

0

回帖

35

积分

管理员

积分
35
发表于 2024-3-16 09:08:56 | 显示全部楼层 |阅读模式
  1. #include<iostream>
  2. #include <cmath>
  3. #include <vector>
  4. #include <algorithm>
  5. #define EPSILON 0.000001
  6. using namespace std;
  7. //二维double矢量
  8. struct  Vec2d
  9. {
  10.         double x, y;
  11.         Vec2d()
  12.         {
  13.                 x = 0.0;
  14.                 y = 0.0;
  15.         }
  16.         Vec2d(double dx, double dy)
  17.         {
  18.                 x = dx;
  19.                 y = dy;
  20.         }
  21.         void Set(double dx, double dy)
  22.         {
  23.                 x = dx;
  24.                 y = dy;
  25.         }
  26. };
  27. //判断点在线段上
  28. bool IsPointOnLine(double px0, double py0, double px1, double py1, double px2, double py2)
  29. {
  30.         bool flag = false;
  31.         double d1 = (px1 - px0) * (py2 - py0) - (px2 - px0) * (py1 - py0);
  32.         if ((abs(d1) < EPSILON) && ((px0 - px1) * (px0 - px2) <= 0) && ((py0 - py1) * (py0 - py2) <= 0))
  33.         {
  34.                 flag = true;
  35.         }
  36.         return flag;
  37. }
  38. //判断两线段相交
  39. bool IsIntersect(double px1, double py1, double px2, double py2, double px3, double py3, double px4, double py4)
  40. {
  41.         bool flag = false;
  42.         double d = (px2 - px1) * (py4 - py3) - (py2 - py1) * (px4 - px3);
  43.         if (d != 0)
  44.         {
  45.                 double r = ((py1 - py3) * (px4 - px3) - (px1 - px3) * (py4 - py3)) / d;
  46.                 double s = ((py1 - py3) * (px2 - px1) - (px1 - px3) * (py2 - py1)) / d;
  47.                 if ((r >= 0) && (r <= 1) && (s >= 0) && (s <= 1))
  48.                 {
  49.                         flag = true;
  50.                 }
  51.         }
  52.         return flag;
  53. }
  54. //判断点在多边形内
  55. bool Point采用In采用Polygon采用2D(double x, double y, const vector<Vec2d> &POL)
  56. {       
  57.         bool isInside = false;
  58.         int count = 0;
  59.        
  60.         //
  61.         double minX = DBL采用MAX;
  62.         for (int i = 0; i < POL.size(); i++)
  63.         {
  64.                 minX = std::min(minX, POL[i].x);
  65.         }
  66.         //
  67.         double px = x;
  68.         double py = y;
  69.         double linePoint1x = x;
  70.         double linePoint1y = y;
  71.         double linePoint2x = minX -10;                        //取最小的X值还小的值作为射线的终点
  72.         double linePoint2y = y;
  73.         //遍历每一条边
  74.         for (int i = 0; i < POL.size() - 1; i++)
  75.         {       
  76.                 double cx1 = POL[i].x;
  77.                 double cy1 = POL[i].y;
  78.                 double cx2 = POL[i + 1].x;
  79.                 double cy2 = POL[i + 1].y;
  80.                                
  81.                 if (IsPointOnLine(px, py, cx1, cy1, cx2, cy2))
  82.                 {
  83.                         return true;
  84.                 }
  85.                 if (fabs(cy2 - cy1) < EPSILON)   //平行则不相交
  86.                 {
  87.                         continue;
  88.                 }
  89.                 if (IsPointOnLine(cx1, cy1, linePoint1x, linePoint1y, linePoint2x, linePoint2y))
  90.                 {
  91.                         if (cy1 > cy2)                        //只保证上端点+1
  92.                         {
  93.                                 count++;
  94.                         }
  95.                 }
  96.                 else if (IsPointOnLine(cx2, cy2, linePoint1x, linePoint1y, linePoint2x, linePoint2y))
  97.                 {
  98.                         if (cy2 > cy1)                        //只保证上端点+1
  99.                         {
  100.                                 count++;
  101.                         }
  102.                 }
  103.                 else if (IsIntersect(cx1, cy1, cx2, cy2, linePoint1x, linePoint1y, linePoint2x, linePoint2y))   //已经排除平行的情况
  104.                 {
  105.                         count++;
  106.                 }
  107.         }
  108.        
  109.         if (count % 2 == 1)
  110.         {
  111.                 isInside = true;
  112.         }
  113.         return isInside;
  114. }
  115. int main()
  116. {       
  117.         //定义一个多边形(六边形)
  118.         vector<Vec2d> POL;       
  119.         POL.push采用back(Vec2d(268.28, 784.75));
  120.         POL.push采用back(Vec2d(153.98, 600.60));
  121.         POL.push采用back(Vec2d(274.63, 336.02));
  122.         POL.push采用back(Vec2d(623.88, 401.64));
  123.         POL.push采用back(Vec2d(676.80, 634.47));
  124.         POL.push采用back(Vec2d(530.75, 822.85));
  125.         POL.push采用back(Vec2d(268.28, 784.75));                                //将起始点放入尾部,方便遍历每一条边
  126.                
  127.         //
  128.         if (Point采用In采用Polygon采用2D(407.98, 579.43, POL))
  129.         {
  130.                 cout << "点(407.98, 579.43)在多边形内" << endl;
  131.         }
  132.         else
  133.         {
  134.                 cout << "点(407.98, 579.43)在多边形外" << endl;
  135.         }
  136.         //
  137.         if (Point采用In采用Polygon采用2D(678.92, 482.07, POL))
  138.         {
  139.                 cout << "点(678.92, 482.07)在多边形内" << endl;
  140.         }
  141.         else
  142.         {
  143.                 cout << "点(678.92, 482.07)在多边形外" << endl;
  144.         }
  145.         return 0;
  146. }
复制代码
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

Archiver|手机版|小黑屋|膜结构网

GMT+8, 2025-1-1 17:05 , Processed in 0.104775 second(s), 21 queries .

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表