mirror of
https://github.com/johndoe6345789/bamboogenerator.git
synced 2026-04-24 13:24:54 +00:00
Add CadQuery wrappers and update docs
This commit is contained in:
38
README.md
38
README.md
@@ -1,8 +1,11 @@
|
||||
# bamboogenerator
|
||||
|
||||
Python scripts for generating 3D printable models using the
|
||||
`trimesh` library. The repository contains a consolidated
|
||||
`parametric_cad` package with example scripts that produce STL files.
|
||||
Python scripts for generating 3D printable models. The project now
|
||||
leverages the [CadQuery](https://github.com/CadQuery/cadquery)
|
||||
library for creating geometry while still providing utilities for
|
||||
scaffolding generation and printability validation. The repository
|
||||
contains a consolidated `parametric_cad` package with example scripts
|
||||
that produce STL files.
|
||||
|
||||
## Folder layout
|
||||
|
||||
@@ -18,7 +21,9 @@ installer script in the repository root. From the desired project directory run
|
||||
python install_requirements.py
|
||||
```
|
||||
|
||||
This installs all Python dependencies and attempts to set up `trimesh` for OpenSCAD rendering.
|
||||
This installs all Python dependencies including CadQuery. It also
|
||||
configures `trimesh` for OpenSCAD rendering which is still used under
|
||||
the hood for mesh operations.
|
||||
|
||||
## Running the examples
|
||||
|
||||
@@ -55,6 +60,31 @@ unioned = combine(boxes)
|
||||
result = safe_difference(unioned, Cylinder(0.5, 1).mesh())
|
||||
```
|
||||
|
||||
### Using CadQuery
|
||||
|
||||
CadQuery models can also be used with the validation and scaffolding
|
||||
utilities by converting a `Workplane` to a `trimesh` mesh:
|
||||
|
||||
```python
|
||||
import cadquery as cq
|
||||
from parametric_cad import workplane_to_mesh, generate_scaffolding
|
||||
|
||||
wp = cq.Workplane("XY").box(10, 10, 5)
|
||||
mesh = workplane_to_mesh(wp)
|
||||
supports = generate_scaffolding(mesh)
|
||||
```
|
||||
|
||||
You can also operate on CadQuery models directly using helper wrappers:
|
||||
|
||||
```python
|
||||
import cadquery as cq
|
||||
from parametric_cad import generate_scaffolding_from_workplane, PrintabilityValidator
|
||||
|
||||
wp = cq.Workplane("XY").box(10, 10, 5)
|
||||
supports = generate_scaffolding_from_workplane(wp)
|
||||
errors = PrintabilityValidator().validate_workplane(wp)
|
||||
```
|
||||
|
||||
## Overhang Scaffolding
|
||||
|
||||
`generate_scaffolding` creates simple cylindrical supports beneath
|
||||
|
||||
@@ -20,8 +20,22 @@ def install_openscad():
|
||||
def install_python_packages():
|
||||
logging.debug("Starting Python package installation process")
|
||||
print("Installing all required Python packages including triangulation engines...")
|
||||
packages = ["trimesh", "numpy", "matplotlib", "pyglet<2", "networkx", "scipy", "shapely",
|
||||
"triangle", "mapbox_earcut", "manifold3d", "pillow", "requests", "beautifulsoup4"]
|
||||
packages = [
|
||||
"trimesh",
|
||||
"cadquery",
|
||||
"numpy",
|
||||
"matplotlib",
|
||||
"pyglet<2",
|
||||
"networkx",
|
||||
"scipy",
|
||||
"shapely",
|
||||
"triangle",
|
||||
"mapbox_earcut",
|
||||
"manifold3d",
|
||||
"pillow",
|
||||
"requests",
|
||||
"beautifulsoup4",
|
||||
]
|
||||
try:
|
||||
subprocess.run([sys.executable, "-m", "pip", "install"] + packages, check=True)
|
||||
logging.info("Python packages installed successfully")
|
||||
|
||||
@@ -11,7 +11,8 @@ from .primitives.sphere import Sphere
|
||||
from .mechanisms.butthinge import ButtHinge
|
||||
from .export.stl import STLExporter
|
||||
from .printability import PrintabilityValidator
|
||||
from .scaffolding import generate_scaffolding
|
||||
from .scaffolding import generate_scaffolding, generate_scaffolding_from_workplane
|
||||
from .cadquery_utils import workplane_to_mesh
|
||||
|
||||
__all__ = [
|
||||
"tm",
|
||||
@@ -28,6 +29,8 @@ __all__ = [
|
||||
"STLExporter",
|
||||
"PrintabilityValidator",
|
||||
"generate_scaffolding",
|
||||
"generate_scaffolding_from_workplane",
|
||||
"workplane_to_mesh",
|
||||
"Polygon",
|
||||
"Point",
|
||||
"box",
|
||||
|
||||
13
parametric_cad/cadquery_utils.py
Normal file
13
parametric_cad/cadquery_utils.py
Normal file
@@ -0,0 +1,13 @@
|
||||
import io
|
||||
import cadquery as cq
|
||||
from cadquery.occ_impl import exporters
|
||||
|
||||
from .core import tm
|
||||
|
||||
|
||||
def workplane_to_mesh(wp: cq.Workplane) -> tm.Trimesh:
|
||||
"""Convert a CadQuery Workplane to a Trimesh mesh."""
|
||||
stl = exporters.toString(wp.val(), exporters.ExportTypes.STL)
|
||||
return tm.load(io.BytesIO(stl.encode("utf-8")), file_type="stl")
|
||||
|
||||
__all__ = ["workplane_to_mesh"]
|
||||
@@ -5,6 +5,8 @@ from pathlib import Path
|
||||
from typing import List
|
||||
|
||||
from .core import tm
|
||||
import cadquery as cq
|
||||
from .cadquery_utils import workplane_to_mesh
|
||||
import numpy as np
|
||||
|
||||
|
||||
@@ -85,5 +87,11 @@ class PrintabilityValidator:
|
||||
mesh = tm.load(file_path)
|
||||
return self.validate_mesh(mesh)
|
||||
|
||||
def validate_workplane(self, wp: cq.Workplane) -> List[str]:
|
||||
"""Validate a CadQuery Workplane."""
|
||||
|
||||
mesh = workplane_to_mesh(wp)
|
||||
return self.validate_mesh(mesh)
|
||||
|
||||
|
||||
__all__ = ["PrintabilityValidator"]
|
||||
|
||||
@@ -3,6 +3,8 @@ from __future__ import annotations
|
||||
import numpy as np
|
||||
|
||||
from .core import tm
|
||||
import cadquery as cq
|
||||
from .cadquery_utils import workplane_to_mesh
|
||||
|
||||
|
||||
def generate_scaffolding(
|
||||
@@ -65,4 +67,14 @@ def generate_scaffolding(
|
||||
return tm.util.concatenate(supports)
|
||||
|
||||
|
||||
__all__ = ["generate_scaffolding"]
|
||||
def generate_scaffolding_from_workplane(
|
||||
wp: cq.Workplane,
|
||||
**kwargs,
|
||||
) -> tm.Trimesh:
|
||||
"""Convert a Workplane and generate scaffolding."""
|
||||
|
||||
mesh = workplane_to_mesh(wp)
|
||||
return generate_scaffolding(mesh, **kwargs)
|
||||
|
||||
|
||||
__all__ = ["generate_scaffolding", "generate_scaffolding_from_workplane"]
|
||||
|
||||
10
tests/test_cadquery_utils.py
Normal file
10
tests/test_cadquery_utils.py
Normal file
@@ -0,0 +1,10 @@
|
||||
import cadquery as cq
|
||||
from parametric_cad.cadquery_utils import workplane_to_mesh
|
||||
from parametric_cad.core import tm
|
||||
|
||||
|
||||
def test_workplane_to_mesh():
|
||||
wp = cq.Workplane("XY").box(1, 1, 1)
|
||||
mesh = workplane_to_mesh(wp)
|
||||
assert isinstance(mesh, tm.Trimesh)
|
||||
assert mesh.volume > 0
|
||||
22
tests/test_cadquery_wrappers.py
Normal file
22
tests/test_cadquery_wrappers.py
Normal file
@@ -0,0 +1,22 @@
|
||||
import cadquery as cq
|
||||
from parametric_cad import (
|
||||
generate_scaffolding_from_workplane,
|
||||
PrintabilityValidator,
|
||||
tm,
|
||||
)
|
||||
|
||||
|
||||
def test_scaffolding_from_workplane():
|
||||
base = cq.Workplane("XY").box(2, 2, 1)
|
||||
overhang = cq.Workplane("XY").box(1, 1, 0.5).translate((1.5, 0.5, 1))
|
||||
wp = base.union(overhang)
|
||||
scaff = generate_scaffolding_from_workplane(wp)
|
||||
assert isinstance(scaff, tm.Trimesh)
|
||||
assert scaff.vertices.shape[0] > 0
|
||||
|
||||
|
||||
def test_validate_workplane():
|
||||
wp = cq.Workplane("XY").box(10, 10, 10)
|
||||
validator = PrintabilityValidator()
|
||||
errors = validator.validate_workplane(wp)
|
||||
assert errors == []
|
||||
Reference in New Issue
Block a user