【图形学】双三次贝塞尔曲线绘制方法

双三次贝塞尔曲线的定义

双三次贝塞尔曲面是由16个控制点定义的曲面,通常表示为4x4矩阵。
在这里插入图片描述

曲面的公式如下:

p ( u , v ) = ∑ i = 0 3 ∑ j = 0 3 P i , j B i , 3 ( u ) B j , 3 ( v ) , ( u , v ) ∈ [ 0 , 1 ] × [ 0 , 1 ] p(u,v)=\sum_{i=0}^3\sum_{j=0}^3P_{i,j}B_{i,3}(u)B_{j,3}(v),\\(u,v)\in[0,1]\times[0,1] p(u,v)=i=03j=03Pi,jBi,3(u)Bj,3(v),(u,v)[0,1]×[0,1]

其中, P i , j , i , j = 0 , 1 , 2 , 3 P_{i,j},i,j=0,1,2,3 Pi,j,i,j=0,1,2,3​是曲面上的16控制点; B i , 3 ( u ) 和 B j , 3 ( v ) B_{i, 3} ( u )和 B_{j,3}( v ) Bi,3(u)Bj,3(v)是三次Bernstein基函数,定义如下:
{ B 0 , 3 ( u ) = ( 1 − u ) 3 B 1 , 3 ( u ) = 3 u ( 1 − u ) 2 B 2 , 3 ( u ) = 3 u 2 ( 1 − u ) B 3 , 3 ( u ) = u 3 { B 0 , 3 ( v ) = ( 1 − v ) 3 B 1 , 3 ( v ) = 3 v ( 1 − v ) 2 B 2 , 3 ( v ) = 3 v 2 ( 1 − v ) B 3 , 3 ( v ) = v 3 \begin{cases} B_{0,3}(u)=(1-u)^3\\ B_{1,3}(u)=3u(1-u)^2\\ B_{2,3}(u)=3u^2(1-u)\\ B_{3,3}(u)=u^3 \end{cases}\begin{cases} B_{0,3}(v)=(1-v)^3\\ B_{1,3}(v)=3v(1-v)^2\\ B_{2,3}(v)=3v^2(1-v)\\ B_{3,3}(v)=v^3 \end{cases} B0,3(u)=(1u)3B1,3(u)=3u(1u)2B2,3(u)=3u2(1u)B3,3(u)=u3 B0,3(v)=(1v)3B1,3(v)=3v(1v)2B2,3(v)=3v2(1v)B3,3(v)=v3
用矩阵表示公式如下
p ( u , v ) = ( B 0 , 3 ( u ) B 1 , 3 ( u ) B 2 , 3 ( u ) B 3 , 3 ( u ) ) ( P 00 P 01 P 02 P 03 P 10 P 11 P 12 P 13 P 20 P 21 P 22 P 23 P 30 P 31 P 32 P 33 ) ( B 0 , 3 ( v ) B 0 , 1 ( v ) B 0 , 2 ( v ) B 0 , 3 ( v ) ) p(u,v)=\begin{pmatrix}B_{0,3}(u)&B_{1,3}(u)&B_{2,3}(u)&B_{3,3}(u) \end{pmatrix}\begin{pmatrix} P_{00}&P_{01}&P_{02}&P_{03}\\ P_{10}&P_{11}&P_{12}&P_{13}\\ P_{20}&P_{21}&P_{22}&P_{23}\\ P_{30}&P_{31}&P_{32}&P_{33}\end{pmatrix}\begin{pmatrix} B_{0,3}(v)&B_{0,1}(v)&B_{0,2}(v)&B_{0,3}(v) \end{pmatrix} p(u,v)=(B0,3(u)B1,3(u)B2,3(u)B3,3(u)) P00P10P20P30P01P11P21P31P02P12P22P32P03P13P23P33 (B0,3(v)B0,1(v)B0,2(v)B0,3(v))
将Bernstein基数带入得到如下公式
p ( u , v ) = ( u 3 u 2 u 1 ) ( − 1 3 − 3 1 3 − 6 3 0 − 3 3 0 0 1 0 0 0 ) ( P 00 P 01 P 02 P 03 P 10 P 11 P 12 P 13 P 20 P 21 P 22 P 23 P 30 P 31 P 32 P 33 ) ( − 1 3 − 3 1 3 − 6 3 0 − 3 3 0 0 1 0 0 0 ) ( v 3 v 2 v 1 ) p(u,v)=\begin{pmatrix}u^3&u^2&u&1\end{pmatrix}\begin{pmatrix} -1&3&-3&1\\3&-6&3&0\\-3&3&0&0\\1&0&0&0 \end{pmatrix}\begin{pmatrix} P_{00}&P_{01}&P_{02}&P_{03}\\ P_{10}&P_{11}&P_{12}&P_{13}\\ P_{20}&P_{21}&P_{22}&P_{23}\\ P_{30}&P_{31}&P_{32}&P_{33}\end{pmatrix}\begin{pmatrix} -1&3&-3&1\\3&-6&3&0\\-3&3&0&0\\1&0&0&0 \end{pmatrix}\begin{pmatrix}v^3\\v^2\\v\\1\end{pmatrix} p(u,v)=(u3u2u1) 1331363033001000 P00P10P20P30P01P11P21P31P02P12P22P32P03P13P23P33 1331363033001000 v3v2v1

令 U = ( u 3 u 2 u 1 ) , V = ( v 3 v 2 v 1 ) M = ( − 1 3 − 3 1 3 − 6 3 0 − 3 3 0 0 1 0 0 0 ) , P = ( P 00 P 01 P 02 P 03 P 10 P 11 P 12 P 13 P 20 P 21 P 22 P 23 P 30 P 31 P 32 P 33 ) 那么 p ( u , v ) = U M P M T V T 令U=\begin{pmatrix}u^3&u^2&u&1\end{pmatrix},V=\begin{pmatrix}v^3&v^2&v&1\end{pmatrix}\\M=\begin{pmatrix} -1&3&-3&1\\3&-6&3&0\\-3&3&0&0\\1&0&0&0 \end{pmatrix},P=\begin{pmatrix} P_{00}&P_{01}&P_{02}&P_{03}\\ P_{10}&P_{11}&P_{12}&P_{13}\\ P_{20}&P_{21}&P_{22}&P_{23}\\ P_{30}&P_{31}&P_{32}&P_{33}\end{pmatrix} \\那么p(u,v)=UMPM^TV^T U=(u3u2u1),V=(v3v2v1)M= 1331363033001000 ,P= P00P10P20P30P01P11P21P31P02P12P22P32P03P13P23P33 那么p(u,v)=UMPMTVT
对得到的这个式子进行编程就可以绘制出一个双三次贝塞尔曲线。

绘制双贝塞尔曲面

双三次贝塞尔曲面可以看着一个弯曲的四面体,采用四叉树递归划分法进行细分,递归细分次数足够时分割出来的子曲面近似为一个平面四边形,这些平面四边形拼成了双三次贝塞尔曲线。
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

递归绘制细分曲面

递归函数

void CBezier::Recursion(CDC* pDC, int ReNumber, CMesh Mesh)
{if (0 == ReNumber){Tessellation(Mesh);//细分曲面,根据公式求坐标,将(u,v)点转换为(x,y)点DrawQuadrilateral(pDC);//绘制小平面四边形return;}else{CDimension2 Mid = (Mesh.m_BottomLeft + Mesh.m_TopRight) / 2.0;CMesh SubMesh[4];//一分为四个//左下子长方形SubMesh[0].m_BottomLeft = Mesh.m_BottomLeft;SubMesh[0].m_BottomRight = CDimension2(Mid.m_u, Mesh.m_BottomLeft.m_v);SubMesh[0].m_TopRight = CDimension2(Mid.m_u, Mid.m_v);SubMesh[0].m_TopLeft = CDimension2(Mesh.m_BottomLeft.m_u, Mid.m_v);//右下子长方形SubMesh[1].m_BottomLeft = SubMesh[0].m_BottomRight;SubMesh[1].m_BottomRight = Mesh.m_BottomRight;SubMesh[1].m_TopRight = CDimension2(Mesh.m_BottomRight.m_u, Mid.m_v);SubMesh[1].m_TopLeft = SubMesh[0].m_TopRight;//右上子长方形SubMesh[2].m_BottomLeft = SubMesh[1].m_TopLeft;SubMesh[2].m_BottomRight = SubMesh[1].m_TopRight;SubMesh[2].m_TopRight = Mesh.m_TopRight;SubMesh[2].m_TopLeft = CDimension2(Mid.m_u, Mesh.m_TopRight.m_v);//左上子长方形SubMesh[3].m_BottomLeft = SubMesh[0].m_TopLeft;SubMesh[3].m_BottomRight = SubMesh[2].m_BottomLeft;SubMesh[3].m_TopRight = SubMesh[2].m_TopLeft;SubMesh[3].m_TopLeft = Mesh.m_TopLeft;Recursion(pDC, ReNumber - 1, SubMesh[0]);//递归绘制4个子曲面Recursion(pDC, ReNumber - 1, SubMesh[1]);Recursion(pDC, ReNumber - 1, SubMesh[2]);Recursion(pDC, ReNumber - 1, SubMesh[3]);}
}

求细分曲面四个顶点的坐标

void CBezier::Tessellation(CMesh Mesh)
{double M[4][4];//系数矩阵MM[0][0] = -1, M[0][1] = 3, M[0][2] = -3, M[0][3] = 1;M[1][0] = 3, M[1][1] = -6, M[1][2] = 3, M[1][3] = 0;M[2][0] = -3, M[2][1] = 3, M[2][2] = 0, M[2][3] = 0;M[3][0] = 1, M[3][1] = 0, M[3][2] = 0, M[3][3] = 0;CPoint3 P3[4][4];//曲线计算用控制点数组for (int i = 0; i < 4; i++)for (int j = 0; j < 4; j++)P3[i][j] = m_CtrPt[i][j];LeftMultiplyMatrix(M, P3);//系数矩阵左乘三维点矩阵TransposeMatrix(M);//计算转置矩阵RightMultiplyMatrix(P3, M);//系数矩阵右乘三维点矩阵double u0, u1, u2, u3, v0, v1, v2, v3;//u、v参数的幂double u[4] = { Mesh.m_BottomLeft.m_u,Mesh.m_BottomRight.m_u ,Mesh.m_TopRight.m_u ,Mesh.m_TopLeft.m_u };double v[4] = { Mesh.m_BottomLeft.m_v,Mesh.m_BottomRight.m_v ,Mesh.m_TopRight.m_v ,Mesh.m_TopLeft.m_v };for (int i = 0; i < 4; i++){u3 = pow(u[i], 3.0), u2 = pow(u[i], 2.0), u1 = u[i], u0 = 1;v3 = pow(v[i], 3.0), v2 = pow(v[i], 2.0), v1 = v[i], v0 = 1;CPoint3 Pt = (u3 * P3[0][0] + u2 * P3[1][0] + u1 * P3[2][0] + u0 * P3[3][0]) * v3+ (u3 * P3[0][1] + u2 * P3[1][1] + u1 * P3[2][1] + u0 * P3[3][1]) * v2+ (u3 * P3[0][2] + u2 * P3[1][2] + u1 * P3[2][2] + u0 * P3[3][2]) * v1+ (u3 * P3[0][3] + u2 * P3[1][3] + u1 * P3[2][3] + u0 * P3[3][3]) * v0;m_QuadrPoint[i] = Pt;}
}

绘制细分曲面,就是知道了四个点绘制四边形

void CBezier::DrawQuadrilateral(CDC* pDC)
{CPoint2 ScreenPoint[4];//二维投影点for (int nPoint = 0; nPoint < 4; nPoint++)ScreenPoint[nPoint] = m_QuadrPoint[nPoint];//正交投影CPen NewPen, * pOldPen;NewPen.CreatePen(PS_SOLID, 2, RGB(255, 0, 0));pOldPen = pDC->SelectObject(&NewPen);pDC->MoveTo(ROUND(ScreenPoint[0].m_x), ROUND(ScreenPoint[0].m_y));pDC->LineTo(ROUND(ScreenPoint[1].m_x), ROUND(ScreenPoint[1].m_y));pDC->LineTo(ROUND(ScreenPoint[2].m_x), ROUND(ScreenPoint[2].m_y));pDC->LineTo(ROUND(ScreenPoint[3].m_x), ROUND(ScreenPoint[3].m_y));pDC->LineTo(ROUND(ScreenPoint[0].m_x), ROUND(ScreenPoint[0].m_y));pDC->SelectObject(pOldPen);NewPen.DeleteObject();
}

第二种方法

在这里插入图片描述

在四根贝塞尔曲线p(t),q(t),r(t),s(t)上去相同的t,根据定义可以得到四个点P,Q,R,S,这四个点又可以画一个三次贝塞尔曲线,那么在t从0递增至1的过程中就会产生一系列的三次贝塞尔曲线,这一组曲线就构成了一个曲面。
在这里插入图片描述

需要项目代码的可以评论区留言或者私信

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

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

相关文章

【程序员英语】【美语从头学】初级篇(入门)(笔记)Lesson10(电话会话Ⅱ)

《美语从头学初级入门篇》 注意&#xff1a;被 删除线 划掉的不一定不正确&#xff0c;只是不是标准答案。 文章目录 Lesson 10 Telephone Conversation Ⅱ 电话会话&#xff08;二&#xff09;会话A会话B笔记I would like to do&#xff08;Id like to to do&#xff09;我想…

如何从视频号中提取视频的文案?抖音文案也可提取

最近不少小伙伴刷抖音看看视频一个一个的进行抄&#xff0c;太慢了。​今天分享一个工具搞定怎么提取视频文案的方法&#xff01; 提取文案小助手 提取文案小助手是专注视频创作者的利器&#xff0c;帮助用户一键提取视频号中的文案&#xff0c;获取的方式比较简单&#xff0c…

Sui TVL跻身全链前十名|全面详解Sui原生功能如何促使DeFi蓬勃发展

根据DefiLlama数据显示&#xff0c;1月28日Sui TVL超过4.02亿美元&#xff0c;跻身所有区块链TVL前十名&#xff01; Sui的创新应用原生功能为DeFi应用铺平了道路&#xff0c;为用户提供了良好的体验。每个原生功能&#xff0c;从促进高效的共享流动性到简化用户互动&#xff0…

js中contextmenu、click和mousedown的区别在哪?

contextmenu、click和mousedown的定义 contextmenu&#xff1a;在鼠标右键点击时触发。可以在此事件中执行特定的操作&#xff0c;比如显示自定义的右键菜单或者阻止浏览器默认的上下文菜单弹窗。它是为了满足特定场景下对右键点击的定制化处理需求。 click事件是通用的鼠标点…

印章制作办法

印章制作办法&#xff1a; 最近在做单位技术支持的培训&#xff0c;需要增加个培训章&#xff0c;自己内容完成即可。 一、excel表格中 &#xff0c;插入-形状-圆&#xff08;按住shift按键&#xff09; 操作三步&#xff1a; 1.填充 无 &#xff1a; 2.形状轮廓 ---“红色…

代码随想录算法训练营day15|104.二叉树的最大深度、111.二叉树的最小深度、222.完全二叉树的节点个数

104.二叉树的最大深度 559.n叉树的最大深度 111.二叉树的最小深度 222.完全二叉树的节点个数 104.二叉树的最大深度 &#xff08;优先掌握递归&#xff09; 什么是深度&#xff0c;什么是高度&#xff0c;如何求深度&#xff0c;如何求高度&#xff0c;这里有关系到二叉树的遍…

数据结构—栈实现后缀表达式的计算

后缀表达式计算 过程分析 中缀表达式 &#xff08;15&#xff09;*3 > 后缀表达式 153* (可参考这篇文章&#xff1a;中缀转后缀) 第一步&#xff1a;我们从左至右扫描 后缀表达式(已经存放在一个字符数组中)&#xff0c;遇到第一个数字字符 ‘1’ 放入栈中第二步&#xf…

幻兽帕鲁服务器出租,腾讯云PK阿里云怎么收费?

幻兽帕鲁服务器价格多少钱&#xff1f;4核16G服务器Palworld官方推荐配置&#xff0c;阿里云4核16G服务器32元1个月、96元3个月&#xff0c;腾讯云换手帕服务器服务器4核16G14M带宽66元一个月、277元3个月&#xff0c;8核32G22M配置115元1个月、345元3个月&#xff0c;16核64G3…

存储技术架构演进

一. 演进过程 存储技术架构的演进主要是从集中式到分布式的一种呈现&#xff0c;集中式存储模式凭借其在稳定性和可靠性方面的优势成为许多业务数据库的数据存储首选&#xff0c;顾名思义&#xff0c;集中式存储主要体现在集中性&#xff0c;一套集中式管理的存储系统&#xff…

python:socket基础操作(4)-《tcp客户端基础》

tcp就和udp不一样了&#xff0c;tcp是客户端和服务器端&#xff0c;如果想通过tcp发送数据&#xff0c;要先让tcp进行连接服务器端 tcp客户端 先让服务器端进行启动 import socketdef main():# 创建套接字tcp_client_socket socket.socket(socket.AF_INET,socket.SOCK_STREAM…

RSTP的P/A机制

如图所示根桥S1和S2之间新添加了一条链路,在当前状态下S2的另外几个端口p2是Alternate端口,p3是指定端口且处于Forwarding状态,p4是边缘端口。新链路连接成功后,P/A机制协商过程如下。 1.P0和P1两个端口马上都先成为指定端口发送RS TBPDU。 2.S2的P1口收到更优的RST BPD…

Google Chrome 中出现 ERR_SSL_KEY_USAGE_INCOMPATIBLE 错误

证书的方式发生了变化&#xff0c;出现了这个新错误&#xff0c;导致我无法浏览该网站。 可以右键属性获取位置 关闭导航器chrome并转到文件夹&#xff0c;找到Local State文件并删除 执行指令结束进程&#xff0c;重新打开浏览器即可 taskkill /im "chrome.exe"…

fastapi报错

初始化报错&#xff0c;非常低级错&#xff0c;扇自己10八张 app FastApi()

sqli.labs靶场(第18~22关)

18、第十八关 经过测试发现User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:122.0) Gecko/20100101 Firefox/122.0加引号报错 这里我们闭合一下试试 User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:122.0) Gecko/20100101 Firefox/122.0,127.0.0.1,adm…

深度解析指针与数组:探索内存管理的艺术

目录 1.数组名的理解 sizeof(数组名)&#xff0c;sizef中单独放数组名&#xff0c;这里的数组名表示整个数组&#xff0c;计算的是整个数组的大小&#xff0c;单位是字节 &数组名&#xff0c;这里的数组名表示整个数组&#xff0c;取出的是整个数组的地址 (整个数组的地…

CSS之定位

定位在CSS当中是一个比较重要的点&#xff0c;接下来&#xff0c;让我为大家介绍一下定位吧&#xff01; 属性描述position-relative相对定位position-absolute绝对定位position-fixed固定定位position-sticky粘性定位position-static静态定位 一、相对定位 给元素设置 posi…

BF16与FP16的区别

参考 BF16 与 FP16 在模型上哪个精度更高呢BF16 与 FP16 在模型上哪个精度更高呢【bf16更适合深度学习计算&#xff0c;精度更高】&#xff1a; 两者差异图示如下&#xff1a; BF16 是对FP32单精度浮点数截断数据&#xff0c;即用8bit 表示指数&#xff0c;7bit 表示小数。…

使用 FHEW-like 自举 BV-like

参考文献&#xff1a; [CDKS21] Chen H, Dai W, Kim M, et al. Efficient homomorphic conversion between (ring) LWE ciphertexts[C]//International Conference on Applied Cryptography and Network Security. Cham: Springer International Publishing, 2021: 460-479.[K…

Linux——磁盘和文件系统(一)

Linux——磁盘和文件系统 磁盘机械式磁盘固态硬盘 机械式磁盘结构磁盘&#xff0c;磁道&#xff0c;扇区柱面 文件系统的初始化划卷&#xff08;划盘&#xff09; 挂载C盘放了什么东西Boot Block&#xff08;启动模块&#xff09; 0号组放了什么东西Super Block&#xff08;超级…

Python爬取猫眼电影专业评分数据中的应用案例

在数据分析和可视化展示中&#xff0c;获取准确的电影专业评分数据至关重要。猫眼电影作为中国领先的电影信息与票务平台&#xff0c;其专业评分对于电影行业和影迷的数据来说具有重要意义。通过Python爬虫技术&#xff0c;我们可以实现从猫眼电影网站上自动获取这些数据目标。…