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