Merge pull request #5 from willblatt/master
It plots it out, it looks mostly correct
This commit is contained in:
commit
4e3573a5b9
258
geometry.py
258
geometry.py
@ -88,7 +88,7 @@ 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, y, z):
|
def __init__(self, x=0, y=0, z=0):
|
||||||
self.x = x
|
self.x = x
|
||||||
self.y = y
|
self.y = y
|
||||||
self.z = z
|
self.z = z
|
||||||
@ -97,6 +97,24 @@ class Vertex(object):
|
|||||||
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)
|
||||||
|
|
||||||
|
def __add__(self, other):
|
||||||
|
# for now just assume type(other) = Vertex... bad, I know
|
||||||
|
return Vertex(self.x + other.x, self.y + other.y, self.z + other.z)
|
||||||
|
|
||||||
|
def __radd__(self, other):
|
||||||
|
return self.__add__(other)
|
||||||
|
|
||||||
|
def __mul__(self, other):
|
||||||
|
# for now just assume type(other) = int or float
|
||||||
|
return Vertex(self.x * other, self.y * other, self.z * other)
|
||||||
|
|
||||||
|
def __rmul__(self, other):
|
||||||
|
return self.__mul__(other)
|
||||||
|
|
||||||
|
def __div__(self, other):
|
||||||
|
# same assumption as __mult__
|
||||||
|
return Vertex(self.x / other, self.y / other, self.z / other)
|
||||||
|
|
||||||
class Edge(object):
|
class Edge(object):
|
||||||
'''
|
'''
|
||||||
'''
|
'''
|
||||||
@ -104,34 +122,49 @@ class Edge(object):
|
|||||||
self.vertices = []
|
self.vertices = []
|
||||||
self.faces = []
|
self.faces = []
|
||||||
self.edges = []
|
self.edges = []
|
||||||
|
self.__edgeVertex = None
|
||||||
|
self.__subEdges = []
|
||||||
|
|
||||||
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, Vertex())/len(self.vertices)
|
||||||
|
midPoint = property(fget=__getMidPoint)
|
||||||
|
|
||||||
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
|
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:
|
||||||
# two neighboring face vertices:
|
# two neighboring face vertices:
|
||||||
neighborVertices = [face.centroid for face in self.faces]
|
neighboringFaceVertices = [face.centroid for face in self.faces]
|
||||||
|
neighboringFaceVertices.extend(self.vertices)
|
||||||
vertices = list(self.vertices)
|
xs = [vertex.x for vertex in neighboringFaceVertices]
|
||||||
vertices.extend(neighborVertices)
|
ys = [vertex.y for vertex in neighboringFaceVertices]
|
||||||
return self.__averageVertices(vertices)
|
zs = [vertex.z for vertex in neighboringFaceVertices]
|
||||||
|
|
||||||
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)
|
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)
|
||||||
return Vertex(x, y, z)
|
self.__edgeVertex = Vertex(x, y, z)
|
||||||
|
self.__edgeVertex.edges.extend(self.__subEdges)
|
||||||
|
return self.__edgeVertex
|
||||||
|
edgeVertex = property(fget=__getEdgeVertex)
|
||||||
|
|
||||||
|
def __averageVertices(self, vertices):
|
||||||
|
|
||||||
|
return
|
||||||
|
|
||||||
class Face(object):
|
class Face(object):
|
||||||
'''
|
'''
|
||||||
@ -139,10 +172,14 @@ class Face(object):
|
|||||||
'''
|
'''
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.edges = []
|
self.edges = []
|
||||||
|
self.__centroid = None
|
||||||
|
self.__interiorEdges = []
|
||||||
|
self.__subFaces = []
|
||||||
|
|
||||||
def __getCentroid(self):
|
def __getCentroid(self):
|
||||||
# gather all vertex coords
|
if not self.__centroid:
|
||||||
faceVertices = self.__getFaceVertices()
|
# 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]
|
xs = [vertex.x for vertex in faceVertices]
|
||||||
ys = [vertex.y for vertex in faceVertices]
|
ys = [vertex.y for vertex in faceVertices]
|
||||||
zs = [vertex.z for vertex in faceVertices]
|
zs = [vertex.z for vertex in faceVertices]
|
||||||
@ -152,12 +189,77 @@ class Face(object):
|
|||||||
y = sum(ys) / len(ys)
|
y = sum(ys) / len(ys)
|
||||||
z = sum(zs) / len(zs)
|
z = sum(zs) / len(zs)
|
||||||
|
|
||||||
return Vertex(x, y, z)
|
self.__centroid = Vertex(x, y, z)
|
||||||
|
return self.__centroid
|
||||||
centroid = property(fget=__getCentroid)
|
centroid = property(fget=__getCentroid)
|
||||||
|
|
||||||
def __getFaceVertices(self):
|
def __getSubFaces(self):
|
||||||
return list([vertex for edge in self.edges for vertex in edge.vertices])
|
self.__setupSubDivisions()
|
||||||
vertices = property(fget=__getFaceVertices)
|
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):
|
class Polygon(object):
|
||||||
'''
|
'''
|
||||||
@ -165,14 +267,10 @@ class Polygon(object):
|
|||||||
it needs to average vertices with all adjoinging faces
|
it needs to average vertices with all adjoinging faces
|
||||||
'''
|
'''
|
||||||
|
|
||||||
def __init__(self, vertices, edges, faces):
|
def __init__(self):
|
||||||
self.vertices = vertices
|
self.vertices = []
|
||||||
self.edges = edges
|
self.edges = []
|
||||||
self.faces = faces
|
self.faces = []
|
||||||
|
|
||||||
def __getFaceNeighbors(self, testFace):
|
|
||||||
for face in self.faces:
|
|
||||||
testFace.isNeighbor(face)
|
|
||||||
|
|
||||||
def catmullClarkRefine(self):
|
def catmullClarkRefine(self):
|
||||||
'''
|
'''
|
||||||
@ -184,33 +282,75 @@ 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
|
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()
|
|
||||||
|
|
||||||
# this returns a vertex at the face centroid
|
|
||||||
print self.faces[0].centroid
|
|
||||||
|
|
||||||
# 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])
|
|
||||||
|
|
||||||
print neighborFace.centroid
|
|
||||||
|
|
||||||
|
# each face knows how to subdivide and create a set of subfaces, including interior edges and setup their references correctly... <- not completely finished...
|
||||||
|
p = Polygon()
|
||||||
|
edges = []
|
||||||
|
vertices = []
|
||||||
|
faces = []
|
||||||
|
|
||||||
|
for face in self.faces:
|
||||||
|
for subFace in face.subFaces:
|
||||||
|
faces.append(subFace)
|
||||||
|
for edge in subFace.edges:
|
||||||
|
edges.append(edge)
|
||||||
|
for vertex in edge.vertices:
|
||||||
|
vertices.append(vertex)
|
||||||
|
|
||||||
|
for vertex in self.vertices:
|
||||||
|
faceVertices = []
|
||||||
|
edgeMidPoints = []
|
||||||
|
for edge in vertex.edges:
|
||||||
|
edgeMidPoints.append(edge.midPoint)
|
||||||
|
for face in edge.faces:
|
||||||
|
faceVertices.append(face.centroid)
|
||||||
|
|
||||||
|
f = sum(list(set(faceVertices)), Vertex())/len(list(set(faceVertices)))
|
||||||
|
|
||||||
|
r = sum(list(set(edgeMidPoints)), Vertex())/len(list(set(edgeMidPoints)))
|
||||||
|
p = vertex
|
||||||
|
n = len(vertex.edges)
|
||||||
|
v = (f + (2.0 * r) + (n - 3.0) * p) / n
|
||||||
|
# print v
|
||||||
|
vertex.x = v.x
|
||||||
|
vertex.y = v.y
|
||||||
|
vertex.z = v.z
|
||||||
|
|
||||||
# so now what.........
|
# 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 + 2R + (n-3) P) / n
|
||||||
#
|
#
|
||||||
# F = average of all face vertices touching P
|
# F = average of all face vertices touching P
|
||||||
# R = average of all edge vertices touching P
|
# R = average of all edge vertices touching P
|
||||||
# P original point
|
# P original point
|
||||||
# n = face vertices or edge vertices (should be the same number)
|
# n = face vertices or edge vertices (should be the same number)
|
||||||
|
return p
|
||||||
|
|
||||||
|
def createPolygon():
|
||||||
v = []
|
v = []
|
||||||
v.append(Vertex(0.0, 1.0, 0.0))
|
v.append(Vertex(0.0, 1.0, 0.0))
|
||||||
v.append(Vertex(1.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(1.0, 0.0, 0.0))
|
||||||
v.append(Vertex(0.0, 0.0, 0.0))
|
v.append(Vertex(0.0, 0.0, 0.0))
|
||||||
|
|
||||||
v.append(Vertex(0.0, 1.0, 1.0))
|
v.append(Vertex(0.0, 1.0, 1.0))
|
||||||
v.append(Vertex(1.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(1.0, 0.0, 1.0))
|
||||||
@ -245,7 +385,7 @@ v[2].edges = [e[1], e[6], e[2]]
|
|||||||
v[3].edges = [e[2], e[7], e[3]]
|
v[3].edges = [e[2], e[7], e[3]]
|
||||||
v[4].edges = [e[4], e[11], e[8]]
|
v[4].edges = [e[4], e[11], e[8]]
|
||||||
v[5].edges = [e[5], e[9], e[8]]
|
v[5].edges = [e[5], e[9], e[8]]
|
||||||
v[6].edges = [e[2], e[9], e[10]]
|
v[6].edges = [e[6], e[9], e[10]]
|
||||||
v[7].edges = [e[7], e[10], e[11]]
|
v[7].edges = [e[7], e[10], e[11]]
|
||||||
|
|
||||||
# face list
|
# face list
|
||||||
@ -259,7 +399,7 @@ f[5].edges = [e[10], e[9], e[8], e[11]]
|
|||||||
#winged edges ordered by face, then by vertex reference
|
#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[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[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[3], e[7], e[1], 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[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[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[5].vertices, e[5].faces, e[5].edges = [v[5], v[1]], [f[4], f[1]], [e[8], e[0], e[9], e[1]]
|
||||||
@ -285,25 +425,27 @@ e[11].vertices, e[11].faces, e[11].edges = [v[4], v[7]], [f[3], f[5]], [e[4], e[
|
|||||||
# print v[0].x
|
# print v[0].x
|
||||||
# print e[0].vertices[0].x
|
# print e[0].vertices[0].x
|
||||||
# print f[0].edges[0].vertices[0].x
|
# print f[0].edges[0].vertices[0].x
|
||||||
|
p = Polygon()
|
||||||
|
p.vertices = v
|
||||||
|
p.edges = e
|
||||||
|
p.faces = f
|
||||||
|
return p
|
||||||
|
|
||||||
polygon = Polygon(v, e, f)
|
polygon = createPolygon()
|
||||||
polygon.catmullClarkRefine()
|
newPolygon = polygon.catmullClarkRefine()
|
||||||
|
|
||||||
|
from numpy import *
|
||||||
|
import pylab
|
||||||
|
import mpl_toolkits.mplot3d.axes3d as p3
|
||||||
|
|
||||||
|
fig = pylab.figure()
|
||||||
# from numpy import *
|
ax = p3.Axes3D(fig)
|
||||||
# import pylab
|
for edge in newPolygon.edges:
|
||||||
# import mpl_toolkits.mplot3d.axes3d as p3
|
xs = [vertex.x for vertex in edge.vertices]
|
||||||
|
ys = [vertex.y for vertex in edge.vertices]
|
||||||
# fig = pylab.figure()
|
zs = [vertex.z for vertex in edge.vertices]
|
||||||
# ax = p3.Axes3D(fig)
|
ax.plot_wireframe(xs, ys, zs)
|
||||||
# ax.plot_wireframe(xs, ys, zs)
|
ax.set_xlabel('X')
|
||||||
# ax.set_xlabel('X')
|
ax.set_ylabel('Y')
|
||||||
# ax.set_ylabel('Y')
|
ax.set_zlabel('Z')
|
||||||
# ax.set_zlabel('Z')
|
pylab.show()
|
||||||
# pylab.show()
|
|
||||||
|
|
||||||
# v4 = Vertex(4, 0, 0, 1)
|
|
||||||
# v5 = Vertex(5, 1, 0, 1)
|
|
||||||
# v6 = Vertex(6, 0, 1, 1)
|
|
||||||
# v7 = Vertex(7, 1, 1, 1)
|
|
Loading…
Reference in New Issue
Block a user