整个项目,从Bezier曲线的创建,到Coons Patch曲面的实现,再到网格的实现和优化,还有最后对表面的光顺,链接如下:
【CAD算法】【计算机图形学】Bezier贝塞尔曲线生成程序(python/numpy实现)[1]
【CAD算法】【计算机图形学】Coons Patch曲面生成程序(python/numpy实现)[2]
【CAD核心算法】基于Laplacian Smoothing的网格mesh优化算法(python实现)[3]
【CAD算法】【遗传算法】采用遗传算法优化Coons Patch曲面程序(python实现)[4]
【CAD算法】基于最速下降法(梯度下降)的最短路径实现(python实现)[5]

1.内容回顾

首先回顾一下,表示一个曲线,有两种方式,implicit表示法和参数表示法。
implicit表示法:通过XYZ坐标表示曲线。
优点:

  • Compact
  • Easy to check if a point belongs to the curve

缺点:

  • Difficult for curve evaluation
  • Difficult for partial curve definition

参数表示法:Represent the X, Y, Z coordinates as a function of a single parameter
优点:

  • Easy for curve evaluation.
  • Convenient for partial curve definition.
  • Many others such as easy for manipulation, intersection.

很明显,参数表示法在工程领域中被广泛运用。

参数表示法有6种,分别是:

  • Conic sections
  • Polynomial Curves
  • Hermite Curves
  • Bezier Curves
  • B-Splines
  • Non-Uniform Rational B-Splines (NURBS)

Conic sections:适用于描述圆锥曲线(圆/椭圆/双曲线/抛物线)。
Polynomial Curves:P(u) = [x(u) y(u) z(u)]T = a0 + a1u + a2u2 + a3u3 (0<=u<=1),这种表示法不能直观地通过改变a0到a3的值预测到曲线形状,一般不被运用。

Hermite Curves:P(u) = f0(u)P0 + f1(u)P1 + f2(u)P0’+ f3(u)P1’ (0<=u<=1),通过确定一条曲线两端点的坐标和斜率来确定一条曲线的坐标。同样不能直观地通过两端点的信息确定曲线的形状。
B spine:也就是B样条曲线,这种表示法得到最广泛的运用,它克服了Bezier曲线某一个控制点坐标变换会整体上地影响曲线形状这个缺点。
Bezier Curves:通过n+1个控制点的坐标,得到曲线的坐标。它的定义如下:

一定要注意,参数u的取值范围只能在0-1之间,包括端点。根据公式可知,只要知道了bezier曲线的维度n,也就是控制点数减一,就能计算出每一项的blending function的值,分别和控制点坐标相乘再求和,就能得到Bezier曲线的表达式。一旦确定了一个u的值,自然能得到对应曲线的坐标。如果想通过pyplot画出来,可以通过采样的方式,用很多个点来描述这个曲线。

2.题目描述

现在开始我们的程序。问题如下,用户通过txt或者控制台输入一组坐标,该程序能自动计算出Bezier曲线并通过画图软件画出来。
其中,输入信息格式如下:

Line 1           m          /*  Bezier 曲线的数量 */
Line 2           n1          /* 第一条Bezier曲线有多少个控制点 */
Line 3           0 or 1      /*0意味着该曲线首尾闭合, 1代表着首尾不相连 */
Line 4           第一个控制点坐标  /* 坐标之间通过“,”或空格分开 */
Line 5           第二个控制点坐标
.
.
.
Line n1+3        第n个控制点坐标

可能这么描述还不是很清楚,举一个例子:

2                           #一共需要绘制2条Bezier曲线
4                           #第一条曲线有4个控制点
1                           #第一条曲线首尾不相连
1.5     0.4 -3              #控制点的三维坐标
1.7     -2.56       4.78    #控制点的三维坐标
0           245.6   10      #控制点的三维坐标
0       0   0               #控制点的三维坐标
3                           #第二条曲线有4个控制点
0                           #第二条曲线首尾相连
3       5   -6              #控制点的三维坐标
-4      3.5 7               #控制点的三维坐标
1.5     -5  -10.5           #控制点的三维坐标

3.解决方案

3.1头文件引用和变量定义

import os
import numpy as np
import matplotlib
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
import pandas as pdnp.set_printoptions(suppress = True)
#database = []
m = np.array([],dtype = np.uint8) # the number of bazier curves
pointsNumber = np.array([],dtype = np.uint8) #for the ith curve, the points number of it
closedOrOpen = np.array([],dtype = np.uint8) #for the ith curve, 0 means it is open, 1 means it is closed
point = np.array([],dtype = np.float64) #the control points for all the curves

