求凸包代码 (采用graham扫描法)

该博客介绍了如何运用Graham扫描法计算平面点集的凸包。首先找到最下且偏左的点作为起点,然后按照极角从小到大排序点集。在遍历过程中,通过叉积判断新点是否在凸包上,不断更新凸包点集。最终返回逆时针排列的凸包点集。
摘要由CSDN通过智能技术生成

原理:凸包算法(Graham扫描法)_よろしくお願いします-CSDN博客_graham扫描法

/**
     * @brief :获取平面点集的凸包,采用GrahamScan计算凸包
     * @param[in] :points:输入的点集,
     * @param[out] :
     * @return :返回凸包的点集,点集是逆时针排序。
     */
    CUBECOM_API vector<iCoord2d> GetConvexHullByGrahamScan(vector<iCoord2d>& points);

 //获取平面向量叉积
    double GetTwoVectorMulti(const iCoord2d &fpt, const iCoord2d &spt, const iCoord2d &oriPt)
    {
       return (fpt[0] - oriPt[0]) * (spt[1] - oriPt[1]) - (spt[0] - oriPt[0]) * (fpt[1]-oriPt[1]);
    }

CUBECOM_API vector<iCoord2d> CubeHelper::GetConvexHullByGrahamScan(vector<iCoord2d>& points)
{
    vector<iCoord2d> pointArray;
    size_t ptSize = points.size();
    size_t           temp   = 0;
    //获取最下而且偏左的点
    for (size_t i = 1; i < ptSize; ++i)
    {
        if (points[i][1] < points[temp][1] || ((points[i][1] == points[temp][1]) && (points[i][0] < points[temp][0])))
        {
            temp = i;
        }
    }
    //将得到的点作为第一个点
    std::swap(points[0], points[temp]);
    //按极角从小到大排列,极角相同则距离偏短的进行排序
    iCoord2d tempPt = points[0];
    std::sort(points.begin()+1, points.end(), [&tempPt](const iCoord2d &fpt, const iCoord2d &spt)
    {
        iVec2d fvec(fpt[0] - tempPt[0], fpt[1] - tempPt[1]);
        iVec2d svec(spt[0] - tempPt[0], spt[1] - tempPt[1]);
        //判断哪一条向量极角更大
        if (fvec.SignZCross(svec) > 0) return true;
            
        //共线
        if (fvec.SignZCross(svec) == 0 && fpt.DistPtPt(tempPt) < spt.DistPtPt(tempPt))  return true;

        return false;
    });

    //存前三个点入栈
    for (int i = 0; i < 3; ++i)
        pointArray.emplace_back(points[i]);
    
    //获取点集合
    size_t top = 2;
    for (size_t i = 3; i < ptSize;++i)
    {
        //判断
        while (top > 1 && CubeHelper::GetTwoVectorMulti(pointArray[top], points[i], pointArray[top - 1]) < 0)
            top--;
        //如果top变化,说明points[i]这个点才是凸点,栈最后的几个点要出栈。
        if (top != (pointArray.size() - 1))
        {
            size_t j = pointArray.size() - 1;
            for (; j > top; --j)
                pointArray.pop_back();
        }
        //将当前点入栈,因为极角排序的原因,过程中会将不符合的点去掉,所以当前的点一定会入栈(注意是极角排序关系)。
        pointArray.emplace_back(points[i]);
        top = pointArray.size()-1;
    }

    return pointArray;
 }
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值