均匀与准均匀 B样条算法

news2025/5/28 18:17:36

B 样条曲线的定义

p ( t ) = ∑ i = 0 n P i F i , k ( t ) p(t) = \sum_{i=0}{n} P_i F_{i, k}(t) p(t)=i=0nPiFi,k(t)

方程中 n + 1 n+1 n+1 个控制点, P i P_i Pi, i = 0 , 1 , ⋯ n i=0, 1, \cdots n i=0,1,n 要用到 n + 1 n+1 n+1 k k k 次 B 样条基函数 F i , k F_{i, k} Fi,k, i = 0 , 1 , ⋯   , n i=0, 1, \cdots, n i=0,1,,n, 节点矢量为 T = [ t 0 , t 1 , ⋯   , t n + k + 1 ] T = [t_0, t_1, \cdots, t_{n+k+1}] T=[t0,t1,,tn+k+1] F i , k ( t ) F_{i, k}(t) Fi,k(t) 是由一个称为节点矢量的非递减的参数 t t t 的序列, t 0 ≤ t 1 ≤ ⋯ ≤ t n + k + 1 t_0 \leq t_1 \leq \cdots \leq t_{n+k+1} t0t1tn+k+1所决定的 k k k 次分段多项式。

B 样条曲线划分为四种类型,均匀 B 样条曲线,准均匀B 样条曲线,分段 Bezier 曲线和非均匀 B 样条曲线。

定义域

给定 n + 1 n+1 n+1 个控制点, P i P_i Pi, i = 0 , 1 , ⋯ n i=0, 1, \cdots n i=0,1,n, 相应地要求 n + 1 n+1 n+1 个 B 样条基函数 F i , k ( t ) F_{i, k}(t) Fi,k(t) 定义一个 k k k 次 B 样条曲线,这 n + 1 n+1 n+1 k k k 次 B 样条由节点矢量 T = [ t 0 , t 1 , ⋯ t n + k + 1 ] T = [t_0, t_1, \cdots t_{n+k+1}] T=[t0,t1,tn+k+1] 所决定。
并非这个些节点矢量所包含的 n + k + 1 n+k +1 n+k+1 个区间都在该曲线的定义域,其中两端的各 k k k 个几点区间,不能作为 B 样条曲线的定义区间。
这是因为 n + 1 n+1 n+1 个控制点中最前的 n + 1 n+1 n+1 个顶点 P i P_i Pi, i = 0 , 1 , ⋯ k i=0,1, \cdots k i=0,1,k 定义了 B 样条曲线的首段,其定义区间为 t ∈ [ t k , t k + 1 ] t\in [t_k, t_{k+1}] t[tk,tk+1] 往后移动一个顶点 P i P_i Pi i = 1 , 2 , ⋯ k + 1 i=1, 2, \cdots k+1 i=1,2,k+1 定义第二段,其定义区间为 t ∈ [ t k + , t k + 2 ] t \in [t_{k+}, t_{k+2}] t[tk+,tk+2] 依次类推,最后 k + 1 k+1 k+1 个顶点, P i P_i Pi, i = n − k , b − k − 1 , ⋯ n i=n-k, b-k-1, \cdots n i=nk,bk1,n 定义最后一段,其定义区间为 t ∈ [ t n , t n + 1 ] t\in[t_n, t_{n+1}] t[tn,tn+1], 因此,高于零次的 k k k 次B 样条曲线的定义域为

t ∈ [ t k , t n + 1 ] t \in [t_k, t_{n+1}] t[tk,tn+1]

三次均匀 B 样条曲线