解释一下,以上四个变量均采用array数据类型,方便在内存中存放很多数据点并可视化。
其中,m是Bezier曲线数量;pointsNumber依次存放着每一条Bezier曲线的控制点数;closedOrOpen依次存放着每一条Bezier曲线是闭合的还是开放的bool数据;point依次存放着每一条Bezier曲线的全部特征点数,配合pointsNumber[i]指针可以很快定位到每一条Bezier曲线的第一个控制点在point数组中的位置。

3.2实现从txt文件的读取

def inputFromText():global filepathfilepath = os.path.abspath('.') + "/" + raw_input("please input the file name(eg:data.txt):")with open (filepath) as data:line_zero = data.readline()line_zero_list = list(line_zero.split())global mm = np.array(line_zero_list, dtype=np.uint8)for i in range(m[0]): pointsNumber_str = data.readline()pointsNumber_list = list(pointsNumber_str.split())temp1 = np.array(pointsNumber_list,dtype=np.uint8)global pointsNumberpointsNumber = np.append(pointsNumber,temp1) # the number of control points of the ith Bezier curveclosedOrOpen_str = data.readline()closedOrOpen_list = list(closedOrOpen_str.split())temp2 = np.array(closedOrOpen_list,dtype=np.uint8)global closedOrOpenclosedOrOpen = np.append(closedOrOpen,temp2) #0 means the ith curve is closed, 1 means it is openglobal pointfor j in range(temp1[0]):#u += 1point_str = data.readline()point_list = list(point_str.split())temp3 = np.array(point_list,dtype=np.float64)point = np.append(point,temp3) # control points for the ith Bezier Curvepoint = np.reshape(point, (-1,3))

读取txt采用python内置的文件操作函数。为了便于理解,采用循环方式依次读取txt的每一行,代码中没有介绍过的变量都是中间变量。

3.3 实现从控制台读取数据并保存数据到txt

def inputFromKeyboard(): m_int = input("the number of Beziercurve:") #the number of Beziercurveglobal mm = np.array([m_int],dtype = np.uint8)filename = raw_input("please input filename:(example: data.txt):")  #input can only read 1 word!with open(filename,mode="w") as file_txt:file_txt.write(str(m_int)+'\n') #change to string!!for i in range(m_int): pointsNumber_str = str(input("numbers of control points of the {}th Bezier curve:".format(i)))pointsNumber_list = list(pointsNumber_str.split())temp1 = np.array(pointsNumber_list,dtype=np.uint8)global pointsNumberpointsNumber = np.append(pointsNumber,temp1) # the number of control points of the ith Bezier curve#u += 1file_txt.write(pointsNumber_str + '\n')closedOrOpen_str = str(input("0 or 1: 0 means the ith curve is closed, 1 means it is open:")) #0 means the ith curve is closed, 1 means it is openclosedOrOpen_list = list(closedOrOpen_str.split())temp2 = np.array(closedOrOpen_list,dtype=np.uint8)global closedOrOpenclosedOrOpen = np.append(closedOrOpen,temp2) #0 means the ith curve is closed, 1 means it is openfile_txt.write(closedOrOpen_str + '\n')global pointfor j in range(temp1[0]):point_str = str(raw_input("the coordinates of control points for the {}th Bezier Curve (eg: '0 0 0'):".format(i))) # control points for the ith Bezier Curvepoint_list = list(point_str.split())temp3 = np.array(point_list,dtype=np.float64)point = np.append(point,temp3) # control points for the ith Bezier Curvefile_txt.write(point_str + '\n')

需要注意的是,保存到txt里的是string类型。

3.4实现Bezier曲线的核心程序

