mirror of
https://github.com/gumyr/build123d.git
synced 2025-12-06 02:30:55 -08:00
Eliminated named from Plane & Literal parameters
This commit is contained in:
parent
e24a7c060d
commit
c7ca0bdf34
24 changed files with 470 additions and 929 deletions
|
|
@ -2,19 +2,34 @@ import build123d as b
|
||||||
|
|
||||||
|
|
||||||
class MyRectangle(b.BaseSketchOperation):
|
class MyRectangle(b.BaseSketchOperation):
|
||||||
def __init__(self, width: float, height: float, rotation: float = 0, centered: tuple[bool, bool] = (True, True), mode: b.Mode = b.Mode.ADD):
|
def __init__(
|
||||||
face = b.Face.makePlane(height, width)
|
self,
|
||||||
|
width: float,
|
||||||
|
height: float,
|
||||||
|
rotation: float = 0,
|
||||||
|
centered: tuple[bool, bool] = (True, True),
|
||||||
|
mode: b.Mode = b.Mode.ADD,
|
||||||
|
):
|
||||||
|
face = b.Face.make_plane(height, width)
|
||||||
super().__init__(face, rotation, centered, mode)
|
super().__init__(face, rotation, centered, mode)
|
||||||
|
|
||||||
|
|
||||||
class MyHole(b.BaseSketchOperation):
|
class MyHole(b.BaseSketchOperation):
|
||||||
def __init__(self, radius: float, rotation: float = 0, centered: tuple[bool, bool] = (True, True), mode: b.Mode = b.Mode.SUBTRACT):
|
def __init__(
|
||||||
face = b.Face.makeFromWires(b.Wire.makeCircle(radius, (0, 0, 0), (0, 0, 1)))
|
self,
|
||||||
|
radius: float,
|
||||||
|
rotation: float = 0,
|
||||||
|
centered: tuple[bool, bool] = (True, True),
|
||||||
|
mode: b.Mode = b.Mode.SUBTRACT,
|
||||||
|
):
|
||||||
|
face = b.Face.make_from_wires(b.Wire.make_circle(radius, (0, 0, 0), (0, 0, 1)))
|
||||||
super().__init__(face, rotation, centered, mode)
|
super().__init__(face, rotation, centered, mode)
|
||||||
|
|
||||||
|
|
||||||
with b.BuildSketch() as builder:
|
with b.BuildSketch() as builder:
|
||||||
MyRectangle(width=20, height=15, centered=(True, True), rotation=45)
|
MyRectangle(width=20, height=15, centered=(True, True), rotation=45)
|
||||||
MyHole(radius=3)
|
MyHole(radius=3)
|
||||||
|
|
||||||
|
|
||||||
if 'show_object' in locals():
|
if "show_object" in locals():
|
||||||
show_object(builder.sketch)
|
show_object(builder.sketch.wrapped)
|
||||||
|
|
|
||||||
|
|
@ -29,12 +29,12 @@ import cadquery as cq
|
||||||
|
|
||||||
with BuildSketch() as logo_text:
|
with BuildSketch() as logo_text:
|
||||||
Text("123d", fontsize=10, valign=Valign.BOTTOM)
|
Text("123d", fontsize=10, valign=Valign.BOTTOM)
|
||||||
font_height = (logo_text.vertices() >> Axis.Y).Y
|
font_height = logo_text.vertices().sort_by(Axis.Y)[-1].Y
|
||||||
|
|
||||||
with BuildSketch() as build_text:
|
with BuildSketch() as build_text:
|
||||||
Text("build", fontsize=5, halign=Halign.CENTER)
|
Text("build", fontsize=5, halign=Halign.CENTER)
|
||||||
build_bb = BoundingBox(build_text.sketch, mode=Mode.PRIVATE)
|
build_bb = BoundingBox(build_text.sketch, mode=Mode.PRIVATE)
|
||||||
build_vertices = build_bb.vertices() > Axis.X
|
build_vertices = build_bb.vertices().sort_by(Axis.X)
|
||||||
build_width = build_vertices[-1].X - build_vertices[0].X
|
build_width = build_vertices[-1].X - build_vertices[0].X
|
||||||
|
|
||||||
with BuildLine() as one:
|
with BuildLine() as one:
|
||||||
|
|
@ -50,11 +50,11 @@ with BuildPart() as three_d:
|
||||||
with BuildSketch():
|
with BuildSketch():
|
||||||
Text("3d", fontsize=10, valign=Valign.BOTTOM)
|
Text("3d", fontsize=10, valign=Valign.BOTTOM)
|
||||||
Extrude(amount=font_height * 0.3)
|
Extrude(amount=font_height * 0.3)
|
||||||
logo_width = (three_d.vertices() >> Axis.X).X
|
logo_width = three_d.vertices().sort_by(Axis.X)[-1].X
|
||||||
|
|
||||||
with BuildLine() as arrow_left:
|
with BuildLine() as arrow_left:
|
||||||
t1 = TangentArc((0, 0), (1, 0.75), tangent=(1, 0))
|
t1 = TangentArc((0, 0), (1, 0.75), tangent=(1, 0))
|
||||||
Mirror(t1, about="XZ")
|
Mirror(t1, about=Plane.XZ)
|
||||||
|
|
||||||
ext_line_length = font_height * 0.5
|
ext_line_length = font_height * 0.5
|
||||||
dim_line_length = (logo_width - build_width - 2 * font_height * 0.05) / 2
|
dim_line_length = (logo_width - build_width - 2 * font_height * 0.05) / 2
|
||||||
|
|
|
||||||
|
|
@ -25,7 +25,6 @@ license:
|
||||||
See the License for the specific language governing permissions and
|
See the License for the specific language governing permissions and
|
||||||
limitations under the License.
|
limitations under the License.
|
||||||
"""
|
"""
|
||||||
from cadquery import Vector
|
|
||||||
from build123d import *
|
from build123d import *
|
||||||
|
|
||||||
with BuildSketch() as leaf:
|
with BuildSketch() as leaf:
|
||||||
|
|
@ -43,7 +42,7 @@ with BuildSketch() as leaf:
|
||||||
Spline(l5 @ 1, l6 @ 0, tangents=(l5 % 1, l6 % 0), tangent_scalars=(2, 2))
|
Spline(l5 @ 1, l6 @ 0, tangents=(l5 % 1, l6 % 0), tangent_scalars=(2, 2))
|
||||||
l7 = Line((0.0692, 0.7808), (0.0000, 0.9167))
|
l7 = Line((0.0692, 0.7808), (0.0000, 0.9167))
|
||||||
TangentArc(l6 @ 1, l7 @ 0, tangent=l6 % 1)
|
TangentArc(l6 @ 1, l7 @ 0, tangent=l6 % 1)
|
||||||
Mirror(*outline.edges(), about="YZ")
|
Mirror(*outline.edges(), about=Plane.YZ)
|
||||||
BuildFace(*leaf.pending_edges)
|
BuildFace(*leaf.pending_edges)
|
||||||
|
|
||||||
with BuildSketch() as west_field:
|
with BuildSketch() as west_field:
|
||||||
|
|
@ -51,7 +50,7 @@ with BuildSketch() as west_field:
|
||||||
Rectangle(0.5, 1, centered=(False, False))
|
Rectangle(0.5, 1, centered=(False, False))
|
||||||
|
|
||||||
with BuildSketch() as east_field:
|
with BuildSketch() as east_field:
|
||||||
Mirror(west_field.sketch, about="YZ")
|
Mirror(west_field.sketch, about=Plane.YZ)
|
||||||
|
|
||||||
with BuildSketch() as centre_field:
|
with BuildSketch() as centre_field:
|
||||||
Rectangle(1, 1, centered=(True, False))
|
Rectangle(1, 1, centered=(True, False))
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,29 @@
|
||||||
|
"""
|
||||||
|
|
||||||
|
name: circuit_board.py
|
||||||
|
by: Gumyr
|
||||||
|
date: September 1st 2022
|
||||||
|
|
||||||
|
desc:
|
||||||
|
|
||||||
|
This example demonstrates placing holes around a part.
|
||||||
|
|
||||||
|
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 build123d import *
|
from build123d import *
|
||||||
|
|
||||||
with BuildPart() as pcb:
|
with BuildPart() as pcb:
|
||||||
|
|
|
||||||
|
|
@ -41,7 +41,7 @@ overall_width, top_width, height, thickness, fillet = 35, 27, 7.5, 1, 0.8
|
||||||
rail_length = 1000
|
rail_length = 1000
|
||||||
slot_width, slot_length, slot_pitch = 6.2, 15, 25
|
slot_width, slot_length, slot_pitch = 6.2, 15, 25
|
||||||
|
|
||||||
with BuildPart("XZ") as rail:
|
with BuildPart(Plane.XZ) as rail:
|
||||||
with BuildSketch() as din:
|
with BuildSketch() as din:
|
||||||
Rectangle(overall_width, thickness, centered=(True, False))
|
Rectangle(overall_width, thickness, centered=(True, False))
|
||||||
Rectangle(top_width, height, centered=(True, False))
|
Rectangle(top_width, height, centered=(True, False))
|
||||||
|
|
|
||||||
|
|
@ -60,7 +60,7 @@ with BuildPart() as single_multiple:
|
||||||
with BuildPart() as non_planar:
|
with BuildPart() as non_planar:
|
||||||
Cylinder(10, 20, rotation=(90, 0, 0), centered=(True, False, True))
|
Cylinder(10, 20, rotation=(90, 0, 0), centered=(True, False, True))
|
||||||
Box(10, 10, 10, centered=(True, True, False), mode=Mode.INTERSECT)
|
Box(10, 10, 10, centered=(True, True, False), mode=Mode.INTERSECT)
|
||||||
Extrude(non_planar.part.faces() << Axis.Z, amount=2, mode=Mode.REPLACE)
|
Extrude(non_planar.part.faces().sort_by(Axis.Z)[0], amount=2, mode=Mode.REPLACE)
|
||||||
|
|
||||||
# Taper Extrude and Extrude to "next" while creating a Cherry MX key cap
|
# Taper Extrude and Extrude to "next" while creating a Cherry MX key cap
|
||||||
# See: https://www.cherrymx.de/en/dev.html
|
# See: https://www.cherrymx.de/en/dev.html
|
||||||
|
|
|
||||||
|
|
@ -39,7 +39,7 @@ with BuildPart() as handle:
|
||||||
tangent_scalars=(1.5, 1.5),
|
tangent_scalars=(1.5, 1.5),
|
||||||
)
|
)
|
||||||
# Record the center line for display and workplane creation
|
# Record the center line for display and workplane creation
|
||||||
handle_path = handle_center_line.wires()[0]
|
handle_path: Wire = handle_center_line.wires()[0]
|
||||||
|
|
||||||
# Create the cross sections - added to pending_faces
|
# Create the cross sections - added to pending_faces
|
||||||
for i in range(segment_count + 1):
|
for i in range(segment_count + 1):
|
||||||
|
|
|
||||||
|
|
@ -39,7 +39,7 @@ fillet_radius = tube_spacing / 3
|
||||||
assert tube_extension > fillet_radius
|
assert tube_extension > fillet_radius
|
||||||
|
|
||||||
# Generate list of tube locations
|
# Generate list of tube locations
|
||||||
with Workplanes("XY"):
|
with Workplanes(Plane.XY):
|
||||||
tube_locations = [
|
tube_locations = [
|
||||||
l
|
l
|
||||||
for l in HexLocations(
|
for l in HexLocations(
|
||||||
|
|
@ -81,7 +81,7 @@ with BuildPart() as heat_exchanger:
|
||||||
radius=fillet_radius,
|
radius=fillet_radius,
|
||||||
)
|
)
|
||||||
half_volume_after_fillet = heat_exchanger.part.volume()
|
half_volume_after_fillet = heat_exchanger.part.volume()
|
||||||
Mirror(about="XY")
|
Mirror(about=Plane.XY)
|
||||||
|
|
||||||
fillet_volume = 2 * (half_volume_after_fillet - half_volume_before_fillet)
|
fillet_volume = 2 * (half_volume_after_fillet - half_volume_before_fillet)
|
||||||
print(f"{fillet_volume=}")
|
print(f"{fillet_volume=}")
|
||||||
|
|
|
||||||
|
|
@ -47,7 +47,7 @@ with BuildPart() as recessed_counter_sink:
|
||||||
with BuildPart() as flush_counter_sink:
|
with BuildPart() as flush_counter_sink:
|
||||||
with Locations((10, 10)):
|
with Locations((10, 10)):
|
||||||
Cylinder(radius=3, height=2)
|
Cylinder(radius=3, height=2)
|
||||||
with Workplanes(flush_counter_sink.part.faces() >> Axis.Z):
|
with Workplanes(flush_counter_sink.part.faces().sort_by(Axis.Z)[-1]):
|
||||||
CounterSinkHole(radius=1, counter_sink_radius=1.5)
|
CounterSinkHole(radius=1, counter_sink_radius=1.5)
|
||||||
|
|
||||||
if "show_object" in locals():
|
if "show_object" in locals():
|
||||||
|
|
|
||||||
|
|
@ -16,4 +16,4 @@ with BuildPart() as blocks:
|
||||||
|
|
||||||
|
|
||||||
if "show_object" in locals():
|
if "show_object" in locals():
|
||||||
show_object(blocks.part)
|
show_object(blocks.part.wrapped)
|
||||||
|
|
|
||||||
|
|
@ -66,7 +66,7 @@ with BuildPart() as lego:
|
||||||
Circle(support_inner_diameter / 2, mode=Mode.SUBTRACT)
|
Circle(support_inner_diameter / 2, mode=Mode.SUBTRACT)
|
||||||
Extrude(amount=base_height - wall_thickness)
|
Extrude(amount=base_height - wall_thickness)
|
||||||
with Workplanes(
|
with Workplanes(
|
||||||
Plane(origin=(0, 0, (lego.vertices() >> Axis.Z).Z), normal=(0, 0, 1))
|
Plane(origin=(0, 0, lego.vertices().sort_by(Axis.Z)[-1].Z), normal=(0, 0, 1))
|
||||||
):
|
):
|
||||||
Box(
|
Box(
|
||||||
block_length,
|
block_length,
|
||||||
|
|
@ -74,7 +74,7 @@ with BuildPart() as lego:
|
||||||
wall_thickness,
|
wall_thickness,
|
||||||
centered=(True, True, False),
|
centered=(True, True, False),
|
||||||
)
|
)
|
||||||
with Workplanes(lego.faces() >> Axis.Z):
|
with Workplanes(lego.faces().sort_by(Axis.Z)[-1]):
|
||||||
with GridLocations(lego_unit_size, lego_unit_size, pip_count, 2):
|
with GridLocations(lego_unit_size, lego_unit_size, pip_count, 2):
|
||||||
Cylinder(
|
Cylinder(
|
||||||
radius=pip_diameter / 2, height=pip_height, centered=(True, True, False)
|
radius=pip_diameter / 2, height=pip_height, centered=(True, True, False)
|
||||||
|
|
|
||||||
|
|
@ -53,7 +53,7 @@ with BuildPart() as vase:
|
||||||
vase.edges().filter_by_position(Axis.Y, 60, 62).filter_by_type(GeomType.CIRCLE)
|
vase.edges().filter_by_position(Axis.Y, 60, 62).filter_by_type(GeomType.CIRCLE)
|
||||||
)
|
)
|
||||||
Fillet(*top_edges, radius=0.25)
|
Fillet(*top_edges, radius=0.25)
|
||||||
Fillet(vase.edges() << Axis.Y, radius=0.5)
|
Fillet(vase.edges().sort_by(Axis.Y)[0], radius=0.5)
|
||||||
|
|
||||||
|
|
||||||
if "show_object" in locals():
|
if "show_object" in locals():
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,5 @@
|
||||||
from build123d import (
|
from build123d import Face, Mode, BuildSketch, Location, LocationList, Compound, Vector
|
||||||
Face,
|
|
||||||
Mode,
|
|
||||||
BuildSketch,
|
|
||||||
Location,
|
|
||||||
LocationList,
|
|
||||||
Compound,
|
|
||||||
Vector
|
|
||||||
)
|
|
||||||
|
|
||||||
class BaseSketchOperation(Compound):
|
class BaseSketchOperation(Compound):
|
||||||
def __init__(
|
def __init__(
|
||||||
|
|
@ -14,11 +7,11 @@ class BaseSketchOperation(Compound):
|
||||||
face: Face,
|
face: Face,
|
||||||
rotation: float = 0,
|
rotation: float = 0,
|
||||||
centered: tuple[bool, bool] = (True, True),
|
centered: tuple[bool, bool] = (True, True),
|
||||||
mode: Mode = Mode.ADD
|
mode: Mode = Mode.ADD,
|
||||||
):
|
):
|
||||||
context: BuildSketch = BuildSketch._get_context()
|
context: BuildSketch = BuildSketch._get_context()
|
||||||
|
|
||||||
bounding_box = face.BoundingBox()
|
bounding_box = face.bounding_box()
|
||||||
center_offset = Vector(
|
center_offset = Vector(
|
||||||
0 if centered[0] else bounding_box.xlen / 2,
|
0 if centered[0] else bounding_box.xlen / 2,
|
||||||
0 if centered[1] else bounding_box.ylen / 2,
|
0 if centered[1] else bounding_box.ylen / 2,
|
||||||
|
|
@ -34,4 +27,4 @@ class BaseSketchOperation(Compound):
|
||||||
for face in new_faces:
|
for face in new_faces:
|
||||||
context._add_to_context(face, mode=mode)
|
context._add_to_context(face, mode=mode)
|
||||||
|
|
||||||
Compound.__init__(self, Compound.makeCompound(new_faces).wrapped)
|
Compound.__init__(self, Compound.make_compound(new_faces).wrapped)
|
||||||
|
|
|
||||||
|
|
@ -77,7 +77,6 @@ from .direct_api import (
|
||||||
Shape,
|
Shape,
|
||||||
Vertex,
|
Vertex,
|
||||||
Plane,
|
Plane,
|
||||||
PlaneLike,
|
|
||||||
Shell,
|
Shell,
|
||||||
ShapeList,
|
ShapeList,
|
||||||
)
|
)
|
||||||
|
|
@ -282,9 +281,6 @@ def validate_inputs(validating_class, builder_context, objects: Shape = None):
|
||||||
# #:TypeVar("RotationLike"): Three tuple of angles about x, y, z or Rotation
|
# #:TypeVar("RotationLike"): Three tuple of angles about x, y, z or Rotation
|
||||||
# RotationLike = Union[tuple[float, float, float], Rotation]
|
# RotationLike = Union[tuple[float, float, float], Rotation]
|
||||||
|
|
||||||
# #:TypeVar("PlaneLike"): Named Plane (e.g. "XY") or Plane
|
|
||||||
# PlaneLike = Union[str, Plane]
|
|
||||||
|
|
||||||
|
|
||||||
# class Axis:
|
# class Axis:
|
||||||
# """Axis
|
# """Axis
|
||||||
|
|
@ -714,7 +710,7 @@ class Builder(ABC):
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
*workplanes: Union[Face, PlaneLike, Location],
|
*workplanes: Union[Face, Plane, Location],
|
||||||
mode: Mode = Mode.ADD,
|
mode: Mode = Mode.ADD,
|
||||||
):
|
):
|
||||||
self.mode = mode
|
self.mode = mode
|
||||||
|
|
@ -732,7 +728,7 @@ class Builder(ABC):
|
||||||
self._reset_tok = self._current.set(self)
|
self._reset_tok = self._current.set(self)
|
||||||
# If there are no workplanes, create a default XY plane
|
# If there are no workplanes, create a default XY plane
|
||||||
if not self.workplanes and not WorkplaneList._get_context():
|
if not self.workplanes and not WorkplaneList._get_context():
|
||||||
self.workplanes_context = Workplanes(Plane.named("XY")).__enter__()
|
self.workplanes_context = Workplanes(Plane.XY).__enter__()
|
||||||
elif self.workplanes:
|
elif self.workplanes:
|
||||||
self.workplanes_context = Workplanes(*self.workplanes).__enter__()
|
self.workplanes_context = Workplanes(*self.workplanes).__enter__()
|
||||||
|
|
||||||
|
|
@ -1171,13 +1167,13 @@ class Workplanes(WorkplaneList):
|
||||||
Create workplanes from the given sequence of planes.
|
Create workplanes from the given sequence of planes.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
objs (Union[Face, PlaneLike, Location]): sequence of faces, planes, or
|
objs (Union[Face, Plane, Location]): sequence of faces, planes, or
|
||||||
locations to use to define workplanes.
|
locations to use to define workplanes.
|
||||||
Raises:
|
Raises:
|
||||||
ValueError: invalid input
|
ValueError: invalid input
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, *objs: Union[Face, PlaneLike, Location]):
|
def __init__(self, *objs: Union[Face, Plane, Location]):
|
||||||
self.workplanes = []
|
self.workplanes = []
|
||||||
for obj in objs:
|
for obj in objs:
|
||||||
if isinstance(obj, Plane):
|
if isinstance(obj, Plane):
|
||||||
|
|
@ -1190,8 +1186,6 @@ class Workplanes(WorkplaneList):
|
||||||
normal=plane_face.normal_at(plane_face.center()),
|
normal=plane_face.normal_at(plane_face.center()),
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
elif isinstance(obj, str):
|
|
||||||
self.workplanes.append(Plane.named(obj))
|
|
||||||
elif isinstance(obj, Face):
|
elif isinstance(obj, Face):
|
||||||
self.workplanes.append(
|
self.workplanes.append(
|
||||||
Plane(origin=obj.center(), normal=obj.normal_at(obj.center()))
|
Plane(origin=obj.center(), normal=obj.normal_at(obj.center()))
|
||||||
|
|
|
||||||
|
|
@ -163,3 +163,43 @@ class GeomType(Enum):
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return f"<{self.__class__.__name__}.{self.name}>"
|
return f"<{self.__class__.__name__}.{self.name}>"
|
||||||
|
|
||||||
|
|
||||||
|
class AngularDirection(Enum):
|
||||||
|
"""Angular rotation direction"""
|
||||||
|
|
||||||
|
CLOCKWISE = auto()
|
||||||
|
COUNTER_CLOCKWISE = auto()
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
return f"<{self.__class__.__name__}.{self.name}>"
|
||||||
|
|
||||||
|
|
||||||
|
class PositionMode(Enum):
|
||||||
|
"""Position along curve mode"""
|
||||||
|
|
||||||
|
LENGTH = auto()
|
||||||
|
PARAMETER = auto()
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
return f"<{self.__class__.__name__}.{self.name}>"
|
||||||
|
|
||||||
|
|
||||||
|
class FrameMethod(Enum):
|
||||||
|
"""Moving frame calculation method"""
|
||||||
|
|
||||||
|
FRENET = auto()
|
||||||
|
CORRECTED = auto()
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
return f"<{self.__class__.__name__}.{self.name}>"
|
||||||
|
|
||||||
|
|
||||||
|
class Direction(Enum):
|
||||||
|
"""Face direction"""
|
||||||
|
|
||||||
|
ALONG_AXIS = auto()
|
||||||
|
OPPOSITE = auto()
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
return f"<{self.__class__.__name__}.{self.name}>"
|
||||||
|
|
|
||||||
|
|
@ -39,7 +39,6 @@ from .direct_api import (
|
||||||
ShapeList,
|
ShapeList,
|
||||||
Face,
|
Face,
|
||||||
Plane,
|
Plane,
|
||||||
PlaneLike,
|
|
||||||
Matrix,
|
Matrix,
|
||||||
Rotation,
|
Rotation,
|
||||||
RotationLike,
|
RotationLike,
|
||||||
|
|
@ -304,14 +303,14 @@ class Mirror(Compound):
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
objects (Union[Edge, Face,Compound]): sequence of edges or faces to mirror
|
objects (Union[Edge, Face,Compound]): sequence of edges or faces to mirror
|
||||||
about (PlaneLike, optional): reference plane. Defaults to "XZ".
|
about (Plane, optional): reference plane. Defaults to "XZ".
|
||||||
mode (Mode, optional): combination mode. Defaults to Mode.ADD.
|
mode (Mode, optional): combination mode. Defaults to Mode.ADD.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
*objects: Union[Edge, Wire, Face, Compound],
|
*objects: Union[Edge, Wire, Face, Compound],
|
||||||
about: PlaneLike = "XZ",
|
about: Plane = Plane.XZ,
|
||||||
mode: Mode = Mode.ADD,
|
mode: Mode = Mode.ADD,
|
||||||
):
|
):
|
||||||
context: Builder = Builder._get_context()
|
context: Builder = Builder._get_context()
|
||||||
|
|
@ -325,7 +324,6 @@ class Mirror(Compound):
|
||||||
self.about = about
|
self.about = about
|
||||||
self.mode = mode
|
self.mode = mode
|
||||||
|
|
||||||
mirror_plane = about if isinstance(about, Plane) else Plane.named(about)
|
|
||||||
scale_matrix = Matrix(
|
scale_matrix = Matrix(
|
||||||
[
|
[
|
||||||
[1.0, 0.0, 00.0, 0.0],
|
[1.0, 0.0, 00.0, 0.0],
|
||||||
|
|
@ -334,9 +332,9 @@ class Mirror(Compound):
|
||||||
[0.0, 0.0, 00.0, 1.0],
|
[0.0, 0.0, 00.0, 1.0],
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
localized = [mirror_plane.to_local_coords(o) for o in objects]
|
localized = [about.to_local_coords(o) for o in objects]
|
||||||
local_mirrored = [o.transform_geometry(scale_matrix) for o in localized]
|
local_mirrored = [o.transform_geometry(scale_matrix) for o in localized]
|
||||||
mirrored = [mirror_plane.from_local_coords(o) for o in local_mirrored]
|
mirrored = [about.from_local_coords(o) for o in local_mirrored]
|
||||||
|
|
||||||
context._add_to_context(*mirrored, mode=mode)
|
context._add_to_context(*mirrored, mode=mode)
|
||||||
super().__init__(Compound.make_compound(mirrored).wrapped)
|
super().__init__(Compound.make_compound(mirrored).wrapped)
|
||||||
|
|
@ -404,16 +402,12 @@ class Offset(Compound):
|
||||||
new_faces = []
|
new_faces = []
|
||||||
for face in faces:
|
for face in faces:
|
||||||
new_faces.append(
|
new_faces.append(
|
||||||
Face.make_from_wires(
|
Face.make_from_wires(face.outer_wire().offset_2d(amount, kind=kind)[0])
|
||||||
face.outer_wire().offset_2d(amount, kind=kind.name.lower())[0]
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
if edges:
|
if edges:
|
||||||
if len(edges) == 1:
|
if len(edges) == 1:
|
||||||
raise ValueError("At least two edges are required")
|
raise ValueError("At least two edges are required")
|
||||||
new_wires = Wire.assemble_edges(edges).offset_2d(
|
new_wires = Wire.assemble_edges(edges).offset_2d(amount, kind=kind)
|
||||||
amount, kind=kind.name.lower()
|
|
||||||
)
|
|
||||||
else:
|
else:
|
||||||
new_wires = []
|
new_wires = []
|
||||||
|
|
||||||
|
|
@ -427,9 +421,7 @@ class Offset(Compound):
|
||||||
else:
|
else:
|
||||||
openings_in_this_solid = []
|
openings_in_this_solid = []
|
||||||
new_solids.append(
|
new_solids.append(
|
||||||
solid.shell(
|
solid.shell(openings_in_this_solid, amount, kind=kind).fix()
|
||||||
openings_in_this_solid, amount, kind=kind.name.lower()
|
|
||||||
).fix()
|
|
||||||
)
|
)
|
||||||
|
|
||||||
new_objects = new_wires + new_faces + new_solids
|
new_objects = new_wires + new_faces + new_solids
|
||||||
|
|
@ -508,7 +500,7 @@ class Split(Compound):
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
objects (Union[Edge, Wire, Face, Solid]), objects to split
|
objects (Union[Edge, Wire, Face, Solid]), objects to split
|
||||||
bisect_by (PlaneLike, optional): plane to segment part. Defaults to Plane.named("XZ").
|
bisect_by (Plane, optional): plane to segment part. Defaults to Plane.XZ.
|
||||||
keep (Keep, optional): selector for which segment to keep. Defaults to Keep.TOP.
|
keep (Keep, optional): selector for which segment to keep. Defaults to Keep.TOP.
|
||||||
mode (Mode, optional): combination mode. Defaults to Mode.INTERSECT.
|
mode (Mode, optional): combination mode. Defaults to Mode.INTERSECT.
|
||||||
"""
|
"""
|
||||||
|
|
@ -516,7 +508,7 @@ class Split(Compound):
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
*objects: Union[Edge, Wire, Face, Solid],
|
*objects: Union[Edge, Wire, Face, Solid],
|
||||||
bisect_by: PlaneLike = Plane.named("XZ"),
|
bisect_by: Plane = Plane.XZ,
|
||||||
keep: Keep = Keep.TOP,
|
keep: Keep = Keep.TOP,
|
||||||
mode: Mode = Mode.REPLACE,
|
mode: Mode = Mode.REPLACE,
|
||||||
):
|
):
|
||||||
|
|
@ -526,7 +518,7 @@ class Split(Compound):
|
||||||
if keep == Keep.TOP
|
if keep == Keep.TOP
|
||||||
else Vector(-max_size, -max_size, -2 * max_size)
|
else Vector(-max_size, -max_size, -2 * max_size)
|
||||||
)
|
)
|
||||||
return bisect_plane.from_local_coords(
|
return bisect_by.from_local_coords(
|
||||||
Solid.make_box(2 * max_size, 2 * max_size, 2 * max_size).moved(
|
Solid.make_box(2 * max_size, 2 * max_size, 2 * max_size).moved(
|
||||||
Location(cutter_center)
|
Location(cutter_center)
|
||||||
)
|
)
|
||||||
|
|
@ -539,10 +531,6 @@ class Split(Compound):
|
||||||
if not objects:
|
if not objects:
|
||||||
objects = [context._obj]
|
objects = [context._obj]
|
||||||
|
|
||||||
bisect_plane = (
|
|
||||||
bisect_by if isinstance(bisect_by, Plane) else Plane.named(bisect_by)
|
|
||||||
)
|
|
||||||
|
|
||||||
self.objects = objects
|
self.objects = objects
|
||||||
self.bisect_by = bisect_by
|
self.bisect_by = bisect_by
|
||||||
self.keep = keep
|
self.keep = keep
|
||||||
|
|
|
||||||
|
|
@ -39,7 +39,6 @@ from .direct_api import (
|
||||||
ShapeList,
|
ShapeList,
|
||||||
Face,
|
Face,
|
||||||
Plane,
|
Plane,
|
||||||
PlaneLike,
|
|
||||||
)
|
)
|
||||||
from .build_common import Builder, logger, validate_inputs
|
from .build_common import Builder, logger, validate_inputs
|
||||||
|
|
||||||
|
|
@ -63,13 +62,12 @@ class BuildLine(Builder):
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
*workplanes: Union[Face, PlaneLike, Location],
|
*workplanes: Union[Face, Plane, Location],
|
||||||
mode: Mode = Mode.ADD,
|
mode: Mode = Mode.ADD,
|
||||||
):
|
):
|
||||||
self.initial_planes = workplanes
|
self.initial_planes = workplanes
|
||||||
self.mode = mode
|
self.mode = mode
|
||||||
self.line: Compound = None
|
self.line: Compound = None
|
||||||
# self.locations: list[Location] = [Location(Vector())]
|
|
||||||
super().__init__(*workplanes, mode=mode)
|
super().__init__(*workplanes, mode=mode)
|
||||||
|
|
||||||
def faces(self):
|
def faces(self):
|
||||||
|
|
|
||||||
|
|
@ -47,7 +47,6 @@ from .direct_api import (
|
||||||
Location,
|
Location,
|
||||||
Face,
|
Face,
|
||||||
Plane,
|
Plane,
|
||||||
PlaneLike,
|
|
||||||
Axis,
|
Axis,
|
||||||
Rotation,
|
Rotation,
|
||||||
RotationLike,
|
RotationLike,
|
||||||
|
|
@ -69,7 +68,7 @@ class BuildPart(Builder):
|
||||||
Create 3D parts (objects with the property of volume) from sketches or 3D objects.
|
Create 3D parts (objects with the property of volume) from sketches or 3D objects.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
workplane (Plane, optional): initial plane to work on. Defaults to Plane.named("XY").
|
workplane (Plane, optional): initial plane to work on. Defaults to Plane.XY.
|
||||||
mode (Mode, optional): combination mode. Defaults to Mode.ADD.
|
mode (Mode, optional): combination mode. Defaults to Mode.ADD.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
@ -89,7 +88,7 @@ class BuildPart(Builder):
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
*workplanes: Union[Face, PlaneLike, Location],
|
*workplanes: Union[Face, Plane, Location],
|
||||||
mode: Mode = Mode.ADD,
|
mode: Mode = Mode.ADD,
|
||||||
):
|
):
|
||||||
self.part: Compound = None
|
self.part: Compound = None
|
||||||
|
|
@ -701,7 +700,7 @@ class Section(Compound):
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
*section_by: PlaneLike,
|
*section_by: Plane,
|
||||||
height: float = 0.0,
|
height: float = 0.0,
|
||||||
mode: Mode = Mode.INTERSECT,
|
mode: Mode = Mode.INTERSECT,
|
||||||
):
|
):
|
||||||
|
|
@ -720,13 +719,6 @@ class Section(Compound):
|
||||||
section_planes = (
|
section_planes = (
|
||||||
section_planes if isinstance(section_planes, Iterable) else [section_planes]
|
section_planes if isinstance(section_planes, Iterable) else [section_planes]
|
||||||
)
|
)
|
||||||
# If the user provided named planes, convert
|
|
||||||
section_planes = [
|
|
||||||
section_plane
|
|
||||||
if isinstance(section_plane, Plane)
|
|
||||||
else Plane.named(section_plane)
|
|
||||||
for section_plane in section_planes
|
|
||||||
]
|
|
||||||
planes = [
|
planes = [
|
||||||
Face.make_plane(
|
Face.make_plane(
|
||||||
2 * max_size,
|
2 * max_size,
|
||||||
|
|
@ -815,7 +807,7 @@ class Sweep(Compound):
|
||||||
True, # make solid
|
True, # make solid
|
||||||
is_frenet,
|
is_frenet,
|
||||||
binormal_mode,
|
binormal_mode,
|
||||||
transition.name.lower(),
|
transition,
|
||||||
).moved(location)
|
).moved(location)
|
||||||
new_solids.append(new_solid)
|
new_solids.append(new_solid)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -53,7 +53,6 @@ from .direct_api import (
|
||||||
ShapeList,
|
ShapeList,
|
||||||
Face,
|
Face,
|
||||||
Plane,
|
Plane,
|
||||||
PlaneLike,
|
|
||||||
)
|
)
|
||||||
from .build_common import (
|
from .build_common import (
|
||||||
Builder,
|
Builder,
|
||||||
|
|
@ -83,7 +82,7 @@ class BuildSketch(Builder):
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
*workplanes: Union[Face, PlaneLike, Location],
|
*workplanes: Union[Face, Plane, Location],
|
||||||
mode: Mode = Mode.ADD,
|
mode: Mode = Mode.ADD,
|
||||||
):
|
):
|
||||||
self.workplanes = workplanes
|
self.workplanes = workplanes
|
||||||
|
|
@ -726,9 +725,9 @@ class Text(Compound):
|
||||||
fontsize=fontsize,
|
fontsize=fontsize,
|
||||||
font=font,
|
font=font,
|
||||||
font_path=font_path,
|
font_path=font_path,
|
||||||
font_style=font_style.name.lower(),
|
font_style=font_style,
|
||||||
halign=halign.name.lower(),
|
halign=halign,
|
||||||
valign=valign.name.lower(),
|
valign=valign,
|
||||||
position_on_path=position_on_path,
|
position_on_path=position_on_path,
|
||||||
text_path=path,
|
text_path=path,
|
||||||
).rotate(Vector(), Vector(0, 0, 1), rotation)
|
).rotate(Vector(), Vector(0, 0, 1), rotation)
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load diff
|
|
@ -284,7 +284,7 @@ class TestBuilder(unittest.TestCase):
|
||||||
|
|
||||||
class TestWorkplanes(unittest.TestCase):
|
class TestWorkplanes(unittest.TestCase):
|
||||||
def test_named(self):
|
def test_named(self):
|
||||||
with Workplanes("XY") as test:
|
with Workplanes(Plane.XY) as test:
|
||||||
self.assertTupleAlmostEquals(
|
self.assertTupleAlmostEquals(
|
||||||
test.workplanes[0].origin.to_tuple(), (0, 0, 0), 5
|
test.workplanes[0].origin.to_tuple(), (0, 0, 0), 5
|
||||||
)
|
)
|
||||||
|
|
@ -293,7 +293,7 @@ class TestWorkplanes(unittest.TestCase):
|
||||||
)
|
)
|
||||||
|
|
||||||
def test_locations(self):
|
def test_locations(self):
|
||||||
with Workplanes("XY"):
|
with Workplanes(Plane.XY):
|
||||||
with Locations((0, 0, 1), (0, 0, 2)) as l:
|
with Locations((0, 0, 1), (0, 0, 2)) as l:
|
||||||
with Workplanes(*l.locations) as w:
|
with Workplanes(*l.locations) as w:
|
||||||
origins = [p.origin.to_tuple() for p in w.workplanes]
|
origins = [p.origin.to_tuple() for p in w.workplanes]
|
||||||
|
|
|
||||||
|
|
@ -277,7 +277,7 @@ class MirrorTests(unittest.TestCase):
|
||||||
edge = Edge.make_line((1, 0, 0), (2, 0, 0))
|
edge = Edge.make_line((1, 0, 0), (2, 0, 0))
|
||||||
wire = Wire.make_circle(1, center=(5, 0, 0), normal=(0, 0, 1))
|
wire = Wire.make_circle(1, center=(5, 0, 0), normal=(0, 0, 1))
|
||||||
with BuildLine() as test:
|
with BuildLine() as test:
|
||||||
Mirror(edge, wire, about="YZ")
|
Mirror(edge, wire, about=Plane.YZ)
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
len(test.edges().filter_by_position(Axis.X, minimum=0, maximum=10)), 0
|
len(test.edges().filter_by_position(Axis.X, minimum=0, maximum=10)), 0
|
||||||
)
|
)
|
||||||
|
|
@ -286,7 +286,7 @@ class MirrorTests(unittest.TestCase):
|
||||||
)
|
)
|
||||||
with BuildLine() as test:
|
with BuildLine() as test:
|
||||||
Line((1, 0), (2, 0))
|
Line((1, 0), (2, 0))
|
||||||
Mirror(about="YZ")
|
Mirror(about=Plane.YZ)
|
||||||
self.assertEqual(len(test.edges()), 2)
|
self.assertEqual(len(test.edges()), 2)
|
||||||
|
|
||||||
def test_mirror_sketch(self):
|
def test_mirror_sketch(self):
|
||||||
|
|
@ -300,7 +300,7 @@ class MirrorTests(unittest.TestCase):
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
with BuildSketch() as test:
|
with BuildSketch() as test:
|
||||||
Mirror(edge, wire, face, compound, about="YZ")
|
Mirror(edge, wire, face, compound, about=Plane.YZ)
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
len(test.pending_edges.filter_by_position(Axis.X, minimum=0, maximum=10)), 0
|
len(test.pending_edges.filter_by_position(Axis.X, minimum=0, maximum=10)), 0
|
||||||
)
|
)
|
||||||
|
|
@ -318,7 +318,7 @@ class MirrorTests(unittest.TestCase):
|
||||||
def test_mirror_part(self):
|
def test_mirror_part(self):
|
||||||
cone = Solid.make_cone(2, 1, 2, pnt=(5, 4, 0))
|
cone = Solid.make_cone(2, 1, 2, pnt=(5, 4, 0))
|
||||||
with BuildPart() as test:
|
with BuildPart() as test:
|
||||||
Mirror(cone, about="YZ")
|
Mirror(cone, about=Plane.YZ)
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
len(test.solids().filter_by_position(Axis.X, minimum=-10, maximum=0)), 1
|
len(test.solids().filter_by_position(Axis.X, minimum=-10, maximum=0)), 1
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -75,7 +75,7 @@ class BuildLineTests(unittest.TestCase):
|
||||||
)
|
)
|
||||||
l7 = Line((0.0692, 0.7808), (0.0000, 0.9167))
|
l7 = Line((0.0692, 0.7808), (0.0000, 0.9167))
|
||||||
TangentArc(l6 @ 1, l7 @ 0, tangent=l6 % 1)
|
TangentArc(l6 @ 1, l7 @ 0, tangent=l6 % 1)
|
||||||
Mirror(*outline.edges(), about="YZ")
|
Mirror(*outline.edges(), about=Plane.YZ)
|
||||||
BuildFace(*leaf.pending_edges)
|
BuildFace(*leaf.pending_edges)
|
||||||
self.assertAlmostEqual(leaf.sketch.area(), 0.2741600685288115, 5)
|
self.assertAlmostEqual(leaf.sketch.area(), 0.2741600685288115, 5)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -142,7 +142,7 @@ class BuildPartTests(unittest.TestCase):
|
||||||
self.assertEqual(len(LocationList._get_context().locations), 5)
|
self.assertEqual(len(LocationList._get_context().locations), 5)
|
||||||
|
|
||||||
def test_named_plane(self):
|
def test_named_plane(self):
|
||||||
with BuildPart("YZ") as test:
|
with BuildPart(Plane.YZ) as test:
|
||||||
self.assertTupleAlmostEquals(
|
self.assertTupleAlmostEquals(
|
||||||
WorkplaneList._get_context().workplanes[0].z_dir.to_tuple(),
|
WorkplaneList._get_context().workplanes[0].z_dir.to_tuple(),
|
||||||
(1, 0, 0),
|
(1, 0, 0),
|
||||||
|
|
@ -340,7 +340,7 @@ class TestSection(unittest.TestCase):
|
||||||
def test_custom_plane(self):
|
def test_custom_plane(self):
|
||||||
with BuildPart() as test:
|
with BuildPart() as test:
|
||||||
Sphere(10)
|
Sphere(10)
|
||||||
Section("XZ")
|
Section(Plane.XZ)
|
||||||
self.assertAlmostEqual(
|
self.assertAlmostEqual(
|
||||||
test.faces().filter_by_axis(Axis.Y)[-1].area(), 100 * pi, 5
|
test.faces().filter_by_axis(Axis.Y)[-1].area(), 100 * pi, 5
|
||||||
)
|
)
|
||||||
|
|
@ -362,7 +362,7 @@ class TestSplit(unittest.TestCase):
|
||||||
def test_custom_plane(self):
|
def test_custom_plane(self):
|
||||||
with BuildPart() as test:
|
with BuildPart() as test:
|
||||||
Sphere(10)
|
Sphere(10)
|
||||||
Split(bisect_by="YZ", keep=Keep.TOP)
|
Split(bisect_by=Plane.YZ, keep=Keep.TOP)
|
||||||
self.assertAlmostEqual(test.part.volume(), (2 / 3) * 1000 * pi, 5)
|
self.assertAlmostEqual(test.part.volume(), (2 / 3) * 1000 * pi, 5)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue