mirror of
https://github.com/gumyr/build123d.git
synced 2025-12-06 02:30:55 -08:00
De-emphasizing Workplanes
This commit is contained in:
parent
caa72c7430
commit
af52e032be
19 changed files with 131 additions and 122 deletions
|
|
@ -1,26 +1,37 @@
|
||||||
import build123d as bd
|
"""
|
||||||
|
|
||||||
# from cadquery import exporters
|
name: boxes_on_faces.py
|
||||||
|
by: Gumyr
|
||||||
|
date: March 6th 2023
|
||||||
|
|
||||||
|
desc: Demo adding features to multiple faces in one operation.
|
||||||
|
|
||||||
|
license:
|
||||||
|
|
||||||
|
Copyright 2023 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.
|
||||||
|
|
||||||
|
"""
|
||||||
|
import build123d as bd
|
||||||
|
|
||||||
with bd.BuildPart() as bp:
|
with bd.BuildPart() as bp:
|
||||||
bd.Box(3, 3, 3)
|
bd.Box(3, 3, 3)
|
||||||
with bd.Workplanes(*bp.faces()):
|
with bd.BuildSketch(*bp.faces()):
|
||||||
bd.Box(1, 2, 0.1, rotation=(0, 0, 45))
|
bd.Rectangle(1, 2, rotation=45)
|
||||||
|
bd.Extrude(amount=0.1)
|
||||||
|
|
||||||
# exporters.export(
|
assert abs(bp.part.volume - (3**3 + 6 * (1 * 2 * 0.1)) < 1e-5)
|
||||||
# bp.part,
|
|
||||||
# "boxes_on_faces.svg",
|
|
||||||
# opt={
|
|
||||||
# "width": 250,
|
|
||||||
# "height": 250,
|
|
||||||
# "marginLeft": 30,
|
|
||||||
# "marginTop": 30,
|
|
||||||
# "showAxes": False,
|
|
||||||
# "projectionDir": (1, 1, 1),
|
|
||||||
# # "strokeWidth": 0.1,
|
|
||||||
# "showHidden": False,
|
|
||||||
# },
|
|
||||||
# )
|
|
||||||
|
|
||||||
if "show_object" in locals():
|
if "show_object" in locals():
|
||||||
show_object(bp.part.wrapped, name="box on faces")
|
show_object(bp.part.wrapped, name="box on faces")
|
||||||
|
|
|
||||||
|
|
@ -69,11 +69,12 @@ with BuildPart(Plane.XZ) as rail:
|
||||||
)
|
)
|
||||||
Fillet(*outside_vertices, radius=fillet + thickness)
|
Fillet(*outside_vertices, radius=fillet + thickness)
|
||||||
Extrude(amount=rail_length)
|
Extrude(amount=rail_length)
|
||||||
with Workplanes(rail.faces().filter_by(Axis.Z)[-1]):
|
with BuildSketch(rail.faces().filter_by(Axis.Z)[-1]) as slots:
|
||||||
with BuildSketch() as slots:
|
with GridLocations(0, slot_pitch, 1, rail_length // slot_pitch - 1):
|
||||||
with GridLocations(0, slot_pitch, 1, rail_length // slot_pitch - 1):
|
SlotOverall(slot_length, slot_width, rotation=90)
|
||||||
SlotOverall(slot_length, slot_width, rotation=90)
|
|
||||||
Extrude(amount=-height, mode=Mode.SUBTRACT)
|
Extrude(amount=-height, mode=Mode.SUBTRACT)
|
||||||
|
|
||||||
|
assert abs(rail.part.volume - 42462.863388694714) < 1e-5
|
||||||
|
|
||||||
if "show_object" in locals():
|
if "show_object" in locals():
|
||||||
show_object(rail.part.wrapped, name="rail")
|
show_object(rail.part.wrapped, name="rail")
|
||||||
|
|
|
||||||
|
|
@ -42,10 +42,9 @@ with BuildPart() as both:
|
||||||
# Extrude multiple pending faces on multiple faces
|
# Extrude multiple pending faces on multiple faces
|
||||||
with BuildPart() as multiple:
|
with BuildPart() as multiple:
|
||||||
Box(10, 10, 10)
|
Box(10, 10, 10)
|
||||||
with Workplanes(*multiple.faces()):
|
with BuildSketch(*multiple.faces()):
|
||||||
with GridLocations(5, 5, 2, 2):
|
with GridLocations(5, 5, 2, 2):
|
||||||
with BuildSketch():
|
Text("Ω", font_size=3)
|
||||||
Text("Ω", font_size=3)
|
|
||||||
Extrude(amount=1)
|
Extrude(amount=1)
|
||||||
|
|
||||||
# Non-planar surface
|
# Non-planar surface
|
||||||
|
|
|
||||||
|
|
@ -43,24 +43,24 @@ with BuildPart() as handle:
|
||||||
|
|
||||||
# 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):
|
||||||
with Workplanes(
|
with BuildSketch(
|
||||||
Plane(
|
Plane(
|
||||||
origin=handle_path @ (i / segment_count),
|
origin=handle_path @ (i / segment_count),
|
||||||
z_dir=handle_path % (i / segment_count),
|
z_dir=handle_path % (i / segment_count),
|
||||||
)
|
)
|
||||||
):
|
) as section:
|
||||||
with BuildSketch() as section:
|
if i % segment_count == 0:
|
||||||
if i % segment_count == 0:
|
Circle(1)
|
||||||
Circle(1)
|
else:
|
||||||
else:
|
Rectangle(1.25, 3)
|
||||||
Rectangle(1.25, 3)
|
Fillet(*section.vertices(), radius=0.2)
|
||||||
Fillet(*section.vertices(), radius=0.2)
|
|
||||||
# Record the sections for display
|
# Record the sections for display
|
||||||
sections = handle.pending_faces
|
sections = handle.pending_faces
|
||||||
|
|
||||||
# Create the handle by sweeping along the path
|
# Create the handle by sweeping along the path
|
||||||
Sweep(multisection=True)
|
Sweep(multisection=True)
|
||||||
|
|
||||||
|
assert abs(handle.part.volume - 94.77361455046953) < 1e-5
|
||||||
|
|
||||||
if "show_object" in locals():
|
if "show_object" in locals():
|
||||||
show_object(handle_path.wrapped, name="handle_path")
|
show_object(handle_path.wrapped, name="handle_path")
|
||||||
|
|
|
||||||
|
|
@ -38,8 +38,9 @@ bundle_diameter = exchanger_diameter - 2 * tube_diameter
|
||||||
fillet_radius = tube_spacing / 3
|
fillet_radius = tube_spacing / 3
|
||||||
assert tube_extension > fillet_radius
|
assert tube_extension > fillet_radius
|
||||||
|
|
||||||
# Generate list of tube locations
|
# Build the heat exchanger
|
||||||
with Workplanes(Plane.XY):
|
with BuildPart() as heat_exchanger:
|
||||||
|
# Generate list of tube locations
|
||||||
tube_locations = [
|
tube_locations = [
|
||||||
l
|
l
|
||||||
for l in HexLocations(
|
for l in HexLocations(
|
||||||
|
|
@ -49,10 +50,7 @@ with Workplanes(Plane.XY):
|
||||||
)
|
)
|
||||||
if l.position.length < bundle_diameter / 2
|
if l.position.length < bundle_diameter / 2
|
||||||
]
|
]
|
||||||
tube_count = len(tube_locations)
|
tube_count = len(tube_locations)
|
||||||
|
|
||||||
# Build the heat exchanger
|
|
||||||
with BuildPart() as heat_exchanger:
|
|
||||||
with BuildSketch() as tube_plan:
|
with BuildSketch() as tube_plan:
|
||||||
with Locations(*tube_locations):
|
with Locations(*tube_locations):
|
||||||
Circle(radius=tube_diameter / 2)
|
Circle(radius=tube_diameter / 2)
|
||||||
|
|
|
||||||
|
|
@ -36,16 +36,17 @@ from build123d import *
|
||||||
# logging.info("Starting pipes test")
|
# logging.info("Starting pipes test")
|
||||||
|
|
||||||
with BuildPart() as pipes:
|
with BuildPart() as pipes:
|
||||||
Box(10, 10, 10, rotation=(10, 20, 30))
|
box = Box(10, 10, 10, rotation=(10, 20, 30))
|
||||||
with Workplanes(*pipes.faces()):
|
with BuildSketch(*box.faces()) as pipe:
|
||||||
with BuildSketch() as pipe:
|
Circle(4)
|
||||||
Circle(4)
|
Extrude(amount=-5, mode=Mode.SUBTRACT)
|
||||||
Extrude(amount=-5, mode=Mode.SUBTRACT)
|
with BuildSketch(*box.faces()) as pipe:
|
||||||
with BuildSketch() as pipe:
|
Circle(4.5)
|
||||||
Circle(4.5)
|
Circle(4, mode=Mode.SUBTRACT)
|
||||||
Circle(4, mode=Mode.SUBTRACT)
|
Extrude(amount=10)
|
||||||
Extrude(amount=10)
|
Fillet(*pipes.edges(Select.LAST), radius=0.2)
|
||||||
Fillet(*pipes.edges(Select.LAST), radius=0.2)
|
|
||||||
|
assert abs(pipes.part.volume - 1015.939005681509) < 1e-5
|
||||||
|
|
||||||
if "show_object" in locals():
|
if "show_object" in locals():
|
||||||
show_object(pipes.part.wrapped, name="intersecting pipes")
|
show_object(pipes.part.wrapped, name="intersecting pipes")
|
||||||
|
|
|
||||||
|
|
@ -48,22 +48,22 @@ with BuildPart() as key_cap:
|
||||||
Scale(by=(0.925, 0.925, 0.85), mode=Mode.SUBTRACT)
|
Scale(by=(0.925, 0.925, 0.85), mode=Mode.SUBTRACT)
|
||||||
|
|
||||||
# Add supporting ribs while leaving room for switch activation
|
# Add supporting ribs while leaving room for switch activation
|
||||||
with Workplanes(Plane(origin=(0, 0, 4 * MM))):
|
with BuildSketch(Plane(origin=(0, 0, 4 * MM))):
|
||||||
with BuildSketch():
|
Rectangle(15 * MM, 0.5 * MM)
|
||||||
Rectangle(15 * MM, 0.5 * MM)
|
Rectangle(0.5 * MM, 15 * MM)
|
||||||
Rectangle(0.5 * MM, 15 * MM)
|
Circle(radius=5.5 * MM / 2)
|
||||||
Circle(radius=5.5 * MM / 2)
|
|
||||||
# Extrude the mount and ribs to the key cap underside
|
# Extrude the mount and ribs to the key cap underside
|
||||||
Extrude(until=Until.NEXT)
|
Extrude(until=Until.NEXT)
|
||||||
# Find the face on the bottom of the ribs to build onto
|
# Find the face on the bottom of the ribs to build onto
|
||||||
rib_bottom = key_cap.faces().filter_by_position(Axis.Z, 4 * MM, 4 * MM)[0]
|
rib_bottom = key_cap.faces().filter_by_position(Axis.Z, 4 * MM, 4 * MM)[0]
|
||||||
# Add the switch socket
|
# Add the switch socket
|
||||||
with Workplanes(rib_bottom):
|
with BuildSketch(rib_bottom) as cruciform:
|
||||||
with BuildSketch() as cruciform:
|
Circle(radius=5.5 * MM / 2)
|
||||||
Circle(radius=5.5 * MM / 2)
|
Rectangle(4.1 * MM, 1.17 * MM, mode=Mode.SUBTRACT)
|
||||||
Rectangle(4.1 * MM, 1.17 * MM, mode=Mode.SUBTRACT)
|
Rectangle(1.17 * MM, 4.1 * MM, mode=Mode.SUBTRACT)
|
||||||
Rectangle(1.17 * MM, 4.1 * MM, mode=Mode.SUBTRACT)
|
|
||||||
Extrude(amount=3.5 * MM, mode=Mode.ADD)
|
Extrude(amount=3.5 * MM, mode=Mode.ADD)
|
||||||
|
|
||||||
|
assert abs(key_cap.part.volume - 644.8900473617498) < 1e-5
|
||||||
|
|
||||||
if "show_object" in locals():
|
if "show_object" in locals():
|
||||||
show_object(key_cap.part.wrapped, name="key cap", options={"alpha": 0.7})
|
show_object(key_cap.part.wrapped, name="key cap", options={"alpha": 0.7})
|
||||||
|
|
|
||||||
|
|
@ -118,7 +118,7 @@ with BuildPart() as lego:
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
# Create a workplane on the top of the block
|
# Create a workplane on the top of the block
|
||||||
with Workplanes(lego.faces().sort_by(Axis.Z)[-1]):
|
with BuildPart(lego.faces().sort_by(Axis.Z)[-1]):
|
||||||
# Create a grid of pips
|
# Create a grid of pips
|
||||||
with GridLocations(lego_unit_size, lego_unit_size, pip_count, 2):
|
with GridLocations(lego_unit_size, lego_unit_size, pip_count, 2):
|
||||||
Cylinder(
|
Cylinder(
|
||||||
|
|
@ -140,6 +140,7 @@ with BuildPart() as lego:
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
assert abs(lego.part.volume - 3212.187337781355) < 1e-5
|
||||||
|
|
||||||
if "show_object" in locals():
|
if "show_object" in locals():
|
||||||
show_object(lego.part.wrapped, name="lego")
|
show_object(lego.part.wrapped, name="lego")
|
||||||
|
|
|
||||||
|
|
@ -31,12 +31,13 @@ from build123d import *
|
||||||
with BuildPart() as art:
|
with BuildPart() as art:
|
||||||
slice_count = 10
|
slice_count = 10
|
||||||
for i in range(slice_count + 1):
|
for i in range(slice_count + 1):
|
||||||
with Workplanes(Plane(origin=(0, 0, i * 3), z_dir=(0, 0, 1))):
|
with BuildSketch(Plane(origin=(0, 0, i * 3), z_dir=(0, 0, 1))) as slice:
|
||||||
with BuildSketch() as slice:
|
Circle(10 * sin(i * pi / slice_count) + 5)
|
||||||
Circle(10 * sin(i * pi / slice_count) + 5)
|
|
||||||
Loft()
|
Loft()
|
||||||
top_bottom = art.faces().filter_by(GeomType.PLANE)
|
top_bottom = art.faces().filter_by(GeomType.PLANE)
|
||||||
Offset(openings=top_bottom, amount=0.5)
|
Offset(openings=top_bottom, amount=0.5)
|
||||||
|
|
||||||
|
assert abs(art.part.volume - 1306.3405290344635) < 1e-5
|
||||||
|
|
||||||
if "show_object" in locals():
|
if "show_object" in locals():
|
||||||
show_object(art.part.wrapped, name="art")
|
show_object(art.part.wrapped, name="art")
|
||||||
|
|
|
||||||
|
|
@ -2,8 +2,10 @@ from build123d import *
|
||||||
|
|
||||||
with BuildPart() as obj:
|
with BuildPart() as obj:
|
||||||
Box(5, 5, 1)
|
Box(5, 5, 1)
|
||||||
with Workplanes(*obj.faces().filter_by(Axis.Z)):
|
with BuildPart(*obj.faces().filter_by(Axis.Z), mode=Mode.SUBTRACT):
|
||||||
Sphere(1.8, mode=Mode.SUBTRACT)
|
Sphere(1.8)
|
||||||
|
|
||||||
|
assert abs(obj.part.volume - 15.083039190168236) < 1e-5
|
||||||
|
|
||||||
if "show_object" in locals():
|
if "show_object" in locals():
|
||||||
show_object(obj.part)
|
show_object(obj.part)
|
||||||
|
|
|
||||||
|
|
@ -37,7 +37,7 @@ with BuildPart() as pillow_block:
|
||||||
Rectangle(width, height)
|
Rectangle(width, height)
|
||||||
Fillet(*plan.vertices(), radius=5)
|
Fillet(*plan.vertices(), radius=5)
|
||||||
Extrude(amount=thickness)
|
Extrude(amount=thickness)
|
||||||
with Workplanes(pillow_block.faces().filter_by(Axis.Z)[-1]):
|
with Locations((0, 0, thickness)):
|
||||||
CounterBoreHole(bearing_axle_radius, bearing_radius, bearing_thickness)
|
CounterBoreHole(bearing_axle_radius, bearing_radius, bearing_thickness)
|
||||||
with GridLocations(width - 2 * padding, height - 2 * padding, 2, 2):
|
with GridLocations(width - 2 * padding, height - 2 * padding, 2, 2):
|
||||||
CounterBoreHole(screw_shaft_radius, screw_head_radius, screw_head_height)
|
CounterBoreHole(screw_shaft_radius, screw_head_radius, screw_head_height)
|
||||||
|
|
|
||||||
|
|
@ -118,6 +118,8 @@ class Add(Compound):
|
||||||
new_edges.extend(new_wire.edges())
|
new_edges.extend(new_wire.edges())
|
||||||
|
|
||||||
# Add the pending Edges in one group
|
# Add the pending Edges in one group
|
||||||
|
if not LocationList._get_context():
|
||||||
|
raise RuntimeError("There is no active Locations context")
|
||||||
located_edges = [
|
located_edges = [
|
||||||
edge.moved(location)
|
edge.moved(location)
|
||||||
for edge in new_edges
|
for edge in new_edges
|
||||||
|
|
|
||||||
|
|
@ -194,10 +194,6 @@ class BuildLine(Builder):
|
||||||
@classmethod
|
@classmethod
|
||||||
def _get_context(cls, caller=None) -> "BuildLine":
|
def _get_context(cls, caller=None) -> "BuildLine":
|
||||||
"""Return the instance of the current builder"""
|
"""Return the instance of the current builder"""
|
||||||
logger.info(
|
|
||||||
"Context requested by %s",
|
|
||||||
type(inspect.currentframe().f_back.f_locals["self"]).__name__,
|
|
||||||
)
|
|
||||||
|
|
||||||
result = cls._current.get(None)
|
result = cls._current.get(None)
|
||||||
if caller is not None and result is None:
|
if caller is not None and result is None:
|
||||||
|
|
@ -207,6 +203,11 @@ class BuildLine(Builder):
|
||||||
)
|
)
|
||||||
raise RuntimeError("No valid context found")
|
raise RuntimeError("No valid context found")
|
||||||
|
|
||||||
|
logger.info(
|
||||||
|
"Context requested by %s",
|
||||||
|
type(inspect.currentframe().f_back.f_locals["self"]).__name__,
|
||||||
|
)
|
||||||
|
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -233,10 +233,6 @@ class BuildPart(Builder):
|
||||||
@classmethod
|
@classmethod
|
||||||
def _get_context(cls, caller=None) -> BuildPart:
|
def _get_context(cls, caller=None) -> BuildPart:
|
||||||
"""Return the instance of the current builder"""
|
"""Return the instance of the current builder"""
|
||||||
logger.info(
|
|
||||||
"Context requested by %s",
|
|
||||||
type(inspect.currentframe().f_back.f_locals["self"]).__name__,
|
|
||||||
)
|
|
||||||
|
|
||||||
result = cls._current.get(None)
|
result = cls._current.get(None)
|
||||||
if caller is not None and result is None:
|
if caller is not None and result is None:
|
||||||
|
|
@ -246,6 +242,11 @@ class BuildPart(Builder):
|
||||||
)
|
)
|
||||||
raise RuntimeError("No valid context found")
|
raise RuntimeError("No valid context found")
|
||||||
|
|
||||||
|
logger.info(
|
||||||
|
"Context requested by %s",
|
||||||
|
type(inspect.currentframe().f_back.f_locals["self"]).__name__,
|
||||||
|
)
|
||||||
|
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -291,6 +292,8 @@ class BasePartObject(Compound):
|
||||||
align_offset.append(-bbox.max.to_tuple()[i])
|
align_offset.append(-bbox.max.to_tuple()[i])
|
||||||
solid.move(Location(Vector(*align_offset)))
|
solid.move(Location(Vector(*align_offset)))
|
||||||
|
|
||||||
|
if not LocationList._get_context():
|
||||||
|
raise RuntimeError("No valid context found")
|
||||||
new_solids = [
|
new_solids = [
|
||||||
solid.moved(location * rotate)
|
solid.moved(location * rotate)
|
||||||
for location in LocationList._get_context().locations
|
for location in LocationList._get_context().locations
|
||||||
|
|
|
||||||
|
|
@ -8,15 +8,6 @@ date: July 12th 2022
|
||||||
desc:
|
desc:
|
||||||
This python module is a library used to build planar sketches.
|
This python module is a library used to build planar sketches.
|
||||||
|
|
||||||
Instead of existing constraints how about constraints that return locations
|
|
||||||
on objects:
|
|
||||||
- two circles: c1, c2
|
|
||||||
- "line tangent to c1 & c2" : 4 locations on each circle
|
|
||||||
- these would be construction geometry
|
|
||||||
- user sorts to select the ones they want
|
|
||||||
- uses these points to build geometry
|
|
||||||
- how many constraints are currently implemented?
|
|
||||||
|
|
||||||
license:
|
license:
|
||||||
|
|
||||||
Copyright 2022 Gumyr
|
Copyright 2022 Gumyr
|
||||||
|
|
@ -209,10 +200,6 @@ class BuildSketch(Builder):
|
||||||
@classmethod
|
@classmethod
|
||||||
def _get_context(cls, caller=None) -> BuildSketch:
|
def _get_context(cls, caller=None) -> BuildSketch:
|
||||||
"""Return the instance of the current builder"""
|
"""Return the instance of the current builder"""
|
||||||
logger.info(
|
|
||||||
"Context requested by %s",
|
|
||||||
type(inspect.currentframe().f_back.f_locals["self"]).__name__,
|
|
||||||
)
|
|
||||||
|
|
||||||
result = cls._current.get(None)
|
result = cls._current.get(None)
|
||||||
if caller is not None and result is None:
|
if caller is not None and result is None:
|
||||||
|
|
@ -222,6 +209,11 @@ class BuildSketch(Builder):
|
||||||
)
|
)
|
||||||
raise RuntimeError("No valid context found")
|
raise RuntimeError("No valid context found")
|
||||||
|
|
||||||
|
logger.info(
|
||||||
|
"Context requested by %s",
|
||||||
|
type(inspect.currentframe().f_back.f_locals["self"]).__name__,
|
||||||
|
)
|
||||||
|
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -343,18 +343,19 @@ class TestWorkplanes(unittest.TestCase):
|
||||||
|
|
||||||
def test_bad_plane(self):
|
def test_bad_plane(self):
|
||||||
with self.assertRaises(ValueError):
|
with self.assertRaises(ValueError):
|
||||||
with Workplanes(4):
|
with BuildPart(4):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def test_locations_after_new_workplane(self):
|
def test_locations_after_new_workplane(self):
|
||||||
with Workplanes(Plane.XY):
|
with BuildPart(Plane.XY):
|
||||||
with Locations((0, 1, 2), (3, 4, 5)):
|
with Locations((0, 1, 2), (3, 4, 5)):
|
||||||
with Workplanes(Plane.XY.offset(2)):
|
with BuildPart(Plane.XY.offset(2)):
|
||||||
self.assertTupleAlmostEquals(
|
self.assertTupleAlmostEquals(
|
||||||
LocationList._get_context().locations[0].position.to_tuple(),
|
LocationList._get_context().locations[0].position.to_tuple(),
|
||||||
(0, 0, 2),
|
(0, 0, 2),
|
||||||
5,
|
5,
|
||||||
)
|
)
|
||||||
|
Box(1, 1, 1)
|
||||||
|
|
||||||
|
|
||||||
class TestWorkplaneList(unittest.TestCase):
|
class TestWorkplaneList(unittest.TestCase):
|
||||||
|
|
@ -366,8 +367,8 @@ class TestWorkplaneList(unittest.TestCase):
|
||||||
self.assertTrue(plane == Plane.YZ)
|
self.assertTrue(plane == Plane.YZ)
|
||||||
|
|
||||||
def test_localize(self):
|
def test_localize(self):
|
||||||
with Workplanes(Plane.YZ):
|
with BuildLine(Plane.YZ):
|
||||||
pnts = Workplanes._get_context().localize((1, 2), (2, 3))
|
pnts = WorkplaneList.localize((1, 2), (2, 3))
|
||||||
self.assertTupleAlmostEquals(pnts[0].to_tuple(), (0, 1, 2), 5)
|
self.assertTupleAlmostEquals(pnts[0].to_tuple(), (0, 1, 2), 5)
|
||||||
self.assertTupleAlmostEquals(pnts[1].to_tuple(), (0, 2, 3), 5)
|
self.assertTupleAlmostEquals(pnts[1].to_tuple(), (0, 2, 3), 5)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -214,10 +214,10 @@ class BuildLineTests(unittest.TestCase):
|
||||||
bl.solids()
|
bl.solids()
|
||||||
|
|
||||||
def test_no_applies_to(self):
|
def test_no_applies_to(self):
|
||||||
with self.assertRaises(RuntimeError):
|
# with self.assertRaises(RuntimeError):
|
||||||
BuildLine._get_context(
|
# BuildLine._get_context(
|
||||||
Compound.make_compound([Face.make_rect(1, 1)]).wrapped
|
# Compound.make_compound([Face.make_rect(1, 1)]).wrapped
|
||||||
)
|
# )
|
||||||
with self.assertRaises(RuntimeError):
|
with self.assertRaises(RuntimeError):
|
||||||
Line((0, 0), (1, 1))
|
Line((0, 0), (1, 1))
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -87,9 +87,8 @@ class TestBuildPart(unittest.TestCase):
|
||||||
with BuildPart() as test:
|
with BuildPart() as test:
|
||||||
Box(10, 10, 10)
|
Box(10, 10, 10)
|
||||||
self.assertEqual(len(test.faces()), 6)
|
self.assertEqual(len(test.faces()), 6)
|
||||||
with Workplanes(test.faces().filter_by(Axis.Z)[-1]):
|
with BuildSketch(test.faces().filter_by(Axis.Z)[-1]):
|
||||||
with BuildSketch():
|
Rectangle(5, 5)
|
||||||
Rectangle(5, 5)
|
|
||||||
Extrude(amount=5)
|
Extrude(amount=5)
|
||||||
self.assertEqual(len(test.faces()), 11)
|
self.assertEqual(len(test.faces()), 11)
|
||||||
self.assertEqual(len(test.faces(Select.LAST)), 6)
|
self.assertEqual(len(test.faces(Select.LAST)), 6)
|
||||||
|
|
@ -133,10 +132,9 @@ class TestBuildPart(unittest.TestCase):
|
||||||
def test_add_pending_faces(self):
|
def test_add_pending_faces(self):
|
||||||
with BuildPart() as test:
|
with BuildPart() as test:
|
||||||
Box(100, 100, 100)
|
Box(100, 100, 100)
|
||||||
with Workplanes(*test.faces()):
|
with BuildSketch(*test.faces()):
|
||||||
with BuildSketch():
|
with PolarLocations(10, 5):
|
||||||
with PolarLocations(10, 5):
|
Circle(2)
|
||||||
Circle(2)
|
|
||||||
self.assertEqual(len(test.pending_faces), 30)
|
self.assertEqual(len(test.pending_faces), 30)
|
||||||
# self.assertEqual(sum([len(s.faces()) for s in test.pending_faces]), 30)
|
# self.assertEqual(sum([len(s.faces()) for s in test.pending_faces]), 30)
|
||||||
|
|
||||||
|
|
@ -182,10 +180,10 @@ class TestBuildPartExceptions(unittest.TestCase):
|
||||||
Sphere(10, mode=Mode.INTERSECT)
|
Sphere(10, mode=Mode.INTERSECT)
|
||||||
|
|
||||||
def test_no_applies_to(self):
|
def test_no_applies_to(self):
|
||||||
with self.assertRaises(RuntimeError):
|
# with self.assertRaises(RuntimeError):
|
||||||
BuildPart._get_context(
|
# BuildPart._get_context(
|
||||||
Compound.make_compound([Face.make_rect(1, 1)]).wrapped
|
# Compound.make_compound([Face.make_rect(1, 1)]).wrapped
|
||||||
)
|
# )
|
||||||
with self.assertRaises(RuntimeError):
|
with self.assertRaises(RuntimeError):
|
||||||
Box(1, 1, 1)
|
Box(1, 1, 1)
|
||||||
|
|
||||||
|
|
@ -289,9 +287,8 @@ class TestLoft(unittest.TestCase):
|
||||||
with BuildPart() as test:
|
with BuildPart() as test:
|
||||||
slice_count = 10
|
slice_count = 10
|
||||||
for i in range(slice_count + 1):
|
for i in range(slice_count + 1):
|
||||||
with Workplanes(Plane(origin=(0, 0, i * 3), z_dir=(0, 0, 1))):
|
with BuildSketch(Plane(origin=(0, 0, i * 3), z_dir=(0, 0, 1))):
|
||||||
with BuildSketch():
|
Circle(10 * sin(i * pi / slice_count) + 5)
|
||||||
Circle(10 * sin(i * pi / slice_count) + 5)
|
|
||||||
Loft()
|
Loft()
|
||||||
self.assertLess(test.part.volume, 225 * pi * 30, 5)
|
self.assertLess(test.part.volume, 225 * pi * 30, 5)
|
||||||
self.assertGreater(test.part.volume, 25 * pi * 30, 5)
|
self.assertGreater(test.part.volume, 25 * pi * 30, 5)
|
||||||
|
|
@ -427,18 +424,17 @@ class TestSweep(unittest.TestCase):
|
||||||
)
|
)
|
||||||
handle_path = handle_center_line.wires()[0]
|
handle_path = handle_center_line.wires()[0]
|
||||||
for i in range(segment_count + 1):
|
for i in range(segment_count + 1):
|
||||||
with Workplanes(
|
with BuildSketch(
|
||||||
Plane(
|
Plane(
|
||||||
origin=handle_path @ (i / segment_count),
|
origin=handle_path @ (i / segment_count),
|
||||||
z_dir=handle_path % (i / segment_count),
|
z_dir=handle_path % (i / segment_count),
|
||||||
)
|
)
|
||||||
):
|
) as section:
|
||||||
with BuildSketch() as section:
|
if i % segment_count == 0:
|
||||||
if i % segment_count == 0:
|
Circle(1)
|
||||||
Circle(1)
|
else:
|
||||||
else:
|
Rectangle(1, 2)
|
||||||
Rectangle(1, 2)
|
Fillet(*section.vertices(), radius=0.2)
|
||||||
Fillet(*section.vertices(), radius=0.2)
|
|
||||||
# Create the handle by sweeping along the path
|
# Create the handle by sweeping along the path
|
||||||
Sweep(multisection=True)
|
Sweep(multisection=True)
|
||||||
self.assertAlmostEqual(handle.part.volume, 54.11246334691092, 5)
|
self.assertAlmostEqual(handle.part.volume, 54.11246334691092, 5)
|
||||||
|
|
|
||||||
|
|
@ -141,10 +141,10 @@ class TestBuildSketchExceptions(unittest.TestCase):
|
||||||
Circle(10, mode=Mode.INTERSECT)
|
Circle(10, mode=Mode.INTERSECT)
|
||||||
|
|
||||||
def test_no_applies_to(self):
|
def test_no_applies_to(self):
|
||||||
with self.assertRaises(RuntimeError):
|
# with self.assertRaises(RuntimeError):
|
||||||
BuildSketch._get_context(
|
# BuildSketch._get_context(
|
||||||
Compound.make_compound([Face.make_rect(1, 1)]).wrapped
|
# Compound.make_compound([Face.make_rect(1, 1)]).wrapped
|
||||||
)
|
# )
|
||||||
with self.assertRaises(RuntimeError):
|
with self.assertRaises(RuntimeError):
|
||||||
Circle(1)
|
Circle(1)
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue