Basic Shapes
Utility functions for creating and manipulating basic 3D shapes and geometric calculations. These functions extend build123d's capabilities with shapes and operations commonly used in 3D design.
Geometric Calculation
adjacent_length
def adjacent_length(angle: float, opposite_length: float) -> float
Calculates the adjacent side length of a right triangle given the angle and opposite side length.
Arguments:
- angle (float): The angle in degrees
- opposite_length (float): The length of the opposite side
Returns:
- float: The length of the adjacent side
apothem_to_radius
def apothem_to_radius(apothem: float, side_count: int = 6) -> float
Arguments
- apothem (float): The apothem of the polygon
- side_count (float): The number of sides of the poygon.
Returns:
- float: The radius of the polygon
circular_intersection
circular_intersection(radius: float, coordinate: float) -> float
calculates the circumradius of a regular polygon given its apothem
Finds the intersection point along one axis given a coordinate on the other axis of a circle's perimeter.
Arguments:
- radius (float): The radius of the circle
- coordinate (float): A coordinate along one axis (must be positive and less than radius)
Returns:
- float: The intersection coordinate on the other axis
Raises:
- ValueError: If coordinate is greater than radius or negative
distance_to_circle_edge
distance_to_circle_edge(radius: float, point: tuple, angle: float) -> float
Calculates the distance from a given point to the edge of a circle in a specified direction.
Arguments:
- radius (float): The radius of the circle
- point (tuple): The starting point (x, y)
- angle (float): The direction angle in degrees
Returns:
- float: Distance to the circle edge
Raises:
- ValueError: If the discriminant is negative (no intersection)
opposite_length
def opposite_length(angle: float, adjacent_length: float) -> float
Calculates the opposite side length of a right triangle given the angle and adjacent side length.
Arguments:
- angle (float): The angle in degrees
- adjacent_length (float): The length of the adjacent side
Returns:
- float: The length of the opposite side
radius_to_appothem
def radius_to_appothem(radius: float, side_count: int = 6) -> float
Arguments:
- radius (float): the radius of the polygon
- side_count (float): the number of sides of the polygon
Returns:
- float: The apothem of the polygon
Part Generaction
diamond_cylinder
diamond_cylinder(
radius: float,
height: float,
rotation: tuple = (0, 0, 0),
align: tuple = (Align.CENTER, Align.CENTER, Align.CENTER),
stretch: tuple = (1, 1, 1)
) -> Part
Creates an extruded diamond (4-sided polygon) that behaves like a cylinder. This is a convenience wrapper for polygonal_cylinder with 4 sides.
Arguments:
- radius (float): The radius of the circumscribed circle
- height (float): The height of the extrusion
- rotation (tuple, default=(0, 0, 0)): Rotation angles (X, Y, Z) in degrees
- align (tuple, default=(Align.CENTER, Align.CENTER, Align.CENTER)): Alignment
- stretch (tuple, default=(1, 1, 1)): Scaling factors (X, Y, Z)
Returns:
- Part: The diamond cylinder
diamond_torus
diamond_torus(
major_radius: float,
minor_radius: float,
stretch: tuple = (1, 1)
) -> Part
Creates a torus by sweeping a diamond (square rotated 45°) along a circular path.
Arguments:
- major_radius (float): The radius of the circular sweep path
- minor_radius (float): The radius of the diamond cross-section
- stretch (tuple, default=(1, 1)): Scaling factors for the diamond shape
Returns:
- Part: The diamond torus
half_part
half_part(
base_part: Part,
cut_alignment: tuple[Align, Align, Align] = (Align.MAX, Align.CENTER, Align.CENTER)
) -> Part
Cuts a part in half along the X axis, useful for creating cross-section views when debugging designs.
Arguments:
- base_part (Part): The part to cut in half
- cut_alignment (tuple, default=(Align.MAX, Align.CENTER, Align.CENTER)): Alignment for the cutting box
Returns:
- Part: The halved part
heatsink_insert_cut
heatsink_insert_cut(
head_radius: float = 3,
head_depth: float = 5,
shaft_radius: float = 2.1,
shaft_length: float = 20
) -> Part
Creates a cutout template for a heatsink and bolt assembly.
Arguments:
- head_radius (float, default=3): Radius of the heatsink head
- head_depth (float, default=5): Depth of the heatsink head cutout
- shaft_radius (float, default=2.1): Radius of the bolt shaft
- shaft_length (float, default=20): Length of the bolt shaft
Returns:
- Part: The heatsink cutout geometry
nut_cut
nut_cut(
head_radius: float = 3,
head_depth: float = 5,
shaft_radius: float = 2.1,
shaft_length: float = 20
) -> Part
Creates a cutout template for a hexagonal nut and bolt assembly.
Arguments:
- head_radius (float, default=3): Radius of the hexagonal nut
- head_depth (float, default=5): Depth of the nut cutout
- shaft_radius (float, default=2.1): Radius of the bolt shaft
- shaft_length (float, default=20): Length of the bolt shaft
Returns:
- Part: The nut cutout geometry
polygonal_cylinder
polygonal_cylinder(
radius: float,
height: float,
sides: int = 6,
rotation: tuple = (0, 0, 0),
align: tuple = (Align.CENTER, Align.CENTER, Align.CENTER),
stretch: tuple = (1, 1, 1)
) -> Part
Creates an extruded regular polygon that behaves like a cylinder.
Arguments:
- radius (float): The radius of the circumscribed circle
- height (float): The height of the extrusion
- sides (int, default=6): Number of sides of the polygon
- rotation (tuple, default=(0, 0, 0)): Rotation angles (X, Y, Z) in degrees
- align (tuple, default=(Align.CENTER, Align.CENTER, Align.CENTER)): Alignment
- stretch (tuple, default=(1, 1, 1)): Scaling factors (X, Y, Z)
Returns:
- Part: The polygonal cylinder
rounded_cylinder
rounded_cylinder(
radius: float,
height: float,
align: tuple = (Align.CENTER, Align.CENTER, Align.CENTER)
) -> Part
Creates a cylinder with rounded (filleted) top and bottom edges.
Arguments:
- radius (float): The radius of the cylinder
- height (float): The height of the cylinder (must be > radius * 2)
- align (tuple, default=(Align.CENTER, Align.CENTER, Align.CENTER)): Alignment of the cylinder
Returns:
- Part: The rounded cylinder
Raises:
- ValueError: If height is not greater than radius * 2
screw_cut
screw_cut(
head_radius: float = 4.5,
head_sink: float = 1.4,
shaft_radius: float = 2.25,
shaft_length: float = 20,
bottom_clearance: float = 20
) -> Part
Creates a cutout template for a countersunk screw with tapered head transition.
Arguments:
- head_radius (float, default=4.5): Radius of the screw head (must be > shaft_radius)
- head_sink (float, default=1.4): Depth of the countersunk head
- shaft_radius (float, default=2.25): Radius of the screw shaft
- shaft_length (float, default=20): Length of the screw shaft
- bottom_clearance (float, default=20): Additional clearance below the head
Returns:
- Part: The screw cutout geometry
Raises:
- ValueError: If head_radius is not larger than shaft_radius
teardrop_cylinder
teardrop_cylinder(
radius: float,
peak_distance: float,
height: float,
rotation: RotationLike = (0, 0, 0),
align: Align | tuple[Align, Align, Align] = (Align.CENTER, Align.CENTER, Align.CENTER),
mode: Mode = Mode.ADD
)
Creates a 3D teardrop-shaped cylinder by extruding a teardrop sketch. Particularly useful for creating holes that print well on FDM printers without supports.
Arguments:
- radius (float): The radius of the circular portion
- peak_distance (float): Distance from circle center to the teardrop peak
- height (float): Height of the extrusion
- rotation (tuple, default=(0, 0, 0)): Rotation angles (X, Y, Z)
- align (tuple, default=(Align.CENTER, Align.CENTER, Align.CENTER)): Alignment
- mode (Mode, default=Mode.ADD): Build mode
Returns:
- Part: The teardrop cylinder
teardrop_sketch
teardrop_sketch(
radius: float,
peak_distance: float,
align: Align | tuple[Align, Align] = (Align.CENTER, Align.CENTER)
) -> Sketch
Creates a 2D teardrop-shaped sketch, useful for 3D printing holes that minimize overhangs.
Arguments:
- radius (float): The radius of the circular portion
- peak_distance (float): Distance from circle center to the teardrop peak
- align (tuple, default=(Align.CENTER, Align.CENTER)): Alignment of the teardrop
Returns:
- Sketch: The teardrop sketch
Examples
from fb_library.basic_shapes import (
rounded_cylinder,
diamond_torus,
teardrop_cylinder,
screw_cut,
half_part,
opposite_length,
adjacent_length
)
from build123d import BuildPart, Mode
# Create a rounded cylinder
rounded_cyl = rounded_cylinder(radius=10, height=30)
# Create a diamond torus
torus = diamond_torus(major_radius=20, minor_radius=3)
# Create a teardrop hole for 3D printing
with BuildPart() as part:
rounded_cylinder(radius=15, height=10)
teardrop_cylinder(
radius=5,
peak_distance=6,
height=15,
mode=Mode.SUBTRACT
)
# Create a screw cutout
screw_hole = screw_cut(
head_radius=5,
head_sink=2,
shaft_radius=2.5,
shaft_length=25
)
# Calculate triangle dimensions
opp = opposite_length(30, 10) # Given 30° angle and adjacent side of 10
adj = adjacent_length(45, 5) # Given 45° angle and opposite side of 5
# Create a cross-section view
cross_section = half_part(part.part)
Notes
- Many functions include 3D printing considerations (like teardrop shapes for overhangs)
- Cutout functions (heatsink_cut, nut_cut, screw_cut) are designed to be used with
Mode.SUBTRACT - The teardrop functions help create printable holes without supports on FDM printers
- Polygonal cylinders can be useful for creating hex bolts, nuts, or decorative elements