From 45b709622cf82dde6e5693b8cad8116a9366dfd0 Mon Sep 17 00:00:00 2001 From: Roger Maitland Date: Fri, 8 Jul 2022 16:05:04 -0400 Subject: [PATCH] Bug fixes and first test object: din rail --- build_part.py | 52 ++++++++++++++++++++++++++-------------------- build_part_test.py | 41 ++++++++++++++++++++++++++++++++++++ build_sketch.py | 4 +--- 3 files changed, 71 insertions(+), 26 deletions(-) create mode 100644 build_part_test.py diff --git a/build_part.py b/build_part.py index b9a5821..204bb22 100644 --- a/build_part.py +++ b/build_part.py @@ -1,6 +1,7 @@ """ TODO: -- add Box, Cone, Cylinder, Sphere, Torus, Wedge +- add Shell, TwistExtrude, ProjectText, Split, Hole(s), +- how about translate & rotate? """ from math import pi, sin, cos, radians, sqrt from typing import Union, Iterable, Callable @@ -159,31 +160,32 @@ class BuildPart: pre_faces = set() if self.part is None else set(self.part.Faces()) pre_solids = set() if self.part is None else set(self.part.Solids()) - if mode == Mode.ADDITION: - if self.part is None: - if len(new_solids) == 1: - self.part = new_solids[0] + if new_solids: + if mode == Mode.ADDITION: + if self.part is None: + if len(new_solids) == 1: + self.part = new_solids[0] + else: + self.part = new_solids.pop().fuse(*new_solids) else: - self.part = new_solids.pop().fuse(*new_solids) + self.part = self.part.fuse(*new_solids).clean() + elif mode == Mode.SUBTRACTION: + if self.part is None: + raise ValueError("Nothing to subtract from") + self.part = self.part.cut(*new_solids).clean() + elif mode == Mode.INTERSECTION: + if self.part is None: + raise ValueError("Nothing to intersect with") + self.part = self.part.intersect(*new_solids).clean() + elif mode == Mode.CONSTRUCTION: + pass else: - self.part = self.part.fuse(*new_solids).clean_op() - elif mode == Mode.SUBTRACTION: - if self.part is None: - raise ValueError("Nothing to subtract from") - self.part = self.part.cut(*new_solids).clean_op() - elif mode == Mode.INTERSECTION: - if self.part is None: - raise ValueError("Nothing to intersect with") - self.part = self.part.intersect(*new_solids).clean_op() - elif mode == Mode.CONSTRUCTION: - pass - else: - raise ValueError(f"Invalid mode: {mode}") + raise ValueError(f"Invalid mode: {mode}") - post_vertices = set(self.part.Vertices()) - post_edges = set(self.part.Edges()) - post_faces = set(self.part.Faces()) - post_solids = set(self.part.Solids()) + post_vertices = set() if self.part is None else set(self.part.Vertices()) + post_edges = set() if self.part is None else set(self.part.Edges()) + post_faces = set() if self.part is None else set(self.part.Faces()) + post_solids = set() if self.part is None else set(self.part.Solids()) self.last_vertices = list(post_vertices - pre_vertices) self.last_edges = list(post_edges - pre_edges) self.last_faces = list(post_faces - pre_faces) @@ -257,6 +259,7 @@ class Extrude(Compound): ) ) + BuildPart.get_context().pending_faces = {0: []} BuildPart.get_context().add_to_context(*new_solids, mode=mode) super().__init__(Compound.makeCompound(new_solids).wrapped) @@ -291,6 +294,7 @@ class Revolve(Compound): for face in BuildPart.get_context().pending_faces[i]: new_solids.append(Solid.revolve(face, angle, *axis)) + BuildPart.get_context().pending_faces = {0: []} BuildPart.get_context().add_to_context(*new_solids, mode=mode) super().__init__(Compound.makeCompound(new_solids).wrapped) @@ -304,6 +308,7 @@ class Loft(Solid): loft_wires.append(face.outerWire()) new_solid = Solid.makeLoft(loft_wires, ruled) + BuildPart.get_context().pending_faces = {0: []} BuildPart.get_context().add_to_context(new_solid, mode=mode) super().__init__(new_solid.wrapped) @@ -354,6 +359,7 @@ class Sweep(Compound): ) ) + BuildPart.get_context().pending_faces = {0: []} BuildPart.get_context().add_to_context(*new_solids, mode=mode) super().__init__(Compound.makeCompound(new_solids).wrapped) diff --git a/build_part_test.py b/build_part_test.py new file mode 100644 index 0000000..a132721 --- /dev/null +++ b/build_part_test.py @@ -0,0 +1,41 @@ +from build_part import * +from build_sketch import * + +with BuildPart(workplane=Plane.named("XZ")) as rail: + with BuildSketch() as din: + PushPoints((0, 0.5)) + Rectangle(35, 1) + PushPoints((0, 7.5 / 2)) + Rectangle(27, 7.5) + PushPoints((0, 6.5 / 2)) + Rectangle(25, 6.5, mode=Mode.SUBTRACTION) + inside_vertices = list( + filter( + lambda v: 7.5 > v.Y > 0 and -17.5 < v.X < 17.5, + din.vertices(), + ) + ) + FilletSketch(*inside_vertices, radius=0.8) + outside_vertices = list( + filter( + lambda v: (v.Y == 0.0 or v.Y == 7.5) and -17.5 < v.X < 17.5, + din.vertices(), + ) + ) + FilletSketch(*outside_vertices, radius=1.8) + Extrude(1000) + xy_faces = list( + filter(lambda f: f.normalAt(f.Center()) == Vector(0, 0, 1), rail.faces()) + ) + top = sorted(xy_faces, key=lambda f: f.Center().z)[-1] + rail.faces_to_workplanes(top, replace=True) + with BuildSketch() as slots: + RectangularArray(0, 25, 1, 39) + SlotOverall(15, 6.2, 90) + slot_holes = Extrude(-20, mode=Mode.SUBTRACTION) + + +if "show_object" in locals(): + show_object(rail.part, name="rail") + show_object(slots.sketch, name="slots") + show_object(slot_holes, name="slot_holes") diff --git a/build_sketch.py b/build_sketch.py index 8a80bd6..875db8f 100644 --- a/build_sketch.py +++ b/build_sketch.py @@ -39,7 +39,6 @@ from cadquery.occ_impl.shapes import VectorLike, Real import cq_warehouse.extensions from build123d_common import * from build_part import BuildPart -import build_line as bl class BuildSketch: @@ -60,8 +59,7 @@ class BuildSketch: context_stack.pop() if context_stack: if isinstance(context_stack[-1], BuildPart): - for edge in self.edge_list: - BuildPart.add_to_context(edge, mode=self.mode) + BuildPart.get_context().add_to_context(self.sketch, mode=self.mode) def vertices(self, select: Select = Select.ALL) -> list[Vertex]: vertex_list = []