From c6434469fb6976c72d179974edce0a6ad2e7faba Mon Sep 17 00:00:00 2001 From: William Blattman Date: Sun, 18 Mar 2012 17:03:07 -0700 Subject: [PATCH] added code to subdivide faces, not quite finished but looks promising --- geometry.py | 163 ++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 120 insertions(+), 43 deletions(-) diff --git a/geometry.py b/geometry.py index 0bfb70a..d75f49c 100755 --- a/geometry.py +++ b/geometry.py @@ -104,6 +104,8 @@ class Edge(object): self.vertices = [] self.faces = [] self.edges = [] + self.__edgeVertex = None + self.__subEdges = [] def neighborFace(self, neighborFace): if neighborFace == self.faces[0]: @@ -111,27 +113,37 @@ class Edge(object): else: return self.faces[0] - def edgeVertex(self): + def __getSubEdges(self): + if not self.__subEdges: + self.__subEdges = [Edge(), Edge()] + self.__subEdges[0].vertices = [self.vertices[0], self.edgeVertex] + self.__subEdges[1].vertices = [self.edgeVertex, self.vertices[1]] + return self.__subEdges + subEdges = property(fget=__getSubEdges) + + def __getEdgeVertex(self): ''' Set each edge vertices to be the average of the two neighboring face vertices and its two original end vertices. ''' - - # two neighboring face vertices: - neighborVertices = [face.centroid for face in self.faces] - - vertices = list(self.vertices) - vertices.extend(neighborVertices) - return self.__averageVertices(vertices) + if not self.__edgeVertex: + # two neighboring face vertices: + neighboringFaceVertices = [face.centroid for face in self.faces] + neighboringFaceVertices.extend(self.vertices) + xs = [vertex.x for vertex in neighboringFaceVertices] + ys = [vertex.y for vertex in neighboringFaceVertices] + zs = [vertex.z for vertex in neighboringFaceVertices] + x = sum(xs)/len(xs) + y = sum(ys)/len(ys) + z = sum(zs)/len(zs) + self.__edgeVertex = Vertex(x, y, z) + self.__edgeVertex.edges.extend(self.__subEdges) + return self.__edgeVertex + edgeVertex = property(fget=__getEdgeVertex) def __averageVertices(self, vertices): - xs = [vertex.x for vertex in vertices] - ys = [vertex.y for vertex in vertices] - zs = [vertex.z for vertex in vertices] - x = sum(xs)/len(xs) - y = sum(ys)/len(ys) - z = sum(zs)/len(zs) - return Vertex(x, y, z) + + return class Face(object): ''' @@ -139,25 +151,94 @@ class Face(object): ''' def __init__(self): self.edges = [] + self.__centroid = None + self.__interiorEdges = [] + self.__subFaces = [] def __getCentroid(self): - # gather all vertex coords - faceVertices = self.__getFaceVertices() - xs = [vertex.x for vertex in faceVertices] - ys = [vertex.y for vertex in faceVertices] - zs = [vertex.z for vertex in faceVertices] - - # average each vertex component - x = sum(xs) / len(xs) - y = sum(ys) / len(ys) - z = sum(zs) / len(zs) - - return Vertex(x, y, z) + if not self.__centroid: + # gather all face vertex coords + faceVertices = list(set([vertex for edge in self.edges for vertex in edge.vertices])) + xs = [vertex.x for vertex in faceVertices] + ys = [vertex.y for vertex in faceVertices] + zs = [vertex.z for vertex in faceVertices] + + # average each vertex component + x = sum(xs) / len(xs) + y = sum(ys) / len(ys) + z = sum(zs) / len(zs) + + self.__centroid = Vertex(x, y, z) + return self.__centroid centroid = property(fget=__getCentroid) - def __getFaceVertices(self): - return list([vertex for edge in self.edges for vertex in edge.vertices]) - vertices = property(fget=__getFaceVertices) + def __getSubFaces(self): + self.__setupSubDivisions() + return self.__subFaces + subFaces = property(fget=__getSubFaces) + + def __getInteriorEdges(self): + self.__setupSubDivisions() + return self.__interiorEdges + interiorEdges = property(fget=__getInteriorEdges ) + + def __setupSubDivisions(self): + ''' + v0 ev0 v1 + *------e0-----* + | | | + | | | + ev3 e|11----f5----e|1 ev1 + | | | + | | | + *------e2-----* + v3 ev2 v2 + ''' + if not self.__subFaces: + # create empty subFaces that will be filled with edge references below + # these need to at least exist so the interior edges have something to reference + self.__subFaces = [Face() for edge in self.edges] + + if not self.__interiorEdges: + # set up empty edge objects to be filled below + self.__interiorEdges = [Edge() for edge in self.edges] + + # each interior edge connects the exterior edge vertex (mid-point) to the faceVertex (centroid) + for index in range(len(self.edges)): + prevIndex = (index - 1) % len(self.edges) + nextIndex = (index + 1) % len(self.edges) + + # end vertices are face centroid and currEdge edgeVertex + self.__interiorEdges[index].vertices = [self.edges[index].edgeVertex, + self.centroid] + + # wing edges are the current edge's subEdges (ordered same as vertex order) and the prev and next interior edges + self.__interiorEdges[index].edges = [self.edges[index].subEdges[0], + self.edges[index].subEdges[1], + self.__interiorEdges[prevIndex], + self.__interiorEdges[nextIndex]] + + # edge faces are the new subFaces (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.__interiorEdges[index].faces = [self.__subFaces[index], + self.__subFaces[nextIndex]] + + # now reference the current edge back into the faces, + # and the edge.subEdges, and the edge.edgeVertex + + # 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.__subFaces[index].edges = [self.edges[index].subEdges[0], + self.__interiorEdges[index], + self.__interiorEdges[prevIndex], + self.edges[prevIndex].subEdges[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].edgeVertex.edges.append(self.__interiorEdges[index]) + + self.edges[index].subEdges[0].faces.append(self.__subFaces[index]) + self.edges[index].subEdges[0].faces.append(self.__subFaces[index]) class Polygon(object): ''' @@ -170,10 +251,8 @@ class Polygon(object): self.edges = edges self.faces = faces - def __getFaceNeighbors(self, testFace): - for face in self.faces: - testFace.isNeighbor(face) - + def __repr__(self): + return str([edge for edge in self.edges]) def catmullClarkRefine(self): ''' For each face, add a face vertex @@ -184,17 +263,16 @@ class Polygon(object): 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 ''' - # this calculates and returns the averaged vertex point - print self.faces[0].edges[0].edgeVertex() + # each face knows how to subdivide and create a set of subfaces, including interior edges and setup their references correctly... <- not completely finished... - # this returns a vertex at the face centroid - print self.faces[0].centroid + for face in self.faces: + for subFace in face.subFaces: + for edge in subFace.edges: + for vertex in edge.vertices: + print vertex - # this will get to the first neighborFace... - # each face knows its faceVertex, and all of its edgeVertices - neighborFace = self.faces[0].edges[0].neighborFace(self.faces[0]) + # plotting these in excel seems to show the correct values (at first glace...) - print neighborFace.centroid # so now what......... @@ -290,7 +368,6 @@ polygon = Polygon(v, e, f) polygon.catmullClarkRefine() - # from numpy import * # import pylab # import mpl_toolkits.mplot3d.axes3d as p3