feat: Export DXF in build system

This commit is contained in:
Leni Aniva 2024-07-04 01:11:16 -07:00
parent 5bceb6180e
commit 66fc02ef44
Signed by: aniva
GPG Key ID: 4D9B1C8D10EA4C50
2 changed files with 54 additions and 21 deletions

View File

@ -2,25 +2,69 @@
The NHF build system
Usage: For any parametric assembly, inherit the `Model` class, and mark the
output objects with the `@target` decorator
output objects with the `@target` decorator. Each marked function should only
take `self` as an argument.
```python
class BuildScaffold(Model):
@target(name="obj1")
def o1(self):
return Cq.Solid.makeBox(10, 10, 10)
def o2(self):
return Cq.Solid.makeCylinder(10, 20)
```
"""
from enum import Enum
from pathlib import Path
from typing import Union
from functools import wraps
from colorama import Fore, Style
import cadquery as Cq
class TargetKind(Enum):
STL = "stl",
DXF = "dxf",
def __init__(self, ext: str):
self.ext = ext
class Target:
def __init__(self,
method,
name: str):
name: str,
kind: TargetKind = TargetKind.STL,
**kwargs):
self._method = method
self.name = name
self.kind = kind
self.kwargs = kwargs
def __str__(self):
return f"<target {self.name}>"
def __call__(self, obj, *args, **kwargs):
"""
Raw call function which passes arguments directly to `_method`
"""
return self._method(obj, *args, **kwargs)
def file_name(self, file_name):
return f"{file_name}.{self.kind.ext}"
def write_to(self, obj, path: str):
x = self._method(obj)
if self.kind == TargetKind.STL:
assert isinstance(x, Union[
Cq.Workplane, Cq.Shape, Cq.Compound, Cq.Assembly])
if isinstance(x, Cq.Workplane):
x = x.val()
if isinstance(x, Cq.Assembly):
x = x.toCompound()
x.exportStl(path, **self.kwargs)
elif self.kind == TargetKind.DXF:
assert isinstance(x, Cq.Workplane)
Cq.exporters.exportDXF(x, path, **self.kwargs)
else:
assert False, f"Invalid kind: {self.kind}"
@classmethod
def methods(cls, subject):
@ -49,13 +93,6 @@ def target(name, **deco_kwargs):
return wrapper
return f
def _to_shape(x: Union[Cq.Workplane, Cq.Shape, Cq.Compound, Cq.Assembly]) -> Cq.Shape:
if isinstance(x, Cq.Workplane):
x = x.val()
if isinstance(x, Cq.Assembly):
x = x.toCompound()
return x
class Model:
"""
@ -76,22 +113,21 @@ class Model:
total += 1
return total
def build_all(self, output_dir: Union[Path, str] ="build", verbose=1):
def build_all(self, output_dir: Union[Path, str] = "build", verbose=1):
"""
Build all targets in this model
"""
output_dir = Path(output_dir)
output_dir.mkdir(exist_ok=True, parents=True)
for k, f in Target.methods(self).items():
output_file = output_dir / f"{k}.stl"
for k, target in Target.methods(self).items():
output_file = output_dir / target.file_name(k)
if output_file.is_file():
if verbose >= 1:
print(f"{Fore.GREEN}Skipping{Style.RESET_ALL} {output_file}")
continue
model = f(self)
if verbose >= 1:
print(f"{Fore.BLUE}Building{Style.RESET_ALL} {output_file}")
_to_shape(model).exportStl(str(output_file))
target.write_to(self, str(output_file))
if verbose >= 1:
print(f"{Fore.GREEN}Built{Style.RESET_ALL} {output_file}")

View File

@ -33,7 +33,7 @@ from dataclasses import dataclass, field
import unittest
import cadquery as Cq
from nhf import Material
from nhf.build import Model, target
from nhf.build import Model, TargetKind, target
from nhf.parts.joints import HirthJoint
from nhf.parts.handle import Handle
import nhf.touhou.houjuu_nue.wing as MW
@ -113,11 +113,6 @@ class Parameters(Model):
"Wing root must be large enough to accomodate joint"
def print_geometries(self):
return [
self.hs_joint_parent()
]
def harness_profile(self) -> Cq.Sketch:
"""
Creates the harness shape
@ -148,6 +143,7 @@ class Parameters(Model):
)
return sketch
@target(name="harness", kind=TargetKind.DXF)
def harness(self) -> Cq.Shape:
"""
Creates the harness shape
@ -249,7 +245,8 @@ class Parameters(Model):
result.faces("<Z").tag("base")
return result
def wing_root(self) -> Cq.Shape:
@target(name="wing_root")
def wing_root(self) -> Cq.Assembly:
"""
Generate the wing root which contains a Hirth joint at its base and a
rectangular opening on its side, with the necessary interfaces.