From ca437c385531cfb205ca06bf3a14d8a1ded2b826 Mon Sep 17 00:00:00 2001 From: Leni Aniva Date: Fri, 6 Dec 2024 16:40:07 -0800 Subject: [PATCH 1/6] feat: Light panel layer --- nhf/tool/__init__.py | 0 nhf/tool/light_panel.py | 54 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 54 insertions(+) create mode 100644 nhf/tool/__init__.py create mode 100644 nhf/tool/light_panel.py diff --git a/nhf/tool/__init__.py b/nhf/tool/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/nhf/tool/light_panel.py b/nhf/tool/light_panel.py new file mode 100644 index 0000000..81c2942 --- /dev/null +++ b/nhf/tool/light_panel.py @@ -0,0 +1,54 @@ +from dataclasses import dataclass +import cadquery as Cq +from nhf import Material, Role +from nhf.build import Model, target, assembly, TargetKind +import nhf.utils + +@dataclass +class LightPanel(Model): + + # Dimensions of the base panel + length: float = 300.0 + width: float = 200.0 + + grid_height: float = 30.0 + grid_top_height: float = 10.0 + # Distance from grid to edge + grid_margin: float = 20.0 + # Number of holes in each row of the grid + grid_holes: int = 5 + grid_layers: int = 10 + grid_hole_width: float = 10.0 + + base_thickness: float = 25.4/16 + grid_thickness: float = 25.4/8 + + def __post_init__(self): + assert self.grid_holes >= 2 + super().__init__(name="crown") + + @target(name="grid", kind=TargetKind.DXF) + def grid_profile(self): + w = self.length - self.grid_margin * 2 + h = self.grid_height + self.grid_top_height + + # The width of one hole (w0) satisfies + # n * w0 + (n+1) t = w + # where t is the thickness of the edge + n = self.grid_holes + w0 = self.grid_hole_width + t = (w - n * w0) / (n + 1) + # The spacing is such that the first and last holes are a distance `t` + # away from the edges, so it satisfies + # t + w0/2 + (n-1) * s + w0/2 + t = w + step = (w - t*2 - w0) / (n - 1) + return ( + Cq.Sketch() + .push([(0, h/2)]) + .rect(w, h) + .push([ + (i * step + t + w0/2 - w/2, self.grid_height/2) + for i in range(0, n) + ]) + .rect(w0, self.grid_height, mode='s') + ) -- 2.44.1 From 3884d75f1ce797571dff8eccdf729ba6029eb57d Mon Sep 17 00:00:00 2001 From: Leni Aniva Date: Fri, 6 Dec 2024 16:43:12 -0800 Subject: [PATCH 2/6] chore: Add build function --- nhf/tool/light_panel.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/nhf/tool/light_panel.py b/nhf/tool/light_panel.py index 81c2942..1818b17 100644 --- a/nhf/tool/light_panel.py +++ b/nhf/tool/light_panel.py @@ -52,3 +52,12 @@ class LightPanel(Model): ]) .rect(w0, self.grid_height, mode='s') ) + + +if __name__ == '__main__': + import sys + + p = LightPanel() + if len(sys.argv) == 1: + p.build_all() + sys.exit(0) -- 2.44.1 From d1fd8307661c34fa856e07ba1252e184c6bb4c99 Mon Sep 17 00:00:00 2001 From: Leni Aniva Date: Sat, 7 Dec 2024 12:09:41 -0800 Subject: [PATCH 3/6] feat: Light panel assembly --- nhf/tool/light_panel.py | 66 +++++++++++++++++++++++++++++++++++++---- 1 file changed, 61 insertions(+), 5 deletions(-) diff --git a/nhf/tool/light_panel.py b/nhf/tool/light_panel.py index 1818b17..86d9983 100644 --- a/nhf/tool/light_panel.py +++ b/nhf/tool/light_panel.py @@ -1,7 +1,9 @@ from dataclasses import dataclass import cadquery as Cq from nhf import Material, Role -from nhf.build import Model, target, assembly, TargetKind +from nhf.build import Model, target, assembly, TargetKind, submodel +from nhf.parts.box import MountingBox, Hole +from nhf.parts.electronics import ArduinoUnoR3 import nhf.utils @dataclass @@ -16,12 +18,16 @@ class LightPanel(Model): # Distance from grid to edge grid_margin: float = 20.0 # Number of holes in each row of the grid - grid_holes: int = 5 - grid_layers: int = 10 - grid_hole_width: float = 10.0 + grid_holes: int = 9 + grid_layers: int = 6 + grid_hole_width: float = 15.0 base_thickness: float = 25.4/16 grid_thickness: float = 25.4/8 + base_material: Material = Material.WOOD_BIRCH + grid_material: Material = Material.ACRYLIC_TRANSPARENT + + controller: ArduinoUnoR3 = ArduinoUnoR3() def __post_init__(self): assert self.grid_holes >= 2 @@ -38,7 +44,7 @@ class LightPanel(Model): n = self.grid_holes w0 = self.grid_hole_width t = (w - n * w0) / (n + 1) - # The spacing is such that the first and last holes are a distance `t` + # The spacing is such that the first and last holes are a distance `margin` # away from the edges, so it satisfies # t + w0/2 + (n-1) * s + w0/2 + t = w step = (w - t*2 - w0) / (n - 1) @@ -53,6 +59,56 @@ class LightPanel(Model): .rect(w0, self.grid_height, mode='s') ) + def grid(self) -> Cq.Workplane: + return ( + Cq.Workplane('XY') + .placeSketch(self.grid_profile()) + .extrude(self.grid_thickness) + ) + + @submodel(name="base") + def base(self) -> MountingBox: + holes = [ + Hole( + x=x, y=y, + diam=self.controller.hole_diam, + tag=f"controller_conn{i}", + ) + for i, (x, y) in enumerate(self.controller.holes) + ] + return MountingBox( + holes=holes, + hole_diam=self.controller.hole_diam, + length=self.length, + width=self.width, + centred=(True, False), + thickness=self.base_thickness, + ) + + def assembly(self) -> Cq.Assembly: + assembly = ( + Cq.Assembly() + .addS( + self.base().generate(), + name="base", + role=Role.STRUCTURE, + material=self.base_material, + ) + ) + # Grid thickness t is fixed, so the spacing of the grid satisfies + # margin + t + (n-1) * (t + spacing) + margin = width + spacing = (self.width - 2 * self.grid_margin - self.grid_thickness) / (self.grid_layers - 1) - self.grid_thickness + shift = self.grid_margin + self.grid_thickness * 2 + for i in range(self.grid_layers): + assembly = assembly.addS( + self.grid(), + name=f"grid_{i}", + role=Role.STRUCTURE, + material=self.grid_material, + loc=Cq.Location(0, spacing * i + shift, self.base_thickness, 90, 0, 0), + ) + return assembly + if __name__ == '__main__': import sys -- 2.44.1 From 418e6517a013c8fbffc31eb29e8f6612013b26ea Mon Sep 17 00:00:00 2001 From: Leni Aniva Date: Sat, 7 Dec 2024 13:44:35 -0800 Subject: [PATCH 4/6] fix: Sketch object attribute --- nhf/build.py | 2 +- nhf/tool/light_panel.py | 14 ++++++++------ 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/nhf/build.py b/nhf/build.py index 106577c..4d4c6c2 100644 --- a/nhf/build.py +++ b/nhf/build.py @@ -90,7 +90,7 @@ class Target: x = ( Cq.Workplane() .add(x._faces) - .add(x._wires) + .add(x.wires) .add(x._edges) ) assert isinstance(x, Cq.Workplane) diff --git a/nhf/tool/light_panel.py b/nhf/tool/light_panel.py index 86d9983..631637f 100644 --- a/nhf/tool/light_panel.py +++ b/nhf/tool/light_panel.py @@ -14,7 +14,7 @@ class LightPanel(Model): width: float = 200.0 grid_height: float = 30.0 - grid_top_height: float = 10.0 + grid_top_height: float = 5.0 # Distance from grid to edge grid_margin: float = 20.0 # Number of holes in each row of the grid @@ -23,7 +23,7 @@ class LightPanel(Model): grid_hole_width: float = 15.0 base_thickness: float = 25.4/16 - grid_thickness: float = 25.4/8 + grid_thickness: float = 25.4/4 base_material: Material = Material.WOOD_BIRCH grid_material: Material = Material.ACRYLIC_TRANSPARENT @@ -68,9 +68,11 @@ class LightPanel(Model): @submodel(name="base") def base(self) -> MountingBox: + xshift = self.length / 2 - self.controller.length - self.grid_margin / 2 + yshift = self.grid_margin / 2 holes = [ Hole( - x=x, y=y, + x=x + xshift, y=y + yshift, diam=self.controller.hole_diam, tag=f"controller_conn{i}", ) @@ -96,9 +98,9 @@ class LightPanel(Model): ) ) # Grid thickness t is fixed, so the spacing of the grid satisfies - # margin + t + (n-1) * (t + spacing) + margin = width - spacing = (self.width - 2 * self.grid_margin - self.grid_thickness) / (self.grid_layers - 1) - self.grid_thickness - shift = self.grid_margin + self.grid_thickness * 2 + # margin + t + (n-1) * spacing + margin = width + spacing = (self.width - 2 * self.grid_margin - self.grid_thickness) / (self.grid_layers - 1) + shift = self.grid_margin + self.grid_thickness / 2 for i in range(self.grid_layers): assembly = assembly.addS( self.grid(), -- 2.44.1 From a6685e6779c3755cf9e7eb28d27e2e1d6978e497 Mon Sep 17 00:00:00 2001 From: Leni Aniva Date: Sat, 7 Dec 2024 13:46:23 -0800 Subject: [PATCH 5/6] feat: Add model name prefix to build path --- nhf/build.py | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/nhf/build.py b/nhf/build.py index 106577c..05e4aaa 100644 --- a/nhf/build.py +++ b/nhf/build.py @@ -214,7 +214,7 @@ class Submodel: def write_to(self, obj, path: str): x = self._method(obj) assert isinstance(x, Model), f"Unexpected type: {type(x)}" - x.build_all(path) + x.build_all(path, prefix=False) @classmethod def methods(cls, subject): @@ -271,11 +271,17 @@ 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", + prefix: bool = True, + verbose=1): """ Build all targets in this model and write the results to file """ output_dir = Path(output_dir) + if prefix: + output_dir = output_dir / self.name targets = Target.methods(self) for t in targets.values(): file_name = t.file_name -- 2.44.1 From 6470010da686fb864b4eb70fb6dc58b223783b39 Mon Sep 17 00:00:00 2001 From: Leni Aniva Date: Sat, 7 Dec 2024 13:47:32 -0800 Subject: [PATCH 6/6] fix: Model name --- nhf/tool/light_panel.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nhf/tool/light_panel.py b/nhf/tool/light_panel.py index 631637f..44c7920 100644 --- a/nhf/tool/light_panel.py +++ b/nhf/tool/light_panel.py @@ -31,7 +31,7 @@ class LightPanel(Model): def __post_init__(self): assert self.grid_holes >= 2 - super().__init__(name="crown") + super().__init__(name="light-panel") @target(name="grid", kind=TargetKind.DXF) def grid_profile(self): -- 2.44.1