diff --git a/surf/__init__.pyc b/surf/__init__.pyc new file mode 100755 index 0000000..6b6222e Binary files /dev/null and b/surf/__init__.pyc differ diff --git a/surf/geometry.py b/surf/geometry.py index 5a81975..97a9595 100755 --- a/surf/geometry.py +++ b/surf/geometry.py @@ -24,13 +24,13 @@ def cross(a, b): k = a.x * b.y - a.y * b.x return Vertex(i, j, k) - class Vertex(object): ''' A vertex is a position along with other information such as color, normal vector and texture coordinates. ''' - def __init__(self, x=0, y=0, z=0): + def __init__(self, polygon, x=0, y=0, z=0): + self.polygon = polygon self.x = x self.y = y self.z = z @@ -73,187 +73,42 @@ class Vertex(object): def __neg__(self): return Vertex(-self.x, -self.y, -self.z) - class Edge(object): ''' ''' - def __init__(self): + + def __init__(self, polygon): + self.polygon = polygon self.vertices = [] self.faces = [] self.edges = [] - self.__edge_vertex = None - self.__sub_edges = [] - + def neighborFace(self, neighborFace): + '''Get neighboring face id + ''' if neighborFace == self.faces[0]: return self.faces[1] else: return self.faces[0] - @property - def mid_point(self): - return sum(self.vertices, Vertex()) / len(self.vertices) - - @property - def sub_edges(self): - if not self.__sub_edges: - self.__sub_edges = [Edge(), Edge()] - self.__sub_edges[0].vertices = [self.vertices[0], self.edge_vertex] - self.__sub_edges[1].vertices = [self.edge_vertex, self.vertices[1]] - return self.__sub_edges - - @property - def edge_vertex(self): - ''' - Set each edge vertices to be the average of the two neighboring - face vertices and its two original end vertices. - ''' - if not self.__edge_vertex: - # 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.__edge_vertex = Vertex(x, y, z) - self.__edge_vertex.edges.extend(self.__sub_edges) - return self.__edge_vertex - - def __averageVertices(self, vertices): - return - - class Face(object): ''' A face is a closed set of edges, in which a triangle face has three edges, and a quad face has four edges. ''' - def __init__(self): + def __init__(self, polygon): + self.polygon = polygon self.edges = [] - self.__centroid = None - self.__interior_edges = [] - self.__sub_faces = [] - - @property - def centroid(self): - if not self.__centroid: - # gather all face vertex coords - face_vertices = list(set([vertex - for edge in self.edges for vertex in edge.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) - - self.__centroid = Vertex(x, y, z) - return self.__centroid - - @property - def sub_faces(self): - self.__setupSubDivisions() - return self.__sub_faces - - @property - def interior_edges(self): - self.__setupSubDivisions() - return self.__interior_edges - - def __setupSubDivisions(self): - ''' - v0 ev0 v1 - *------e0-----* - | | | - | | | - ev3 e|11----f5----e|1 ev1 - | | | - | | | - *------e2-----* - v3 ev2 v2 - ''' - if not self.__sub_faces: - # 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 - self.__sub_faces = [Face() for edge in self.edges] - - if not self.__interior_edges: - # set up empty edge objects to be filled below - self.__interior_edges = [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 edge_vertex - self.__interior_edges[index].vertices = [ - self.edges[index].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]) - - + class Polygon(object): ''' - Face splitting should happend on the polygon level(?). It doesn't make - sense to split just one face since it needs to average vertices with all - adjoinging faces ''' - def __init__(self, v=None, e=None, f=None): - self.vertices = v or [] - self.edges = e or [] - self.faces = f or [] - + def __init__(self, vs=None, es=None, fs=None): + self.vertices = vs or [] + self.edges = es or [] + self.faces = fs or [] + def __unicode__(self): d = { 'vertices': self.vertices, @@ -261,6 +116,6 @@ class Polygon(object): 'faces': self.faces, } return pprint.pformat(d) - + __str__ = __unicode__ - __repr__ = __unicode__ + __repr__ = __unicode__ \ No newline at end of file diff --git a/surf/geometry.pyc b/surf/geometry.pyc new file mode 100755 index 0000000..638bb49 Binary files /dev/null and b/surf/geometry.pyc differ diff --git a/surf/subd/__init__.pyc b/surf/subd/__init__.pyc new file mode 100755 index 0000000..d3b74f0 Binary files /dev/null and b/surf/subd/__init__.pyc differ diff --git a/surf/subd/cc.py b/surf/subd/cc.py index 4b73e54..cd7de8e 100644 --- a/surf/subd/cc.py +++ b/surf/subd/cc.py @@ -1,5 +1,135 @@ from surf.geometry import Vertex, Polygon +def mid_point(self): + vertex_objs = [self.polygon.vertices[v_id] for v_id in self.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 edge_vertex(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: + neighboringFaceVertices = [p.faces[f_id].centroid for f_id 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.__edge_vertex = Vertex(x, y, z) + self.__edge_vertex.edges.extend(self.__sub_edges) + return self.__edge_vertex + +def centroid(self): + if not self.__centroid: + # gather all face vertex coords + face_vertices = list(set([vertex + for edge in self.edges for vertex in edge.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) + + self.__centroid = Vertex(x, y, z) + return self.__centroid + +def sub_faces(self): + self.__setupSubDivisions() + return self.__sub_faces + +def interior_edges(self): + self.__setupSubDivisions() + return self.__interior_edges + +def __setupSubDivisions(self): + ''' + v0 ev0 v1 + *------e0-----* + | | | + | | | + ev3 e|11----f5----e|1 ev1 + | | | + | | | + *------e2-----* + v3 ev2 v2 + ''' + if not self.__sub_faces: + # 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 + self.__sub_faces = [Face() for edge in self.edges] + + if not self.__interior_edges: + # set up empty edge objects to be filled below + self.__interior_edges = [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 edge_vertex + self.__interior_edges[index].vertices = [ + self.edges[index].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]) def refine(poly): ''' diff --git a/surf/util.py b/surf/util.py index cfbb84a..53f607a 100644 --- a/surf/util.py +++ b/surf/util.py @@ -1,4 +1,4 @@ -from surf.geometry import Vertex, Edge, Face, Polygon +from geometry import Vertex, Edge, Face, Polygon def cube(): @@ -75,85 +75,110 @@ def cube(): v6 - e2, e9, e10 v7 - e7, e10, e11 """ + p = Polygon() + p.vertices.append(Vertex(p, 1.0, 1.0, 0.0)) + p.vertices.append(Vertex(p, 1.0, 0.0, 0.0)) + p.vertices.append(Vertex(p, 0.0, 1.0, 0.0)) + p.vertices.append(Vertex(p, 0.0, 0.0, 0.0)) + + p.vertices.append(Vertex(p, 0.0, 1.0, 1.0)) + p.vertices.append(Vertex(p, 1.0, 1.0, 1.0)) + p.vertices.append(Vertex(p, 1.0, 0.0, 1.0)) + p.vertices.append(Vertex(p, 0.0, 0.0, 1.0)) - v = [] - v.append(Vertex(0.0, 1.0, 0.0)) - v.append(Vertex(1.0, 1.0, 0.0)) - v.append(Vertex(1.0, 0.0, 0.0)) - v.append(Vertex(0.0, 0.0, 0.0)) + p.edges.append(Edge(p)) + p.edges.append(Edge(p)) + p.edges.append(Edge(p)) + p.edges.append(Edge(p)) + p.edges.append(Edge(p)) + p.edges.append(Edge(p)) + p.edges.append(Edge(p)) + p.edges.append(Edge(p)) + p.edges.append(Edge(p)) + p.edges.append(Edge(p)) + p.edges.append(Edge(p)) + p.edges.append(Edge(p)) - v.append(Vertex(0.0, 1.0, 1.0)) - v.append(Vertex(1.0, 1.0, 1.0)) - v.append(Vertex(1.0, 0.0, 1.0)) - v.append(Vertex(0.0, 0.0, 1.0)) + p.faces.append(Face(p)) + p.faces.append(Face(p)) + p.faces.append(Face(p)) + p.faces.append(Face(p)) + p.faces.append(Face(p)) + p.faces.append(Face(p)) - e = [] - e.append(Edge()) - e.append(Edge()) - e.append(Edge()) - e.append(Edge()) - e.append(Edge()) - e.append(Edge()) - e.append(Edge()) - e.append(Edge()) - e.append(Edge()) - e.append(Edge()) - e.append(Edge()) - e.append(Edge()) - - f = [] - f.append(Face()) - f.append(Face()) - f.append(Face()) - f.append(Face()) - f.append(Face()) - f.append(Face()) - - # vertex list - v[0].edges = [e[0], e[3], e[4]] - v[1].edges = [e[0], e[5], e[1]] - v[2].edges = [e[1], e[6], e[2]] - v[3].edges = [e[2], e[7], e[3]] - v[4].edges = [e[4], e[11], e[8]] - v[5].edges = [e[5], e[9], e[8]] - v[6].edges = [e[6], e[9], e[10]] - v[7].edges = [e[7], e[10], e[11]] + p.vertices[0].edges = [0, 3, 4] + p.vertices[1].edges = [0, 5, 1] + p.vertices[2].edges = [1, 6, 2] + p.vertices[3].edges = [2, 7, 3] + p.vertices[4].edges = [4, 11, 8] + p.vertices[5].edges = [5, 9, 8] + p.vertices[6].edges = [6, 9, 10] + p.vertices[7].edges = [7, 10, 11] # face list - f[0].edges = [e[0], e[1], e[2], e[3]] - f[1].edges = [e[1], e[5], e[9], e[6]] - f[2].edges = [e[2], e[6], e[10], e[7]] - f[3].edges = [e[4], e[3], e[7], e[11]] - f[4].edges = [e[8], e[5], e[0], e[4]] - f[5].edges = [e[10], e[9], e[8], e[11]] + p.faces[0].edges = [0, 1, 2, 3] + p.faces[1].edges = [1, 5, 9, 6] + p.faces[2].edges = [2, 6, 10, 7] + p.faces[3].edges = [4, 3, 7, 11] + p.faces[4].edges = [8, 5, 0, 4] + p.faces[5].edges = [10, 9, 8, 11] #winged edges ordered by face, then by vertex reference - e[0].vertices, e[0].faces, e[0].edges = [v[0], v[1]], [f[0], f[4]], [e[3], e[1], e[4], e[5]] - e[1].vertices, e[1].faces, e[1].edges = [v[1], v[2]], [f[0], f[1]], [e[0], e[2], e[5], e[6]] - e[2].vertices, e[2].faces, e[2].edges = [v[2], v[3]], [f[0], f[2]], [e[1], e[3], e[6], e[7]] - e[3].vertices, e[3].faces, e[3].edges = [v[3], v[0]], [f[3], f[0]], [e[4], e[7], e[0], e[2]] - e[4].vertices, e[4].faces, e[4].edges = [v[0], v[4]], [f[3], f[4]], [e[11], e[3], e[0], e[8]] - e[5].vertices, e[5].faces, e[5].edges = [v[5], v[1]], [f[4], f[1]], [e[8], e[0], e[9], e[1]] - e[6].vertices, e[6].faces, e[6].edges = [v[2], v[6]], [f[1], f[2]], [e[1], e[9], e[2], e[10]] - e[7].vertices, e[7].faces, e[7].edges = [v[7], v[3]], [f[3], f[2]], [e[11], e[3], e[10], e[2]] - e[8].vertices, e[8].faces, e[8].edges = [v[4], v[5]], [f[4], f[5]], [e[4], e[5], e[11], e[9]] - e[9].vertices, e[9].faces, e[9].edges = [v[5], v[6]], [f[1], f[5]], [e[5], e[6], e[8], e[10]] - e[10].vertices, e[10].faces, e[10].edges = [v[7], v[6]], [f[2], f[5]], [e[7], e[6], e[11], e[9]] - e[11].vertices, e[11].faces, e[11].edges = [v[4], v[7]], [f[3], f[5]], [e[4], e[7], e[8], e[10]] + p.edges[0].vertices = [0, 1] + p.edges[1].vertices = [1, 2] + p.edges[2].vertices = [2, 3] + p.edges[3].vertices = [3, 0] + p.edges[4].vertices = [0, 4] + p.edges[5].vertices = [5, 1] + p.edges[6].vertices = [2, 6] + p.edges[7].vertices = [7, 3] + p.edges[8].vertices = [4, 5] + p.edges[9].vertices = [5, 6] + p.edges[10].vertices = [7, 6] + p.edges[11].vertices = [4, 7] + p.edges[0].edges = [3, 1, 4, 5] + p.edges[1].edges = [0, 2, 5, 6] + p.edges[2].edges = [1, 3, 6, 7] + p.edges[3].edges = [4, 7, 0, 2] + p.edges[4].edges = [11, 3, 0, 8] + p.edges[5].edges = [8, 0, 9, 1] + p.edges[6].edges = [1, 9, 2, 10] + p.edges[7].edges = [11, 3, 10, 2] + p.edges[8].edges = [4, 5, 11, 9] + p.edges[9].edges = [5, 6, 8, 10] + p.edges[10].edges = [7, 6, 11, 9] + p.edges[11].edges = [4, 7, 8, 10] + p.edges[0].faces = [0, 4] + p.edges[1].faces = [0, 1] + p.edges[2].faces = [0, 2] + p.edges[3].faces = [3, 0] + p.edges[4].faces = [3, 4] + p.edges[5].faces = [4, 1] + p.edges[6].faces = [1, 2] + p.edges[7].faces = [3, 2] + p.edges[8].faces = [4, 5] + p.edges[9].faces = [1, 5] + p.edges[10].faces = [2, 5] + p.edges[11].faces = [3, 5] - # just to prove to myself that the objects are the same, this is what years of pass by value have done to me... + # Polygon stores all the actual data. + # Every other class only stores indices to + # the original data. This could be slightly + # dangerous if any items get appended to the + # list of objects or the indices get changed. + + + # These are all the same vertex, just testing to make + # sure I did it right. + print p.vertices[1].x + + edge_v_id = p.edges[1].vertices[0] + print p.vertices[edge_v_id].x + + face_edge_id = p.faces[0].edges[1] + edge_v_id = p.edges[face_edge_id].vertices[0] + print p.vertices[edge_v_id].x - # print id(v[0].x) - # print id(e[0].vertices[0].x) - # print id(f[0].edges[0].vertices[0].x) + return p - # v[0].x = 9 - - # print id(v[0].x) - # print id(e[0].vertices[0].x) - # print id(f[0].edges[0].vertices[0].x) - - # print v[0].x - # print e[0].vertices[0].x - # print f[0].edges[0].vertices[0].x - return Polygon(v, e, f) +print cube() diff --git a/surf/util.pyc b/surf/util.pyc new file mode 100755 index 0000000..d1bc6dd Binary files /dev/null and b/surf/util.pyc differ diff --git a/test00.py b/test00.py new file mode 100755 index 0000000..0a03945 --- /dev/null +++ b/test00.py @@ -0,0 +1,24 @@ +from surf.util import cube +from surf.subd import cc + +polygon = cube() +print polygon + +refined_poly = cc.refine(polygon) +print refined_poly +# +# +# import pylab +# import mpl_toolkits.mplot3d.axes3d as p3 +# +# fig = pylab.figure() +# ax = p3.Axes3D(fig) +# for edge in newPolygon.edges: +# xs = [vertex.x for vertex in edge.vertices] +# ys = [vertex.y for vertex in edge.vertices] +# zs = [vertex.z for vertex in edge.vertices] +# ax.plot_wireframe(xs, ys, zs) +# ax.set_xlabel('X') +# ax.set_ylabel('Y') +# ax.set_zlabel('Z') +# pylab.show()