"""
BuildPart
name: build_part.py
by: Gumyr
date: July 12th 2022
desc:
This python module is a library used to build 3D parts.
TODO:
- add TwistExtrude, ProjectText
license:
Copyright 2022 Gumyr
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
"""
from __future__ import annotations
from build123d.build_common import Builder, logger
from build123d.build_enums import Mode
from build123d.geometry import Location, Plane
from build123d.topology import Edge, Face, Joint, Part, Solid, Wire
[docs]
class BuildPart(Builder):
"""BuildPart
The BuildPart class is another subclass of Builder for building parts
(objects with the property of volume) from sketches or 3D objects.
It has an _obj property that returns the current part being built, and
several pending lists for storing faces, edges, and planes that will be
integrated into the final part later. The class overrides the _add_to_pending
method of Builder.
Args:
workplanes (Plane, optional): initial plane to work on. Defaults to Plane.XY.
mode (Mode, optional): combination mode. Defaults to Mode.ADD.
"""
_tag = "BuildPart" # Alternate for __class__.__name__
_obj_name = "part" # Name of primary instance variable
_shape = Solid # Type of shapes being constructed
_sub_class = Part # Class of part/_obj
def __init__(
self,
*workplanes: Face | Plane | Location,
mode: Mode = Mode.ADD,
):
self.joints: dict[str, Joint] = {}
self._part: Part | None = None # Use a private attribute
self.pending_faces: list[Face] = []
self.pending_face_planes: list[Plane] = []
self.pending_planes: list[Plane] = []
self.pending_edges: list[Edge] = []
super().__init__(*workplanes, mode=mode)
@property
def part(self) -> Part | None:
"""Get the current part"""
return self._part
@part.setter
def part(self, value: Part) -> None:
"""Set the current part"""
self._part = value
_obj = part # Alias _obj to part
@property
def pending_edges_as_wire(self) -> Wire:
"""Return a wire representation of the pending edges"""
return Wire.combine(self.pending_edges)[0]
@property
def location(self) -> Location | None:
"""Builder's location"""
return self.part.location if self.part is not None else Location()
def _add_to_pending(self, *objects: Edge | Face, face_plane: Plane | None = None):
"""Add objects to BuildPart pending lists
Args:
objects (Union[Edge, Face]): sequence of objects to add
"""
new_faces = [o for o in objects if isinstance(o, Face)]
for face in new_faces:
logger.debug(
"Adding Face to pending_faces at %s on pending_face_plane %s",
face.location,
face_plane,
)
self.pending_faces.append(face)
if face_plane is not None:
self.pending_face_planes.append(face_plane)
new_edges = [o for o in objects if isinstance(o, Edge)]
for edge in new_edges:
logger.debug(
"Adding Edge to pending_edges at %s",
edge.location,
)
self.pending_edges.append(edge)
def _exit_extras(self):
"""Transfer joints on exit"""
if self.joints:
self.part.joints = self.joints
for joint in self.part.joints.values():
joint.parent = self.part