def drawCurve(closedOrOpen,pointsNumber,point,point_index):C = []n = pointsNumber - 1 # n is fewer in numbers than the total control points number. According to definition.point_show = np.array([],dtype=np.float64)for i in range(n+1):point_show = np.append(point_show,point[point_index + i])  if (closedOrOpen == 0): # if it is closed, means the oth and nth control points are the same.n += 1point_show = np.append(point_show,point[point_index])elif (closedOrOpen == 1):passpoint_show = point_show.reshape((-1,3))#根据Bizier曲线定义if ((n+1) % 2 == 0):for i in range((n+1) / 2):up = 1down = 1j = nwhile (j > i):up *= jj = j - 1j = n - iwhile (j > 0):down *= jj = j - 1C.append(up / down)elif ((n+1) % 2 == 1):for i in range(n / 2):up = 1down = 1j = nwhile (j > i):up *= jj = j - 1j = n - iwhile (j > 0):down *= jj = j - 1C.append(up / down)up = 1down = 1j = nwhile (j > n/2):up *= jj = j - 1j = n/2while (j > 0):down *= jj = j - 1C.append(up / down)if (n%2 == 1):for i in range(int((n+1)/2)):C.append(C[int(n/2-i)])if (n%2 == 0):for i in range(int((n+1)/2)):C.append(C[int(n/2-i-1)])print("C",C) f = np.array([],dtype=np.float64)u = 0fx = 0fy = 0 #not this place!!fz = 0#print(f_unit.shape)print("point_show\n",point_show)print("n+1",n+1)for j in range(100): fx = 0fy = 0  #do not forget return 0!fz = 0for i in range(n+1):#这一条语句和Bezier曲线的表达式对应上了fx += C[i] * u**i * (1-u)**(n-i) * point_show[i][0]fy += C[i] * u**i * (1-u)**(n-i) * point_show[i][1]fz += C[i] * u**i * (1-u)**(n-i) * point_show[i][2]list = []list.append(fx)list.append(fy) list.append(fz)array_list = np.array([list],dtype=np.float64) u += 0.01f = np.append(f,array_list)f_show = f.reshape((-1,3))print(f_show.shape)#print(f_show)#show the control lines!ax.plot(f_show[:,0],f_show[:,1],f_show[:,2],'b.',markersize=1,label='open bazier curve')#bezier曲线,把'b.'改为'-'可以得到连续的曲线ax.plot(point_show[:,0],point_show[:,1],point_show[:,2],'-',markersize=1, label='control line')#控制点的连线ax.plot(point_show[:,0],point_show[:,1],point_show[:,2],'r.',markersize=8, label='control points')#控制点print(point_show.shape[0])

注意,当closedOrOpen为0时,也就是说这是一条封闭的Bezier,那么需要在末尾再把这个曲线的第一个控制点push进array里, 这样就能首尾相连。

3.5 main()函数

inputType = input("Please choose data from text/0 or keyboard/1 ?:")
#print(inputType.type())if ( inputType == 0): # not '0'!!inputFromText()#从txt获取数据
elif ( inputType == 1):inputFromKeyboard()#从键盘获取数据point_index = 0
fig = plt.figure()
ax = fig.gca(projection='3d')for i in range(m[0]):#绘制m条Bezier曲线drawCurve(closedOrOpen[i],pointsNumber[i],point,point_index)point_index += pointsNumber[i]#获取每一条Bezier曲线第一个控制点在数组中的位置ax.legend()
ax.set_xlabel('X')
ax.set_ylabel('Y')
ax.set_zlabel('Z')
plt.show()

4.试验结果

这个结果是根据样例数据绘制,红色点为各个Bezier曲线的控制点,中间的点为Bezier曲线,如果在plt.plot()中增加"-"参数或者增加点数,j这条曲线就能更好看一些。

采用Ubuntu16.03进行调试,交互界面如上。下图为一个更加残暴的数据所绘制出来的图像。


所有代码的链接如下:https://github.com/iwander-all/CAD.git

参考文献
K. TANG, Fundamental Theories and Algorithms of CAD/CAE/CAM

