实验目的
通过参数的计算,把二维裁剪问题转化成为一维裁剪问题。
算法思想
要裁剪的线段是P0P1。 P0P1和窗口边界交于A,B,C,D四点,见图。算法的基本思想是从A,B和P0三点中找出最靠近P1的点,图中要找的点是B。从C,D和P1中找出最靠近P0的点。图中要找的点是P1 点。那么P1B就是P0P1线段上的可见部分。
求出P0P1与两条始边的交点参数u0, u1 , 令ul=max(u0 ,u1,0),则ul即为三者中离P1最近的点的参数
求出P0P1与两条终边的交点参数u2, u3, 令uu=min(u2,u3,1) ,则uu即为三者中离P0最近的点的参数
若uu > ul,则可见线段区间 [ul , uu]
若ul > uu ,则线段不可见。
算法步骤
(1)输入直线段的两端点坐标:(x1,y1)和(x2,y2),以及窗口的四条边界坐标:XL、XR、YB和YT。
(2)若Δx=0,则p1=p2=0。此时进一步判断是否满足q1<0或q2<0,若满足,则该直线段不在窗口内,算法转(7)。否则,满足q1>0且q2>0,则进一步计算u1和u2。算法转(5)。
(3)若Δy=0,则p3=p4=0。此时进一步判断是否满足q3<0或q4<0,若满足,则该直线段不在窗口内,算法转(7)。否则,满足q1>0且q2>0,则进一步计算u1和u2。算法转(5)。
(4)若上述两条均不满足,则有pk≠0(k=1,2,3,4),此时计算u1和u2。
(5)求得u1和u2后,进行判断:若u1>u2,则直线段在窗口外,算法转(7)。若u1小于u2,利用直线的参数方程求得直线段在窗口内的两端点坐标。
(6)利用直线的扫描转换算法绘制在窗口内的直线段。
(7)算法结束。
测试代码
采用多边形来进行裁剪,只是对多边形的每条边单独裁剪画线。等同于是直线的集合,在这里我选择的测试多边形,边有全在窗口内的,有全部在窗口内的,有部分在窗口内部分在窗口外,还有更特殊的:顶点
在裁剪窗口上,中点在裁剪窗口上等等,这样更具有良好的测试作用
凹:polygon=[
[20,20],
[120,20],
[70,100],
[50,80],
[30,120],
[20,50],
[50,50]
]
]
凹
实验结果与分析
*空间复杂度:*空间复杂度可忽略不计
*时间复杂度:单条线段:时间复杂度近似为O(n)。
多边形:时间复杂度近似为O(ne)。
算法亮点和感想
*亮点:*直线上任何一个点都可以用一个参数来决定,任何一条线段都可以用两个参数来决定
*感想:*在编写代码的时候,按照此算法思想很容易就写完了,运行也没什么问题。而且对上述特殊情况的处理也包括进来了。改进了Cohen-Sutherland的大量求交了计算复杂性问题,也改善了中点分割效率低,特殊情况多的问题。而参数化思想是这个算法的核心所在,对于数思想是根据给定的条件,用一个与数个已知变量有密切关系的中间变量,把已知量间接地联系起来,从而获得想要的结果.在解决数学问题时对于无公式可套,又不能直接列式,用代数法也不能奏效的较难数学问题,可用参数法加以解决. 简而言之, “参数思想就是利用参数刻画过程的变化状态,以参数为媒介揭示变量之间的内在联系来研究事物变化规律的思维方法”。引入参数能为解决某些特殊的数学问题铺平道路,使解题思路清晰,运算过程简洁。此算法中使用了参数法使得二维裁剪问题转换为一位,效率高。在今后的学习中,参数化越来越重要了,这也体现了数学思想解决编程问题的高效性。学好数学很重要。
代码
'''
liang-Barskey算法
'''
import matplotlib.pyplot as plt
import numpy as np
XL=40
XR=100
YB=40
YT=100
def DDALine(image,x0, y0, x1, y1, color):
if x0 > x1:
temp = x1
x1 = x0
x0 = temp
temp = y1
y1 = y0
y0 = temp
dx = x1 - x0
dy = y1 - y0
dx = x1 - x0
dy = y1 - y0
if dx != 0:
k = dy / dx
else:
for i in range(y0, y0 + dy + 1):
image[i][x0] = color
else:
for i in range(y1, y1 - dy + 1):
image[i][x0] = color
return
if k>=0:
if abs(k)<1:
y = y0
xmin = x0
xmax = x1
for i in range(xmin,xmax+1):
image[int(y+0.5)][i] = color
y = y+k
else:
x = x0
if y0-1:
y = y0
xmin = x0
xmax = x1
for i in range(xmin,xmax+1):
image[int(y+0.5)][i] = color
y = y+k
else:
x = x1
if y0 x1:
temp = x1
x1 = x0
x0 = temp
temp = y1
y1 = y0
y0 = temp
DDALine(image, x0, y0, x1, y1, color)
def ClipT(p,q,u1,u2):
if(p<0):
r=q/p
if(r>u2):
return [u1,u2,False]
if(r>u1):
u1=r
elif(p>0):
r=q/p
if(r=0):
return [u1,u2,True]
else:
return [u1,u2,False]
return [u1,u2,True]
return(u1,u2,bool)
def LBarskey(polygon,image,color):
image=image
l = len(polygon)
for i in range(l):
[x1, y1] = polygon[i]
[x2, y2] = polygon[(i + 1 + l) % l]
print([x1,y1])
print([x2,y2])
u1=0
u2=1
dx=x2-x1
dy=y2-y1
[u1,u2,bool]=ClipT(-dx,x1-XL,u1,u2)
print(u1)
print(u2)
print("\n")
if(bool==True):
[u1,u2,bool]=ClipT(dx,XR-x1,u1,u2)
print(u1)
print(u2)
print("\n")
if(bool==True):
[u1, u2, bool] = ClipT(-dy, y1 - YB, u1, u2)
print(u1)
print(u2)
print("\n")
if(bool==True):
[u1,u2,bool]=ClipT(dy,YT-y1,u1,u2)
print(u1)
print(u2)
print("\n")
if(bool==True):
print([(int)(x1+u1*dx),(int)(y1+u1*dy),(int)(x1+u2*dx),(int)(y1+u2*dy)])
DDALine(image,(int)(x1+u1*dx),(int)(y1+u1*dy),(int)(x1+u2*dx),(int)(y1+u2*dy),color)
if __name__ == '__main__':
image = np.ones([150, 150])
plt.xlim(0, 150)
plt.ylim(0, 150)
window=[
[40,40],
[40,100],
[100,100],
[100,40]
]
polygon = [
[20, 20],
[120, 20],
[70, 100],
[50, 80],
[30, 120],
[20, 50],
[50, 50]
]
draw(image, window, False)
LBarskey(polygon,image,False)
plt.imshow(image, plt.cm.gray)
plt.show()