besier打断和升阶,高阶性质

news2024/11/15 8:18:15

欢迎关注更多精彩
关注我,学习常用算法与数据结构,一题多解,降维打击。

问题描述

  1. 对besier曲线在u处打断,生成两条besier曲线
  2. 对besier曲线升阶处理

bezier高阶性质

求导推导

P ( t ) = ∑ i = 0 n B i n ( t ) b i \boldsymbol P(t) = \displaystyle \sum_{i=0}^nB_i^n(t)\boldsymbol b_i P(t)=i=0nBin(t)bi

B i n ( t ) = ( n i ) t i ( 1 − t ) n − i B_i^n(t)=\left (\begin{array}{l}n \\i \end{array} \right)t^i(1-t)^{n-i} Bin(t)=(ni)ti(1t)ni

矩阵表示

P ( t ) = [ B 0 n B 1 n ⋯ B n n ] [ b 0 b 1 ⋮ b n ] P(t) = \begin {bmatrix} B_0^n & B_1^n &\cdots& B_n^n \end{bmatrix} \begin {bmatrix} \boldsymbol b_0\\\boldsymbol b_1\\\vdots\\\boldsymbol b_n\end{bmatrix} P(t)=[B0nB1nBnn] b0b1bn

只要对每个系数求导即可

B i n ( t ) ′ = i ( n i ) t i − 1 ( 1 − t ) n − i − ( n − i ) ( n i ) t i ( 1 − t ) n − i − 1 ⋯ ( 1 ) B_i^n(t)'=i\left (\begin{array}{l}n \\i \end{array} \right)t^{i-1}(1-t)^{n-i}-(n-i)\left (\begin{array}{l}n \\i \end{array} \right)t^i(1-t)^{n-i-1} \cdots (1) Bin(t)=i(ni)ti1(1t)ni(ni)(ni)ti(1t)ni1(1)

对组合数展开可以发现

B i n ( t ) ′ = n ( n − 1 i − 1 ) t i − 1 ( 1 − t ) n − i − n ( n − 1 i ) t i ( 1 − t ) n − i − 1 = n B i − 1 n − 1 ( t ) − n B i n − 1 ( t ) B_i^n(t)'=n\left (\begin{array}{cl}n-1 \\i-1 \end{array} \right)t^{i-1}(1-t)^{n-i}-n\left (\begin{array}{cl}n-1 \\i \end{array} \right)t^i(1-t)^{n-i-1}=nB_{i-1}^{n-1}(t)-nB_i^{n-1}(t) Bin(t)=n(n1i1)ti1(1t)nin(n1i)ti(1t)ni1=nBi1n1(t)nBin1(t)

从(1)式可知,当i=0时, B i − 1 n − 1 ( t ) = 0 B_{i-1}^{n-1}(t)=0 Bi1n1(t)=0

设 q i = B i n − 1 ( t ) 设q_i = B_{i}^{n-1}(t) qi=Bin1(t)

P ′ ( t ) = n [ q 0   ⋯   q n − 1 ] [ b 1 ⋮ b n ] + n [ q 0   ⋯   q n − 1 ] [ − b 0 ⋮ − b n − 1 ] \boldsymbol P'(t)=n[q_0\ \cdots \ q_{n-1}] \begin {bmatrix} \boldsymbol b_1\\\vdots\\\boldsymbol b_n\end{bmatrix}+n[q_0\ \cdots \ q_{n-1}] \begin {bmatrix} -\boldsymbol b_0\\\vdots\\-\boldsymbol b_{n-1}\end{bmatrix} P(t)=n[q0  qn1] b1bn +n[q0  qn1] b0bn1

= ∑ i = 0 n − 1 B i n − 1 ( t ) ( b i + 1 − b i ) = \displaystyle \sum_{i=0}^{n-1}B_i^{n-1}(t)(\boldsymbol b_{i+1}-\boldsymbol b_i) =i=0n1Bin1(t)(bi+1bi)

