生成直线的DDA算法:
假设待扫描转换的直线段为 Pb(xb, yb), Pe(xe, ye),如图所示:
令 , 斜率
, 则直线方程为
为方便起见,这里 假定 。 显然,对于每一个 xi 的取值(x 的变化规律是每次递增1),都有唯一的 yi 值与之对应,通过对 yi 值做四舍五入运算,最终确定每一扫描列上的像素值。
但这种策略效率不高,因为每次迭代都要做一次浮点(或二进制分数)乘法、加法和一个舍入运算。可以使用下式跳过乘法:
若 , 则
, 即 x, y 的值可由它们的前一个值确定。
注意: 如果 , 则x 的步进值会使 y 的步进值超过1.在这种情况下,应颠倒x 与 y 的位置,给 y 以单位增量,即
,而x 的增量为
, 即取x 轴和 y 轴中变化较快的轴作为参变量,则可在直线上绘制更多的点。
核心代码:
from PySide2.QtCore import *
import math
class Line:
def __init__(self, p):
self.p = p
def points_list_dda(self):
points = []
if self.p[0].y() == self.p[1].y():
if self.p[0].x() > self.p[1].x():
self.p.reverse()
x = self.p[0].x()
y = self.p[0].y()
while x < self.p[1].x():
points.append(QPoint(x, y))
x = x+1
return points
if self.p[0].x() == self.p[1].x():
if self.p[0].y() > self.p[1].y():
self.p.reverse()
x = self.p[0].x()
y = self.p[0].y()
while y < self.p[1].y():
points.append(QPoint(x, y))
y = y+1
return points
m = (self.p[1].y()-self.p[0].y())/(self.p[1].x()-self.p[0].x())
if m <= 1 and m >= -1:
if self.p[0].x() > self.p[1].x():
self.p.reverse()
x = self.p[0].x()
y = self.p[0].y()
points.append(self.p[0])
while x < self.p[1].x():
x = x+1
y = y+m
yy = round(y)
points.append(QPoint(x, yy))
return points
else:
if self.p[0].y() > self.p[1].y():
self.p.reverse()
x = self.p[0].x()
y = self.p[0].y()
points.append(self.p[0])
while y < self.p[1].y():
xx = int(x+0.5)
points.append(QPoint(xx, y))
y = y+1
x = x+1/m
return points
注意: 这里采用的四舍五入方法有 yy = round(y) 和 xx = int(x+0.5) ,但是由于在负数区域 xx = int(x+0.5)并不是那么灵便,比如:int(-0.6)= 0,而我们期望的值为 -1 , 所以建议使用 round() 函数。
eg:使用 xx = int(x+0.5)
使用 xx = round(x)
加上UI界面实现效果:
PS: 如需参考完整代码,请移步:https://download.csdn.net/download/qq_42185999/11834669 进行下载