{ F 0 , 3 ( t ) = 1 6 ( 1 − t ) 3 = ( − t 3 + 3 t 2 − 3 t + 1 ) F 1 , 3 ( t ) = 1 6 ( 3 t 3 − 6 t 2 + 4 ) F 2 , 3 ( t ) = 1 6 ( − 3 t 3 + 3 t 2 + 3 t + 1 ) F 3 , 3 ( t ) = 1 6 t 3 \begin{cases} F_{0,3}(t) = \frac{1}{6} (1-t)^3 = (-t^3 + 3t^2 -3t+1)\\ F_{1,3}(t) = \frac{1}{6} (3t^3 - 6t^2 +4)\\ F_{2,3}(t) = \frac{1}{6} (-3t^3 + 3t^2 + 3t +1) \\ F_{3,3}(t) = \frac{1}{6} t^3\\ \end{cases} F0,3(t)=61(1t)3=(t3+3t23t+1)F1,3(t)=61(3t36t2+4)F2,3(t)=61(3t3+3t2+3t+1)F3,3(t)=61t3

在这里插入图片描述

三次 B 样条的几何性质

{ p ( 0 ) = 1 6 ( p 0 + 4 p 1 + p 2 ) = 1 3 ( p 0 + p 2 2 ) + 2 3 p 1 = 1 3 p m + 2 3 p 1 p ( 1 ) = 1 6 ( p 1 + 4 p 2 + p 3 ) = 1 3 ( p 1 + p 3 2 ) + 2 3 p 2 = 1 3 p n + 2 3 p 2 \begin{cases} p(0) = \frac{1}{6}(p_0 + 4 p_1 + p_2) = \frac{1}{3} (\frac{p_0 + p_2}{2}) + \frac{2}{3}p_1 = \frac{1}{3}p_m + \frac{2}{3}p_1\\ p(1) = \frac{1}{6}(p_1 + 4 p_2 + p_3) = \frac{1}{3} (\frac{p_1 + p_3}{2}) + \frac{2}{3}p_2 = \frac{1}{3}p_n + \frac{2}{3}p_2\\ \end{cases} {p(0)=61(p0+4p1+p2)=31(2p0+p2)+32p1=31pm+32p1p(1)=61(p1+4p2+p3)=31(2p1+p3)+32p2=31pn+32p2

{ p ′ ( 0 ) = 1 2 ( p 2 − p 0 ) p ′ ( 1 ) = 1 2 ( p 3 + p 1 ) \begin{cases} p'(0) = \frac{1}{2}(p_2 - p_0) \\ p'(1) = \frac{1}{2}(p_3 + p_1) \\ \end{cases} {p(0)=21(p2p0)p(1)=21(p3+p1)

{ p ′ ′ ( 0 ) = p 0 − 2 p 1 + p 2 = 2 ( p 0 + p 2 2 − p ) = 2 ( p m − p 1 ) p ′ ′ ( 1 ) = p 1 − 2 p 2 + p 3 = 2 ( p 1 + p 3 2 − p 2 ) = 2 ( p n − p 2 ) \begin{cases} p''(0) = p_0 - 2p_1 + p_2 = 2(\frac{p_0 + p_2}{2} -p)= 2(p_m - p_1) \\ p''(1) = p_1 - 2p_2 + p_3 = 2(\frac{p_1 + p_3}{2} -p_2)= 2(p_n - p_2) \\ \end{cases} {p′′(0)=p02p1+p2=2(2p0+p2p)=2(pmp1)p′′(1)=p12p2+p3=2(2p1+p3p2)=2(pnp2)

在这里插入图片描述

#include <QWidget>
#include <QApplication>
#include <QPainter>
#include <QPointF>
#include <QPainterPath>


const double knot[13] = {-3/6.0, -2/6.0, -1/6.0, 0.0, 1 / 6.0, 2 / 6.0, 3 / 6.0, 4 / 6.0, 5 / 6.0, 1.0, 7/ 6.0, 8/ 6.0, 9/6.0};


double BasisFunctionValue(double t, int i, int k)
{
    double val1, val2, val;
    if (k == 0)
    {
        if ((t >= knot[i]) && t < knot[i + 1])
        {
            return 1.0;
        }
        else
        {	// 其它
            return 0.0;
        }
    }
    if (k > 0)
    {
        if (t < knot[i] || t > knot[i + k + 1]) {
            return 0.0;		// 其它
        }
        else
        {
            double coffcient1, coffcient2;	// 凸组合系数1 凸组合系数 2
            double denominator = 0.0;		// 分母
            denominator = knot[i + k] - knot[i];
            if (denominator == 0.0)
            {
                // 约定 0/0 = 0
                coffcient1 = 0.0;
            }
            else
            {
                coffcient1 = (t - knot[i]) / denominator;	// 计算的第一项
            }
            denominator = knot[i + k + 1] - knot[i + 1];	// 递推公式第二项分母
            if (denominator == 0.0)
            {
                // 约定 0/0 = 0
                coffcient2 = 0.0;
            }
            else
            {
                coffcient2 = (knot[i + k + 1] - t) / denominator;	// 递推公式第二项
            }
            val1 = coffcient1 * BasisFunctionValue(t, i, k - 1);	// 递推公式第一项的只
            val2 = coffcient2 * BasisFunctionValue(t, i+1, k - 1);	// 递推公式第二项的只
            val = val1 + val2;	// 基函数的值
        }
    }
    return val;
}




void drawBSplineCure(QPainter* painter, const std::vector<QPointF>& P)
{
    // Set line color
    QColor lineColor(0, 0, 255);
    // Set point color
    QColor pointColor(255, 0, 0);

    QPainterPath bezierPath;
    QPen pen(lineColor);
    pen.setWidth(2);  // Set the line width as needed
    painter->setPen(pen);

    QPointF center(900, 600);  // Center coordinates

    int k = 3;  // Degree of the B-spline curve

    for (int i = k; i <= P.size() - k; ++i)
    {
        double tStep = 0.01;
        for (double t = 0.0; t <= 1.0; t += tStep)
        {
            QPointF p(0, 0);  // Discrete point
            for (int j = 0; j < P.size(); ++j)
            {
                double BValue = BasisFunctionValue(t, j, k);
                p += P[j] * BValue;
            }

            if (t == 0.0)
            {
                bezierPath.moveTo(p + center);
            }
            else
            {
                bezierPath.lineTo(p + center);

            }


            painter->setPen(pointColor);
            painter->setBrush(Qt::NoBrush);
            painter->drawEllipse(p + center, 5, 5);

        }
    }

    painter->drawPath(bezierPath);
}



void drawControlPolygon(QPainter* painter, std::vector<QPointF> P)
{
    QColor lineColor(0, 0, 0);
    QColor pointColor(0, 0, 255);  // Blue color for points

    QPen polyLinePen(lineColor);
    painter->setPen(polyLinePen);


    QBrush pointBrush(pointColor);
    painter->setBrush(pointBrush);

    QPointF center(900, 600);

    QVector<QPointF> shiftedPoints;
    std::transform(P.begin(), P.end(), std::back_inserter(shiftedPoints),
                   [center](const QPointF& point) { return point + center; });


    painter->drawPolyline(shiftedPoints.data(), shiftedPoints.size());


    for (const QPointF& point : shiftedPoints)
    {
        painter->drawEllipse(point, 5, 5);
    }

}


std::vector<QPointF> getControlPoints(){
    std::vector<QPointF> controlPoints = {
        QPointF(-600, -50),
        QPointF(-500, 200),  // 控制点
        QPointF(-160, 250),
        QPointF(-250, -300),
        QPointF(160, -200),  // 控制点
        QPointF(200, 200),
        QPointF(600, 180),
        QPointF(700, -60),   // 控制点
        QPointF(500, -200)
    };
    return controlPoints;
}



class MyWidget : public QWidget {
public:
    MyWidget(QWidget* parent = nullptr) : QWidget(parent) {
        setFixedSize(1800, 1200);
    }

protected:
    void paintEvent(QPaintEvent* event) override {
        Q_UNUSED(event);

        QPainter painter(this);
        painter.setRenderHint(QPainter::Antialiasing, true);

        std::vector<QPointF> controlPoints = getControlPoints();
        drawBSplineCure(&painter, controlPoints);
        drawControlPolygon(&painter, controlPoints);
    }




public:
    int n = 8;
    int k = 3;



};


int main(int argc, char* argv[]) {
    QApplication app(argc, argv);

    MyWidget widget;
    widget.show();

    return app.exec();
}

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1355579.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Unity中URP下统一不同平台下的z值

文章目录 前言一、ComputeFogFactor 来计算雾效混合因子二、UNITY_Z_0_FAR_FROM_CLIPSPACE 来统一计算不同平台下的Z值1、DirectX平台2、GL平台下&#xff08;在Unity.2022.LTS下&#xff0c;该功能没有完善)3、Opengl下 前言 在之前的文章中&#xff0c;我们实现了URP下的雾效…

企业培训系统开发:构建灵活高效的学习平台

企业培训系统的开发在当今数字化时代是至关重要的。本文将介绍一些关键技术和代码示例&#xff0c;以帮助您构建一个灵活、高效的企业培训系统。 1. 技术选型 在开始企业培训系统的开发之前&#xff0c;首先需要选择合适的技术栈。以下是一个基本的技术选型示例&#xff1a;…

【mars3d】FixedRoute的circle没有跟polyline贴着模型的解决方案

问题&#xff1a;【mars3d】官网的贴模型示例中&#xff0c;参考api文档增加了circle的配置&#xff0c;但是FixedRoute的circle没有跟polyline贴着模型 circle: { radius: 10, materialType: mars3d.MaterialType.CircleWave, materialOptions: { color: "#ffff00"…

柱面,盘片,盘面,扇面,磁头,磁道,扇区,CHS地址,LAB地址

柱面&#xff0c;盘片&#xff0c;盘面&#xff0c;扇面&#xff0c;磁头&#xff0c;磁道&#xff0c;扇区&#xff0c;CHS地址&#xff0c;LAB地址1 CHS地址 CHS地址指的是柱面&#xff08;Cylinder&#xff09;、磁头&#xff08;Head&#xff09;、扇区&#xff08;Secto…

新年话节能 电梯也减排

小伍恭祝大家2024年元旦快乐&#xff01;&#xff01; 目前&#xff0c;电梯的节能已经得到业界的广泛重视&#xff0c;积极推动相关的节能技术的实施&#xff0c;努力宣传和倡导规范的电梯的使用行为&#xff0c;将极大地改变我国电梯的耗能状况&#xff0c;为节能减排做出较大…

Linux进程管理和计划任务

前言 上篇关于进程管理命令使用说明尚未完结&#xff0c;本篇将继续介绍相关命令以及计划任务管理。 目录 前言 一、控制进程 1. vmstat 2. free 3. iostat 4. iotop/iftop 5. uptime 6. mpstat 7. dstat 8. webadin 9. 服务器五大性能 二、进程管理 1. 手动…

SemCms外贸网站商城系统 SQL注入漏洞复现(CVE-2023-50563)

0x01 产品简介 SemCms是国内团队打造的专门针对外贸网站的开源CMS,主要用于外贸企业,兼容IE,Firefox等主流浏览器。建设商城性质的外贸网站,多语言(小语种)网站。 0x02 漏洞概述 SemCms外贸网站商城系统SEMCMS_Function.php 中的 AID 参数存在SQL注入漏洞,未经身份认…

Zuul相关面试题及到案(2024)

1、什么是Zuul&#xff1f;它在微服务架构中有什么作用&#xff1f; Zuul是Netflix开源的一种提供API网关服务的应用程序&#xff0c;它在微服务架构中扮演着流量的前门角色。主要功能包括以下几点&#xff1a; 路由转发&#xff1a;Zuul网关将外部请求转发到具体的微服务实例…

【QT】中英文切换

很高兴在雪易的CSDN遇见你 前言 本文分享QT中如何进行中英文切换&#xff0c;希望对各位小伙伴有所帮助&#xff01; 感谢各位小伙伴的点赞关注&#xff0c;小易会继续努力分享&#xff0c;一起进步&#xff01; 你的点赞就是我的动力(&#xff3e;&#xff35;&#xff3e…

EtherCAT FP介绍系列文章—热插拔

EtherCAT主站能够顺利初始化和操作网络&#xff0c;离不开EtherCAT网络信息文件&#xff08;ENI&#xff09;&#xff0c;它包含与EtherCAT主站本机以及连接到主站上每个从站设备的配置一般性信息。该文件由配置工具创建&#xff0c;并由EtherCAT主站程序加载&#xff0c;如下图…

由于无法找到mfc100u.dll怎么解决,mfc100u.dll丢失的6个解决方法分享

本文将为您详细介绍mfc100u.dll文件以及丢失时的六个不同解决方法&#xff0c;帮助您更好地了解和解决这一问题。 一、mfc100u.dll是什么文件&#xff1f; mfc100u.dll是Microsoft Foundation Classes&#xff08;微软基础类库&#xff09;中的一个动态链接库文件。它是Visua…

AI的突破与融合:2024年中国智能技术的新纪元_光点科技

随着人工智能领域的不断突破&#xff0c;2024年注定将成为中国智能技术发展的一个新纪元。当下&#xff0c;AI技术不仅在理论研究上取得了重大进展&#xff0c;其在商业应用、社会服务等领域的融合也日益深入。本文将结合近期网络上的AI热点&#xff0c;展望中国在AI技术方面的…

印象笔记03 衍生软件使用

印象笔记03 衍生软件使用 Verse 以下内容来源于官方介绍 VERSE是一款面向未来的智能化生产力工具&#xff0c;由印象笔记团队诚意推出。 你可以用VERSE&#xff1a; 管理数字内容&#xff0c;让信息有序高效运转&#xff1b;搭建知识体系&#xff0c;构建你的强大知识库&am…

SwiftUI 打造一款“可收缩”的 HStack(一)

概览 拥有雄心壮志(亦或是自我感觉良好)的秃头码农们都喜欢接受编程上各种颇有难度的挑战,比如刷刷力扣(LeetCode)或 codeforces 上难题啥的。 为了满足小伙伴们的“冒险精神”(亦或是“自虐癖”),加上这篇博文我们会用连续 4 篇系列文章通过不同的方式来解决同一道与…

倍思科技红海突围要义:紧随新趋势,“实用而美”理念从一而终

移动数码周边市场始终不缺热度。 销售端是业绩的节节高升&#xff0c;如在2023年京东双十一&#xff0c;移动数码周边产品销售成果丰硕&#xff0c;根据京东战报&#xff0c;大功率充电器成交额同比提升 200%&#xff0c;65W以上移动电源成交额同比提升 150%&#xff0c;自带线…

[实用小知识]:Google浏览器添加代理SwitchyOmega

Google浏览器添加代理SwitchyOmega 1. 下载插件到本地 SwitchyOmega_2.5.21.crx OmegaOptions_20230615.bak 2. 开始配置Google代理 1、打开Google浏览器&#xff0c;点开右上角三个点&#xff0c;在更多工具里选择扩展程序 2、在扩展程序里打开开发者模式 3、将Google文件…

世微AP5125 外置MOS管5-100V 8A平均电流型LED降压恒流驱动器 SOT23-6

产品描述 AP5125 是一款外围电路简单的 Buck 型平均电流检测模式的 LED 恒流驱动器&#xff0c;适用于 8-100V 电压范围的非隔离式大功率恒流 LED 驱动领域。芯片采用固定频率 140kHz 的 PWM 工作模式&#xff0c; 利用平均电流检测模式&#xff0c;因此具有优异的负载调整 率特…

windows x86 calling convention

stdcall 全部压入栈里面 第一个参数最后一个入栈&#xff08;在栈顶&#xff09; fastcall ecx edx前两个 后面的压栈&#xff0c;顺序和stdcall一样

【代数学作业1-python实现GNFS一般数域筛】构造特定的整系数不可约多项式:涉及素数、模运算和优化问题

代数学作业1-完整版&#xff1a;python实现GNFS一般数域筛 写在最前面背景在GNFS算法中选择互质多项式时&#xff0c;需要考虑哪些关键因素&#xff0c;它们对算法的整体运行时间有何影响? 练习1题目题目分析Kleinjung方法简介通用数域筛法&#xff08;GNFS&#xff09;中的多…

Linux——搭建KVM环境

KVM虚拟化 一、安装所需软件 1、yum安装软件 [rootlocalhost ~]# yum -y install qemu-kvm qemu-kvm-tools virt-install qemu-img bridge-utils libvirt virt-manager 重新启动 [rootlocalhost ~]reboot 2、查看CPU是否支持虚拟化 [rootlocalhost ~]# cat /proc/cpuinf…