上式一共是n项,所以n阶bezier曲线的导数可以由n-1阶bezier曲线得到

控制点如下

D i = n ( b i + 1 − b i ) , i ∈ [ 0 , n − 1 ] D_i = n(b_{i+1}-b_i), i\in[0, n-1] Di=n(bi+1bi),i[0,n1]

导数的计算也可以由De Casteljau algorithm 来算

端点导数

将t=0, t=1代入公式,发现首末端的导数刚好是初始两点和末端两点连线的n倍。

高阶导数

参数曲线的d阶导为在d-1阶导数基础上再求一次导。

P ′ ′ ( t ) = ∑ i = 0 n − 2 B i n − 2 ( t ) ( ( n − 1 ) ( D i + 1 − D i ) ) \boldsymbol P''(t)= \displaystyle \sum_{i=0}^{n-2}B_i^{n-2}(t)((n-1)(\boldsymbol D_{i+1}-\boldsymbol D_i)) P′′(t)=i=0n2Bin2(t)((n1)(Di+1Di))

= n ( n − 1 ) ∑ i = 0 n − 2 B i n − 2 ( t ) ( b i + 2 − 2 b i + 1 + b i ) =n(n-1) \displaystyle \sum_{i=0}^{n-2}B_i^{n-2}(t)(\boldsymbol b_{i+2} -2\boldsymbol b_{i+1}+\boldsymbol b_i) =n(n1)i=0n2Bin2(t)(bi+22bi+1+bi)

从u处打断

根据 De Casteljau algorithm 的过程可以观察到。

每次迭代后,数组中的第1个点和最后一个点,分别是左右子段的控制点。


/*!
 *\brief Bezier曲线的打断
*\ param const std::vector<Point> & A 控制点序列
*\ param double u 打断处的参数 (0,1)
*\ param std::vector<Point> & cv_left 打断后前半部分的控制点
*\ param std::vector<Point> & cv_right 打断后后半部分的控制点
*\ Returns:   std::pair<List2f, List2f>
*/
std::pair<List2f, List2f> subDevide(const std::vector<Eigen::Vector2f> &A, float u)
{
    List2f cv_left = A;
    List2f cv_right = A;
    if(A.size()<2)return {cv_left, cv_right};

    int p = A.size()-1;
    //p次迭代
    for (int i = 0;i<p;++i)
    {
        for (int j = 0;j<p - i;++j)
            cv_right[j] = (1.0 - u)*cv_right[j] + u*cv_right[j + 1];
        //左侧控制点为每次迭代的首点
        cv_left[i + 1] = cv_right[0];
    }

    return {cv_left, cv_right};
}

升阶

设原来曲线控制点为b0, b1, … bn n+1个控制点,

升阶后的点为c0, c1, … cn, cn+1 n+2个控制点

c0=b0, cn+1=bn

中间控制点

c i = i n + 1 b i − 1 + ( 1 + i n + 1 ) b i , i ∈ [ 1 , n ] c_i = \frac {i}{n+1}b_{i-1} + (1+\frac{i}{n+1})b_i, i \in[1,n] ci=n+1ibi1+(1+n+1i)bi,i[1,n]


List2f degreeElevation(const std::vector<Eigen::Vector2f> &A)
{
    int n=A.size(); // 为公式中的n+1
    List2f res (n+1);
    res.front() = A[0];
    res.back() = A.back();

    for(int i=1;i<n;++i) {
        float ratio = 1.0*i/n;
        res[i] = ratio *A[i-1] + (1-ratio)*A[i];
    }

    return res;
}

实现

代码:
https://gitcode.com/chenbb1989/geometric_model/tree/master/gohw4-3

演示视频

besier 打断与升阶

打断
在这里插入图片描述

升阶

在这里插入图片描述


本人码农,希望通过自己的分享,让大家更容易学懂计算机知识。创作不易,帮忙点击公众号的链接,帮忙转发,感激不尽。

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

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

相关文章

uniapp中H5网页怎么实现自动点击事件

