资源下载地址:https://download.csdn.net/download/sheziqiong/86768948
资源下载地址:https://download.csdn.net/download/sheziqiong/86768948

基本图形生成算法

直线段

基础算法

计算斜率和截距,通过y = kx + b的直线表达式计算每一个x对应的y

'''基础算法'''
def drawLine_Basic(grid, start, end):k = (end.y-start.y)/(end.x-start.x)b = start.y - k * start.xfor xi in range(start.x, end.x):    # 栅格的性质yi = k * xi + bdrawPixel(xi, int(yi+0.5), 1, grid)     # y坐标要进行近似



数值微分算法(DDA)

  • 采用**“增量”**的思想

    • |k|<=1时,x每增加1y增加k
    • |k|>1时,y每增加1x增加1/k
  • 证明: (这里只考虑|k|<=1当情况)

    由xi+1=xi+1x_{i+1} = x_{i} + 1xi+1​=xi​+1

    yi+1=k∗xi+1+b=k∗(xi+1)+b=k∗xi+b+k=yi+ky_{i+1} = k*x_{i+1} + b = k*(x_{i}+1) + b = k*x_{i} + b + k = y_{i} + kyi+1​=k∗xi+1​+b=k∗(xi​+1)+b=k∗xi​+b+k=yi​+k

'''数值微分算法(DDA)'''
def drawLine_DDA(grid, start, end):k = (end.y - start.y) / (end.x - start.x)xi, yi = start.x, start.yif(abs(k<=1)):for xi in range(start.x, end.x):drawPixel(xi, int(yi+0.5), 1, grid)yi += kelse:for yi in range(start.y, end.y):drawPixel(int(xi+0.5), yi, 1, grid)xi += 1/k


如果不对k进行分类讨论

