Refactored returned objects to Line, Sketch, Part & added BuildSketch/Fillet

This commit is contained in:
Roger Maitland 2022-07-06 11:36:01 -04:00
parent 7b971e3eaa
commit 02a579a728
5 changed files with 108 additions and 99 deletions

View file

@ -23,56 +23,35 @@ from build_part import BuildPart
class BuildLine:
@property
def working_line(self) -> Wire:
return Wire.assembleEdges(self.edge_list)
def line_as_wire(self) -> Wire:
return Wire.assembleEdges(self.line)
def __init__(self, mode: Mode = Mode.ADDITION):
self.edge_list = []
self.line = []
self.tags: dict[str, Edge] = {}
self.mode = mode
# def __enter__(self):
# if "context_stack" in globals():
# context_stack.append(self)
# else:
# globals()["context_stack"] = [self]
# return self
def __enter__(self):
context_stack.append(self)
return self
def __exit__(self, exception_type, exception_value, traceback):
# if self.parent is not None:
# self.parent.add(*self.edge_list, mode=self.mode)
# if "context_stack" in globals():
# context_stack.pop()
# if context_stack:
# if isinstance(context_stack[-1], Build2D):
# for edge in self.edge_list:
# Build2D.add_to_context(edge, mode=self.mode)
# elif isinstance(context_stack[-1], Build3D):
# for edge in self.edge_list:
# Build3D.add_to_context(edge, mode=self.mode)
# if not context_stack:
# del globals()["context_stack"]
context_stack.pop()
if context_stack:
if isinstance(context_stack[-1], BuildSketch):
for edge in self.edge_list:
for edge in self.line:
BuildSketch.add_to_context(edge, mode=self.mode)
elif isinstance(context_stack[-1], BuildPart):
for edge in self.edge_list:
for edge in self.line:
BuildPart.add_to_context(edge, mode=self.mode)
def edges(self) -> EdgeList:
# return EdgeList(*self.edge_list)
return self.edge_list
return self.line
def vertices(self) -> list[Vertex]:
vertex_list = []
for e in self.edge_list:
for e in self.line:
vertex_list.extend(e.Vertices())
return list(set(vertex_list))
@ -87,7 +66,7 @@ class BuildLine:
# if not isinstance(edge, Edge):
# if not issubclass(type(edge),Edge):
# raise ValueError("Build1D.add only accepts edges")
context_stack[-1].edge_list.append(edge)
context_stack[-1].line.append(edge)
@staticmethod
def get_context() -> "BuildLine":

View file

@ -49,8 +49,8 @@ with BuildLine() as roller_coaster:
Spline(screw @ 1, (-100, 30, 10), powerup @ 0, tangents=(screw % 1, powerup % 0))
if "show_object" in locals():
show_object(ml.edge_list, "maple leaf")
show_object(mirror_example.edge_list, "mirror_example")
show_object(mirror_example2.edge_list, "mirror_example2")
show_object(private_example.edge_list, "private_example")
show_object(roller_coaster.edge_list, "roller coaster")
show_object(ml.line, "maple leaf")
show_object(mirror_example.line, "mirror_example")
show_object(mirror_example2.line, "mirror_example2")
show_object(private_example.line, "private_example")
show_object(roller_coaster.line, "roller coaster")

View file