【CAD算法】【计算机图形学】Bezier贝塞尔曲线生成程序(python/numpy实现)[1]相关推荐

  1. 计算机图形学作业( 七):利用 OpenGL 绘制 Bezier 贝塞尔曲线

    计算机图形学作业( 七):利用 OpenGL 绘制 Bezier 贝塞尔曲线 Bezier 曲线原理 OpenGL 实现思路 捕获鼠标点击时的坐标 根据顶点画出连续的线段 根据顶点画出 Bezier ...

  2. 计算机图形学中的曲线问题——贝塞尔曲线的绘制

    贝塞尔曲线的绘制 由于 CSDN 的博客修改字数的限制,我们不得不将这一部分放到一个新的博客中.原文详见: GGN_2015 计算机图形学中的曲线问题 贝塞尔曲线的几何作图法 在上面介绍儿时的回忆中, ...

  3. 计算机图形学中的曲线问题

    文章目录 免责 前言 拉格朗日插值多项式 第一步:得到一个基函数 第二步:得到所有基函数 第三步:对所有基函数进行线性组合 举例验证 拉格朗日插值曲线绘制实践 三次埃尔米特插值多项式 第一步:得到第一 ...

  4. 刘慎权逝世:中国CAD与计算机图形学先驱,川大数学系校友,享年92岁

    鱼羊 发自 凹非寺 量子位 | 公众号 QbitAI 巨星陨落! 昨晚,中科院计算所发布讣告称,我国计算机辅助设计(CAD)与计算机图形学领域杰出专家刘慎权先生,2022年10月12日在京逝世,享年9 ...

  5. 自动驾驶算法详解(5): 贝塞尔曲线进行路径规划的python实现

    一.理论知识 1.路径规划定义 路径规划智能物流.无人驾驶等智能领域中重要的组成部分.路径规划的目标是实现从目的地到终点之间寻找一条安全(无碰撞).高效(最短距离或 最短时间)的一条最优或接近最优的路 ...

  6. 做出新闻联播片头的人走了:齐东旭教授逝世,中国CAD与计算机图形学痛失巨匠...

    明敏 发自 凹非寺 量子位 | 公众号 QbitAI 中国CAD与计算机图形学领域巨匠齐东旭教授,不幸离世,享年83岁. <新闻联播>片头旋转地球的动画,正是出自他手. 齐东旭教授是澳门科 ...

  7. 计算机图形学Bezier曲线试题,《计算机图形学》试题-C卷及参考答案

    计算机图形学试题 C 一.选择题(20分) 1.计算机图形显示器一般使用什么颜色模型?(A ) A. RGB B. CMY C. HSV D. HLS 2.分辨率为1024×1024的显示器各需要多少 ...

  8. 计算机图形学空间曲线,课程追忆之《计算机图形学》【曲线曲面篇】

    大家好,距离上一篇博文将近一个月,时间过得好快,原本计划周更的,后面推到半月跟,实际到现在是月更,每次在准备写点什么的时候,都会被一些杂乱的事物打扰,哎,重度拖延症.懒癌晚期- 继上次述说了<计 ...

  9. [1106]python bezier(贝塞尔)曲线

    文章目录 三阶贝塞尔曲线 python bezier曲线 首先简单了解一下什么是贝塞尔曲线(余弦函数曲线我就不多说了哈!),贝塞尔曲线又称贝兹曲线,是法国工程师皮埃尔.贝塞尔于1962年发表.贝塞尔曲 ...

最新文章

  1. 三菱伺服电机选型手册_PLC触摸屏控制伺服电机程序设计
  2. java redis 批量删除key_Redis,就是这么朴实无华
  3. python树莓派串口通信实例_树莓派通过串口发送数据
  4. ROS 中文教程目录(最好不要过度依赖这种,建议养成看英文原版习惯)
  5. 苏宁数据中台架构实践,高清技术版
  6. python应聘要求_python爬取招聘要求等信息实例
  7. SAP PK Oracle
  8. BAT 文件 常用 代码 大全
  9. 获取苹果收集设备ID的方法
  10. 【SpringBoot教程】根据环境自动装配
  11. 常用性能工具:工欲善其事,必先利其器
  12. 让你的Linux支持WEB修改密码(转)
  13. 蚂蚁资深技术专家刘晓莹十年支付宝回忆录
  14. Frenetic Python实验(二)
  15. VS2017无法调试Unity
  16. viper4android io错误,Go之Viper
  17. 晨曦记账本,记账一目了然
  18. 《提问的智慧》读后感
  19. k8s 容器编排(高级版)
  20. R语言 主成分分析 代码

热门文章

  1. element vue 上传模板_Vue Element UI upload 组件上传文件之后 file list 依旧是空数组
  2. 在一家虚拟现实公司工作是什么感受?
  3. android checkbox 文字和图标间距,CheckBox选择框和文字设置间距
  4. 关于datanode进程无法启动的另一种解决方法 java.io.IOException: Incompatible clusterIDs in /export/servers/hadoop-3.1.
  5. c200系列服务器主板,主板厂商的曲线救主,E3-1230 v5/技嘉X150-PLUS WS主板评测
  6. itext 合并 pdf 并插入页码
  7. 对今天知识的回顾15
  8. 51单片机 | LED点阵实验 | 点亮一个点 | 显示数字 | 显示图像
  9. 编程范式(斯坦福大学)学习笔记《四》
  10. 图片转换为矩阵/矩阵转换为图片