不对k进行分类讨论 ![在这里插入图片描述](https://img-blog.csdnimg.cn/d1bbad90a0874dc3aaa6a9f8e584cfbe.png) 对k进行分类讨论 ------

中点画线法

  • 直线方程为:ax + by + c =0

    • a = y0 - y1
    • b = x1 - x0
    • c = x0y1 - x1y0
  • **考核点:**(xp+1, yp+0.5)

  • 判别式:Δ=F(xp+1,yp+0.5)=a∗(xp+1)+b∗(yp+0.5)+c\Delta = F(x_p+1, y_p+0.5) = a*(x_p+1) + b*(y_p+0.5) + cΔ=F(xp​+1,yp​+0.5)=a∗(xp​+1)+b∗(yp​+0.5)+c

    • 如果Δ<0\Delta<0Δ<0 => Q点在M下方 => 选p2 (x+1, y+1)

    • else, 选p1 (x+1, y)

'''中点画线法(k<=1)'''
def drwaLine_MidPoint(grid, start, end):a, b, c = start.y-end.y, end.x-start.x, start.x*end.y-end.x*start.yxp, yp = start.x, start.yfor xp in range(start.x, end.x):drawPixel(xp, yp, 1, grid)delta = a*(xp+1) + b*(yp+0.5) + c   # 考核点(xp+1, yp+0.5)if delta<0:yp += 1else:# yp += 0pass


在中点画线法中添加增量的思想

  • 若取p1,增量为a
  • 若取p2,增量为a+b
  • 初值d0 = a + 0.5*b
  • 由于只用d的符号来判断,可以用2d代替d,摆脱浮点数
'''中点画线法 with DDA'''
def drawLine_MidPoint_with_DDA(grid, start, end):a, b = start.y-end.y, end.x-start.xd = a + (b<<2)      # 用2d代替d, 摆脱小数d1, d2 = a<<2, (a+b)<<2xp, yp = start.x, start.yfor xp in range(start.x, end.x):drawPixel(xp, yp, 1, grid)if d<0:yp += 1d += d2else:d += d1



Bresenham画线法

  • 误差项符号决定下一个像素选正右方还是右上方
  • 判别式:ε=yi+1−yi,r−0.5\varepsilon = y_{i+1} - y_{i,r} - 0.5ε=yi+1​−yi,r​−0.5
    • ε>0\varepsilon > 0ε>0, 取右上 (x+1, y+1)
    • else,取正右 (x+1, y)
  • 引入增量思想:
    • ε>0\varepsilon > 0ε>0,增量为 k-1
    • else,增量为 k
    • 初始值:-0.5
'''Bresenham画线法(k<=1)'''
def drawLine_Bresenham(grid, start, end):k = (end.y - start.y) / (end.x - start.x)x, y = start.x, start.ye = -0.5for x in range(start.x, end.x):drawPixel(x, y, 1, grid)if e > 0:e += k - 1y += 1else:e += k# y += 0


去点浮

  • 用ε′=2∗ε∗dx\varepsilon' = 2 * \varepsilon * dxε′=2∗ε∗dx代替ε\varepsilonε
  • 去掉k的计算
  • 引入增量思想:
    • ε>0\varepsilon > 0ε>0,增量为 2(dy - dx)
    • else,增量为 2dy
    • 初始值-dx
'''Bresenham画线法(去点浮)(k<=1)'''
def drawLine_Bresenham_nonreal(grid, start, end):dx, dy = (end.x - start.x), (end.y - start.y)x, y = start.x, start.ye = -dxfor x in range(start.x, end.x):drawPixel(x, y, 1, grid)if e > 0:e += (dy - dx) << 2y += 1else:e += (dy) << 2# y += 0



圆弧

暴力算法

  • y2=R2−x2y^2 = \sqrt{R^2 - x^2}y2=R2−x2​


中点画圆法

  • 只需画1/8圆(第一象限 y>x 部分)
  • 判别式:F(x,y)=x2+y2−R2F(x,y) = x^2 + y^2 - R^2F(x,y)=x2+y2−R2
    • F>0,取正右方 (x+1, y)
    • else,取右下方 (x+1, y-1)
  • 增量思想:
    • d<0, 增量为 2*x + 3
    • else, 增量为 2*(x-y) + 5
    • 初始值:1.25 - R
  • **去点浮:**用e = d - 0.25代替 d
    • 初始值:e = 1-R
    • 循环条件:d < 0 <=> e < 0.25 <= e始终为整数 => e < 0
'''中点画圆法(DDA)'''
def drawArc_MidPoint_with_DDA(grid, R):d = 1 - Rx, y = 0, Rwhile x < y:drawPixel_symmetry8(x, y, 1, grid)if d < 0:x += 1d += 2*x + 3else:x += 1y -= 1d += ((x-y) << 1) + 5

对增量本身再次使用增量思想

  • x递增1,d递增Δx=2\Delta x = 2Δx=2
  • y递减1,d递增Δy=2\Delta\ y = 2Δ y=2
  • 初始值:
    • Δx=3\Delta x = 3Δx=3
    • Δy=−2r+2\Delta\ y = -2r + 2Δ y=−2r+2
'''中点画圆法(DDA)(去点浮)'''
def drawArc_MidPoint_with_DDA_nonreal(grid, R):d = 1 - Rdeltax, deltay = 3, 2 - (R << 1)x, y = 0, Rwhile x < y:drawPixel_symmetry8(x, y, 1, grid)if d < 0:x += 1d += deltaxdeltax += 2else:x += 1y -= 1d += (deltax + deltay)deltax += 2deltay += 2


Bresenham画圆法

  • 选取距离真正的圆曲线近的点进行扩展

    如果|OP1| > |OP2|,则选P2

    <=> x12+y12−R2>R2−x22−y22\sqrt{x_1^2 + y_1^2 - R^2} > \sqrt{R^2 - x_2^2 - y_2^2}x12​+y12​−R2​>R2−x22​−y22​​

    <=> x12+y12+x22+y22−2R2>0x_1^2 + y_1^2 + x_2^2 + y_2^2 - 2R^2 > 0x12​+y12​+x22​+y22​−2R2>0

  • 当前像素的下一个扩展节点:正右方右下方正下方

  1. H
  2. HD中选更近的
  3. D
  4. VD中选更近的
  5. V
  • 令ΔH=∣OH∣\Delta H = |OH|ΔH=∣OH∣, ΔD=∣OD∣\Delta D = |OD|ΔD=∣OD∣, ΔV=∣OV∣\Delta V = |OV|ΔV=∣OV∣

    令δHD=∣ΔH∣−∣ΔD∣=∣OH∣−∣OD∣\delta HD = |\Delta H| - |\Delta D| = |OH| - |OD|δHD=∣ΔH∣−∣ΔD∣=∣OH∣−∣OD∣, δDV=∣ΔD∣−∣ΔV∣\delta DV = |\Delta D| - |\Delta V|δDV=∣ΔD∣−∣ΔV∣

    1. δHD=2ΔD+2y−1\delta HD = 2\Delta D + 2y - 1δHD=2ΔD+2y−1

    2. δDV=2ΔD−2x−1\delta DV = 2\Delta D - 2x - 1δDV=2ΔD−2x−1

      • ΔD>0\Delta D > 0ΔD>0,若δDV<=0\delta DV <= 0δDV<=0,取D;else取V
      • ΔD<0\Delta D < 0ΔD<0,δHD<=0\delta HD <= 0δHD<=0,取H;else,取D
      • ΔD=0\Delta D = 0ΔD=0,取D
  • 用增量法简化ΔD\Delta DΔD,下一个像素取:

    • H,增量取2x + 1
    • D,增量取2x - 2y + 2
    • V,增量取-2y + 1
    • 初始值:-2r + 2
'''Bresenham画圆法'''
def drawArc_Bresenham(grid, R):delta = (1 - R) << 1x, y = 0, Rwhile y >= 0:drawPixel_symmetry4(x, y, 1, grid)if delta < 0:delta1 = ((delta + y) << 1) - 1if delta1 <= 0:direction = 1else:direction = 2elif delta > 0:delta2 = ((delta - x) << 1) - 1if delta2 <= 0:direction = 2else:direction = 3else:direction = 2if direction == 1:      # 前进到 正右x += 1delta += (x << 1) + 1elif direction == 2:    # 前进到 右下x += 1y -= 1delta += ((x - y) << 1) + 2else:                   # 前进到 正下y -= 1delta += 1 - (y << 1)


正负法

  • 圆方程:F(x,y)=x2+y2−R2F(x,y) = x^2 + y^2 - R^2F(x,y)=x2+y2−R2
  • 设P(xi,yi)P(x_i, y_i)P(xi​,yi​)
    • P在圆内 -> D(xi,yi)<=0D(x_i,y_i) <= 0D(xi​,yi​)<=0 -> 向右
    • P在圆外 -> D(xi,yi)>0D(x_i,y_i) > 0D(xi​,yi​)>0 -> 向下
  • 引入增量思想:
    • F<=0,增量为2x + 1
    • else,增量为-2y + 1
    • 初始值:0
'''正负法'''
def drawArc_PositiveNegative(grid, R):F = 0x, y = 0, Rwhile x <= y:drawPixel_symmetry8(x, y, 1, grid)print(F)if F <= 0:F += (x << 1) + 1x += 1else:F += 1 - (y << 1)y -= 1


圆内接正多边形逼近法

  • limn−>∞(n边正内接多边形)=圆lim_{n->\infin}(n边正内接多边形) = 圆limn−>∞​(n边正内接多边形)=圆

    • 工程上,n−>2πRn -> 2\pi Rn−>2πR就可以了,两个点的距离达到1pixel之后再小也没用了
  • 圆的参数方程:

    • xi=Rcosθix_i = Rcos\theta_ixi​=Rcosθi​
    • yi=Rsinθiy_i = Rsin\theta_iyi​=Rsinθi​
  • 引入增量思想:
    (xi+1yi+1)=(cosα−sinαsinαcosα)(xiyi)=(cosαxi−sinαyisinαxi+cosαyi)(\begin{matrix}x_{i+1} \\ y_{i+1} \end{matrix}) = (\begin{matrix}cos\alpha & -sin\alpha \\ sin\alpha & cos\alpha \end{matrix})(\begin{matrix}x_{i} \\ y_{i} \end{matrix}) = (\begin{matrix}cos\alpha x_i - sin\alpha y_i \\ sin\alpha x_i + cos\alpha y_i \end{matrix}) (xi+1​yi+1​​)=(cosαsinα​−sinαcosα​)(xi​yi​​)=(cosαxi​−sinαyi​sinαxi​+cosαyi​​)

'''圆内接正多边形逼近法'''
def drawArc_InscribedRegularPolygonApproximate(grid, R):Alpha = 1/RcosAlpha, sinAlpha = cos(Alpha), sin(Alpha)x, y = R, 0while x >= y:drawPixel_symmetry8(int(x+0.5), int(y+0.5), 1, grid)x = cosAlpha * x - sinAlpha * yy = sinAlpha * x + cosAlpha * y


资源下载地址:https://download.csdn.net/download/sheziqiong/86768948
资源下载地址:https://download.csdn.net/download/sheziqiong/86768948

Python实现的直线段生成算法和圆弧生成算法相关推荐

  1. 中点分割裁剪算法 c语言,裁剪算法——中点分割算法/Liang-Barsky算法

    三.中点分割法 首先对直线段的端点进行编码. [核心思想:通过二分逼近来确定直线段与窗口的交点.] 具体方法: 1.若中点不在窗口内,则把[中点]和离窗口边界[最远点]构成的线段丢掉,以线段上的另一点 ...

  2. 计算机图形学:直线段的生成算法,VS实现数值微分法和中点Bresenham算法

    实验要求: 实现直线段生成的两种方法: 1) 数值微分法 和 2) 中点Bresenham算法.用户用鼠标点击两个点,两个点都确定后,利用直线段的绘制算法绘制两个点之间的一条直线段.本文章仅涉及算法的 ...

  3. 计算机图形学直线段的生成算法

    计算机图形学直线段的生成算法C++实现,包括:DDA,中点画线,改进的Bresenham画线 文章目录 1.实验目的和内容 1.1实验目的 1.2实验内容 2.算法原理 2.1 DDA(数值微分算法) ...

  4. 直线段检测算法(LSD:a Line Segment Detector)

    直线段检测算法(LSD:a Line Segment Detector) 1 简介 LSD是一种线段检测算法,该方法能在较短的时间内获得较高精度的直线段检测结果. LSD直线检测算法首先计算图像中所有 ...

  5. MFC鼠标绘制直线段并使用编码裁剪算法

    聪明的你通过本文可以学会在MFC中 初始化时绘制自定义矩形框 使用鼠标来实时绘制你想要的直线段 实现编码裁剪算法裁去直线段在自定义矩形框以外的部分 完成效果如下 进入运行界面 鼠标绘制直线 编码算法裁 ...

  6. 计算机图形学-扫描转换直线段-直线方程法-DDA算法-中点算法-OPENGL实现-详解

    扫描转换直线段 说明与环境配置 环境配置 扫描转换直线段 方法一: 直线方程法 代码描述: 算法比较简单, 暂无代码. 方法二: 数字差分分析DDA算法 代码描述: 方法三: 中点算法 代码描述: 所 ...

  7. 直线段检测算法---LSD

    直线段检测算法---LSD:a Line Segment Detector LSD的核心是像素合并于误差控制.利用合并像素来检测直线段并不是什么新鲜的方法,但是合并像素的方法通常运算量较大.LSD号称 ...

  8. 【转】 LSD(Line Segment Detector) 直线段检测算法学习~

    论文回顾之一 一种新的直线段检测算法---LSD:a Line Segment Detector 原文地址:http://blog.csdn.net/polly_yang/article/detail ...

  9. 实验二 实现中点分割直线段裁剪算法

    一.目的 1. 了解直线裁剪的基本原理和常用方法. 2. 掌握中点分割直线段裁剪算法的基本原理和步骤. 3. 使用C++.OpenGL编程实现如下内容:输入直线段的起始点和终止点坐标位置.用四边形模拟 ...

