def __init__(self,x=0.0,y=0.0,z=0.0) : ''' Create an localview object with: -) an position represented by an Vertex. -) 3 free axes initialise as the X, Y, Z axes. ''' self.pos=Vertex(x,y,z) # Position from the localview. self.right=Vector(1.,0.,0.) # Axe X representing vector. self.up=Vector(0.,1.,0.) # Axe Y representing vector. self.sight=Vector(0.,0.,1.) # Axe Z representing vector.
def generate_polygon_on_xz_side_length(edges,side_length,offset=0) : ''' Return an polygon on plan XZ: with edges edges from length side_length, with offset offset. z / _____/____x / / plan XZ. ''' angle=360.0/side_length polygon=[] # Polygon vertice container. scale=360.0/edges # Computing of the angle separating 2 points from the polygon. start_vertex1=Vertex(-side_length/2.,0.0,0) start_vertex2=Vertex(side_length/2.,0.0,0) point_to_rotate=start_vertex1 rotate_point=start_vertex2 polygon.append(point_to_rotate) polygon.append(rotate_point) i=2 while i < edges : vertex=rotate_on_xz(rotate_point,abs(180-scale),point_to_rotate) point_to_rotate=rotate_point rotate_point=vertex polygon.append(vertex) i += 1 center=get_center_from_polygon(polygon) # Compute polygon center. tmp=[] for v in polygon : # Translate polygon vertices so as his center is the display center. tmp.append(translate(v,-center.wx,-center.wy,-center.wz)) if offset : offset_set=[] for v in tmp : offset_set.append(rotate_y(v,offset)) tmp=offset_set polygon=tmp return polygon
def generate_tetrahedron(side_length): ''' Generate an tetrahedron in relationship to the given side length. And return an sequence from triangles composing the tetrahedron. ''' # Compute cube side length to get the diagonale length egal to the given argument, # so that the inscribe tetrahedron have the correct side length. side_length = sqrt(pow(side_length, 2) + pow(side_length, 2)) / 2. # Generate the cube where the tetrahedron is inscribe. vertex_list = [ # We begin with the back side. Vertex(-side_length / 2., -side_length / 2., -side_length / 2.), Vertex(side_length / 2., -side_length / 2., -side_length / 2.), Vertex(side_length / 2., side_length / 2., -side_length / 2.), Vertex(-side_length / 2., side_length / 2., -side_length / 2.), # Then with the front side. Vertex(-side_length / 2., -side_length / 2., side_length / 2.), Vertex(side_length / 2., -side_length / 2., side_length / 2.), Vertex(side_length / 2., side_length / 2., side_length / 2.), Vertex(-side_length / 2., side_length / 2., side_length / 2.) ] # Define the 4 triangles composing the tetrahedron: tetrahedron_triangle_1 = (vertex_list[6], vertex_list[3], vertex_list[4]) tetrahedron_triangle_2 = (vertex_list[6], vertex_list[3], vertex_list[1]) tetrahedron_triangle_3 = (vertex_list[4], vertex_list[1], vertex_list[3]) tetrahedron_triangle_4 = (vertex_list[4], vertex_list[1], vertex_list[6]) # Assemble triangles to an tetrahedron: tetrahedron = (tetrahedron_triangle_1, tetrahedron_triangle_2, tetrahedron_triangle_3, tetrahedron_triangle_4) return tetrahedron
def __mul__(self,mult) : ''' Multiply sign wrapper. ''' if isinstance(mult,Vertex) : # The right operator is an vertex. res_x= mult.wx * self.main_matrix[0] + mult.wy * self.main_matrix[4] + mult.wz * self.main_matrix[8] + self.main_matrix[12] res_y= mult.wx * self.main_matrix[1] + mult.wy * self.main_matrix[5] + mult.wz * self.main_matrix[9] + self.main_matrix[13] res_z= mult.wx * self.main_matrix[2] + mult.wy * self.main_matrix[6] + mult.wz * self.main_matrix[10] + self.main_matrix[14] return Vertex(res_x,res_y,res_z) elif isinstance(mult,Vector) : # The right operator is an vector. x= mult.x*self.main_matrix[0] + mult.y*self.main_matrix[4] + mult.z*self.main_matrix[8] y= mult.x*self.main_matrix[1] + mult.y*self.main_matrix[5] + mult.z*self.main_matrix[9] z= mult.x*self.main_matrix[2] + mult.y*self.main_matrix[6] + mult.z*self.main_matrix[10] return Vector(x,y,z) else : # The right operator is suppose to be an Localview otherwise. try : mult.pos=self.mult_vertex(mult.pos) # Localview position multiplying. mult.right=self.mult_vector(mult.right) # Localview X axe vector multiplying. mult.up=self.mult_vector(mult.up) # Localview Y axe vector multiplying. mult.sight=self.mult_vector(mult.sight) # Localview Z axe vector multiplying. return mult except : return None
def get_middle_from_segment(vertex1,vertex2) : ''' Return the middle point of an segment as an object from type Vertex ''' if not isinstance(vertex1,Vertex) or not isinstance(vertex2,Vertex) : raise TypeError(Vertex) return Vertex((vertex1.wx+vertex2.wx)/2.,(vertex1.wy+vertex2.wy)/2.,(vertex1.wz+vertex2.wz)/2.)
def get_result(self) : ''' Return an vertex issue from the main matrix multiplying. ''' res_x= self.x * self.main_matrix[0] + self.y * self.main_matrix[4] + self.z * self.main_matrix[8] + self.main_matrix[12] res_y= self.x * self.main_matrix[1] + self.y * self.main_matrix[5] + self.z * self.main_matrix[9] + self.main_matrix[13] res_z= self.x * self.main_matrix[2] + self.y * self.main_matrix[6] + self.z * self.main_matrix[10] + self.main_matrix[14] return Vertex(res_x,res_y,res_z)
def scale(vertex, factor): ''' Scale from the given factor. ''' if not isinstance(vertex, Vertex): # Type control. raise TypeError(Vertex) # We simply multiply every vertex component (wx,wy,wz) with the given scaling factor. return Vertex(vertex.wx * factor, vertex.wy * factor, vertex.wz * factor)
def add_vertex(self,vertex,vector=False) : ''' Add the given vertex and vector and return the result as an Vertex object. ''' if not isinstance(vertex,Vertex) : raise TypeError(Vertex) if vector : if not isinstance(vector,Vector) : raise TypeError(Vector) return Vertex(vector.x + vertex.wx, vector.y + vertex.wy, vector.z + vertex.wz) else : self.x=self.x + vertex.wx self.y=self.y + vertex.wy self.z=self.z + vertex.wz return Vertex(self.x,self.y,self.z)
def div_segment_into_vertices(vertex1, vertex2, divider): ''' Return an sequence from vertices between vertex1 and vertex2. which has divide the segment (vertex1,vertex2) in the given number of vertices. ''' if not isinstance(vertex1, Vertex) or not isinstance(vertex2, Vertex): raise TypeError(Vertex) if not isinstance(divider, int): raise TypeError(int) if divider <= 1: raise ValueError(divider) # Define a vertice representing the length between vertex1 and vertex2 length_vertex = Vertex(vertex2.wx - vertex1.wx, vertex2.wy - vertex1.wy, vertex2.wz - vertex1.wz) divider += 1 # Increment divider to get the right result. mult = 1.0 / divider # Compute the value for step unit setting. # Define a step vertice representing a step in the segment division into vertices. step_vertex = Vertex(length_vertex.wx * mult, length_vertex.wy * mult, length_vertex.wz * mult) position = vertex1 # Setting the start position. steps_vertices = [] # Add the initial position to the result: steps_vertices.append(position) for x in range(divider): # Computing next vertice. position = Vertex(position.wx + step_vertex.wx, position.wy + step_vertex.wy, position.wz + step_vertex.wz) steps_vertices.append(position) return steps_vertices # We could return only the vertices between the start and end position: steps_vertices[1:-1]
def mult_vertex(self,vertex) : ''' Multiply the current main matrix with the given vertex. And return the result as an Vertex. ''' if not isinstance(vertex,Vertex) : raise TypeError(Vertex) res_x= vertex.wx * self.main_matrix[0] + vertex.wy * self.main_matrix[4] + vertex.wz * self.main_matrix[8] + self.main_matrix[12] res_y= vertex.wx * self.main_matrix[1] + vertex.wy * self.main_matrix[5] + vertex.wz * self.main_matrix[9] + self.main_matrix[13] res_z= vertex.wx * self.main_matrix[2] + vertex.wy * self.main_matrix[6] + vertex.wz * self.main_matrix[10] + self.main_matrix[14] return Vertex(res_x,res_y,res_z)
def get_center_from_polyhedron(points) : ''' Return the center of an polyhedron as an object from type Vertex ''' if not isinstance(points,tuple) and not isinstance(points,list) : raise TypeError(tuple,list) for v in points : if not isinstance(v,Vertex) : raise TypeError(Vertex) center=[(max(map(lambda e : e.wx ,points))+min(map(lambda e : e.wx,points)))/2.,(max(map(lambda e : e.wy,points))+min(map(lambda e : e.wy,points)))/2.,(max(map(lambda e : e.wz,points))+min(map(lambda e : e.wz,points)))/2.] return Vertex(vertexv=center)
def rotate_z(vertex, angle): ''' Rotate an vertice around the z axe and return the result position vertice. ''' if not isinstance(vertex, Vertex): # Type control. raise TypeError(Vertex) x = cos(radians(angle)) * vertex.wx - sin( radians(angle)) * vertex.wy # Sea explications. y = sin(radians(angle)) * vertex.wx + cos( radians(angle)) * vertex.wy # Sea explications. z = vertex.wz # Because we rotate on the z axe the z value don't change. return Vertex(x, y, z)
def rotate_x(vertex, angle): ''' Rotate an vertice around the x axe and return the result position vertice. ''' if not isinstance(vertex, Vertex): # Type control. raise TypeError(Vertex) x = vertex.wx # Because we rotate on the x axe the x value don't change. y = (cos(radians(angle)) * vertex.wy) - (sin(radians(angle)) * vertex.wz ) # Sea explications. z = (sin(radians(angle)) * vertex.wy) + (cos(radians(angle)) * vertex.wz ) # Sea explications. return Vertex(x, y, z)
def generate_cube(side_length): ''' Generate an cube in relationship to the given side length. And return an sequence from quads composing the cube. ''' cube_vertex_list = [ # We begin with the back side. Vertex(-side_length / 2., side_length / 2., side_length / 2.), Vertex(side_length / 2., side_length / 2., side_length / 2.), Vertex(side_length / 2., -side_length / 2., side_length / 2.), Vertex(-side_length / 2., -side_length / 2., side_length / 2.), # Then with the front side. Vertex(-side_length / 2., side_length / 2., -side_length / 2.), Vertex(side_length / 2., side_length / 2., -side_length / 2.), Vertex(side_length / 2., -side_length / 2., -side_length / 2.), Vertex(-side_length / 2., -side_length / 2., -side_length / 2.) ] front = [ cube_vertex_list[4], cube_vertex_list[5], cube_vertex_list[6], cube_vertex_list[7] ] # Front QUADS. back = [ cube_vertex_list[0], cube_vertex_list[1], cube_vertex_list[2], cube_vertex_list[3] ] # Back QUADS. left = [ cube_vertex_list[0], cube_vertex_list[4], cube_vertex_list[7], cube_vertex_list[3] ] # Left QUADS. right = [ cube_vertex_list[5], cube_vertex_list[1], cube_vertex_list[2], cube_vertex_list[6] ] # right QUADS. up = [ cube_vertex_list[0], cube_vertex_list[1], cube_vertex_list[5], cube_vertex_list[4] ] # up QUADS. down = [ cube_vertex_list[7], cube_vertex_list[6], cube_vertex_list[2], cube_vertex_list[3] ] # down QUADS. return (front, back, left, right, up, down)
def translate(vertex, value_x, value_y, value_z): ''' Translate an vertice from the given offset in every axe. ''' if not isinstance(vertex, Vertex): # Type control. raise TypeError(Vertex) x = ( value_x + vertex.wx ) # We simply add the given value to translate vertex in direction x, even if it is an negativ value it work. y = ( value_y + vertex.wy ) # We simply add the given value to translate vertex in direction y, even if it is an negativ value it work. z = ( value_z + vertex.wz ) # We simply add the given value to translate vertex in direction z, even if it is an negativ value it work. return Vertex(x, y, z)
def rotate_on_xz(center, angle, vertex): ''' Function to rotate an vertex given as the argument vertex around a center vertex in the xz plan from the value angle in clock sens. Return the rotated vertex as an object from <type 'Vertex'>. ''' if not isinstance(center, Vertex): raise TypeError(Vertex) if not isinstance(vertex, Vertex): raise TypeError(Vertex) return_x = vertex.wx * cos(radians(angle)) - vertex.wz * sin( radians(angle)) + center.wx * ( 1 - cos(radians(angle))) + center.wz * sin(radians(angle)) return_z = vertex.wx * sin(radians(angle)) + vertex.wz * cos( radians(angle)) + center.wz * ( 1 - cos(radians(angle))) - center.wx * sin(radians(angle)) return Vertex(return_x, 0., return_z)
def get_center_from_polygon(points) : ''' Return the center of an polygon as an object from type Vertex ''' if not isinstance(points,tuple) and not isinstance(points,list) : raise TypeError(tuple,list) for v in points : if not isinstance(v,Vertex) : raise TypeError(Vertex) tmp=[] i=-1 while i < len(points)-1 : # We compute the inner (inscribe) circle points. To get the right polygone center. tmp.append(get_middle_from_segment(points[i],points[i+1])) i += 1 points=tmp center=[(max(map(lambda e : e.wx ,points))+min(map(lambda e : e.wx,points)))/2.,(max(map(lambda e : e.wy,points))+min(map(lambda e : e.wy,points)))/2.,(max(map(lambda e : e.wz,points))+min(map(lambda e : e.wz,points)))/2.] return Vertex(vertexv=center)
def generate_toros(base, base_radius, toros_radius): ''' Generate an toros in relationship to the given settings: base: the toros basis polygon. base_radius: the toros basis polygon radius. toros_radius: the toros radius (without the base polygon radius). and return an sequence of polygons base from the toros. ''' base_polygon = generate_polygon_on_yz_radius(base, base_radius, Vertex(0., 0., 0.)) i = 0 toros = [] while i < 360.0: polygon = [] for v in base_polygon: vertex = rotate_y(translate(v, 0.0, 0.0, toros_radius), i) polygon.append(vertex) i += 360.0 / base toros.append(polygon) return toros
def generate_polygon_on_xz_radius(edges,radius,center,offset=0) : ''' Return an polygon on plan XZ: from edges sides, from radius radius, with offset offset. z / _____/____x / / plan XZ. ''' if not isinstance(center,Vertex) : raise TypeError(Vertex) polygon=[] # Polygon vertice container. scale=360./edges # Computing of the angle separating 2 points from the polygon. i=0 while i < edges : polygon.append(Vertex(radius*cos(radians((scale*i)+offset))+center.wx,center.wy,radius*sin(radians((scale*i)+offset))+center.wz)) i += 1 return polygon
def __init__(self,base_polygon,base_radius,toros_radius,display_mode="lined",lines_color=False,faces_color=False,lines_width=1,display_ls=False) : ''' Generate an toros object with the given radius and basis polygone settings. base_polygon = the toros basis polygon. base_radius = the toros basis polygon radius. toros_radius = the toros radius (without the base polygon radius). display_mode = "lined" -> only the lines will be displayed. display_mode = "faced" -> only the faces will be displayed. display_mode = "twice" -> The lines and the faces will be displayed. lines_color = an objet <type 'Color'> representing the lines color. faces_color = an objet <type 'Color'> representing the faces color. line_width = an integer representing the lines width. ''' if not isinstance(base_polygon,int) : raise TypeError("base_polygon argument",int) if base_polygon <= 2 : print "the base polygon must be greater than 2 " quit() if not isinstance(base_radius,int) and not isinstance(base_radius,float) : raise TypeError("base_radius argument",int,float) elif base_radius <= 0.0 : raise ValueError("Value of base_radius must be greater than 0.0") if not isinstance(toros_radius,int) and not isinstance(toros_radius,float) : raise TypeError("toros_radius argument",int,float) elif toros_radius <= 0.0 : raise ValueError("Value of toros_radius must be greater than 0.0") if display_mode == "lined" or display_mode == "faced" or display_mode == "twice" : self.display_mode=display_mode else : raise ValueError("Argument display_mode","lined","faced","twice") if lines_color : if not isinstance(lines_color,Color) : raise TypeError("Argument lines_color",Color) if faces_color : if not isinstance(faces_color,Color) : raise TypeError("Argument faces_color",Color) if not isinstance(lines_width,int) : raise TypeError(lines_width,int) elif lines_width < 1 : raise ValueError("Lines width value too little.") if isinstance(lines_color,Color) : if type(lines_color.a) == bool : lines_color.a=0 if isinstance(faces_color,Color) : if type(faces_color.a) == bool : faces_color.a=0 if isinstance(display_ls,bool) : self.display_ls=display_ls self.base_polygon=base_polygon self.base_radius=base_radius self.toros_radius=toros_radius self.lines_color=lines_color self.faces_color=faces_color self.lines_width=lines_width self.toros=generate_toros(base_polygon,base_radius,toros_radius) self.ls=Localview() self.center=Vertex(0.0,0.0,0.0)
def __init__(self, side_length, display_mode="lined", lines_color=False, quads_color=False, triangles_color=False, lines_width=1, display_ls=False): ''' generate an 26 faces polyhedron object with the given side length settings. display_mode = "lined" -> only the lines will be displayed. display_mode = "faced" -> only the faces will be displayed. display_mode = "twice" -> The lines and the faces will be displayed. lines_color = an objet <type 'Color'> representing the lines color. quads_color = an objet <type 'Color'> representing the quads color. an 18-items-list contains <type 'Color'> objects. triangles_color = an objet <type 'Color'> representing the triangles color. an 8-items-list contains <type 'Color'> objects. line_width = an integer representing the lines width. ''' if not isinstance(side_length, int) and not isinstance( side_length, float): raise TypeError(int, float) elif side_length < 0.0: raise ValueError("Value of side_length must be greater than 0.0") if display_mode == "lined" or display_mode == "faced" or display_mode == "twice": self.display_mode = display_mode else: raise ValueError("lined", "faced", "twice") if lines_color: if not isinstance(lines_color, Color): raise TypeError(lines_color, Color) if quads_color: if not isinstance(quads_color, Color) and not isinstance( quads_color, list): raise TypeError(quads_color, Color, list) elif isinstance(quads_color, list) and len(quads_color) != 18: print "Error quads_color argument:\nYou must give an list from 18 Color objects.\nOne Color object per face." quit() elif isinstance(quads_color, list) and len(quads_color) == 18: tmp = [] quads_color_index = 0 while quads_color_index < 18: if type(quads_color[quads_color_index].a) == bool: quads_color[quads_color_index].a = 0 quads_color_index += 1 if triangles_color: if not isinstance(triangles_color, Color) and not isinstance( triangles_color, list): raise TypeError(triangles_color, Color, list) elif isinstance(triangles_color, list) and len(triangles_color) != 8: print "Error triangles_color argument:\nYou must give an list from 8 Color objects.\nOne Color object per face." quit() elif isinstance(triangles_color, list) and len(triangles_color) == 8: tmp = [] triangles_color_index = 0 while triangles_color_index < 8: if type(triangles_color[triangles_color_index].a) == bool: triangles_color[triangles_color_index].a = 0 triangles_color_index += 1 if not isinstance(lines_width, int): raise TypeError(lines_width, int) elif lines_width < 1: raise ValueError(lines_width, "Lines width value too little.") if isinstance(lines_color, Color): if type(lines_color.a) == bool: lines_color.a = 0 if isinstance(quads_color, Color): if type(quads_color.a) == bool: quads_color.a = 0 if isinstance(triangles_color, Color): if type(triangles_color.a) == bool: triangles_color.a = 0 if isinstance(display_ls, bool): self.display_ls = display_ls self.side_length = side_length self.lines_color = lines_color self.quads_color = quads_color self.triangles_color = triangles_color self.lines_width = lines_width self.triangles, self.quads = generate_polyhedron_26_faces(side_length) self.ls = Localview() self.center = Vertex(0.0, 0.0, 0.0)
def __init__(self, side_length, display_mode="lined", lines_color=False, faces_color=False, lines_width=1, display_ls=False): ''' Generate an Icosahedron object with the given side length settings. display_mode = "lined" -> Only the lines will be displayed. display_mode = "faced" -> Only the faces will be displayed. display_mode = "twice" -> The lines and the faces will be displayed. lines_color = An objet <type 'Color'> representing the lines color. faces_color = An objet <type 'Color'> representing the faces color. An 8-items-list from object <type 'Color'>. One item per icosahedron face. lines_width = An integer representing the lines width. display_ls = Define if the localview should be display. ''' if not isinstance(side_length, int) and not isinstance( side_length, float): raise TypeError("Argument side_length", int, float) elif side_length <= 0.0: raise ValueError( "Value of argument side_length must be greater than 0.0") if display_mode == "lined" or display_mode == "faced" or display_mode == "twice": self.display_mode = display_mode else: raise ValueError("Argument display_mode", "lined", "faced", "twice") if lines_color: if not isinstance(lines_color, Color): raise TypeError("Argument lines_color", Color) if faces_color: if not isinstance(faces_color, Color) and not isinstance( faces_color, list): raise TypeError(faces_color, Color, list) elif isinstance(faces_color, list) and len(faces_color) != 20: print "Error faces_color argument:\nYou must give an list from 20 Color objects.\nOne Color object per face." quit() elif isinstance(faces_color, list) and len(faces_color) == 20: tmp = [] faces_color_index = 0 while faces_color_index < 20: if type(faces_color[faces_color_index].a) == bool: faces_color[faces_color_index].a = 0 faces_color_index += 1 if not isinstance(lines_width, int): raise TypeError("Argument lines_width", int) elif lines_width < 1: raise ValueError(lines_width, "Lines width value too little.") if isinstance(lines_color, Color): if type(lines_color.a) == bool: lines_color.a = 0 if isinstance(faces_color, Color): if type(faces_color.a) == bool: faces_color.a = 0 if isinstance(display_ls, bool): self.display_ls = display_ls self.side_length = side_length self.lines_color = lines_color self.faces_color = faces_color self.lines_width = lines_width self.polyhedron = generate_icosahedron(side_length)[1] self.ls = Localview() self.center = Vertex(0.0, 0.0, 0.0)
def generate_icosahedron(side_length): ''' Generate an icosahedron from the given side length and return an array of 20 triangles component from the icosahedron and his construction base quad set. ''' side_lt = side_length # Define the littler side of the rectangle. side_gt = side_length * ( (1 + sqrt(5)) / 2. ) # Compute the length of the greater side with the gold number ( (1+sqrt(5))/2. ) # Define the base quad so that his center is Vertex(0.0, 0.0, 0.0) : quad1 = [ Vertex(-side_lt / 2., -side_gt / 2., 0.0), Vertex(side_lt / 2., -side_gt / 2., 0.0), Vertex(side_lt / 2., side_gt / 2., 0.0), Vertex(-side_lt / 2., side_gt / 2., 0.0) ] # Rotate the base quad on the y and z axes from 90°, to obtain the second crossing quad. quad2 = [ rotate_z(rotate_y(quad1[0], 90), 90), rotate_z(rotate_y(quad1[1], 90), 90), rotate_z(rotate_y(quad1[2], 90), 90), rotate_z(rotate_y(quad1[3], 90), 90) ] # Rotate the base quad on the y and x axes from 90°, to obtain the third crossing quad. quad3 = [ rotate_x(rotate_y(quad1[0], 90), 90), rotate_x(rotate_y(quad1[1], 90), 90), rotate_x(rotate_y(quad1[2], 90), 90), rotate_x(rotate_y(quad1[3], 90), 90) ] icosahedron_base_quads = [ quad1, quad2, quad3 ] # We set the bases quads for our polyhedron: an icosahedron. # Define an array composed of triangles because an icosahedron is composed from 20 equilateral triangles: icosahedron_triangle_array = [ (icosahedron_base_quads[0][0], icosahedron_base_quads[0][1], icosahedron_base_quads[2][1]), (icosahedron_base_quads[0][1], icosahedron_base_quads[1][0], icosahedron_base_quads[1][1]), (icosahedron_base_quads[0][0], icosahedron_base_quads[0][1], icosahedron_base_quads[2][2]), (icosahedron_base_quads[0][0], icosahedron_base_quads[1][2], icosahedron_base_quads[1][3]), (icosahedron_base_quads[0][0], icosahedron_base_quads[1][3], icosahedron_base_quads[2][1]), (icosahedron_base_quads[0][1], icosahedron_base_quads[2][1], icosahedron_base_quads[1][0]), (icosahedron_base_quads[0][1], icosahedron_base_quads[1][1], icosahedron_base_quads[2][2]), (icosahedron_base_quads[0][0], icosahedron_base_quads[2][2], icosahedron_base_quads[1][2]), (icosahedron_base_quads[0][2], icosahedron_base_quads[0][3], icosahedron_base_quads[2][3]), (icosahedron_base_quads[0][3], icosahedron_base_quads[1][2], icosahedron_base_quads[1][3]), (icosahedron_base_quads[0][2], icosahedron_base_quads[0][3], icosahedron_base_quads[2][0]), (icosahedron_base_quads[0][2], icosahedron_base_quads[1][0], icosahedron_base_quads[1][1]), (icosahedron_base_quads[0][2], icosahedron_base_quads[1][1], icosahedron_base_quads[2][3]), (icosahedron_base_quads[0][3], icosahedron_base_quads[2][3], icosahedron_base_quads[1][2]), (icosahedron_base_quads[0][3], icosahedron_base_quads[1][3], icosahedron_base_quads[2][0]), (icosahedron_base_quads[0][2], icosahedron_base_quads[2][0], icosahedron_base_quads[1][0]), (icosahedron_base_quads[2][0], icosahedron_base_quads[2][1], icosahedron_base_quads[1][3]), (icosahedron_base_quads[2][0], icosahedron_base_quads[2][1], icosahedron_base_quads[1][0]), (icosahedron_base_quads[2][2], icosahedron_base_quads[2][3], icosahedron_base_quads[1][1]), (icosahedron_base_quads[2][2], icosahedron_base_quads[2][3], icosahedron_base_quads[1][2]) ] # We return the base quad set and the triangle array. return [quad1, quad2, quad3], icosahedron_triangle_array
def generate_quad_sphere(basis,radius) : ''' Generate an quads sphere and return an tuple from 2 arrays: (lined displaying vertices sequence list, surface displaying vertices sequence list). In relationship with the base for the sphere generating: faces count = basis * basis and the given sphere radius. ''' if not isinstance(basis,int) : raise TypeError(int) if basis < 6 or basis % 2 : print "the basis for the sphere must be greater as 5 and basis % 2 == 0 " quit() if not isinstance(radius,int) and not isinstance(radius,float) : raise TypeError(int,float) # We generate the base polygon for the sphere generating with the given radius: polygon_1=generate_polygon_on_xy_radius(basis,radius,Vertex(0.0,0.0,0.0),0) polygons=[] # Container for the polygons. i=2 # The iterator variable is initialise with the value 2 # because this one is used for string formating and the polygon_1 variable exist. while i <= basis : # Generate from empty lists by execution, with the directive exec(), # from formattted strings. # Instead of defining variables because the number of polygons is relativ to the basis argument value. exec("polygon_{0}=[]".format(i)) exec("polygons.append(polygon_{0})".format(i)) i += 1 for v in polygon_1 : # Iteration over every vertice from our base polygon. i=0 angle=360.0/basis # Computing of the degress between 2 polygons on the XZ surface. while i < len(polygons) : # generating of all polygons containing the vertices from the sphere. polygons[i].append(rotate_y(v,angle)) i += 1 angle += 360./basis polygons_array=[] # temporary container variable definition. i=1 # The iterator variable is initialise with the value 1 # because this one is used for string formating. while i <= basis : # Filling from the temporary container variable # with the computed polygons containing the vertice from our sphere. # Which we gonna need to compute the quads from composing the sphere . exec("polygons_array.append(polygon_{0})".format(i)) i += 1 i=0 tmp_1=[] while i < len(polygons_array) : # Iteration over the temporary polygon container variable to compute the quads. ii=0 tmp_2=[] while ii < basis-1 : # We compute the quads: from the polygons list to an quads list. if not i == basis-1 : tmp_2.append(polygons_array[i][ii]) tmp_2.append(polygons_array[i+1][ii]) tmp_2.append(polygons_array[i+1][ii+1]) tmp_2.append(polygons_array[i][ii+1]) else : tmp_2.append(polygons_array[i][ii]) tmp_2.append(polygons_array[0][ii]) tmp_2.append(polygons_array[0][ii+1]) tmp_2.append(polygons_array[i][ii+1]) ii += 1 tmp_1.append(tmp_2) i += 1 polygons_line_array=polygons_array # Affectation of the variable to return for the case of lined sphere displaying. polygons_quad_array=tmp_1 # Affectation of the variable to return for the case of surfaces sphere displaying. return (polygons_line_array,polygons_quad_array)
def __init__(self, side_length, display_mode="lined", lines_color=False, pentagons_color=False, hexagons_color=False, lines_width=1, display_ls=False): ''' generate an cube object with the given side length settings. display_mode = "lined" -> only the lines will be displayed. display_mode = "faced" -> only the faces will be displayed. display_mode = "twice" -> The lines and the faces will be displayed. lines_color = an objet <type 'Color'> representing the lines color. pentagons_color = an objet <type 'Color'> representing the pentagons color. an 12-items-list contains <type 'Color'> objects. hexagons_color = an objet <type 'Color'> representing the hexagons color. an 20-items-list contains <type 'Color'> objects. line_width = an integer representing the lines width. ''' if not isinstance(side_length, int) and not isinstance( side_length, float): raise TypeError(int, float) elif side_length <= 0.0: raise ValueError("Value of side_length must be greater than 0.0") if display_mode == "lined" or display_mode == "faced" or display_mode == "twice": self.display_mode = display_mode else: raise ValueError("lined", "faced", "twice") if lines_color: if not isinstance(lines_color, Color): raise TypeError(lines_color, Color) if pentagons_color: if not isinstance(pentagons_color, Color) and not isinstance( pentagons_color, list): raise TypeError(pentagons_color, Color, list) elif isinstance(pentagons_color, list) and len(pentagons_color) != 12: print "Error pentagons_color argument:\nYou must give an list from 12 Color objects.\nOne Color object per face." quit() elif isinstance(pentagons_color, list) and len(pentagons_color) == 12: tmp = [] pentagons_color_index = 0 while pentagons_color_index < 12: if type(pentagons_color[pentagons_color_index].a) == bool: pentagons_color[pentagons_color_index].a = 0 pentagons_color_index += 1 if hexagons_color: if not isinstance(hexagons_color, Color) and not isinstance( hexagons_color, list): raise TypeError(hexagons_color, Color, list) elif isinstance(hexagons_color, list) and len(hexagons_color) != 20: print "Error hexagons_color argument:\nYou must give an list from 20 Color objects.\nOne Color object per face." quit() elif isinstance(hexagons_color, list) and len(hexagons_color) == 20: tmp = [] hexagons_color_index = 0 while hexagons_color_index < 20: if type(hexagons_color[hexagons_color_index].a) == bool: hexagons_color[hexagons_color_index].a = 0 hexagons_color_index += 1 if not isinstance(lines_width, int): raise TypeError(lines_width, int) elif lines_width < 1: raise ValueError(lines_width, "Lines width value too little.") if isinstance(lines_color, Color): if type(lines_color.a) == bool: lines_color.a = 0 if isinstance(pentagons_color, Color): if type(pentagons_color.a) == bool: pentagons_color.a = 0 if isinstance(hexagons_color, Color): if type(hexagons_color.a) == bool: hexagons_color.a = 0 if isinstance(display_ls, bool): self.display_ls = display_ls self.side_length = side_length self.lines_color = lines_color self.pentagons_color = pentagons_color self.hexagons_color = hexagons_color self.lines_width = lines_width self.hexagons, self.pentagons = generate_fulleren(side_length) self.ls = Localview() self.center = Vertex(0.0, 0.0, 0.0)
def __init__(self,radius,basis,display_mode="lined",lines_color=False,faces_color=False,lines_width=1,display_ls=False) : ''' generate an trigon sphere object with the given radius and polygone basis. basis = Integer taken as basis for the sphere generating. radius = Radius of the sphere. display_mode = "lined" -> only the lines will be displayed. display_mode = "faced" -> only the faces will be displayed. display_mode = "twice" -> The lines and the faces will be displayed. lines_color = an objet <type 'Color'> representing the lines color. faces_color = an objet <type 'Color'> representing the faces color. line_width = an integer representing the lines width. ''' if not isinstance(radius,int) and not isinstance(radius,float) : raise TypeError(int,float) elif radius <= 0.0 : raise ValueError("Value of radius must be greater than 0.0") if not isinstance(basis,int) : raise TypeError(int) if basis < 6 or basis % 4 : print "the basis for the sphere must be greater as 5 and basis % 4 == 0 " quit() if display_mode == "lined" or display_mode == "faced" or display_mode == "twice" : self.display_mode=display_mode else : raise ValueError("Argument display_mode","lined","faced","twice") if lines_color : if not isinstance(lines_color,Color) : raise TypeError("Argument lines_color",Color) if faces_color : if not isinstance(faces_color,Color) : raise TypeError("Argument faces_color",Color) if not isinstance(lines_width,int) : raise TypeError(lines_width,int) elif lines_width < 1 : raise ValueError("Lines width value too little.") if isinstance(lines_color,Color) : if type(lines_color.a) == bool : lines_color.a=0 if not type(faces_color) == bool : if type(faces_color.a) == bool : faces_color.a=0 if isinstance(display_ls,bool) : self.display_ls=display_ls self.lines_color=lines_color self.faces_color=faces_color self.lines_width=lines_width self.basis=basis self.radius=radius self.trigons=generate_trigon_sphere(basis,radius)[0] self.ls=Localview() self.center=Vertex(0.0,0.0,0.0)
def generate_trigon_sphere(basis,radius) : ''' Sphere generating function which has for faces triangles and return an tuple from 2 arrays: (lined displaying vertices sequence list, surface displaying vertices sequence list). In relationship with the base for the sphere generating: faces count = basis * basis and the given sphere radius. ''' if not isinstance(basis,int) : raise TypeError(int) if basis < 8 or basis % 4 : print "the basis for the sphere miust be greater as 7 and basis % 4 == 0 " quit() if not isinstance(radius,int) and not isinstance(radius,float) : raise TypeError(int,float) # We generate the base polygon for the sphere generating with the given radius: base_polygon=generate_polygon_on_xy_radius(basis,radius,Vertex(0.0,0.0,0.0),0) polygons=[] # Polygon for trigonized sphere generating container. i=0 angle=360./basis # Computing of the degress between 2 polygons on the XZ surface. while i < basis : # Loop generating an quads sphere polygons list. tmp=[] for v in base_polygon : # Iteration over every vertice from the base polygon # and compting from the next polygon vertices rotate from # the distance between the base polygon and the next polygon. tmp.append(rotate_y(v,angle)) polygons.append(tmp) i += 1 angle += 360./basis # Distance between the base polygon and the next polygon inctrementing. boolean=False tmp_1=[] i=0 while i < len(polygons) : # Iteration over the quads sphere polygons # to compute the polygons on the XZ surface with an alternativ offset. ii=0 tmp_2=[] while ii < len(polygons[0]) : if boolean : tmp_2.append(rotate_y(polygons[ii][i],360./basis/2.)) else : tmp_2.append(polygons[ii][i]) ii += 1 if boolean : boolean=False else : boolean=True i += 1 tmp_1.append(tmp_2) tmp_2=tmp_1 i=-1 polygons_trigons_array=[] boolean=False while i < len(tmp_2)-1 : # Loop to compute the triangles from our sphere. # Throught iterating over the polygons on the XZ surface. ii=-1 while ii < len(tmp_2[i])-1 : tmp=[] if boolean : tmp.append(tmp_2[i][ii]) tmp.append(tmp_2[i][ii+1]) tmp.append(tmp_2[i+1][ii]) else : tmp.append(tmp_2[i][ii]) tmp.append(tmp_2[i][ii+1]) tmp.append(tmp_2[i+1][ii+1]) polygons_trigons_array.append(tmp) ii += 1 if boolean : boolean=False else : boolean=True i += 1 polygon_vertice_array=tmp_1 # Return an polygon array building an sphere and an array of triangles composing our trigon sphere. return (polygon_vertice_array,polygons_trigons_array)
class Localview(object) : def __init__(self,x=0.0,y=0.0,z=0.0) : ''' Create an localview object with: -) an position represented by an Vertex. -) 3 free axes initialise as the X, Y, Z axes. ''' self.pos=Vertex(x,y,z) # Position from the localview. self.right=Vector(1.,0.,0.) # Axe X representing vector. self.up=Vector(0.,1.,0.) # Axe Y representing vector. self.sight=Vector(0.,0.,1.) # Axe Z representing vector. def mult_matrix(self,matrix,localview) : ''' Multiply the localview with an matrix, given as argument, which settings change the localview. ''' if not isinstance(matrix,Matrix) : raise TypeError(Matrix) if not isinstance(localview,Localview) : raise TypeError(Localview) localview.pos=matrix.mult_vertex(localview.pos) # Multiply the matrix with the position Vertex. localview.up=matrix.mult_vector(localview.up) # Multiply the matrix with the X axe representing vector. localview.right=matrix.mult_vector(localview.right) # Multiply the matrix with the Y axe representing vector. localview.sight=matrix.mult_vector(localview.sight) # Multiply the matrix with the Z axe representing vector. return localview def __mul__(self,matrix) : ''' Localview and Localview multiplication sign '*' wrapper. Multiplying the current localview with the right operator Matrix object. ''' if not isinstance(matrix,Matrix) : raise TypeError(Matrix) self.pos=matrix.mult_vertex(self.pos) # Multiply the matrix with the position Vertex. self.up=matrix.mult_vector(self.up) # Multiply the matrix with the X axe representing vector. self.right=matrix.mult_vector(self.right) # Multiply the matrix with the Y axe representing vector. self.sight=matrix.mult_vector(self.sight) # Multiply the matrix with the Z axe representing vector. return self def display(self,factor) : ''' Function to display the localview axes. ''' right_arrow = self.right.add_vertex(self.pos,self.right.mult_vector(factor,self.right)) up_arrow = self.up.add_vertex(self.pos,self.up.mult_vector(factor,self.up)) sight_arrow = self.sight.add_vertex(self.pos,self.sight.mult_vector(factor,self.sight)) glLineWidth(4) glColor(255,0,0) glBegin(GL_LINES) glVertex(self.pos.get_vertex()) glVertex(right_arrow.get_vertex()) glEnd() glColor(0,255,0) glBegin(GL_LINES) glVertex(self.pos.get_vertex()) glVertex(up_arrow.get_vertex()) glEnd() glColor(0,0,255) glBegin(GL_LINES) glVertex(self.pos.get_vertex()) glVertex(sight_arrow.get_vertex()) glEnd() def __doc__(self) : ''' print documentation ''' print ''' Localview management class implementing an <type 'Localview'> datatype. An localview is an object representing either an -> Camera view. -> Local axes (X, Y, Z) of an 3D object. An locaview is made from: -> An localview position vertex, object from <type 'Vertex'>. which is the position from: -> The camera. -> The center from the 3D object. referenced as an attribute named: Localview.pos -> 3 axes, objects from <type 'Vector'>. Representing either: -> The camera orientation. -> The own axes from the 3D object. The Localview class implement: -) multiplication with an matrix methods: either as the method: -> Localview.mult_matrix(matrix) which take an matrix containing the changing to apply to the localview. -> an multiply sign placeholder: The matrix to multiply with must be at the right to the localview: Localview * Matrix -) An Locaview display method for debugging purpose. Which display the axes in their current orientation from the center to the greater values from the axes. At the current Localview position. '''
class Localview(object) : # This class is redefine here because we cannot import it because it cause import crossing errors: # The Localview class depends from the Matrix class and # The Matrix class depends from the Localview class !!! def __init__(self,x=0.0,y=0.0,z=0.0) : ''' Create an localview object with: -) an position represented by an Vertex. -) 3 free axes initialise as the X, Y, Z axes. ''' self.pos=Vertex(x,y,z) # Position from the localview. self.right=Vector(1.,0.,0.) # Axe X representing vector. self.up=Vector(0.,1.,0.) # Axe Y representing vector. self.sight=Vector(0.,0.,1.) # Axe Z representing vector. def mult_matrix(self,matrix,localview) : ''' Multiply the localview with an matrix, given as argument, which settings change the localview. ''' if not isinstance(matrix,Matrix) : raise TypeError(Matrix) if not isinstance(localview,Localview) : raise TypeError(Localview) localview.pos=matrix.mult_vertex(localview.pos) # Multiply the matrix with the position Vertex. localview.up=matrix.mult_vector(localview.up) # Multiply the matrix with the X axe representing vector. localview.right=matrix.mult_vector(localview.right) # Multiply the matrix with the Y axe representing vector. localview.sight=matrix.mult_vector(localview.sight) # Multiply the matrix with the Z axe representing vector. return localview def __mul__(self,matrix) : ''' Localview and Localview multiplication sign '*' wrapper. Multiplying the current localview with the right operator Matrix object. ''' if not isinstance(matrix,Matrix) : raise TypeError(Matrix) self.pos=matrix.mult_vertex(self.pos) # Multiply the matrix with the position Vertex. self.up=matrix.mult_vector(self.up) # Multiply the matrix with the X axe representing vector. self.right=matrix.mult_vector(self.right) # Multiply the matrix with the Y axe representing vector. self.sight=matrix.mult_vector(self.sight) # Multiply the matrix with the Z axe representing vector. return self def display(self,factor) : ''' Function to display the localview axes. ''' right_arrow = self.right.add_vertex(self.pos,self.right.mult_vector(factor,self.right)) up_arrow = self.up.add_vertex(self.pos,self.up.mult_vector(factor,self.up)) sight_arrow = self.sight.add_vertex(self.pos,self.sight.mult_vector(factor,self.sight)) glLineWidth(4) glColor(255,0,0) glBegin(GL_LINES) glVertex(self.pos.get_vertex()) glVertex(right_arrow.get_vertex()) glEnd() glColor(0,255,0) glBegin(GL_LINES) glVertex(self.pos.get_vertex()) glVertex(up_arrow.get_vertex()) glEnd() glColor(0,0,255) glBegin(GL_LINES) glVertex(self.pos.get_vertex()) glVertex(sight_arrow.get_vertex()) glEnd()