211 lines
7.5 KiB
Python
211 lines
7.5 KiB
Python
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):
|
|
'''
|
|
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
|
|
'''
|
|
|
|
# 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 poly.faces:
|
|
for subFace in face.sub_faces:
|
|
faces.append(subFace)
|
|
for edge in subFace.edges:
|
|
edges.append(edge)
|
|
for vertex in edge.vertices:
|
|
vertices.append(vertex)
|
|
|
|
newVertices = []
|
|
for vertex in poly.vertices:
|
|
face_vertices = []
|
|
edge_mid_points = []
|
|
for edge in vertex.edges:
|
|
edge_mid_points.append(edge.mid_point)
|
|
for face in edge.faces:
|
|
face_vertices.append(face.centroid)
|
|
|
|
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)
|