# 计算机图形学大作业
# 一、综述
在老师所给框架代码上进行修改完善,完成了所有要求的指令输入输出,GUI 界面实现了 CLI 部分的所有功能,包括设置画笔颜色、重置画布、保存画布、两种算法绘制线段、两种算法绘制多边形、绘制椭圆、两种算法绘制曲线、平移、旋转、缩放和两种算法裁剪线段。
额外实现了如下内容:
点击画布右、下、右下角边框调整画布大小; 点击画布选择图元; 编辑时显示平移等操作控制点。
删除选中图元,复制选中图元,粘贴已复制图元。
绘制虚线段; 凸多边形和椭圆填充。
更美观的界面。
# 二、算法介绍
## 绘制线段
### DDA 算法
基本思想是记下起点,然后让长的一边变量不断加一,短的一边则不断加斜率乘 1 后近似为 int 值.代码参照[7].
### Bresenham 算法
基本思想其实和 DDA 是一样的.只是 Bresenham 算法通过变形避免了浮点运算.这样一来,既提高了运算的效率,又避免了浮点数不断累加造成的长线段误差.所以本质上,Bresenham 是 DDA 算法的优化形式.代码参照[7].
### 代码处理
特判使得能够处理两端点相等的情况。
因为讲义中说不要求像素级一致,所以和伪代码一样只亮一边端点,即线段点的范围[P0,P1)。
### 绘制多边形
默认指令中的点是排好序的, 直接调用线段绘制算法按顺序连点。
### 绘制椭圆
使用 ppt 上的中点椭圆算法, 先画出 1/4 椭圆, 然后对称. 画 1/4 椭圆时,根据是否到达切线斜率为-1 的位置, 来判断选点的方向是基于 x 还是基于 y, 再根据实际椭圆上的点离哪个点更近取近似。
实际代码要先求出中心和长短轴, 然后以中心为原点求点, 再映射回原来的坐标系。
对称的时候考虑了 x 轴和 y 轴上的特例, 不然 x=0 和 y=0 的点对称后相当于 1 个点出现了两次。
代码流程参考书上 ppt 相关部分。
### 绘制曲线
### Bezier 曲线
书上给出了 Bezier 曲线关于控制点的参数方程和矩阵形式, 但直接这样计算参数 u 对应的点效率太低, 于是又给出了 de Casteljau 递推算法来快速计算一个 u 值对应的曲线上点的坐标。
有了这个递推算法后, 由于参数 u 位于[0,1]之间,理论上我们只要将[0,1]分割的足够小,就可以得到精度足够高的一条 Bezier 曲线。
但这样分割, 为了确保精度, 我们往往要将步长设置的非常小, 从而导致计算次数过多. 于是书上给出了一种二分逼近的办法.也就是每次先计算 u=1/2 处的点, 然后用这个点将曲线分为两段, 再对这两段曲线进行 u 值的二分, 重复这个二分的操作, 最后每段曲线的控制多边形会很接近理论曲线, 就可以直接拿控制多边形当作实际曲线。
实现参考[9]中 6.3.3 和 6.3.4。
### spline 曲线
B 样条曲线的绘制本质上和 Bezier 没什么不同, 都是要根据递推式求参数 u 对应的离散点. 但具体实现起来还是有所不同的。
B 样条曲线实际上是按照次数进行分段绘制的, k 次 B 样条就是每 k+1 个控制点一段, 相邻两段有 k 个公共控制点, 这也解释了为什么它具有局部性。
不过, 由于它的控制多边形不像 Bezier 曲线那样可以随着二分不断逼近, 在具体绘制一段 B 样条曲线时, 只能设置步长密集取点, 这既导致了步长取密时曲线会变粗(重叠部分), 也导致了效率的降低。
实现参考[8]。
代码处理
B-spline 曲线绘制其中一段时, 目前选择取 100 个离散点, 再往大取 GUI 绘制时就会很卡。
### 平移
平移部分参考 ppt, 直接令各图形的控制点偏移[dx,dy]即可。
### 旋转
旋转部分参考 ppt, 直接套用公式, 各图形的控制点相对于旋转中心[x,y]顺时针旋转 r 度即可。
### 缩放
缩放部分参考 ppt, 直接套用公式, 控制点相对于缩放中心[x,y]缩放 s 倍即可。
### 裁剪
### Cohen-Sutherland
这个算法的特别之处在于位运算的思想,用 4 位二进制数表示左右上下四个位置的是否. 接着再分类讨论不同情况下线段裁剪时, 就可以用位运算来判断怎么裁剪线段. 它会重复裁剪直到线段完全在窗口内或者完全在窗口外. 代码参考[6]。
### Liang-Barskey 算法
这个算法不同于 Cohen-Sutherland 算法, 它希望一步直接将线段裁剪出来, 而不是重复裁剪. 它用 P = P1 + u (P2 P1)来表示直线 P, 并分情况判断和裁剪窗口相交点处的 u1,u2 值, 根据 u1,u2 的情况来判断结果. 代码参考[2]和 ppt。
## 二.系统介绍
### CLI 框架
沿用了老师的框架, 每次进行绘制图元或编辑图元操作时, 将需要的绘制信息储存在字典 item dict 中, 等到 save Canvas 时再根据每个 item 的 item type, 调用相应算法计算图元的像素点, 并修改 canvas 中的值。
### GUI 框架
gui 部分沿用了老师 MainWindow(继承 QMainWindow)作为主窗口, MyCanvas(继承 QGraphicsView)作为画布, MyItem(继承 QGraphicsItem)储存图元信息的框架。
原始代码由于点击绘制图元和在画布上 press mouse 时都调用 get id 方法, 使 item cnt 加 1,因此图元编号并不连续. 对此进行了修改, 令 get id 方法不修改 item cnt, 另外声明方法 id inc 来修改 item cnt。
窗口布局情况如下图:
最上面是菜单栏,由 self.menuBar()方法返回, 可以进行设置画笔颜色等操作。
下面一行是编辑工具栏,由 self.addToolBar 方法添加, 可以对图元进行平移等操作。
左边是绘图工具栏,由 self.addToolBar 方法添加, 可以选择要绘制的图元类型及算法。
右边窗口显示图元类型及编号, 由 self.list widget()返回, 点击可以用于选择图元。
下方状态栏, 由 self.statusBar()方法返回, 显示当前在进行什么操作。
最中间的则是画布区域, 定义 MyCanvas 类, 可以用鼠标操作绘图。
![](https://www.writebug.com/myres/static/uploads/2022/6/20/3adf15b5e2d4ebe8da029bbdbada31c0.writebug)
### GUI 功能
#### 菜单栏
画笔颜色选择参考了[3], 利用 QColorDialog 唤出调色板, 将选取的颜色值存在全局变量 g penColor 中, 每次要绘制图元的时候将 g penColor 作为画笔颜色, 关键代码如下:
```c++
global gpenColor
color = QColorDialog . getColor( )
gpenColor = color
```
重置画布操作也参考了[3], 调用两次 QInputDialog 获取新画布的 x,y 轴大小, 然后清空画布和场景, 初始化各个变量。
保存画布的代码参考了[1], 利用 QFileDialog.getSaveFileName 输入要生成文件的目录和名字, 然后再用 QGraphicsScene 的 render 方法将画布的内容储存到 QPixmap 类中, 最后用 QPixmap 类的 save 方法生成文件.关键代码如下:
```c++
fname = QFileDialog . getSaveFileName ( self,’Save file’,\’/home/output/ default ’,’Image files(.bmp)’)
# cancel save
if (fname[0]== ’’) :
return
# Get QRectF
rect = self . scene . sceneRect ()
# Create a pixmap , fill with white color
pixmap = QPixmap( g width , g height)
# set background white
pixmap . fill (QColor(255 ,255 ,255))
# painter
painter = QPainter(pixmap)
# Render scene to the pixmap
self.scene.render ( painter,rect,rect)
painter.end ()
# save bmp file
pixmap . save (fname [0])
```
#### 2.6.3 绘图工具栏
绘制线段和绘制椭圆其实是类似的, 都是先在 mousePressEvent 中记录一个端点, 然后在 mouseMoveEvent 中记录另一个端点, 然后利用 updateScene 方法更新画布, 这样在 MyItem 类中会自动调用 paint 方法绘制图形。
绘制多边形又和绘制曲线类似, 都是�
没有合适的资源?快使用搜索试试~ 我知道了~
温馨提示
资源包含文件:课程论文word+运行说明书+演示视频+源码及资料文件+项目截图 完成了所有要求的指令输入输出,GUI界面实现了CLI部分的所有功能,包括设置画笔颜色、重置画布、保存画布、两种算法绘制线段、两种算法绘制多边形、绘制椭圆、两种算法绘制曲线、平移、旋转、缩放和两种算法裁剪线段. 额外实现了如下内容: •点击画布右、下、右下角边框调整画布大小; 点击画布选择图元; 编辑时显示平移等操 作控制点. •删除选中图元,复制选中图元,粘贴已复制图元. •绘制虚线段; 凸多边形和椭圆填充. •更美观的界面. 详细介绍参考:https://biyezuopin.blog.csdn.net/article/details/125402176
资源推荐
资源详情
资源评论
收起资源包目录
基于PythonGUI实现的绘图工具软件设计.zip (84个子文件)
运行说明书.pdf 1.62MB
运行说明书.docx 847KB
基于PythonGUI实现的绘图工具软件设计 源码及资料文件
myoutput.md.md 17KB
171240511_6
icons
art-prices.png 7KB
select.png 8KB
ellipse.png 3KB
clip.png 3KB
curve_bs.png 2KB
move.png 2KB
padding.png 2KB
copy.png 2KB
pencil.png 1KB
rotate.png 2KB
clip_c.png 4KB
polygon_b.png 2KB
exit.png 6KB
line_d.png 836B
clip_l.png 3KB
delete.png 4KB
curve_be.png 2KB
scale.png 1KB
polygon_d.png 2KB
save.png 3KB
paste.png 2KB
reset.png 3KB
dotted_line.png 2KB
line_b.png 864B
source
cg_gui.py 41KB
cg_algorithms.py 17KB
cg_cli.py 5KB
LICENSE 1KB
暂时放报告
171240511_报告.doc 96KB
total.png 53KB
cgref.bib 2KB
171240511_报告.tex 18KB
171240511_报告.out 3KB
171240511_报告.pdf 694KB
imgs
文件结构.png 53KB
.gitignore 101B
CG_demo
cg_gui.py 41KB
cg_algorithms.py 17KB
yinput.txt 509B
cg_cli.py 5KB
test3.txt 529B
translate.txt 843B
rotate.txt 837B
clip.txt 953B
scale.txt 800B
cg_input_massimo.txt 1KB
test2.txt 1KB
test1.txt 596B
README.md 16KB
截图
L3N5M$[M]JWHD7%T9DARX}B.png 70KB
%_}AW67@)73`0AU$K(M0J3A.png 39KB
JNS`08FSU0)(4A3F$RT)V{U.png 508KB
total.png 53KB
6T4H[_C6]LT4[MELFDB{XGQ.png 41KB
translate1.png 56KB
choose.png 58KB
rotate2.png 56KB
AA[{O4FUNMARQW)4{Y``{)U.png 163KB
ellipse.png 57KB
color.png 141KB
clip.png 285KB
FG6I9ZD`WY4GKOWLJ}@)KTY.png 185KB
]_GL{LU01ZPQAGF~W%86N`2.png 44KB
scale1.png 56KB
translate2.png 56KB
rotate1.png 56KB
padding.png 59KB
scale2.png 55KB
paste2.png 59KB
delete.png 52KB
curve.png 57KB
polygon.png 57KB
paste1.png 58KB
save.png 45KB
line.png 55KB
delete1.png 57KB
reset.png 59KB
dotted_line.png 55KB
delete2.png 54KB
基于PythonGUI实现的绘图工具软件设计 课程论文.docx 113KB
演示视频.mp4 15.05MB
共 84 条
- 1
shejizuopin
- 粉丝: 1w+
- 资源: 1300
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
最新资源
资源上传下载、课程学习等过程中有任何疑问或建议,欢迎提出宝贵意见哦~我们会及时处理!
点击此处反馈
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功
- 1
- 2
前往页