Sort Examples

SortBy

SortBy enums are shape property shorthands which work across Shape multiple object types. SortBy is a criteria for both sort_by and group_by.

  • SortBy.LENGTH works with Edge, Wire

  • SortBy.AREA works with Face, Solid

  • SortBy.VOLUME works with Solid

  • SortBy.RADIUS works with Edge, Face with GeomType CIRCLE, CYLINDER, SPHERE

  • SortBy.DISTANCE works Vertex, Edge, Wire, Face, Solid

SortBy is often interchangeable with specific shape properties and can alternatively be used with``group_by``.

Setup
from build123d import *

with BuildPart() as part:
    Box(5, 5, 1)
    Cylinder(2, 5)
    edges = part.edges().filter_by(lambda a: a.length == 1)
    fillet(edges, 1)
part.wires().sort_by(SortBy.LENGTH)[:4]

part.wires().sort_by(Wire.length)[:4]
part.wires().group_by(SortBy.LENGTH)[0]
../_images/sort_sortby_length.png

part.vertices().sort_by(SortBy.DISTANCE)[-2:]

part.vertices().sort_by_distance(Vertex())[-2:]
part.vertices().group_by(Vertex().distance)[-1]
../_images/sort_sortby_distance.png

Along Wire

Vertices selected from an edge or wire might have a useful ordering when created from a single object, but when created from multiple objects, the ordering not useful. For example, when applying incrementing fillet radii to a list of vertices from the face, the order is random.

Setup
from build123d import *

with BuildSketch() as along_wire:
    Rectangle(48, 16, align=Align.MIN)
    Rectangle(16, 48, align=Align.MIN)
    Rectangle(32, 32, align=Align.MIN)
    for i, v in enumerate(along_wire.vertices()):
        fillet(v, i + 1)
../_images/sort_not_along_wire.png

Vertices may be sorted along the wire they fall on to create order. Notice the fillet radii now increase in order.

    sorted_verts = along_wire.vertices().sort_by(along_wire.wire())
    for i, v in enumerate(sorted_verts):
        fillet(v, i + 1)
../_images/sort_along_wire.png

Axis

Sorting by axis is often the most straightforward way to optimize selections. In this part we want to revolve the face at the end around an inside edge of the completed extrusion. First, the face to extrude can be found by sorting along x-axis and the revolution edge can be found sorting along y-axis.

Setup
from build123d import *

with BuildPart() as part:
    with BuildSketch(Plane.YZ) as profile:
        with BuildLine():
            l1 = FilletPolyline((16, 0), (32, 0), (32, 25), radius=12)
            l2 = FilletPolyline((16, 4), (28, 4), (28, 15), radius=8)
            Line(l1 @ 0, l2 @ 0)
            Polyline(l1 @ 1, l1 @ 1 - Vector(2, 0), l2 @ 1 + Vector(2, 0), l2 @ 1)
        make_face()
    extrude(amount=34)
    face = part.faces().sort_by(Axis.X)[-1]
    edge = face.edges().sort_by(Axis.Y)[0]
    revolve(face, -Axis(edge), 90)
../_images/sort_axis.png

Distance From

A sort_by_distance can be used to sort objects by their distance from another object. Here we are sorting the boxes by distance from the origin, using an empty Vertex (at the origin) as the reference shape to find distance to.

Setup
from itertools import product

from build123d import *
from ocp_vscode import *

boxes = ShapeList(
    Box(1, 1, 1).scale(0.75 if (i, j) == (1, 2) else 0.25).translate((i, j, 0))
    for i, j in product(range(-3, 4), repeat=2)
)
boxes = boxes.sort_by_distance(Vertex())
show(*boxes, colors=ColorMap.listed(len(boxes)))
../_images/sort_distance_from_origin.png

The example can be extended by first sorting the boxes by volume using the Solid property volume, and getting the last (largest) box. Then, the boxes sorted by their distance from the largest box.

boxes = boxes.sort_by_distance(boxes.sort_by(Solid.volume).last)
show(*boxes, colors=ColorMap.listed(len(boxes)))
../_images/sort_distance_from_largest.png