基本图形生成算法

直线段

基础算法

计算斜率和截距,通过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.x

  for xi in range(start.x, end.x):    # 栅格的性质
    yi = k * xi + b
    drawPixel(xi, int(yi+0.5), 1, grid)     # y坐标要进行近似

python 曲线垂直斜率 python求直线斜率_python 曲线垂直斜率


python 曲线垂直斜率 python求直线斜率_概率论_02


数值微分算法(DDA)

  • 采用**“增量”**的思想
  • |k|<=1时,x每增加1y增加k
  • |k|>1时,y每增加1x增加1/k
  • 证明: (这里只考虑|k|<=1当情况)
    python 曲线垂直斜率 python求直线斜率_算法_03
    python 曲线垂直斜率 python求直线斜率_python_04
'''数值微分算法(DDA)'''
def drawLine_DDA(grid, start, end):
  k = (end.y - start.y) / (end.x - start.x)
  xi, yi = start.x, start.y

  if(abs(k<=1)):
    for xi in range(start.x, end.x):
      drawPixel(xi, int(yi+0.5), 1, grid)
      yi += k
  else:
    for yi in range(start.y, end.y):
      drawPixel(int(xi+0.5), yi, 1, grid)
      xi += 1/k

python 曲线垂直斜率 python求直线斜率_概率论_05


python 曲线垂直斜率 python求直线斜率_直线段生成算法_06

如果不对k进行分类讨论

python 曲线垂直斜率 python求直线斜率_概率论_07

不对k进行分类讨论

![在这里插入图片描述]() 对k进行分类讨论 ------

中点画线法

  • 直线方程为:ax + by + c =0
  • a = y0 - y1
  • b = x1 - x0
  • c = x0y1 - x1y0
  • **考核点:**(xp+1, yp+0.5)
  • 判别式:python 曲线垂直斜率 python求直线斜率_python 曲线垂直斜率_08
  • 如果python 曲线垂直斜率 python求直线斜率_算法_09 => Q点在M下方 => 选p2 (x+1, y+1)
  • else, 选p1 (x+1, y)

python 曲线垂直斜率 python求直线斜率_python 曲线垂直斜率_10