最新文章

  1. 初见shell,设置端口参数
  2. 多功能复合机基于用户认证功能的实现过程详解
  3. java ee maven_真正释放Maven和Java EE的强大功能
  4. nginx下只能通过域名,禁止使用ip访问
  5. python流程控制框架_Python基础(相关历史、交互、简单流程控制)
  6. android 克隆对象,克隆会破坏单例对象吗?
  7. 查找有序数组中某个数首次出现的位置
  8. Java学习之反射机制及应用场景
  9. C++ 常量引用用法
  10. 深度学习笔记 —— 卷积层
  11. 计算机在机械工程中的应用英语作文,关于机械工程英语作文
  12. Windows系统邮件中如何绑定QQ邮箱
  13. 由于CredSSP加密数据库修正
  14. C stdlib.h
  15. Excel办公中的应用(中秋快乐学习)(注意:全部为英文符号)
  16. Debian虚拟机安装常用软件
  17. Linux人机界面用什么软件,浙江Linux人机界面品牌,人机界面界面设计品牌
  18. c# 实现两个窗体来回跳转
  19. 阅读笔记:What Uncertainties Do We Need in Bayesian Deep Learning for Computer Vision?
  20. 大数据技术 学习笔记

热门文章

  1. python字符串匹配验证邮箱地址_Python-如何检查有效的电子邮件地址?
  2. 网球小组赛对阵表如何php,2019上海网球大师赛决赛对阵表+看点
  3. 植物大战僵尸老是报错不能运行如何解决
  4. 漫谈物理设计 - Floorplan
  5. 百事可乐高级副总裁兼Tom Trainer:领导力、IT
  6. 【已解决】除非另外还指定了 TOP、OFFSET 或 FOR XML,否则,ORDER BY 子句在视图...
  7. ES6 浅谈箭头函数,双冒号符号
  8. Java数据结构的实现
  9. 每天在家带娃的全职宝妈,做什么副业合适?
  10. 创维代工M302A(2+8)、E900V22E(2+8)、E900V21E、E900V21C晶晨S905L3-B通刷卡刷固件及教程分享