Files

90 lines
2.9 KiB
Python
Raw Permalink Normal View History

import os
from .config import Config
from .robot import Robot
from .processor import Processor
from .message import bright, info, error
class ProcessorSimplifySTLs(Processor):
"""
Allow for mesh simplifications using MeshLab
"""
def __init__(self, config: Config):
super().__init__(config)
# STL merge / simplification
self.simplify_stls = config.get("simplify_stls", False)
self.max_stl_size = config.get("max_stl_size", 3)
if self.simplify_stls:
self.pymeshlab = self.check_meshlab()
def check_meshlab(self):
print(bright("* Checking pymeshlab presence..."))
try:
import pymeshlab
return pymeshlab
except ImportError:
self.simplify_stls = False
print(error("No pymeshlab, disabling STL simplification support"))
print(info("TIP: consider installing pymeshlab:"))
print(info("pip install pymeshlab"))
def process(self, robot: Robot):
if self.simplify_stls:
simplify_all = (
self.simplify_stls != "visual" and self.simplify_stls != "collision"
)
simplified = set()
getcwd = os.getcwd()
# Changing directory to output to have relative paths working
os.chdir(self.config.output_directory)
for link in robot.links:
for part in link.parts:
for mesh in part.meshes:
if (
simplify_all or mesh.is_type(self.simplify_stls)
) and mesh.filename not in simplified:
simplified.add(mesh.filename)
self.simplify_stl(mesh.filename)
os.chdir(getcwd)
def reduce_faces(self, filename: str, reduction: float = 0.9):
mesh_set = self.pymeshlab.MeshSet()
# Add input mesh
mesh_set.load_new_mesh(filename)
# Apply filter
mesh_set.apply_filter(
"meshing_decimation_quadric_edge_collapse",
targetperc=reduction,
qualitythr=0.5,
preserveboundary=False,
boundaryweight=1,
preservenormal=True,
preservetopology=False,
optimalplacement=True,
planarquadric=True,
qualityweight=False,
planarweight=0.001,
autoclean=True,
selected=False,
)
# Save mesh
mesh_set.save_current_mesh(filename)
def simplify_stl(self, filename: str):
size_M = os.path.getsize(filename) / (1024 * 1024)
if size_M > self.max_stl_size:
print(
info(
f"+ {os.path.basename(filename)} is {size_M:.2f} M, running mesh simplification"
)
)
self.reduce_faces(filename, self.max_stl_size / size_M)