Python Turtle透视投影立方体的着色与轮廓绘制问题求助
立方体透视投影的面遮挡问题(Turtle库实现)
我用Python的Turtle库编写了立方体透视投影程序,但Turtle不支持透明效果,导致着色时面会互相覆盖:
- 最初通过识别最远点过滤填充面,该方法在正交投影中有效,但透视投影中仍存在后方面错误填充的问题
- 后续尝试按面积排序绘制面,但同时进行X、Y轴旋转时仍有隐患
- 绘制轮廓线采用类似逻辑,也在透视投影中出现相同问题
以下是实现代码:
#imports import turtle import time from math import * #turtle and some variables t = turtle.Turtle() turtle.tracer(0, 0) turtle.bgcolor("lightblue") t.width(20) t.hideturtle() angle1 = 0 angle2 = 0 scale = 200 #matrices multiplication def mult(matrix1, matrix2): result = [] if len(matrix1[0]) == len(matrix2): for _ in range(len(matrix1)): result += [[0]*len(matrix2[0])] for i in range(len(matrix1)): for j in range(len(matrix2[0])): for k in range(len(matrix2)): result[i][j] += matrix1[i][k] * matrix2[k][j] return result #forms of points def point_matrix(point_as_3Dpvector): p = point_as_3Dpvector return [[p[0]], [p[1]], [p[2]]] def point_3Dpvector(point_as_matrix): p = point_as_matrix return (p[0][0],p[1][0], p[2][0]) def point_2Dpvector(point_as_3Dpvector): p = point_as_3Dpvector return (p[0], p[1]) #make a line def line(ln): t.up() t.goto(point_2Dpvector(ln[0])) t.down() t.goto(point_2Dpvector(ln[1])) t.up() #make multiple lines from a list def line_a_list(list): for i in list: line(i) #fill a square def fill(s): t.color(s[4]) t.goto(point_2Dpvector(s[0])) t.begin_fill() t.goto(point_2Dpvector(s[1])) t.goto(point_2Dpvector(s[2])) t.goto(point_2Dpvector(s[3])) t.end_fill() t.up() #fill muliple squares from a list def fill_a_list(list): for i in list: fill(i) #knows if a point is in a list or not def isthere(point, list): r = 0 for i in list: if point == i: r += 1 if r > 0: return True else: return False #calculates the area of a square def area(se): a1 = se[0][0] a2 = se[1][0] a3 = se[2][0] b1 = se[0][1] b2 = se[1][1] b3 = se[2][1] a = a2 * b3 - b2 * a3 b = -a1 * b3 + b1 * a3 c = a1 * b2 - b1 * a2 return abs(a + b + c) #tell the turtle what squares to fill and the ones not #by knowing the farest point by the z value #and do not fill any square that have this point def do_squares(list_squares, list_points): #variables furthest_point = list_points[0] do_not_points = [] do_not_squares = [] large_square = () do_squares = [] #find the farest point by its z value for i in list_points: if i[2] < furthest_point[2]: furthest_point = i #find the other points that have the same z value for i in list_points: if i[2] == furthest_point[2]: do_not_points += [i] #find the squares that have this points for i in list_squares: for j in do_not_points: if isthere(j, i) == True: do_not_squares += [i] #remove the squares that have the points from #the squares list and leave the rest there for i in list_squares: if isthere(i, do_not_squares) == False: do_squares += [i] #find the largest square and make it the last large = do_squares[0] for i in do_squares: if area(i) > area(large): large = i large_square = large do_squares.remove(large) do_squares += [large_square] return do_squares #as the def before but for lines def do_lines(list_lines, list_points): furthest_point = list_points[0] do_not_points = [] do_not_lines = [] do_lines = [] for i in list_points: if i[2] < furthest_point[2]: furthest_point = i for i in list_points: if i[2] == furthest_point[2]: do_not_points += [i] for i in list_lines: for j in do_not_points: if isthere(j, i) == True: do_not_lines += [i] for i in list_lines: if isthere(i, do_not_lines) == False: do_lines += [i] return do_lines #the cube's points and points' list p0 = (-0.5, -0.5, -0.5) p1 = (0.5, -0.5, -0.5) p2 = (0.5, 0.5, -0.5) p3 = (-0.5, 0.5, -0.5) p4 = (-0.5, -0.5, 0.5) p5 = (0.5, -0.5, 0.5) p6 = (0.5, 0.5, 0.5) p7 = (-0.5, 0.5, 0.5) points_list = [p0, p1, p2, p3, p4, p5, p6, p7] #the loop of operations that do the work while True: #variables t.clear() l = [] # list of rotated squares angle1 += .012 / 3 #radian angle2 += .005 / 3 #rotation matrices rotateZ = [ [cos(angle1), -sin(angle1), 0], [sin(angle1), cos(angle1), 0], [0, 0, 1] ] #Z axis rotateX = [ [1, 0, 0], [0, cos(angle1), -sin(angle1)], [0, sin(angle1), cos(angle1)] ] #X axis rotateY = [ [cos(angle2), 0, -sin(angle2)], [0, 1, 0], [sin(angle2), 0, cos(angle2)] ] #Y axis for point in points_list: #rotate points rotated = mult(rotateY, point_matrix(point)) rotated = mult(rotateX, rotated) rotated = mult(rotateZ, rotated) #project points z = 1 / (2 - rotated[2][0]) * 2 #prespective #z = 1 #orthographic projection =[ [z*scale, 0, 0], [0, z*scale, 0], [0, 0, 1] ] projected_points = mult(projection, rotated) l += [point_3Dpvector(projected_points)] # list of squares squar = [ (l[0], l[1], l[2], l[3], "pink"), (l[4], l[5], l[6], l[7], "#5676AA"), (l[1], l[5], l[6], l[2], "#FF7777"), (l[0], l[4], l[7], l[3], "cyan"), (l[0], l[1], l[5], l[4], "#FFAA55"), (l[3], l[2], l[6], l[7], "#DA90F5") ] fill_a_list(do_squares(squar,l)) #list of lines lines = [ (l[0], l[1]), (l[0], l[4]), (l[1], l[5]), (l[4], l[5]), (l[1], l[2]), (l[5], l[6]), (l[6], l[2]), (l[0], l[3]), (l[2], l[3]), (l[3], l[7]), (l[7], l[4]), (l[7], l[6]) ] t.color("black") line_a_list(do_lines(lines, l)) #you can turn it off to see the coloring problem turtle.update() turtle.done()
内容的提问来源于stack exchange,提问作者Ahmed Shshtawy
相关产品推荐
相关产品推荐

