Group Examples
Axis and Length
This heatsink component could use fillets on the ends of the fins on the long ends. One way to accomplish this is to filter by length, sort by axis, and slice the result knowing how many edges to expect.
Setup
from build123d import *
with BuildPart() as fins:
with GridLocations(4, 6, 4, 4):
Box(2, 3, 10, align=(Align.CENTER, Align.CENTER, Align.MIN))
with BuildPart() as part:
Box(34, 48, 5, align=(Align.CENTER, Align.CENTER, Align.MAX))
with GridLocations(20, 27, 2, 2):
add(fins)
However, group_by can be used to first group all the edges by z-axis position and then
group again by length. In both cases, you can select the desired edges from the last group.
target = part.edges().group_by(Axis.Z)[-1].group_by(Edge.length)[-1]
fillet(target, .75)
Hole Area
Callables are available to group_by, like sort_by. Here, the first inner wire
is converted to a face and then that area is the grouping criteria to find the faces
with the largest hole.
Setup
from build123d import *
with BuildPart() as part:
Cylinder(10, 30, rotation=(90, 0, 0))
Cylinder(8, 40, rotation=(90, 0, 0), align=(Align.CENTER, Align.CENTER, Align.MAX))
Cylinder(8, 23, rotation=(90, 0, 0), align=(Align.CENTER, Align.CENTER, Align.MIN))
Cylinder(5, 40, rotation=(90, 0, 0), align=(Align.CENTER, Align.CENTER, Align.MIN))
with BuildSketch(Plane.XY.offset(8)) as s:
SlotCenterPoint((0, 38), (0, 48), 5)
extrude(amount=2.5, both=True, mode=Mode.SUBTRACT)
faces = part.faces().group_by(
lambda f: Face(f.inner_wires()[0]).area if f.inner_wires() else 0
)
chamfer([f.outer_wire().edges() for f in faces[-1]], 0.5)
Properties with Keys
Groups are usually selected by list slice, often smallest [0] or largest [-1],
but they can also be selected by key with the group method if the keys are known.
Starting with an incomplete bearing block we are looking to add fillets to the ribs
and corners. We know the edge lengths so the edges can be grouped by Edge.Length and
then the desired groups are selected with the group method using the lengths as keys.
Setup
from build123d import *
with BuildPart() as part:
with BuildSketch(Plane.XZ) as sketch:
with BuildLine():
CenterArc((-6, 12), 10, 0, 360)
Line((-16, 0), (16, 0))
make_hull()
Rectangle(50, 5, align=(Align.CENTER, Align.MAX))
extrude(amount=12)
Box(38, 6, 22, align=(Align.CENTER, Align.MAX, Align.MIN), mode=Mode.SUBTRACT)
circle = part.edges().filter_by(GeomType.CIRCLE).sort_by(Axis.Y)[0]
with Locations(Plane(circle.arc_center, z_dir=circle.normal())):
CounterBoreHole(13 / 2, 16 / 2, 4)
mirror(about=Plane.XZ)
length_groups = part.edges().group_by(Edge.length)
fillet(length_groups.group(6) + length_groups.group(5), 4)
Next, we add alignment pin and counterbore holes after the fillets to make sure
screw heads sit flush where they overlap the fillet. Once that is done, it's time to
finalize the tight-tolerance bearing and pin holes with chamfers to make installation
easier. We can filter by GeomType.CIRCLE and group by Edge.radius to group the
circular edges. Again, the radii are known, so we can retrieve those groups directly
and then further specify only the edges the bearings and pins are installed from.
Adding holes
with BuildSketch() as pins:
with Locations((-21, 0)):
Circle(3 / 2)
with Locations((21, 0)):
SlotCenterToCenter(1, 3)
extrude(amount=-12, mode=Mode.SUBTRACT)
with GridLocations(42, 16, 2, 2):
CounterBoreHole(3.5 / 2, 3.5, 0)
radius_groups = part.edges().filter_by(GeomType.CIRCLE).group_by(Edge.radius)
bearing_edges = radius_groups.group(8).group_by(SortBy.DISTANCE)[-1]
pin_edges = radius_groups.group(1.5).filter_by_position(Axis.Z, -5, -5)
chamfer([pin_edges, bearing_edges], .5)
Note that group_by is not the only way to capture edges with a known property
value! filter_by with a lambda expression can be used as well:
radius_groups = part.edges().filter_by(GeomType.CIRCLE)
bearing_edges = radius_groups.filter_by(lambda e: e.radius == 8)
pin_edges = radius_groups.filter_by(lambda e: e.radius == 1.5)