Merge pull request #32 from Rich43/codex/enforce-stl-printability-checks

Enforce printability validation for STL export
This commit is contained in:
Richard Ward
2025-07-18 11:47:49 +01:00
committed by GitHub
3 changed files with 274 additions and 9806 deletions

View File

@@ -5,13 +5,16 @@ import numpy as np
from pathlib import Path
from datetime import datetime
from parametric_cad.printability import PrintabilityValidator
class STLExporter:
"""Export trimesh objects to STL with optional previews."""
def __init__(self, output_dir="output", binary=False):
def __init__(self, output_dir: str = "output", binary: bool = False) -> None:
self.output_dir = output_dir
self.binary = binary
os.makedirs(self.output_dir, exist_ok=True)
self.validator = PrintabilityValidator()
def _ensure_mesh(self, obj):
if isinstance(obj, tm.Trimesh):
@@ -35,6 +38,12 @@ class STLExporter:
else:
combined = combined.convex_hull
errors = self.validator.validate_mesh(combined)
if errors:
raise ValueError(
"Printability validation failed: " + ", ".join(errors)
)
filename = f"{base_filename}.stl"
if timestamp:
ts = datetime.now().strftime("%Y%m%d_%H%M%S")

File diff suppressed because it is too large Load Diff

View File

@@ -1,8 +1,8 @@
import os
from pathlib import Path
import pytest
from parametric_cad.primitives.box import Box
from parametric_cad.primitives.cylinder import Cylinder
from parametric_cad.primitives.sphere import Sphere
from parametric_cad.export.stl import STLExporter
EXPECTED_DIR = Path(__file__).parent / "expected_stl"
@@ -23,10 +23,10 @@ def test_stl_exporter(tmp_path):
def test_ascii_stl_multiple_objects(tmp_path):
exporter = STLExporter(output_dir=tmp_path)
box = Box(1.0, 2.0, 1.0)
cyl = Cylinder(radius=0.5, height=1.0)
sph = Sphere(radius=0.25)
path = exporter.export_meshes([box, cyl, sph], "combo", preview=False)
box = Box(1.0, 2.0, 1.0).at(0, 0, 0.5)
cyl = Cylinder(radius=2.0, height=1.0, sections=8).at(3, 0, 0.5)
box2 = Box(0.5, 0.5, 0.5).at(0, 3, 0.25)
path = exporter.export_meshes([box, cyl, box2], "combo", preview=False)
assert os.path.isfile(path)
assert path == str(tmp_path / "combo.stl")
with open(path, "r", encoding="utf-8") as f:
@@ -34,3 +34,10 @@ def test_ascii_stl_multiple_objects(tmp_path):
with open(EXPECTED_DIR / "combo.stl", "r", encoding="utf-8") as f:
expected = f.read()
assert contents == expected
def test_exporter_printability_failure(tmp_path):
exporter = STLExporter(output_dir=tmp_path)
big_box = Box(300.0, 10.0, 10.0)
with pytest.raises(ValueError):
exporter.export_mesh(big_box, "bad_box", preview=False)