'''中点画线法(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.y

  xp, yp = start.x, start.y
  for 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 += 1
    else:
      # yp += 0
      pass

python 曲线垂直斜率 python求直线斜率_python 曲线垂直斜率_11


python 曲线垂直斜率 python求直线斜率_python 曲线垂直斜率_12

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

  • 若取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.x

  d = a + (b<<2)      # 用2d代替d, 摆脱小数
  d1, d2 = a<<2, (a+b)<<2

  xp, yp = start.x, start.y
  for xp in range(start.x, end.x):
    drawPixel(xp, yp, 1, grid)

    if d<0:
      yp += 1
      d += d2
    else:
      d += d1

python 曲线垂直斜率 python求直线斜率_概率论_13


python 曲线垂直斜率 python求直线斜率_python_14


Bresenham画线法

  • 误差项符号决定下一个像素选正右方还是右上方
  • 判别式:python 曲线垂直斜率 python求直线斜率_python 曲线垂直斜率_15
  • python 曲线垂直斜率 python求直线斜率_python_16, 取右上 (x+1, y+1)
  • else,取正右 (x+1, y)
  • 引入增量思想:
  • python 曲线垂直斜率 python求直线斜率_python_16,增量为 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.y
  e = -0.5

  for x in range(start.x, end.x):
    drawPixel(x, y, 1, grid)

    if e > 0:
      e += k - 1
      y += 1
    else:
      e += k
      # y += 0

python 曲线垂直斜率 python求直线斜率_python 曲线垂直斜率_18


python 曲线垂直斜率 python求直线斜率_直线段生成算法_19

去点浮

  • python 曲线垂直斜率 python求直线斜率_算法_20代替python 曲线垂直斜率 python求直线斜率_算法_21
  • 去掉k的计算
  • 引入增量思想:
  • python 曲线垂直斜率 python求直线斜率_python_16,增量为 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.y
    e = -dx

    for x in range(start.x, end.x):
      drawPixel(x, y, 1, grid)

      if e > 0:
        e += (dy - dx) << 2
        y += 1
      else:
        e += (dy) << 2
        # y += 0

python 曲线垂直斜率 python求直线斜率_直线段生成算法_23


python 曲线垂直斜率 python求直线斜率_算法_24


圆弧

暴力算法

  • python 曲线垂直斜率 python求直线斜率_python 曲线垂直斜率_25

python 曲线垂直斜率 python求直线斜率_python 曲线垂直斜率_26


中点画圆法

  • 只需画1/8圆(第一象限 y>x 部分)
  • 判别式:python 曲线垂直斜率 python求直线斜率_概率论_27
  • 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 - R

  x, y = 0, R
  while x < y:
    drawPixel_symmetry8(x, y, 1, grid)

    if d < 0:
      x += 1
      d += 2*x + 3
    else:
      x += 1
      y -= 1
      d += ((x-y) << 1) + 5

python 曲线垂直斜率 python求直线斜率_概率论_28

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

  • x递增1,d递增python 曲线垂直斜率 python求直线斜率_python_29
  • y递减1,d递增python 曲线垂直斜率 python求直线斜率_算法_30
  • 初始值:
  • python 曲线垂直斜率 python求直线斜率_算法_31
  • python 曲线垂直斜率 python求直线斜率_概率论_32
'''中点画圆法(DDA)(去点浮)'''
def drawArc_MidPoint_with_DDA_nonreal(grid, R):
  d = 1 - R
  deltax, deltay = 3, 2 - (R << 1)

  x, y = 0, R
  while x < y:
    drawPixel_symmetry8(x, y, 1, grid)

    if d < 0:
      x += 1
      d += deltax
      deltax += 2
    else:
      x += 1
      y -= 1
      d += (deltax + deltay)
      deltax += 2
      deltay += 2

python 曲线垂直斜率 python求直线斜率_python_33


Bresenham画圆法

  • 选取距离真正的圆曲线近的点进行扩展
  • python 曲线垂直斜率 python求直线斜率_python_34

  • 如果|OP1| > |OP2|,则选P2<=> python 曲线垂直斜率 python求直线斜率_概率论_35
    <=> python 曲线垂直斜率 python求直线斜率_直线段生成算法_36
  • 当前像素的下一个扩展节点:正右方右下方正下方

python 曲线垂直斜率 python求直线斜率_算法_37

  1. H
  2. HD中选更近的
  3. D
  4. VD中选更近的
  5. V
  • python 曲线垂直斜率 python求直线斜率_python_38, python 曲线垂直斜率 python求直线斜率_直线段生成算法_39, python 曲线垂直斜率 python求直线斜率_算法_40
    python 曲线垂直斜率 python求直线斜率_python_41, python 曲线垂直斜率 python求直线斜率_概率论_42
  1. python 曲线垂直斜率 python求直线斜率_概率论_43
  2. python 曲线垂直斜率 python求直线斜率_直线段生成算法_44
  • python 曲线垂直斜率 python求直线斜率_概率论_45,若python 曲线垂直斜率 python求直线斜率_python_46,取D;else取V
  • python 曲线垂直斜率 python求直线斜率_算法_47python 曲线垂直斜率 python求直线斜率_python 曲线垂直斜率_48,取H;else,取D
  • python 曲线垂直斜率 python求直线斜率_直线段生成算法_49,取D
  • 用增量法简化python 曲线垂直斜率 python求直线斜率_python_50,下一个像素取:
  • H,增量取2x + 1
  • D,增量取2x - 2y + 2
  • V,增量取-2y + 1
  • 初始值:-2r + 2
'''Bresenham画圆法'''
def drawArc_Bresenham(grid, R):
    delta = (1 - R) << 1

    x, y = 0, R
    while y >= 0:
        drawPixel_symmetry4(x, y, 1, grid)

        if delta < 0:
            delta1 = ((delta + y) << 1) - 1
            if delta1 <= 0:
                direction = 1
            else:
                direction = 2
        elif delta > 0:
            delta2 = ((delta - x) << 1) - 1
            if delta2 <= 0:
                direction = 2
            else:
                direction = 3
        else:
            direction = 2


        if direction == 1:      # 前进到 正右
            x += 1
            delta += (x << 1) + 1
        elif direction == 2:    # 前进到 右下
            x += 1
            y -= 1
            delta += ((x - y) << 1) + 2
        else:                   # 前进到 正下
            y -= 1
            delta += 1 - (y << 1)

python 曲线垂直斜率 python求直线斜率_python 曲线垂直斜率_51


正负法

  • 圆方程:python 曲线垂直斜率 python求直线斜率_概率论_27
  • python 曲线垂直斜率 python求直线斜率_python 曲线垂直斜率_53
  • P在圆内 -> python 曲线垂直斜率 python求直线斜率_直线段生成算法_54
  • P在圆外 -> python 曲线垂直斜率 python求直线斜率_直线段生成算法_55
  • 引入增量思想:
  • F<=0,增量为2x + 1
  • else,增量为-2y + 1
  • 初始值:0
'''正负法'''
def drawArc_PositiveNegative(grid, R):
    F = 0

    x, y = 0, R
    while x <= y:
        drawPixel_symmetry8(x, y, 1, grid)
        print(F)
        if F <= 0:
            F += (x << 1) + 1
            x += 1
        else:
            F += 1 - (y << 1)
            y -= 1

python 曲线垂直斜率 python求直线斜率_直线段生成算法_56


圆内接正多边形逼近法

  • python 曲线垂直斜率 python求直线斜率_python 曲线垂直斜率_57
  • 工程上,python 曲线垂直斜率 python求直线斜率_算法_58就可以了,两个点的距离达到1pixel之后再小也没用了
  • 圆的参数方程:
  • python 曲线垂直斜率 python求直线斜率_直线段生成算法_59
  • python 曲线垂直斜率 python求直线斜率_python 曲线垂直斜率_60
  • 引入增量思想:
    python 曲线垂直斜率 python求直线斜率_python_61
'''圆内接正多边形逼近法'''
def drawArc_InscribedRegularPolygonApproximate(grid, R):
    Alpha = 1/R
    cosAlpha, sinAlpha = cos(Alpha), sin(Alpha)

    x, y = R, 0
    while x >= y:
        drawPixel_symmetry8(int(x+0.5), int(y+0.5), 1, grid)

        x = cosAlpha * x - sinAlpha * y
        y = sinAlpha * x + cosAlpha * y

python 曲线垂直斜率 python求直线斜率_python 曲线垂直斜率_62