三阶B样条生成方法

B样条计算方法

    // 三次B样条基函数
    double F03(double t) { return 1.0 / 6 * (-t * t * t + 3 * t * t - 3 * t + 1); }
    double F13(double t) { return 1.0 / 6 * (3 * t * t * t - 6 * t * t + 4); }
    double F23(double t) { return 1.0 / 6 * (-3 * t * t * t + 3 * t * t + 3 * t + 1); }
    double F33(double t) { return 1.0 / 6 * t * t * t; }

    ///
    /// \brief generateBSplinePoints 生成三阶B样条路线点
    /// \param length               返回路线长度
    /// \param p0                   起点
    /// \param p1                   终点
    /// \param ctrl0                控制点1
    /// \param ctrl1                控制点2
    /// \param dis                  采样距离,单位mm, 默认20mm
    /// \param num                  每一段路线上的插值,总点数为3*num+4
    /// \return                     路线点集合
    ///
    static QList<QPointF> generateBSplinePoints(int &length,
                                                const QPointF &p0,
                                                const QPointF &p1,
                                                const QPointF &ctrl0,
                                                const QPointF &ctrl1,
                                                int dis = 20,
                                                int num = 100)
    {
        QList<QPointF> tmpath, path;
        tmpath.push_back(p0); //先占位
        tmpath.push_back(p0);
        tmpath.push_back(ctrl0);
        tmpath.push_back(ctrl1);
        tmpath.push_back(p1);
        tmpath.push_back(p1); //先占位

        tmpath[0].setX(2 * tmpath[1].x() - tmpath[2].x()); //  将折线延长线上两点加入作为首点和尾点
        tmpath[0].setY(2 * tmpath[1].y() - tmpath[2].y());

        tmpath[5].setX(2 * tmpath[4].x() - tmpath[3].x());
        tmpath[5].setY(2 * tmpath[4].y() - tmpath[3].y());

        QPointF NodePt1, NodePt2, NodePt3, NodePt4;
        double t;
        int totalnum = 0;
        for (int i = 0; i < 3; i++) {
            NodePt1 = tmpath[i];
            NodePt2 = tmpath[i + 1];
            NodePt3 = tmpath[i + 2];
            NodePt4 = tmpath[i + 3];

            double dt = 1.0 / (num + 1);

            for (int j = 0; j < num + 1; j++) {
                t = dt * j;
                QPointF tmp;
                tmp.setX(F03(t) * NodePt1.x() + F13(t) * NodePt2.x() + F23(t) * NodePt3.x()
                         + F33(t) * NodePt4.x());
                tmp.setY(F03(t) * NodePt1.y() + F13(t) * NodePt2.y() + F23(t) * NodePt3.y()
                         + F33(t) * NodePt4.y());
                path.push_back(tmp);
            }

            if (i == num - 2) { //  最后一个尾点
                t = 1;
                QPointF tmp;
                tmp.setX(F03(t) * NodePt1.x() + F13(t) * NodePt2.x() + F23(t) * NodePt3.x()
                         + F33(t) * NodePt4.x());
                tmp.setY(F03(t) * NodePt1.y() + F13(t) * NodePt2.y() + F23(t) * NodePt3.y()
                         + F33(t) * NodePt4.y());
                path.push_back(tmp);
            }
        }
        //补充终点
        path.push_back(p1);
        double len = 0.0;
        for (int i = 1; i < path.size(); i++) {
            auto p = path[i] - path[i - 1];
            len = len + std::sqrt(p.x() * p.x() + p.y() * p.y());
        }

        length = len;
        return std::move(path);
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Haoh-Smile

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值
>