<template><view><button ref"myButton" click"handleClick">点击我</button></view> </template><script> export default {mounted() {this.$nextTick(() > {const button this.$refs.myButton;console.l…

【系统分析师】-综合知识-计算机系统基础

1、流水线的吞吐率是指流水线在单位时间里所完成的任务数或输出的结果数。设某流水线有 5 段&#xff0c;有 1 段的时间为 2ns &#xff0c;另外 4 段的每段时间为 1ns&#xff0c;利用此流水线完成 100 个任务的吞吐率约为&#xff08;16&#xff09;个/s 。 2、矢量图像通过使…

Python+PyCharm安装和配置(详细步骤)

Python的安装步骤可以根据用户选择的安装方式&#xff08;如使用安装包安装或源码安装&#xff09;而有所不同。以下将详细讲解两种安装方式的步骤&#xff0c;并附上源码安装的相关说明。 一、使用安装包安装Python 1. 访问Python官网 打开浏览器&#xff0c;输入Python官…

Resilience4J服务熔断隔离与限流

为了保障文章的流畅性&#xff08;文章穿插大量的环境搭建没意思&#xff0c;会干扰文章的主题&#xff0c;无聊的很&#xff09;&#xff0c;将环境的搭建与测试&#xff0c;工具的版本说明放了文末&#xff1a; 六、环境搭建。 一、Circuit Breaker是什么 1.1、官网 https…

C++笔记---内存管理

1. 内存分布 在对操作系统有更加深入的了解之前&#xff0c;在写代码的层面我们需要对下面的几个内存区域有所了解&#xff1a; 1. 栈又叫堆栈--非静态局部变量/函数参数/返回值等等&#xff0c;栈是向下增长的。 2. 堆--用于程序运行时动态内存分配&#xff0c;堆是可以上增长…

【数据结构3】哈希表、哈希表的应用(集合与字典、md5算法和文件的哈希值)

1 哈希表 哈希表一个通过哈希函数来计算数据存 储位置的数据结构&#xff0c;通常支持如下操作: 插入(键&#xff0c;值):插入键值对(键&#xff0c;值) Get(key):如果存在键为键的键值对则返回其值&#xff0c;否则返回空值 删除(键):删除键为键的键值对哈希表(Hash Table&am…

数据仓库系列 2:数据仓库的核心特点是什么?

想象一下,你正站在一座巨大的数据金矿前。这座金矿蕴含着海量的商业洞察,可以帮助你的公司做出精准决策,提升效率,远超竞争对手。但是,如何高效地开采、提炼和利用这些数据黄金呢?答案就是:数据仓库。 目录 什么是数据仓库?数据仓库的核心特点面向主题的组织集成性非易失性…

RTL-SDR SpectrumPy频谱显示

GITHUB大佬开源的基于RTL-SDR的python频谱显示程序链接&#xff0c;下载下来后&#xff0c;安装必要的库&#xff0c;编译运行&#xff0c;运行报错。 修改了以下两个地方&#xff1a; 修改点1&#xff1a; 修改前&#xff1a; self.spinBoxFrequency.setValue(self.center_fr…

【Python从入门到进阶】63.Pandas如何实现数据的Merge

接上篇《62、Pandas中DataFrame对象案例实践》 上一篇我们延续之前学习的DataFrame对象的知识&#xff0c;结合一个数据案例进行了实践操作。本篇我们来学习Pandas如何实现数据的Merge。 一、引言 在当今数据驱动的时代&#xff0c;数据分析已成为各行各业不可或缺的一部分。…

【JAVA基础】四则运算符

文章目录 四则运算结合运算符自增运算符关系和boolean运算符 四则运算 在java当中&#xff0c;使用运算符、-、*、/ 表示加减乘除&#xff0c;当参与 / 运算的两个操作数都是整数的时候&#xff0c;表示整数除法&#xff1b;否则表示浮点数。整数的求余操作用 % 表示。 Syste…

【Java】/* 与树有关的一些概念 */

一、关于树的一些概念 1. 树是一种非线性的数据结构&#xff0c;它是由n&#xff08;n>0&#xff09;个有限结点组成一个具有层次关系的集合。把它叫做树是因为它看 起来像一棵倒挂的树&#xff0c;也就是说它是根朝上&#xff0c;而叶朝下的。它具有以下的特点&#xff1a;…

记录一次经历:使用flask_sqlalchemy集成flask造成循环导入问题

前言&#xff1a; 工作需求&#xff0c;写一个接口&#xff0c;用Python来编写&#xff0c;我首先想到用flask小型框架来支撑&#xff0c;配置sqlalchemy来实现&#xff0c;但是在实现的过程中&#xff0c;发生循环导入问题 我想到用蓝图来解决此问题&#xff0c;但是仍然会出死…

UI测试使用webdriver-manager免安装浏览器驱动

引言&#xff1a; selenium传统的方式是下载浏览器对应的driver&#xff08;驱动&#xff09;&#xff0c;放到本地的指定位置&#xff0c;然后写代码加载这个driver&#xff08;驱动&#xff09;再执行相应的操作。 弊端&#xff1a; 传统方法存在两个麻烦的地方: 1.需要下…

安全面试常见问题任意文件下载

《网安面试指南》http://mp.weixin.qq.com/s?__bizMzkwNjY1Mzc0Nw&mid2247484339&idx1&sn356300f169de74e7a778b04bfbbbd0ab&chksmc0e47aeff793f3f9a5f7abcfa57695e8944e52bca2de2c7a3eb1aecb3c1e6b9cb6abe509d51f&scene21#wechat_redirect 1.1 任意文件下…

Git的使用教程及常用语法03

七.如何从版本库中删除文件 第一种方式&#xff1a;直接在工作区删除文件&#xff0c;然后提交 rm ffile1.txt (注意&#xff1a;这个不是git命令&#xff0c;而是linux命令) 看到状态发现&#xff0c;文件file1.txt已经被删除&#xff0c;提示需要提交到暂存区。 因为我们只…

蓝牙对象交换协议(OBEX) - 概念介绍

零.声明 本专栏文章我们会以连载的方式持续更新&#xff0c;本专栏计划更新内容如下&#xff1a; 第一篇:蓝牙综合介绍 &#xff0c;主要介绍蓝牙的一些概念&#xff0c;产生背景&#xff0c;发展轨迹&#xff0c;市面蓝牙介绍&#xff0c;以及蓝牙开发板介绍。 第二篇:Trans…

SpringBoot集成kafka-监听器注解

SpringBoot集成kafka-监听器注解 1、application.yml2、生产者3、消费者4、测试类5、测试 1、application.yml #自定义配置 kafka:topic:name: helloTopicconsumer:group: helloGroup2、生产者 package com.power.producer;import com.power.model.User; import com.power.uti…

Windows系统上进行项目管理工具VisualSVN Server服务端的保姆级安装教程与配置和SVN客户端保姆级安装教程和使用

一、VisualSVN Server简介 Subversion Server for Windows | VisualSVN ServerGet an easy to use Subversion (SVN) server for Windows. It works out-of-the-box and is suitable both for small business and enterprises. Available for free!https://www.visualsvn.com/…

4.Redis单线程和多线程

1.Redis的单线程 Redis的单线程主要是指Redis的网络IO和键值对读写是由一个线程完成的&#xff0c;Redis在处理客户端的请求时包括获取&#xff08;Socket读&#xff09;、解析、执行、内容返回&#xff08;Socket写&#xff09;等都由一个顺序串行的主线程处理&#xff0c;这…

Linux 下命令行参数和环境变量

Linux 下命令行参数和环境变量 命令行参数为什么要有命令行参数谁可以做到结论 环境变量一些现象查看环境变量添加环境变量添加内存级环境变量永久有效 其他环境变量HOMEPWDSHELLHISTSIZE 自定义环境变量定义取消 本地变量整体理解环境变量环境变量的组织方式Linux 代码获取环境…