extrude_until improvement - extrude examples

This commit is contained in:
Roger Maitland 2023-01-14 16:01:53 -05:00
parent 15395573ea
commit 1fb55a299e
3 changed files with 138 additions and 40 deletions

View file

@ -54,43 +54,41 @@ with BuildPart() as non_planar:
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().sort_by(Axis.Z)[0], 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
# See: https://www.cherrymx.de/en/dev.html
with BuildPart() as key_cap:
# Start with the plan of the key cap and extrude it
with BuildSketch() as plan:
Rectangle(18 * MM, 18 * MM)
Extrude(amount=10 * MM, taper=15)
# Create a dished top
with Locations((0, -3 * MM, 47 * MM)):
Sphere(40 * MM, mode=Mode.SUBTRACT, rotation=(90, 0, 0))
# Fillet all the edges except the bottom
Fillet(
*key_cap.edges().filter_by_position(
Axis.Z, 0, 30 * MM, inclusive=(False, True)
),
radius=1 * MM,
)
# Hollow out the key by subtracting a scaled version
Scale(by=(0.925, 0.925, 0.85), mode=Mode.SUBTRACT)
# Add supporting ribs while leaving room for switch activation rad, rev = 3, 25
with Workplanes(Plane(origin=(0, 0, 4 * MM))):
with BuildSketch(): # Extrude last
Rectangle(15 * MM, 0.5 * MM) with BuildPart() as ex26:
Rectangle(0.5 * MM, 15 * MM) with BuildSketch() as ex26_sk:
Circle(radius=5.51 * MM / 2) with Locations((0, rev)):
# Extrude the mount and ribs to the key cap underside Circle(rad)
Extrude(until=Until.NEXT) Revolve(axis=Axis.X, revolution_arc=90)
# Find the face on the bottom of the ribs to build onto Mirror(about=Plane.XZ)
rib_bottom = key_cap.faces().filter_by_position(Axis.Z, 4 * MM, 4 * MM)[0] with BuildSketch() as ex26_sk2:
# Add the switch socket Rectangle(rad, rev)
with Workplanes(rib_bottom): ex26_target = ex26.part
with BuildSketch() as cruciform: Extrude(until=Until.LAST, mode=Mode.REPLACE)
Circle(radius=5.5 * MM / 2)
Rectangle(4.1 * MM, 1.17 * MM, mode=Mode.SUBTRACT) # Extrude next
Rectangle(1.17 * MM, 4.1 * MM, mode=Mode.SUBTRACT) with BuildPart() as ex27:
Extrude(amount=3.5 * MM, mode=Mode.ADD) with BuildSketch():
with Locations((0, rev)):
Circle(rad)
Revolve(axis=Axis.X, revolution_arc=90)
with BuildSketch(Plane.XZ):
with Locations((0, rev)):
Circle(rad)
Revolve(axis=Axis.X, revolution_arc=150)
with BuildSketch(Plane.XY.offset(-60)):
Rectangle(rad, rev + 25)
extrusion27 = Extrude(until=Until.NEXT, mode=Mode.ADD)
# Extrude next both
with BuildPart() as ex28:
Torus(25, 5, rotation=(0, 90, 0))
with BuildSketch():
Rectangle(rad, rev)
extrusion28 = Extrude(until=Until.NEXT, both=True)
if "show_object" in locals(): if "show_object" in locals():
show_object( show_object(
@ -101,4 +99,30 @@ if "show_object" in locals():
multiple.part.translate((0, -20, 0)).wrapped, name="multiple pending extrude" multiple.part.translate((0, -20, 0)).wrapped, name="multiple pending extrude"
) )
show_object(non_planar.part.translate((20, -10, 0)).wrapped, name="non planar") show_object(non_planar.part.translate((20, -10, 0)).wrapped, name="non planar")
show_object(key_cap.part.wrapped, name="key cap", options={"alpha": 0.7}) show_object(
ex26_target.translate((-40, 0, 0)).wrapped,
name="extrude until last target",
options={"alpha": 0.8},
)
show_object(
ex26.part.translate((-40, 0, 0)).wrapped,
name="extrude until last",
)
show_object(
ex27.part.rotate(Axis.Z, 90).translate((0, 50, 0)).wrapped,
name="extrude until next target",
options={"alpha": 0.8},
)
show_object(
extrusion27.rotate(Axis.Z, 90).translate((0, 50, 0)).wrapped,
name="extrude until next",
)
show_object(
ex28.part.rotate(Axis.Z, -90).translate((0, -50, 0)).wrapped,
name="extrude until next both target",
options={"alpha": 0.8},
)
show_object(
extrusion28.rotate(Axis.Z, -90).translate((0, -50, 0)).wrapped,
name="extrude until next both",
)

