mirror of
https://github.com/johndoe6345789/bamboogenerator.git
synced 2026-04-24 13:24:54 +00:00
Merge pull request #13 from Rich43/codex/refactor-api-for-difference-method
Add safe_difference helper
This commit is contained in:
@@ -1,9 +1,9 @@
|
||||
"""Consolidated parametric_cad package."""
|
||||
|
||||
from .core import tm
|
||||
from .core import tm, safe_difference
|
||||
from .primitives.box import Box
|
||||
from .primitives.gear import SpurGear
|
||||
from .mechanisms.butthinge import ButtHinge
|
||||
from .export.stl import STLExporter
|
||||
|
||||
__all__ = ["tm", "Box", "SpurGear", "ButtHinge", "STLExporter"]
|
||||
__all__ = ["tm", "safe_difference", "Box", "SpurGear", "ButtHinge", "STLExporter"]
|
||||
|
||||
@@ -8,8 +8,38 @@ wrapper allows the backend to be swapped or mocked easily.
|
||||
|
||||
import trimesh as _trimesh
|
||||
|
||||
|
||||
def safe_difference(mesh, other, *, engine="scad"):
|
||||
"""Perform a boolean difference with graceful fallback.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
mesh : _trimesh.Trimesh
|
||||
Base mesh to subtract from.
|
||||
other : _trimesh.Trimesh or list
|
||||
Mesh or list of meshes to subtract.
|
||||
engine : str or None, optional
|
||||
Preferred boolean engine. ``"scad"`` is tried by default.
|
||||
|
||||
Returns
|
||||
-------
|
||||
_trimesh.Trimesh
|
||||
Resulting mesh if the operation succeeds, otherwise the original
|
||||
``mesh`` if all boolean attempts fail.
|
||||
"""
|
||||
|
||||
try:
|
||||
if engine:
|
||||
return mesh.difference(other, engine=engine)
|
||||
return mesh.difference(other)
|
||||
except Exception:
|
||||
try:
|
||||
return mesh.difference(other)
|
||||
except Exception:
|
||||
return mesh
|
||||
|
||||
# Public alias so that other modules can use the backend without
|
||||
# importing ``trimesh`` themselves.
|
||||
tm = _trimesh
|
||||
|
||||
__all__ = ["tm"]
|
||||
__all__ = ["tm", "safe_difference"]
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
from parametric_cad.primitives.box import Box
|
||||
from parametric_cad.export.stl import STLExporter
|
||||
from parametric_cad.core import safe_difference
|
||||
|
||||
outer = Box(100, 60, 40).at(0, 0, 0)
|
||||
inner = Box(90, 50, 30).at(5, 5, 5)
|
||||
@@ -7,13 +8,7 @@ inner = Box(90, 50, 30).at(5, 5, 5)
|
||||
# Create hollow box by subtracting inner from outer
|
||||
outer_mesh = outer.mesh()
|
||||
inner_mesh = inner.mesh()
|
||||
try:
|
||||
hollow_box = outer_mesh.difference(inner_mesh, engine='scad')
|
||||
except Exception:
|
||||
try:
|
||||
hollow_box = outer_mesh.difference(inner_mesh)
|
||||
except Exception:
|
||||
hollow_box = outer_mesh
|
||||
hollow_box = safe_difference(outer_mesh, inner_mesh)
|
||||
|
||||
exporter = STLExporter(output_dir="output/hollow_box_output")
|
||||
exporter.export_mesh(hollow_box, "hollow_box")
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import numpy as np
|
||||
from parametric_cad.core import tm
|
||||
from parametric_cad.core import tm, safe_difference
|
||||
from shapely.geometry import Polygon
|
||||
from math import pi, sin, cos, tan
|
||||
import logging
|
||||
@@ -91,14 +91,7 @@ class SpurGear:
|
||||
|
||||
bore = tm.creation.cylinder(radius=self.bore_diameter / 2, height=self.width + 0.1)
|
||||
bore.apply_translation([0, 0, self.width / 2])
|
||||
try:
|
||||
gear = gear_body.difference(bore, engine='scad')
|
||||
except Exception:
|
||||
try:
|
||||
gear = gear_body.difference(bore)
|
||||
except Exception:
|
||||
logging.warning("Boolean difference not available, skipping bore subtraction")
|
||||
gear = gear_body
|
||||
gear = safe_difference(gear_body, bore)
|
||||
logging.debug(f"Subtracted bore, resulting mesh has {len(gear.vertices)} vertices")
|
||||
|
||||
if self.hole_count > 0:
|
||||
@@ -112,13 +105,7 @@ class SpurGear:
|
||||
if not hole.is_volume:
|
||||
hole = hole.convex_hull
|
||||
hole_cylinders.append(hole)
|
||||
try:
|
||||
gear = gear.difference(hole_cylinders, engine='scad')
|
||||
except Exception:
|
||||
try:
|
||||
gear = gear.difference(hole_cylinders)
|
||||
except Exception:
|
||||
logging.warning("Boolean difference not available, skipping hole subtraction")
|
||||
gear = safe_difference(gear, hole_cylinders)
|
||||
logging.debug(f"Subtracted {self.hole_count} holes, resulting mesh has {len(gear.vertices)} vertices")
|
||||
|
||||
if not gear.is_watertight:
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import pytest
|
||||
import numpy as np
|
||||
from parametric_cad.core import tm
|
||||
from parametric_cad.core import tm, safe_difference
|
||||
from math import cos, pi
|
||||
|
||||
from parametric_cad.primitives.box import Box
|
||||
@@ -34,3 +34,10 @@ def test_cylinder_and_sphere_meshes():
|
||||
assert isinstance(sph_mesh, tm.Trimesh)
|
||||
assert cyl_mesh.is_watertight
|
||||
assert sph_mesh.is_watertight
|
||||
|
||||
|
||||
def test_safe_difference_returns_mesh():
|
||||
outer = Box(1.0, 1.0, 1.0)
|
||||
inner = Box(0.5, 0.5, 0.5).at(0.25, 0.25, 0.25)
|
||||
result = safe_difference(outer.mesh(), inner.mesh(), engine="invalid")
|
||||
assert isinstance(result, tm.Trimesh)
|
||||
|
||||
Reference in New Issue
Block a user