from surf.geometry import Vertex, Edge, Face, Polygon from copy import deepcopy import pprint def mid_point(edge): vertex_objs = [edge.vertices[v_id] for v_id in edge.vertices] return sum(vertex_objs, Vertex()) / len(self.vertices) def sub_edges(self): temp_p = Polygon() temp_p.edges = [Edge(), Edge()] # temp_p.vertices = sub_edges[0].vertices = [self.vertices[0], self.edge_vertex] sub_edges[1].vertices = [self.edge_vertex, self.vertices[1]] return self.__sub_edges def centroid(face, poly): ''' ''' # gather all face vertex coords face_vertices = face.vertices xs = [vertex.x for vertex in face_vertices] ys = [vertex.y for vertex in face_vertices] zs = [vertex.z for vertex in face_vertices] # average each vertex component x = sum(xs) / len(xs) y = sum(ys) / len(ys) z = sum(zs) / len(zs) return Vertex(poly, x, y, z) def edge_divide(edge, poly): ''' Set each edge vertices to be the average of the two neighboring face vertices and its two original end vertices. ''' edge_ids = poly.edge_ids_with_parent(edge.id) if edge_ids: return edge_ids else: # otherwise split it xs = [] ys = [] zs = [] for face in edge.faces: centroid_v = centroid(face, None) xs.append(centroid_v.x) ys.append(centroid_v.y) zs.append(centroid_v.z) for vertex in edge.vertices: xs.append(vertex.x) ys.append(vertex.y) zs.append(vertex.z) x = sum(xs) / len(xs) y = sum(ys) / len(ys) z = sum(zs) / len(zs) e0 = Edge(poly) e1 = Edge(poly) edge_vertex = Vertex(poly, x, y, z) edge_vertex.edge_ids = [e0.id, e1.id] e0.vertex_ids = [edge.vertices[0].id, edge_vertex.id] e1.vertex_ids = [edge_vertex.id, edge.vertices[1].id] e0.edge_ids = edge.winged_edges_at_vertex(0) e0.edge_ids.append(e1.id) e1.edge_ids = edge.winged_edges_at_vertex(1) e1.edge_ids.append(e0.id) e0.parent_id = edge.id e1.parent_id = edge.id # add all these to the new polygon poly.edge_ids.append(e0.id) poly.edge_ids.append(e1.id) poly.vertices.append(edge_vertex.id) return e0.id, e1.id, edge_vertex.id def sub_faces(self): setup_sub_divisions() return sub_faces() def interior_edges(self): setup_sub_divisions() return self.__interior_edges def setup_sub_divisions(polygon, face): ''' v0 ev0 v1 *------e0-----* | | | | | | ev3 e|11----f5----e|1 ev1 | | | | | | *------e2-----* v3 ev2 v2 ''' # create empty sub_faces that will be filled with edge references # below # these need to at least exist so the interior edges have # something to reference sub_faces = [Face(polygon) for edge in face.edge_ids] # set up empty edge objects to be filled below interior_edges = [Edge(polygon) for edge in face.edge_ids] # # each interior edge connects the exterior edge vertex (mid-point) # # to the faceVertex (centroid) # for edge_id in range(len(face.edges)): # prevIndex = (edge_id - 1) % len(face.edges) # nextIndex = (edge_id + 1) % len(face.edges) # # end vertices are face centroid and currEdge edge_vertex # interior_edges[edge_id].vertices = [ # face.edges[edge_id], # edge_vertex, self.centroid # ] # # wing edges are the current edge's sub_edges (ordered same as # # vertex order) and the prev and next interior edges # self.__interior_edges[index].edges = [ # self.edges[index].sub_edges[0], # self.edges[index].sub_edges[1], # self.__interior_edges[prevIndex], # self.__interior_edges[nextIndex] # ] # # edge faces are the new sub_faces (current and next faces), the # # current will be define below # # and the next will be defined on the next iteration (or # # already defined on the last iteration) # self.__interior_edges[index].faces = [ # self.__sub_faces[index], # self.__sub_faces[nextIndex] # ] # # now reference the current edge back into the faces, # # and the edge.sub_edges, and the edge.edge_vertex # # current subFace (same index as current interior edge) # # set its edges to reference the same edges used to setup the # # interior edge # # order will be pretty important on these steps... # self.__sub_faces[index].edges = [ # self.edges[index].sub_edges[0], # self.__interior_edges[index], # self.__interior_edges[prevIndex], # self.edges[prevIndex].sub_edges[1] # ] # # just set one of the vertex edges, the other belongs to # # another face and will get added when that face is run # self.edges[index].edge_vertex.edges.append( # self.__interior_edges[index]) # self.edges[index].sub_edges[0].faces.append( # self.__sub_faces[index]) # self.edges[index].sub_edges[0].faces.append( # self.__sub_faces[index]) pass def subdivide_face(poly, face): # ''' # ''' # # find face centroid # fc = face.centroid # # find edge vertices # for edge in face.edges: # x, y, z = edge_mid_vertex(edge) pass def refine(poly): ''' For each face, add a face vertex Set each face vertex to be the centroid of all original vertices for the respective face. For each edge, add an edge vertex. Set each edge vertex to be the average of the two neighbouring face vertices and its two original endvertices. For each face vertex, add an edge for every edge of the face, connecting the face vertex to each edge vertex for the face. For each original vertex P, take the average F of all n face vertices for faces touching P, and take the average R of all n edge midvertices for edges touching P, where each edge midvertex is the average of its two endvertex vertices. Move each original vertex to the vertex ''' # create a new storage container for the items new_poly = Polygon() # for now just test with the first face start_face = poly.faces[0] # go through the face vertices and add them to the new polygon for vertex in start_face.vertices: # truly, this needs to be a 'copy' of the vertex, I'll fix that later new_poly.vertices.append(vertex) # find the face centroid # and add the face centroid to the new polygon start_centroid = centroid(start_face, new_poly) new_poly.vertices.append(start_centroid) # for each edge on the face, for edge in start_face.edges: # divide that edge into two new edges with an edge vertex # set their parent object as the original edge new_e0_id, new_e1_id, edge_v_id = edge_divide(edge, new_poly) # create a new edge connecting the centroid to the edge_vertex centroid_to_edge = Edge(new_poly) new_poly.edges.append(centroid_to_edge) # set the new edge's vertex references centroid_to_edge.vertex_ids = [edge_v_id, start_centroid.id] # set the new edge's winged_edge references centroid_to_edge.edge_ids = poly.edges ==> get edge by id not yet implemented... edge_v_id.edges # set the edge vertex edge references edge_v_id.edges.append(centroid_to_edge.id) # set the centroid's edge reference start_centroid.edge_ids.append(centroid_to_edge.id) # now walk through the edges connected to the centroid start_centroid.edges[0] # need to get an adjacent edge, based on the the shared vertex of the # original polygon... centroid to edge_vertex to shared point... # start_face.neighbors # f = sum(list( # set(face_vertices)), Vertex()) / len(list(set(face_vertices))) # r = sum(list( # set(edge_mid_points)), Vertex()) / len(list(set(edge_mid_points))) # p = vertex # n = len(vertex.edges) # v = (f + 2.0 * r + (n - 3.0) * p) / n # newVertices.append(v) # for vertex, newVertex in zip(poly.vertices, newVertices): # vertex.x = newVertex.x # vertex.y = newVertex.y # vertex.z = newVertex.z # # so now what......... # # (F + 2R + (n-3) P) / n # # # # F = average of all face vertices touching P # # R = average of all edge vertices touching P # # P original point # # n = number of edges connecting to P # p.faces = faces # p.vertices = vertices # p.edges = edges # # plotting these in excel seems to show the correct values (at first # # glace...) # # so now what......... # # (F + 2R + (n-3) P) / n # # # # F = average of all face vertices touching P # # R = average of all edge vertices touching P # # P original point # # n = face vertices or edge vertices (should be the same number) # return Polygon(vertices, edges, faces)