69
examples/key_cap.py Normal file
View file

@ -0,0 +1,69 @@
"""
name: key_cap.py
by: Gumyr
date: September 20th 2022
desc:
This example demonstrates the design of a Cherry MX key cap by using
extrude with a taper and extrude until next.
See: https://www.cherrymx.de/en/dev.html
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 *
with BuildPart() as key_cap:
# Start with the plan of the key cap and extrude it
with BuildSketch() as plan:
Rectangle(18 * MM, 18 * MM)
Extrude(amount=10 * MM, taper=15)
# Create a dished top
with Locations((0, -3 * MM, 47 * MM)):
Sphere(40 * MM, mode=Mode.SUBTRACT, rotation=(90, 0, 0))
# Fillet all the edges except the bottom
Fillet(
*key_cap.edges().filter_by_position(
Axis.Z, 0, 30 * MM, inclusive=(False, True)
),
radius=1 * MM,
)
# Hollow out the key by subtracting a scaled version
Scale(by=(0.925, 0.925, 0.85), mode=Mode.SUBTRACT)
# Add supporting ribs while leaving room for switch activation
with Workplanes(Plane(origin=(0, 0, 4 * MM))):
with BuildSketch():
Rectangle(15 * MM, 0.5 * MM)
Rectangle(0.5 * MM, 15 * MM)
Circle(radius=5.5 * MM / 2)
# Extrude the mount and ribs to the key cap underside
Extrude(until=Until.NEXT)
# 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]
# Add the switch socket
with Workplanes(rib_bottom):
with BuildSketch() as cruciform:
Circle(radius=5.5 * MM / 2)
Rectangle(4.1 * MM, 1.17 * MM, mode=Mode.SUBTRACT)
Rectangle(1.17 * MM, 4.1 * MM, mode=Mode.SUBTRACT)
Extrude(amount=3.5 * MM, mode=Mode.ADD)
if "show_object" in locals():
show_object(key_cap.part.wrapped, name="key cap", options={"alpha": 0.7})

View file

@ -2155,6 +2155,7 @@ class Shape(NodeMixin):
children (list[Shape], optional): assembly children - only valid for Compounds. children (list[Shape], optional): assembly children - only valid for Compounds.
Defaults to None. Defaults to None.
""" """
def __init__( def __init__(
self, self,
obj: TopoDS_Shape = None, obj: TopoDS_Shape = None,
@ -6509,6 +6510,7 @@ class Solid(Shape, Mixin3D):
Union[Compound, Solid]: extruded Face Union[Compound, Solid]: extruded Face
""" """
direction = Vector(direction) direction = Vector(direction)
direction_axis = Axis(section.center(), direction)
max_dimension = ( max_dimension = (
Compound.make_compound([section, target_object]) Compound.make_compound([section, target_object])
@ -6520,7 +6522,6 @@ class Solid(Shape, Mixin3D):
if until == Until.NEXT if until == Until.NEXT
else -direction * max_dimension else -direction * max_dimension
) )
# Create a linear extrusion to start # Create a linear extrusion to start
extrusion = Solid.extrude_linear(section, direction * max_dimension) extrusion = Solid.extrude_linear(section, direction * max_dimension)
@ -6537,7 +6538,7 @@ class Solid(Shape, Mixin3D):
# Create the objects that will clip the linear extrusion # Create the objects that will clip the linear extrusion
clipping_objects = [ clipping_objects = [
Solid.extrude_linear(f, clipping_direction) for f in clip_faces Solid.extrude_linear(f, clipping_direction).fix() for f in clip_faces
] ]
if until == Until.NEXT: if until == Until.NEXT:
@ -6547,7 +6548,11 @@ class Solid(Shape, Mixin3D):
# thus they could be non manifold which results failed boolean operations # thus they could be non manifold which results failed boolean operations
# - so skip these objects # - so skip these objects
try: try:
extrusion = extrusion.cut(clipping_object) extrusion = (
extrusion.cut(clipping_object)
.solids()
.sort_by(direction_axis)[0]
)
except: except:
warnings.warn("clipping error - extrusion may be incorrect") warnings.warn("clipping error - extrusion may be incorrect")
else: else: