Cavity Feature Recognition#

Detect pockets, slots and cut-outs, and read the dimensions a drawing states.

Note

Prerequisites: Attributed Adjacency Graph (AAG)

The CavityExtractor requires an Attributed Adjacency Graph (AAG) representation of the shape. If you’re new to AAG, start with the concepts documentation.

Cavity Feature Recognition#

A cavity is material removed through a face’s inner wire — a pocket, a slot, a cut-out. CavityExtractor finds them; Cavity.from_faces_and_nodes classifies each one by the shape of its walls, and the resulting object reports the dimensions a drawing states.

Cavity Types#

Classification reads the wall faces: the planar faces parallel to the cavity’s axis. Floors and lids are set aside first, so a blind cutout classifies the same way its through twin does.

RoundCavity#

A cylindrical cut-out, at most two faces, all cylindrical.

Key Properties:

  • diameter - Diameter of the widest cylindrical face, or None if there is none

  • axis / location - Direction and centre, or None

SquareCavity#

Four or more planar walls spanning two directions, with corners that may be sharp or rounded by cylindrical corner faces. Length and width are equal within 1e-6.

Key Properties:

  • length / width - The widest pair of opposite walls in each direction

  • corner_radius - Smallest corner rounding; 0.0 when any corner is sharp

RectangularCavity#

A SquareCavity whose length and width differ beyond the tolerance.

SlottedCavity#

Two parallel side walls closed off by cylindrical end caps. A plain slot has two caps; a keyhole slot carries more, of differing radii, so the face count is not fixed.

Key Properties:

  • end_circles - One EndCircle (centre and radius) per cylindrical end cap

  • center_distance - Centre-to-centre distance of the two extreme end circles (entraxe)

  • slot_length - center_distance plus both end radii (longueur totale), the quantity slot design rules are stated against

  • length - The bounding extent along the slot’s long direction. Coincides with slot_length on a clean slot; it is the one that still answers when a boundary is irregular

  • width - Twice the narrowest cap radius, the width the slot is constrained to

Parameters (All Cavity Types)#

Property

Type

Description

depth

float | None

Extent of the wall faces along the cavity axis. Excludes a planar floor or lid, so a blind cavity’s depth stops at the floor rather than being set by it

corner_radius

float | None

Smallest corner rounding of the cut-out; 0.0 when two walls of different directions touch

cavity_axis()

Vector3D | None

The axis the cutout runs along, read from the faces themselves

cavity_axis() is deliberately not the inherited axis, which comes from the oriented bounding box. The box’s third axis is not always the extrusion axis: on a 5 × 4 × 50 mm pocket it points across the width, and a depth measured along it answers 4 mm instead of 50.

Two Failure Contracts#

SlottedCavity keeps two conventions side by side, and it is worth knowing which is which:

  • The measured parameters — length, center_distance, slot_length, end_circles — answer None (or an empty list) when the slot is too degenerate to have them. A caller can read them across a mixed batch of cavities without guarding each one.

  • The cached dimensions — width, axis, location — raise ValueError when the slot exposes fewer than two cylindrical faces.

Using the Cavity Parameters#

from volmdlr_tools.features.core import FeatureProcessor
from volmdlr_tools.features.feature_types import RectangularCavity, SlottedCavity

processor = FeatureProcessor(shape=shape)
processor.extract_cavities()

for cavity in processor.cavities:
    print(f"{type(cavity).__name__}: depth={cavity.depth}")

    if isinstance(cavity, SlottedCavity):
        print(f"  slot length {cavity.slot_length}, centres {cavity.center_distance}")
        for end_circle in cavity.end_circles:
            print(f"  end circle r={end_circle.radius} at {end_circle.center}")

    if isinstance(cavity, RectangularCavity):
        print(f"  {cavity.length} x {cavity.width}, corners r={cavity.corner_radius}")

FeatureProcessor.cavities returns every Cavity subclass — the types are read off the class hierarchy, so a new subclass is picked up without editing a list.

See Also#

  • The project glossary (CONTEXT.md) defines end circle, center distance, slot length and depth in the vocabulary these properties are named for.

  • scripts/features/demo_cavity_parameters.py prints every parameter of the fixture plate against the literal its generator states.

See Also#