C++ 判断点是否在闭合多边形内部(射线法)

1.判断是否在多边形内,法则是点A沿一个方向轴发射一条射线,其中以x轴的右正方向发射射线。接触到多边形的个数为奇数就是在多边形内,否则在多边形外。

2.主要有两种特例,接触顶点和接触线段。

1.接触顶点

图1

 2.接触线段

这两种的处理方法的巧妙之处就在于一开始规定x正向轴发射射线。

这时候可以将与A接触的线段进行判断,如果接触的线段的一个端点的y轴低于A的y轴,认为算一个接触点,否则不算。比如A点的坐标是(10,10) ,图1中的第一个图形,接触顶点的两条线段的两个端点的y轴都没有低于A的y轴坐标,所以不算接触点,总共的接触只有1个。图二中,接触顶点的两条线段的两个端点都低于A的y轴坐标,所以算2个接触点,总共的接触只有3个,所以在多边形内。

//判断点是否在平面多边形范围内,传入一堆顺序的点,每两个点构成一条直线
bool CubeExportYJKHelper::CheckPointIsInPolygon(const iCoord3d &originPt, const vector<iCoord3d> &pts)
{
    //将所有的点转化成线段,首尾相接
    vector<pair<iCoord2d, iCoord2d>> lines;
    for (int i=0;i<pts.size();++i)
    {
        int nextPt = (i + 1) % pts.size();
        lines.emplace_back(make_pair(pts[i], pts[nextPt]));
    }
    iCoord2d oriPt(originPt);
    iVec2d   vec(1,0);
    iCoord2d contactPt(0,0);
    int      count = 0;
    for (const auto&line:lines)
    {
        //判断射线是否和直线相交
        InterResult result =
            Cube::Intersection2Impl::Inter_Segment_Ray(line.first, line.second, oriPt, vec, &contactPt);
        //只要不是交于一点,就继续
        if (result != InterResult::InterPoint)
            continue;
        //判断交点是端点,判断另一点是否在射线下端,如果是,就加1
        double disStartPt = contactPt.DistPtPt(line.first);
        double disEndPt   = contactPt.DistPtPt(line.second);
        //如果不是端点,就加一,跳出
        if (disStartPt > DTE && disEndPt>DTE)
        {
            count++;
            continue;
        }
        //如果一个点大于0,则另外一个点一定小于0
        contactPt = disStartPt <= DTE ? line.second : line.first;
        //如果这个端点的y轴小于起始点的y轴,就加1
        count += contactPt[1] < oriPt[1] ? 1:0;
    }  
    //如果接触点的个数是奇数,就在多边形内部
    return count % 2 == 1 ? true : false;
}

  • 5
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值