射线法判断点在多边形内

参考:【精选】判断地图上一个点是否在多边形内部--射线法_地图上算点是否在多边形内-CSDN博客

解决方案:以点为起点做水平向右的射线,判断射线与边的交点数,若交点数为奇数则点在多边形内,若交点数为偶数则点在多边形外。

特殊情况

  • 1.点与多边形的顶点重合视为点在多边形内
  • 2.点与多边形的顶边重合视为点在多边形内
  • 3.射线与任意一边的一个顶点重合,则判断边的另外一个顶点是否在交点的上方,若在上方则交点有效,否则舍弃
  • 4.射线与边平行视为没有交点

实验结果

关键代码: 


#ifndef  EPS
#define  EPS		 5E-5
#endif // ! ESP


template<typename T>
bool OnSegment(T P1, T P2, T Q)
{
    double x1 = P1.x() - Q.x();
    double y1 = P1.y() - Q.y();
    double x2 = P2.x() - Q.x();
    double y2 = P2.y() - Q.y();
    return (x1 * y2- y1 * x2 == 0) && (x1 * x2 + y1 * y2 <= 0);
}

template<typename T>
bool judge_point_polygon(T* data, std::vector<std::pair<int,int>>& edge, T P){
    int number = 0;
    T P1,P2;
     for(int i = 0; i < edge.size(); i++)
     {
         int id1 = edge[i].first;
         int id2 = edge[i].second;
         P1 = data[id1];
         P2 = data[id2];

         //点在线上
         if(OnSegment(P1,P2,P))
             return true;
         //水平的边
         if(P1.y() == P2.y())
             continue;

        //不相交
        if ((P1.y() - P.y() > EPS) && (P2.y() - P.y() > EPS))
            continue;
        if ((P1.y() - P.y() < -EPS) && (P2.y() - P.y() < -EPS))
            continue;

         //不相交
         double x =(P.y()-P1.y())*(P1.x()-P2.x())/(P1.y()-P2.y())+P1.x();
         if(x <= P.x())
             continue;

        if(fabs(x - P1.x())<EPS && abs(P.y() - P1.y())<EPS){
            if(P2.y() > P.y())
                ++number;
        }
        else if(fabs(x - P2.x())<EPS && abs(P.y() - P2.y())<EPS){
            if(P1.y() > P.y())
                ++number;
        }
        else
            ++number;
     }
     return number%2 == 1;
}
void Widget::paintEvent(QPaintEvent *event)
{
    QPainter painter(this);
    painter.setRenderHint(QPainter::Antialiasing);

    painter.setPen(Qt::black);
    for(auto& pair : edges){
        QPoint p1 = pts[pair.first];
        QPoint p2 = pts[pair.second];
        painter.drawLine(p1, p2);
    }

    for(QPoint& pt : pt_test){
        bool in = judge_point_polygon<QPoint>(pts.data(), edges, pt);
        if(in){
           painter.setBrush(Qt::blue);
           painter.drawEllipse(pt, 5,5);
           painter.drawText(pt+QPoint(5,0), "in");
        }
        else{
            painter.setBrush(Qt::red);
            painter.drawEllipse(pt, 5,5);
            painter.drawText(pt+QPoint(5,0), "out");
         }
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值