what if ALL meses work?
This commit is contained in:
parent
9f9d271693
commit
b542c7783f
116
maps.py
116
maps.py
|
@ -1,4 +1,5 @@
|
|||
import io
|
||||
from requests import delete
|
||||
from rich.progress import Progress
|
||||
|
||||
import obja.obja as obja
|
||||
|
@ -6,6 +7,10 @@ from object import Edge, Face, Vertex
|
|||
from utils import *
|
||||
|
||||
|
||||
class FixModel(Exception):
|
||||
pass
|
||||
|
||||
|
||||
class MAPS(obja.Model):
|
||||
"""MAPS compression model"""
|
||||
|
||||
|
@ -40,34 +45,32 @@ class MAPS(obja.Model):
|
|||
def fix(self) -> None:
|
||||
"""Fix the model"""
|
||||
|
||||
fixed = True
|
||||
|
||||
# Find a vertex with less than 3 faces
|
||||
for i, vertex in enumerate(self.vertices):
|
||||
if vertex is None:
|
||||
continue
|
||||
|
||||
if len(vertex.face_ring) < 3:
|
||||
# Remove the vertex and its faces
|
||||
for face in vertex.face_ring:
|
||||
if not self.final_only:
|
||||
self.operations.append(
|
||||
('af', face, self.faces[face].to_obja()))
|
||||
self.faces[face] = None
|
||||
if not self.final_only:
|
||||
self.operations.append(
|
||||
('av', i, vertex.to_obja()))
|
||||
self.vertices[i] = None
|
||||
# Remove lonely vertices
|
||||
if len(vertex.face_ring) == 0:
|
||||
self.delete_vertex(i)
|
||||
raise FixModel
|
||||
|
||||
# Indicate that the model has to be fixed again
|
||||
fixed = False
|
||||
# Pass if vertex has only 2 same faces
|
||||
if len(vertex.face_ring) != 2:
|
||||
continue
|
||||
if self.faces[vertex.face_ring[0]] != self.faces[vertex.face_ring[1]]:
|
||||
continue
|
||||
|
||||
return fixed
|
||||
# Remove the vertex and its faces
|
||||
self.delete_vertex(i)
|
||||
|
||||
# Indicate that the model has to be fixed again
|
||||
raise FixModel
|
||||
|
||||
def update_edges(self) -> None:
|
||||
"""Update edges"""
|
||||
|
||||
self.edges = {}
|
||||
self.edges: dict[str, Edge] = {}
|
||||
|
||||
for face in self.faces:
|
||||
if face is None:
|
||||
|
@ -98,14 +101,28 @@ class MAPS(obja.Model):
|
|||
|
||||
# Add the new edge to the list
|
||||
self.edges[f"{new_edge.a}:{new_edge.b}"] = new_edge
|
||||
|
||||
def delete_vertex(self, index: int) -> None:
|
||||
"""Delete a vertex and its faces
|
||||
|
||||
Args:
|
||||
index (int): index of the vertex to delete
|
||||
"""
|
||||
vertex = self.vertices[index]
|
||||
|
||||
for face in vertex.face_ring:
|
||||
if not self.final_only:
|
||||
self.operations.append(
|
||||
('af', face, self.faces[face].to_obja()))
|
||||
self.faces[face] = None
|
||||
if not self.final_only:
|
||||
self.operations.append(
|
||||
('av', index, vertex.to_obja()))
|
||||
self.vertices[index] = None
|
||||
|
||||
def update_rings(self) -> None:
|
||||
"""Update vertex and face rings"""
|
||||
|
||||
fixed = False
|
||||
|
||||
# Wait till the model is fixed
|
||||
while not fixed:
|
||||
try:
|
||||
for vertex in self.vertices:
|
||||
# Reset vertex ring
|
||||
if vertex is None:
|
||||
|
@ -120,16 +137,19 @@ class MAPS(obja.Model):
|
|||
self.vertices[vertex_i].face_ring.append(i)
|
||||
|
||||
# Fix the model
|
||||
fixed = self.fix()
|
||||
self.fix()
|
||||
|
||||
for i, vertex in enumerate(self.vertices):
|
||||
vertex = self.vertices[i]
|
||||
if vertex is None:
|
||||
continue
|
||||
for i, vertex in enumerate(self.vertices):
|
||||
vertex = self.vertices[i]
|
||||
if vertex is None:
|
||||
continue
|
||||
|
||||
# Compute rings
|
||||
ring = self.one_ring(i)
|
||||
vertex.vertex_ring = ring
|
||||
# Compute rings
|
||||
ring = self.one_ring(i)
|
||||
vertex.vertex_ring = ring
|
||||
|
||||
except FixModel:
|
||||
self.update_rings()
|
||||
|
||||
def update_area_curvature(self) -> None:
|
||||
"""Update area and curvature"""
|
||||
|
@ -146,6 +166,9 @@ class MAPS(obja.Model):
|
|||
# Find feature edges
|
||||
self.feature_edges = []
|
||||
for edge in self.edges.values():
|
||||
if edge.face2 is None:
|
||||
continue
|
||||
|
||||
edge.fold = np.dot(edge.face1.normal, edge.face2.normal)
|
||||
|
||||
if edge.fold < 0.5:
|
||||
|
@ -197,16 +220,21 @@ class MAPS(obja.Model):
|
|||
ring_faces = [self.faces[i] for i in self.vertices[index].face_ring]
|
||||
|
||||
# Initialize the ring
|
||||
start_index = (ring_faces[0].a if ring_faces[0].a != index and ring_faces[0].c != index else
|
||||
ring_faces[0].b if ring_faces[0].a != index and ring_faces[0].b != index else
|
||||
ring_faces[0].c)
|
||||
start_index, revert_index = (
|
||||
(ring_faces[0].c, ring_faces[0].b) if ring_faces[0].a == index else
|
||||
(ring_faces[0].a, ring_faces[0].c) if ring_faces[0].b == index else
|
||||
(ring_faces[0].b, ring_faces[0].a)
|
||||
)
|
||||
|
||||
ring = [start_index]
|
||||
|
||||
ring_faces.pop(0)
|
||||
revert_looking = False
|
||||
|
||||
# Select the indexes of the ring in the right order
|
||||
while len(ring_faces) > 0:
|
||||
broke = False
|
||||
prev_index = ring[-1]
|
||||
prev_index = ring[-1] if not revert_looking else ring[0]
|
||||
for i, face in enumerate(ring_faces):
|
||||
if prev_index in (face.a, face.b, face.c):
|
||||
# Found the face that correspond to the next vertex
|
||||
|
@ -215,13 +243,22 @@ class MAPS(obja.Model):
|
|||
face.b if face.b != index and face.b != prev_index else
|
||||
face.c
|
||||
)
|
||||
ring.append(current_index)
|
||||
if not revert_looking:
|
||||
ring.append(current_index)
|
||||
else:
|
||||
ring.insert(0, current_index)
|
||||
ring_faces.pop(i)
|
||||
broke = True
|
||||
break
|
||||
|
||||
if not broke:
|
||||
raise Exception('Ring corrupted')
|
||||
if revert_looking:
|
||||
self.delete_vertex(index)
|
||||
raise FixModel
|
||||
|
||||
revert_looking = True
|
||||
ring.insert(0, revert_index)
|
||||
self.vertices[index].border = True
|
||||
|
||||
return ring
|
||||
|
||||
|
@ -284,7 +321,7 @@ class MAPS(obja.Model):
|
|||
# Compute priorities
|
||||
priorities = []
|
||||
for vertex in self.vertices:
|
||||
if vertex is not None and len(vertex.vertex_ring) < max_length:
|
||||
if vertex is not None and 1 < len(vertex.vertex_ring) < max_length:
|
||||
# Compute priority
|
||||
priority = (
|
||||
lamb * vertex.area / max_area +
|
||||
|
@ -365,7 +402,10 @@ class MAPS(obja.Model):
|
|||
teta += self.compute_angle(index1, index, index2) # add new angle
|
||||
radius.append(r)
|
||||
angles.append(teta)
|
||||
angles = [2 * np.pi * a / teta for a in angles] # normalize angles
|
||||
|
||||
full_rotate = 2 * np.pi if not self.vertices[index].border else np.pi
|
||||
|
||||
angles = [full_rotate * a / teta for a in angles] # normalize angles
|
||||
coordinates = [np.array([r * np.cos(a), r * np.sin(a)])
|
||||
for r, a in zip(radius, angles)] # parse polar to cartesian
|
||||
|
||||
|
|
Loading…
Reference in a new issue