@ -44,13 +44,12 @@ class BuildPart:
workplane: Plane = Plane.named("XY"),
):
self.parent = parent
self.working_volume: Solid = None
self.part: Solid = None
self.workplanes: list[Plane] = [workplane]
self.pending_faces: dict[int : list[Face]] = {0: []}
self.pending_edges: dict[int : list[Edge]] = {0: []}
self.locations: dict[int : list[Location]] = {0: []}
self.last_operation: dict[CqObject : list[Shape]] = {}
# self.last_operation_edges: list[Edge] = []
def __enter__(self):
return self
@ -103,40 +102,40 @@ class BuildPart:
def edges(self, sort_by: SortBy = SortBy.NONE, reverse: bool = False) -> list[Edge]:
if sort_by == SortBy.NONE:
edges = self.working_volume.Edges()
edges = self.part.Edges()
elif sort_by == SortBy.X:
edges = sorted(
self.working_volume.Edges(),
self.part.Edges(),
key=lambda obj: obj.Center().x,
reverse=reverse,
)
elif sort_by == SortBy.Y:
edges = sorted(
self.working_volume.Edges(),
self.part.Edges(),
key=lambda obj: obj.Center().y,
reverse=reverse,
)
elif sort_by == SortBy.Z:
edges = sorted(
self.working_volume.Edges(),
self.part.Edges(),
key=lambda obj: obj.Center().z,
reverse=reverse,
)
elif sort_by == SortBy.LENGTH:
edges = sorted(
self.working_volume.Edges(),
self.part.Edges(),
key=lambda obj: obj.Length(),
reverse=reverse,
)
elif sort_by == SortBy.RADIUS:
edges = sorted(
self.working_volume.Edges(),
self.part.Edges(),
key=lambda obj: obj.radius(),
reverse=reverse,
)
elif sort_by == SortBy.DISTANCE:
edges = sorted(
self.working_volume.Edges(),
self.part.Edges(),
key=lambda obj: obj.Center().Length,
reverse=reverse,
)
@ -147,32 +146,32 @@ class BuildPart:
def faces(self, sort_by: SortBy = SortBy.NONE, reverse: bool = False) -> list[Face]:
if sort_by == SortBy.NONE:
faces = self.working_volume.Faces()
faces = self.part.Faces()
elif sort_by == SortBy.X:
faces = sorted(
self.working_volume.Faces(),
self.part.Faces(),
key=lambda obj: obj.Center().x,
reverse=reverse,
)
elif sort_by == SortBy.Y:
faces = sorted(
self.working_volume.Faces(),
self.part.Faces(),
key=lambda obj: obj.Center().y,
reverse=reverse,
)
elif sort_by == SortBy.Z:
faces = sorted(
self.working_volume.Faces(),
self.part.Faces(),
key=lambda obj: obj.Center().z,
reverse=reverse,
)
elif sort_by == SortBy.AREA:
faces = sorted(
self.working_volume.Faces(), key=lambda obj: obj.Area(), reverse=reverse
self.part.Faces(), key=lambda obj: obj.Area(), reverse=reverse
)
elif sort_by == SortBy.DISTANCE:
faces = sorted(
self.working_volume.Faces(),
self.part.Faces(),
key=lambda obj: obj.Center().Length,
reverse=reverse,
)
@ -184,28 +183,28 @@ class BuildPart:
self, sort_by: SortBy = SortBy.NONE, reverse: bool = False
) -> list[Vertex]:
if sort_by == SortBy.NONE:
vertices = self.working_volume.Vertices()
vertices = self.part.Vertices()
elif sort_by == SortBy.X:
vertices = sorted(
self.working_volume.Vertices(),
self.part.Vertices(),
key=lambda obj: obj.Center().x,
reverse=reverse,
)
elif sort_by == SortBy.Y:
vertices = sorted(
self.working_volume.Vertices(),
self.part.Vertices(),
key=lambda obj: obj.Center().y,
reverse=reverse,
)
elif sort_by == SortBy.Z:
vertices = sorted(
self.working_volume.Vertices(),
self.part.Vertices(),
key=lambda obj: obj.Center().z,
reverse=reverse,
)
elif sort_by == SortBy.DISTANCE:
vertices = sorted(
self.working_volume.Vertices(),
self.part.Vertices(),
key=lambda obj: obj.Center().Length,
reverse=reverse,
)
@ -223,44 +222,32 @@ class BuildPart:
Solid.clean_op = Solid.clean if clean else Solid.null
Compound.clean_op = Compound.clean if clean else Compound.null
before_vertices = (
set()
if self.working_volume is None
else set(self.working_volume.Vertices())
)
before_edges = (
set() if self.working_volume is None else set(self.working_volume.Edges())
)
before_faces = (
set() if self.working_volume is None else set(self.working_volume.Faces())
)
before_vertices = set() if self.part is None else set(self.part.Vertices())
before_edges = set() if self.part is None else set(self.part.Edges())
before_faces = set() if self.part is None else set(self.part.Faces())
if mode == Mode.ADDITION:
if self.working_volume is None:
if self.part is None:
if len(new_solids) == 1:
self.working_volume = new_solids[0]
self.part = new_solids[0]
else:
self.working_volume = new_solids.pop().fuse(*new_solids)
self.part = new_solids.pop().fuse(*new_solids)
else:
self.working_volume = self.working_volume.fuse(*new_solids).clean_op()
self.part = self.part.fuse(*new_solids).clean_op()
elif mode == Mode.SUBTRACTION:
if self.working_volume is None:
if self.part is None:
raise ValueError("Nothing to subtract from")
self.working_volume = self.working_volume.cut(*new_solids).clean_op()
self.part = self.part.cut(*new_solids).clean_op()
elif mode == Mode.INTERSECTION:
if self.working_volume is None:
if self.part is None:
raise ValueError("Nothing to intersect with")
self.working_volume = self.working_volume.intersect(*new_solids).clean_op()
self.part = self.part.intersect(*new_solids).clean_op()
self.last_operation[CqObject.VERTEX] = list(
set(self.working_volume.Vertices()) - before_vertices
)
self.last_operation[CqObject.EDGE] = list(
set(self.working_volume.Edges()) - before_edges
)
self.last_operation[CqObject.FACE] = list(
set(self.working_volume.Faces()) - before_faces
set(self.part.Vertices()) - before_vertices
)
self.last_operation[CqObject.EDGE] = list(set(self.part.Edges()) - before_edges)
self.last_operation[CqObject.FACE] = list(set(self.part.Faces()) - before_faces)
def extrude(
self,
@ -385,7 +372,7 @@ class BuildPart:
return new_solids
def fillet(self, *edges: Sequence[Edge], radius: float):
self.working_volume = self.working_volume.fillet(radius, [e for e in edges])
self.part = self.part.fillet(radius, [e for e in edges])
def chamfer(self, *edges: Sequence[Edge], length1: float, length2: float = None):
self.working_volume = self.working_volume.chamfer(length1, length2, list(edges))
self.part = self.part.chamfer(length1, length2, list(edges))

View file

@ -23,7 +23,7 @@ from build_part import BuildPart
class BuildSketch:
def __init__(self, mode: Mode = Mode.ADDITION):
self.surface = Compound.makeCompound(())
self.sketch = Compound.makeCompound(())
self.pending_edges: list[Edge] = []
self.locations: list[Location] = [Location(Vector())]
self.mode = mode
@ -35,25 +35,33 @@ class BuildSketch:
def __exit__(self, exception_type, exception_value, traceback):
context_stack.pop()
if context_stack:
if isinstance(context_stack[-1], Build3D):
if isinstance(context_stack[-1], BuildPart):
for edge in self.edge_list:
Build3D.add_to_context(edge, mode=self.mode)
BuildPart.add_to_context(edge, mode=self.mode)
def edges(self) -> list[Edge]:
return self.surface.Edges()
return self.sketch.Edges()
def vertices(self) -> list[Vertex]:
vertex_list = []
for e in self.surface.Edges():
for e in self.sketch.Edges():
vertex_list.extend(e.Vertices())
return list(set(vertex_list))
def consolidate_edges(self) -> Wire:
return Wire.combine(self.pending_edges)[0]
# def add(self, f: Face, mode: Mode = Mode.ADDITION):
# new_faces = self.place_face(f, mode)
# return new_faces if len(new_faces) > 1 else new_faces[0]
def _matchFacesToVertices(self) -> dict[Face, list[Vertex]]:
rv = {}
for f in self.sketch.Faces():
f_vertices = f.Vertices()
rv[f] = [
v for v in self._selection if isinstance(v, Vertex) and v in f_vertices
]
return rv
@staticmethod
def add_to_context(*objects: Union[Edge, Face], mode: Mode = Mode.ADDITION):
@ -63,16 +71,16 @@ class BuildSketch:
new_edges = [obj for obj in objects if isinstance(obj, Edge)]
if mode == Mode.ADDITION:
context_stack[-1].surface = (
context_stack[-1].surface.fuse(*new_faces).clean()
context_stack[-1].sketch = (
context_stack[-1].sketch.fuse(*new_faces).clean()
)
elif mode == Mode.SUBTRACTION:
context_stack[-1].surface = (
context_stack[-1].surface.cut(*new_faces).clean()
context_stack[-1].sketch = (
context_stack[-1].sketch.cut(*new_faces).clean()
)
elif mode == Mode.INTERSECTION:
context_stack[-1].surface = (
context_stack[-1].surface.intersect(*new_faces).clean()
context_stack[-1].sketch = (
context_stack[-1].sketch.intersect(*new_faces).clean()
)
elif mode == Mode.CONSTRUCTION or mode == Mode.PRIVATE:
pass
@ -88,7 +96,6 @@ class BuildSketch:
class BuildFace:
def __init__(self, *edges: Edge, mode: Mode = Mode.ADDITION):
# pending_face = Face.makeFromWires(Build2D.get_context().consolidate_edges())
pending_face = Face.makeFromWires(Wire.combine(edges)[0])
BuildSketch.get_context().add_to_context(pending_face, mode)
BuildSketch.get_context().pending_edges = []
@ -115,6 +122,20 @@ class PushPoints:
BuildSketch.get_context().locations = new_locations
class Fillet(Compound):
def __init__(self, *vertices: Vertex, radius: float):
new_faces = []
for face in BuildSketch.get_context().sketch.Faces():
vertices_in_face = filter(lambda v: v in face.Vertices(), vertices)
if vertices_in_face:
new_faces.append(face.fillet2D(radius, vertices_in_face))
else:
new_faces.append(face)
new_sketch = Compound.makeCompound(new_faces)
BuildSketch.get_context().sketch = new_sketch
super().__init__(new_sketch.wrapped)
class Rect(Compound):
def __init__(
self,

View file

@ -23,6 +23,28 @@ with BuildSketch() as flag:
Mirror(*leaf.edges(), axis=Axis.Y)
BuildFace(*flag.pending_edges)
with BuildSketch() as din:
PushPoints((0, 0.5))
Rect(35, 1)
PushPoints((0, 7.5 / 2))
Rect(27, 7.5)
PushPoints((0, 6.5 / 2))
Rect(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(),
)
)
Fillet(*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(),
)
)
Fillet(*outside_vertices, radius=1.8)
if "show_object" in locals():
show_object(flag.surface, "pending_face")
# show_object(flag.pending_edges, "pending_edges")
show_object(flag.sketch, name="flag")
show_object(din.sketch, name="din rail")