天气与日历 切换到窄版

 找回密码
 立即注册
中国膜结构网
十大进口膜材评选 十大国产膜材评选 十大膜结构设计评选 十大膜结构公司评选
查看: 56|回复: 0

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

[复制链接]

该用户从未签到

主题

0

回帖

2912

积分

管理员

积分
2912
发表于 2024-6-22 09:46:18 | 显示全部楼层 |阅读模式
算法步骤如下:

已知点point(x,y)和多边形Polygon的点有序集合(x1,y1;x2,y2;….xn,yn;);
以point为起点,以无穷远为终点作平行于X轴的射线line(x,y; -∞,y);循环取得多边形的每一条边side(xi,yi;xi+1,yi+1):

1). 判断point(x,y)是否在side上,如果是,则返回true。

2). 判断line与side是否有交点,如果有则count++。
判断交点的总数count,如果为奇数则返回true,偶数则返回false。

[code]#include<iostream>
#include <cmath>
#include <vector>
#include <algorithm>
#define EPSILON 0.000001
using namespace std;
//二维double矢量
struct  Vec2d
{
        double x, y;
        Vec2d()
        {
                x = 0.0;
                y = 0.0;
        }
        Vec2d(double dx, double dy)
        {
                x = dx;
                y = dy;
        }
        void Set(double dx, double dy)
        {
                x = dx;
                y = dy;
        }
};
//判断点在线段上
bool IsPointOnLine(double px0, double py0, double px1, double py1, double px2, double py2)
{
        bool flag = false;
        double d1 = (px1 - px0) * (py2 - py0) - (px2 - px0) * (py1 - py0);
        if ((abs(d1) < EPSILON) && ((px0 - px1) * (px0 - px2) <= 0) && ((py0 - py1) * (py0 - py2) <= 0))
        {
                flag = true;
        }
        return flag;
}
//判断两线段相交
bool IsIntersect(double px1, double py1, double px2, double py2, double px3, double py3, double px4, double py4)
{
        bool flag = false;
        double d = (px2 - px1) * (py4 - py3) - (py2 - py1) * (px4 - px3);
        if (d != 0)
        {
                double r = ((py1 - py3) * (px4 - px3) - (px1 - px3) * (py4 - py3)) / d;
                double s = ((py1 - py3) * (px2 - px1) - (px1 - px3) * (py2 - py1)) / d;
                if ((r >= 0) && (r <= 1) && (s >= 0) && (s <= 1))
                {
                        flag = true;
                }
        }
        return flag;
}
//判断点在多边形内
bool Point_In_Polygon_2D(double x, double y, const vector<Vec2d> &POL)
{
        bool isInside = false;
        int count = 0;
        //
        double minX = DBL_MAX;
        for (int i = 0; i < POL.size(); i++)
        {
                minX = std::min(minX, POL[i].x);
        }
        //
        double px = x;
        double py = y;
        double linePoint1x = x;
        double linePoint1y = y;
        double linePoint2x = minX -10;                        //取最小的X值还小的值作为射线的终点
        double linePoint2y = y;
        //遍历每一条边
        for (int i = 0; i < POL.size() - 1; i++)
        {
                double cx1 = POL[i].x;
                double cy1 = POL[i].y;
                double cx2 = POL[i + 1].x;
                double cy2 = POL[i + 1].y;
                if (IsPointOnLine(px, py, cx1, cy1, cx2, cy2))
                {
                        return true;
                }
                if (fabs(cy2 - cy1) < EPSILON)   //平行则不相交
                {
                        continue;
                }
                if (IsPointOnLine(cx1, cy1, linePoint1x, linePoint1y, linePoint2x, linePoint2y))
                {
                        if (cy1 > cy2)                        //只保证上端点+1
                        {
                                count++;
                        }
                }
                else if (IsPointOnLine(cx2, cy2, linePoint1x, linePoint1y, linePoint2x, linePoint2y))
                {
                        if (cy2 > cy1)                        //只保证上端点+1
                        {
                                count++;
                        }
                }
                else if (IsIntersect(cx1, cy1, cx2, cy2, linePoint1x, linePoint1y, linePoint2x, linePoint2y))   //已经排除平行的情况
                {
                        count++;
                }
        }
        if (count % 2 == 1)
        {
                isInside = true;
        }
        return isInside;
}
int main()
{
        //定义一个多边形(六边形)
        vector<Vec2d> POL;
        POL.push_back(Vec2d(268.28, 784.75));
        POL.push_back(Vec2d(153.98, 600.60));
        POL.push_back(Vec2d(274.63, 336.02));
        POL.push_back(Vec2d(623.88, 401.64));
        POL.push_back(Vec2d(676.80, 634.47));
        POL.push_back(Vec2d(530.75, 822.85));
        POL.push_back(Vec2d(268.28, 784.75));                                //将起始点放入尾部,方便遍历每一条边
        //
        if (Point_In_Polygon_2D(407.98, 579.43, POL))
        {
                cout << "点(407.98, 579.43)在多边形内" << endl;
        }
        else
        {
                cout << "点(407.98, 579.43)在多边形外" << endl;
        }
        //
        if (Point_In_Polygon_2D(678.92, 482.07, POL))
        {
                cout << "点(678.92, 482.07)在多边形内" << endl;
        }
        else
        {
                cout << "点(678.92, 482.07)在多边形外" << endl;
        }
        return 0;
}[/code]

 

 

 

 

判断点在多边形内算法的C++实现
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|Archiver|中国膜结构网|中国膜结构协会|进口膜材|国产膜材|ETFE|PVDF|PTFE|设计|施工|安装|车棚|看台|污水池|中国膜结构网_中国空间膜结构协会

GMT+8, 2024-11-1 10:32 , Processed in 0.160441 second(s), 25 queries .

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

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