C++ 计算几何 判断一个点是否在多边形内
多边形由多个线段确定,在多边形内部可能有0或多个挖孔。
判断一个点是否在多边形内部,但不位于挖孔内部。
思路:
从点出发作向右延伸的射线,判断射线经过的线段个数。
交点为奇数则在内部,偶数则在外部。
需要用到直线方程的两点式
#include <iostream> #include <vector> #include <list> using namespace std; template<class T> struct Point { T x; T y; }; template<class T> class Polygon { private: list<Point<T>> points; // 外环点集合 vector<list<Point<T>>> inners; // 内环点集合 public: void AddPoint(const Point<T>& point) { points.push_back(point); } void AddInnerPolygon(const list<Point<T>>& innerPolygon) { inners.push_back(innerPolygon); } // 列出所有边 void ListEdges() { cout << "多边形的边:" << endl; auto nextPoint = points.begin(); for (const auto& point : points) { nextPoint++; if (nextPoint == points.end()) nextPoint = points.begin(); cout << "(" << point.x << ", " << point.y << ") - (" << nextPoint->x << ", " << nextPoint->y << ")" << endl; } } bool IsInPolygon(const Point<T>& targetPoint) { bool isInOuterPolygon = IsInPolygonHelper(points, targetPoint); if (!isInOuterPolygon) return false; for (const auto& inner : inners) { if (IsInPolygonHelper(inner, targetPoint)) return false; } return true; } private: bool IsInPolygonHelper(const list<Point<T>>& polygon, const Point<T>& targetPoint) { int intersectCount = 0; auto toPoint = polygon.begin(); for (const auto& fromPoint : polygon) { toPoint++; if (toPoint == polygon.end()) toPoint = polygon.begin(); // 检查射线与多边形的边是否相交 // 仅当检测点的垂直坐标位于线段之前才有可能相交 if ((fromPoint.y <= targetPoint.y) && (toPoint->y >= targetPoint.y) || (fromPoint.y >= targetPoint.y) && (toPoint->y <= targetPoint.y) ) { // 根据直线方程的两点式,代入射线(向右延伸)的方程,得到交点的X坐标 double interSecX = (toPoint->x - fromPoint.x) / (toPoint->y - fromPoint.y) * (targetPoint.y - fromPoint.y) + fromPoint.x; if (targetPoint.x < interSecX) intersectCount++; } } return (intersectCount % 2) == 1; } }; int main() { // 创建一个多边形 Polygon<double> polygon; // 添加外环的点 polygon.AddPoint({ 1.0, 1.0 }); polygon.AddPoint({ 5.0, 1.0 }); polygon.AddPoint({ 5.0, 4.0 }); polygon.AddPoint({ 3.0, 5.0 }); polygon.AddPoint({ 1.0, 4.0 }); // 添加一个内环 list<Point<double>> innerPolygon; innerPolygon.push_back({ 2.0, 2.0 }); innerPolygon.push_back({ 4.0, 2.0 }); innerPolygon.push_back({ 4.0, 3.0 }); polygon.AddInnerPolygon(innerPolygon); // 列出多边形的边 polygon.ListEdges(); // 测试一个点是否在多边形内部 Point<double> testPoint = { 0, 1 }; bool isInPolygon = polygon.IsInPolygon(testPoint); if (isInPolygon) cout << "点在多边形内部。" << endl; else cout << "点在多边形外部。" << endl; return 0; }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
· AI与.NET技术实操系列(六):基于图像分类模型对图像进行分类