Cleaned up some pep8 violations
- changed camelCase variables to under_case - wrapped lines that were longer than 80 chars - used @property decorator - changed the cc refine test to print before running refine - refine seems to be destructive
This commit is contained in:
parent
84712d5613
commit
9a5fc54f12
183
surf/geometry.py
183
surf/geometry.py
@ -3,16 +3,18 @@ import pprint
|
|||||||
'''
|
'''
|
||||||
http://en.wikipedia.org/wiki/Polygon_mesh
|
http://en.wikipedia.org/wiki/Polygon_mesh
|
||||||
|
|
||||||
Polygon meshes may be represented in a variety of ways, using different methods to store the vertex, edge and face data. These include:
|
Polygon meshes may be represented in a variety of ways, using different methods
|
||||||
Face-vertex meshes: A simple list of vertices, and a set of polygons that vertex to the vertices it uses.
|
to store the vertex, edge and face data. These include:
|
||||||
Winged-edge meshes, in which each edge vertices to two vertices, two faces, and the four (clockwise and counterclockwise) edges that touch it. Winged-edge meshes allow constant time traversal of the surface, but with higher storage requirements.
|
- Face-vertex
|
||||||
Half-edge meshes: Similar to winged-edge meshes except that only half the edge traversal information is used.
|
- Winged-edge
|
||||||
Quad-edge meshes, which store edges, half-edges, and vertices without any reference to polygons. The polygons are implicit in the representation, and may be found by traversing the structure. Memory requirements are similar to half-edge meshes.
|
- Half-edge
|
||||||
Corner-tables, which store vertices in a predefined table, such that traversing the table implicitly defines polygons. This is in essence the "triangle fan" used in hardware graphics rendering. The representation is more compact, and more efficient to retrieve polygons, but operations to change polygons are slow. Furthermore, corner-tables do not represent meshes completely. Multiple corner-tables (triangle fans) are needed to represent most meshes.
|
- Quad-edge
|
||||||
Vertex-vertex meshes: A "VV" mesh represents only vertices, which vertex to other vertices. Both the edge and face information is implicit in the representation. However, the simplicity of the representation allows for many efficient operations to be performed on meshes.
|
- Corner-tables
|
||||||
|
- Vertex-vertex
|
||||||
|
- Face-vertex
|
||||||
|
|
||||||
|
We have chosen to use a winged-edge style mesh for our purpopses.
|
||||||
|
|
||||||
Face-vertex meshes represent an object as a set of faces and a set of vertices. This is the most widely used mesh representation, being the input typically accepted by modern graphics hardware.
|
|
||||||
v4 v5
|
v4 v5
|
||||||
*-----e8-----*
|
*-----e8-----*
|
||||||
| |
|
| |
|
||||||
@ -84,9 +86,11 @@ Polygon meshes may be represented in a variety of ways, using different methods
|
|||||||
|
|
||||||
'''
|
'''
|
||||||
|
|
||||||
|
|
||||||
class Vertex(object):
|
class Vertex(object):
|
||||||
'''
|
'''
|
||||||
A vertex is a position along with other information such as color, normal vector and texture coordinates.
|
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, x=0, y=0, z=0):
|
||||||
self.x = x
|
self.x = x
|
||||||
@ -100,7 +104,6 @@ class Vertex(object):
|
|||||||
else:
|
else:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return "[%.2f, %.2f, %.2f]" % (self.x, self.y, self.z)
|
return "[%.2f, %.2f, %.2f]" % (self.x, self.y, self.z)
|
||||||
|
|
||||||
@ -123,6 +126,7 @@ class Vertex(object):
|
|||||||
other = float(other)
|
other = float(other)
|
||||||
return Vertex(self.x / other, self.y / other, self.z / other)
|
return Vertex(self.x / other, self.y / other, self.z / other)
|
||||||
|
|
||||||
|
|
||||||
class Edge(object):
|
class Edge(object):
|
||||||
'''
|
'''
|
||||||
'''
|
'''
|
||||||
@ -130,67 +134,71 @@ class Edge(object):
|
|||||||
self.vertices = []
|
self.vertices = []
|
||||||
self.faces = []
|
self.faces = []
|
||||||
self.edges = []
|
self.edges = []
|
||||||
self.__edgeVertex = None
|
self.__edge_vertex = None
|
||||||
self.__subEdges = []
|
self.__sub_edges = []
|
||||||
|
|
||||||
def neighborFace(self, neighborFace):
|
def neighborFace(self, neighborFace):
|
||||||
if neighborFace == self.faces[0]:
|
if neighborFace == self.faces[0]:
|
||||||
return self.faces[1]
|
return self.faces[1]
|
||||||
else:
|
else:
|
||||||
return self.faces[0]
|
return self.faces[0]
|
||||||
def __getMidPoint(self):
|
|
||||||
return sum(self.vertices) / len(self.vertices)
|
|
||||||
midPoint = property(fget=__getMidPoint)
|
|
||||||
|
|
||||||
def __getSubEdges(self):
|
@property
|
||||||
if not self.__subEdges:
|
def mid_point(self):
|
||||||
self.__subEdges = [Edge(), Edge()]
|
return sum(self.vertices, Vertex()) / len(self.vertices)
|
||||||
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):
|
@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
|
Set each edge vertices to be the average of the two neighboring
|
||||||
face vertices and its two original end vertices.
|
face vertices and its two original end vertices.
|
||||||
'''
|
'''
|
||||||
if not self.__edgeVertex:
|
if not self.__edge_vertex:
|
||||||
# two neighboring face vertices:
|
# two neighboring face vertices:
|
||||||
neighboringFaceVertices = [face.centroid for face in self.faces]
|
neighboringFaceVertices = [face.centroid for face in self.faces]
|
||||||
neighboringFaceVertices.extend(self.vertices)
|
neighboringFaceVertices.extend(self.vertices)
|
||||||
xs = [vertex.x for vertex in neighboringFaceVertices]
|
xs = [vertex.x for vertex in neighboringFaceVertices]
|
||||||
ys = [vertex.y for vertex in neighboringFaceVertices]
|
ys = [vertex.y for vertex in neighboringFaceVertices]
|
||||||
zs = [vertex.z for vertex in neighboringFaceVertices]
|
zs = [vertex.z for vertex in neighboringFaceVertices]
|
||||||
x = sum(xs)/len(xs)
|
x = sum(xs) / len(xs)
|
||||||
y = sum(ys)/len(ys)
|
y = sum(ys) / len(ys)
|
||||||
z = sum(zs)/len(zs)
|
z = sum(zs) / len(zs)
|
||||||
self.__edgeVertex = Vertex(x, y, z)
|
self.__edge_vertex = Vertex(x, y, z)
|
||||||
self.__edgeVertex.edges.extend(self.__subEdges)
|
self.__edge_vertex.edges.extend(self.__sub_edges)
|
||||||
return self.__edgeVertex
|
return self.__edge_vertex
|
||||||
edgeVertex = property(fget=__getEdgeVertex)
|
|
||||||
|
|
||||||
def __averageVertices(self, vertices):
|
def __averageVertices(self, vertices):
|
||||||
|
|
||||||
return
|
return
|
||||||
|
|
||||||
|
|
||||||
class Face(object):
|
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.
|
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):
|
||||||
self.edges = []
|
self.edges = []
|
||||||
self.__centroid = None
|
self.__centroid = None
|
||||||
self.__interiorEdges = []
|
self.__interior_edges = []
|
||||||
self.__subFaces = []
|
self.__sub_faces = []
|
||||||
|
|
||||||
def __getCentroid(self):
|
@property
|
||||||
|
def centroid(self):
|
||||||
if not self.__centroid:
|
if not self.__centroid:
|
||||||
# gather all face vertex coords
|
# gather all face vertex coords
|
||||||
faceVertices = list(set([vertex for edge in self.edges for vertex in edge.vertices]))
|
face_vertices = list(set([vertex
|
||||||
xs = [vertex.x for vertex in faceVertices]
|
for edge in self.edges for vertex in edge.vertices]))
|
||||||
ys = [vertex.y for vertex in faceVertices]
|
xs = [vertex.x for vertex in face_vertices]
|
||||||
zs = [vertex.z for vertex in faceVertices]
|
ys = [vertex.y for vertex in face_vertices]
|
||||||
|
zs = [vertex.z for vertex in face_vertices]
|
||||||
|
|
||||||
# average each vertex component
|
# average each vertex component
|
||||||
x = sum(xs) / len(xs)
|
x = sum(xs) / len(xs)
|
||||||
@ -199,17 +207,16 @@ class Face(object):
|
|||||||
|
|
||||||
self.__centroid = Vertex(x, y, z)
|
self.__centroid = Vertex(x, y, z)
|
||||||
return self.__centroid
|
return self.__centroid
|
||||||
centroid = property(fget=__getCentroid)
|
|
||||||
|
|
||||||
def __getSubFaces(self):
|
@property
|
||||||
|
def sub_faces(self):
|
||||||
self.__setupSubDivisions()
|
self.__setupSubDivisions()
|
||||||
return self.__subFaces
|
return self.__sub_faces
|
||||||
subFaces = property(fget=__getSubFaces)
|
|
||||||
|
|
||||||
def __getInteriorEdges(self):
|
@property
|
||||||
|
def interior_edges(self):
|
||||||
self.__setupSubDivisions()
|
self.__setupSubDivisions()
|
||||||
return self.__interiorEdges
|
return self.__interior_edges
|
||||||
interiorEdges = property(fget=__getInteriorEdges )
|
|
||||||
|
|
||||||
def __setupSubDivisions(self):
|
def __setupSubDivisions(self):
|
||||||
'''
|
'''
|
||||||
@ -223,56 +230,76 @@ class Face(object):
|
|||||||
*------e2-----*
|
*------e2-----*
|
||||||
v3 ev2 v2
|
v3 ev2 v2
|
||||||
'''
|
'''
|
||||||
if not self.__subFaces:
|
if not self.__sub_faces:
|
||||||
# create empty subFaces that will be filled with edge references below
|
# create empty sub_faces that will be filled with edge references
|
||||||
# these need to at least exist so the interior edges have something to reference
|
# below
|
||||||
self.__subFaces = [Face() for edge in self.edges]
|
# 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.__interiorEdges:
|
if not self.__interior_edges:
|
||||||
# set up empty edge objects to be filled below
|
# set up empty edge objects to be filled below
|
||||||
self.__interiorEdges = [Edge() for edge in self.edges]
|
self.__interior_edges = [Edge() for edge in self.edges]
|
||||||
|
|
||||||
# each interior edge connects the exterior edge vertex (mid-point) to the faceVertex (centroid)
|
# each interior edge connects the exterior edge vertex (mid-point)
|
||||||
|
# to the faceVertex (centroid)
|
||||||
for index in range(len(self.edges)):
|
for index in range(len(self.edges)):
|
||||||
prevIndex = (index - 1) % len(self.edges)
|
prevIndex = (index - 1) % len(self.edges)
|
||||||
nextIndex = (index + 1) % len(self.edges)
|
nextIndex = (index + 1) % len(self.edges)
|
||||||
|
|
||||||
# end vertices are face centroid and currEdge edgeVertex
|
# end vertices are face centroid and currEdge edge_vertex
|
||||||
self.__interiorEdges[index].vertices = [self.edges[index].edgeVertex,
|
self.__interior_edges[index].vertices = [
|
||||||
self.centroid]
|
self.edges[index].edge_vertex, self.centroid
|
||||||
|
]
|
||||||
|
|
||||||
# wing edges are the current edge's subEdges (ordered same as vertex order) and the prev and next interior edges
|
# wing edges are the current edge's sub_edges (ordered same as
|
||||||
self.__interiorEdges[index].edges = [self.edges[index].subEdges[0],
|
# vertex order) and the prev and next interior edges
|
||||||
self.edges[index].subEdges[1],
|
self.__interior_edges[index].edges = [
|
||||||
self.__interiorEdges[prevIndex],
|
self.edges[index].sub_edges[0],
|
||||||
self.__interiorEdges[nextIndex]]
|
self.edges[index].sub_edges[1],
|
||||||
|
self.__interior_edges[prevIndex],
|
||||||
|
self.__interior_edges[nextIndex]
|
||||||
|
]
|
||||||
|
|
||||||
# edge faces are the new subFaces (current and next faces), the current will be define below
|
# edge faces are the new sub_faces (current and next faces), the
|
||||||
# and the next will be defined on the next iteration (or already defined on the last iteration)
|
# current will be define below
|
||||||
self.__interiorEdges[index].faces = [self.__subFaces[index],
|
# and the next will be defined on the next iteration (or
|
||||||
self.__subFaces[nextIndex]]
|
# 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,
|
# now reference the current edge back into the faces,
|
||||||
# and the edge.subEdges, and the edge.edgeVertex
|
# and the edge.sub_edges, and the edge.edge_vertex
|
||||||
|
|
||||||
# current subFace (same index as current interior edge)
|
# current subFace (same index as current interior edge)
|
||||||
# set its edges to reference the same edges used to setup the interior edge
|
# set its edges to reference the same edges used to setup the
|
||||||
|
# interior edge
|
||||||
# order will be pretty important on these steps...
|
# order will be pretty important on these steps...
|
||||||
self.__subFaces[index].edges = [self.edges[index].subEdges[0],
|
self.__sub_faces[index].edges = [
|
||||||
self.__interiorEdges[index],
|
self.edges[index].sub_edges[0],
|
||||||
self.__interiorEdges[prevIndex],
|
self.__interior_edges[index],
|
||||||
self.edges[prevIndex].subEdges[1]]
|
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
|
# just set one of the vertex edges, the other belongs to
|
||||||
self.edges[index].edgeVertex.edges.append(self.__interiorEdges[index])
|
# 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])
|
||||||
|
|
||||||
self.edges[index].subEdges[0].faces.append(self.__subFaces[index])
|
|
||||||
self.edges[index].subEdges[0].faces.append(self.__subFaces[index])
|
|
||||||
|
|
||||||
class Polygon(object):
|
class Polygon(object):
|
||||||
'''
|
'''
|
||||||
Face splitting should happend on the polygon level(?). It doesn't make sense to split just one face since
|
Face splitting should happend on the polygon level(?). It doesn't make
|
||||||
it needs to average vertices with all adjoinging faces
|
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):
|
def __init__(self, v=None, e=None, f=None):
|
||||||
|
@ -1,24 +1,32 @@
|
|||||||
from surf.geometry import Vertex, Polygon
|
from surf.geometry import Vertex, Polygon
|
||||||
|
|
||||||
|
|
||||||
def refine(poly):
|
def refine(poly):
|
||||||
'''
|
'''
|
||||||
For each face, add a face vertex
|
For each face, add a face vertex
|
||||||
Set each face vertex to be the centroid of all original vertices for the respective face.
|
Set each face vertex to be the centroid of all original vertices for
|
||||||
|
the respective face.
|
||||||
For each edge, add an edge vertex.
|
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.
|
Set each edge vertex to be the average of the two neighbouring face
|
||||||
For each face vertex, add an edge for every edge of the face, connecting the face vertex to each edge vertex for the face.
|
vertices and its two original endvertices.
|
||||||
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
|
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
|
||||||
'''
|
'''
|
||||||
|
|
||||||
|
# each face knows how to subdivide and create a set of subfaces, including
|
||||||
# each face knows how to subdivide and create a set of subfaces, including interior edges and setup their references correctly... <- not completely finished...
|
# interior edges and setup their references correctly... <- not completely
|
||||||
|
# finished...
|
||||||
p = Polygon()
|
p = Polygon()
|
||||||
edges = []
|
edges = []
|
||||||
vertices = []
|
vertices = []
|
||||||
faces = []
|
faces = []
|
||||||
|
|
||||||
for face in poly.faces:
|
for face in poly.faces:
|
||||||
for subFace in face.subFaces:
|
for subFace in face.sub_faces:
|
||||||
faces.append(subFace)
|
faces.append(subFace)
|
||||||
for edge in subFace.edges:
|
for edge in subFace.edges:
|
||||||
edges.append(edge)
|
edges.append(edge)
|
||||||
@ -27,15 +35,17 @@ def refine(poly):
|
|||||||
|
|
||||||
newVertices = []
|
newVertices = []
|
||||||
for vertex in poly.vertices:
|
for vertex in poly.vertices:
|
||||||
faceVertices = []
|
face_vertices = []
|
||||||
edgeMidPoints = []
|
edge_mid_points = []
|
||||||
for edge in vertex.edges:
|
for edge in vertex.edges:
|
||||||
edgeMidPoints.append(edge.midPoint)
|
edge_mid_points.append(edge.mid_point)
|
||||||
for face in edge.faces:
|
for face in edge.faces:
|
||||||
faceVertices.append(face.centroid)
|
face_vertices.append(face.centroid)
|
||||||
|
|
||||||
f = sum(list(set(faceVertices)), Vertex())/len(list(set(faceVertices)))
|
f = sum(list(
|
||||||
r = sum(list(set(edgeMidPoints)), Vertex())/len(list(set(edgeMidPoints)))
|
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
|
p = vertex
|
||||||
n = len(vertex.edges)
|
n = len(vertex.edges)
|
||||||
v = (f + 2.0 * r + (n - 3.0) * p) / n
|
v = (f + 2.0 * r + (n - 3.0) * p) / n
|
||||||
@ -57,8 +67,8 @@ def refine(poly):
|
|||||||
p.vertices = vertices
|
p.vertices = vertices
|
||||||
p.edges = edges
|
p.edges = edges
|
||||||
|
|
||||||
|
# plotting these in excel seems to show the correct values (at first
|
||||||
# plotting these in excel seems to show the correct values (at first glace...)
|
# glace...)
|
||||||
|
|
||||||
# so now what.........
|
# so now what.........
|
||||||
# (F + 2R + (n-3) P) / n
|
# (F + 2R + (n-3) P) / n
|
||||||
|
@ -2,9 +2,9 @@ from surf.util import cube
|
|||||||
from surf.subd import cc
|
from surf.subd import cc
|
||||||
|
|
||||||
polygon = cube()
|
polygon = cube()
|
||||||
refined_poly = cc.refine(polygon)
|
|
||||||
|
|
||||||
print polygon
|
print polygon
|
||||||
|
|
||||||
|
refined_poly = cc.refine(polygon)
|
||||||
print refined_poly
|
print refined_poly
|
||||||
#
|
#
|
||||||
#
|
#
|
||||||
|
Loading…
Reference in New Issue
Block a user