what if ALL meses work?

This commit is contained in:
gdamms 2022-10-19 19:44:16 +02:00
parent 9f9d271693
commit b542c7783f
2 changed files with 80 additions and 38 deletions

116
maps.py
View file

@ -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:
@ -99,13 +102,27 @@ 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

View file

@ -101,6 +101,8 @@ class Vertex:
self.area: float = 0.0
self.curvature: float = 0.0
self.border: bool = False
def to_obja(self) -> np.ndarray:
"""Convert vertex to obja format