volmdlr_tools.shapes package#

Shape recognition and abstraction classes for CAD models.

Subpackages#

Submodules#

volmdlr_tools.shapes.base module#

Base classes for shape recognition and abstractions.

This module defines the base classes that all recognized shapes should inherit from, establishing a common interface for shape classification and feature extraction.

class volmdlr_tools.shapes.base.RecognizedShape(shape: Shape, aag: AttributedAdjacencyGraph, name: str = '')#

Bases: DessiaObject, ABC

Base class for all recognized shape abstractions.

A RecognizedShape represents a classified geometric shape that knows how to extract its own features based on its Attributed Adjacency Graph (AAG).

This class establishes the interface that all shape abstractions should follow: - Hold reference to the original volmdlr shape - Hold reference to the AAG for topological analysis - Implement validation logic - Implement feature extraction logic

abstractmethod extract_features() dict#

Extract all relevant features for this shape type.

This method should return a dictionary containing all the key features and parameters that characterize this shape type.

Returns:

Dictionary of features (structure depends on shape type)

get_aag() AttributedAdjacencyGraph#

Get the AttributedAdjacencyGraph.

Returns:

The AAG used for topological analysis

get_shape() Shape#

Get the underlying volmdlr shape.

Returns:

The original volmdlr shape

abstractmethod validate() bool#

Validate that this shape matches expected structure.

This method should check that the classified shape has the correct topological structure for its type (e.g., sheet metal has two sides separated by thickness faces).

Returns:

True if valid, False otherwise

volmdlr_tools.shapes.sheet_metal module#

Sheet metal shape abstraction.

This module defines the SheetMetalShape class, which represents a classified sheet metal part and knows how to extract sheet-metal-specific features like thickness, sides, and contours.

class volmdlr_tools.shapes.sheet_metal.FanShapedFace(face_id: int, inner_circular_edge: Any, inner_circular_edge_index: int, outer_circular_edge: Any, outer_circular_edge_index: int, thickness_edges: list[Any], arc_center: Any, normal: Any, angle: float)#

Bases: object

Represents a fan-shaped thickness face.

A fan-shaped face is planar and has: - Two concentric circular edges (inner and outer radius) - Two straight thickness edges connecting them

can_pair_with(other: FanShapedFace, aag: AttributedAdjacencyGraph) bool#

Check if this fan-shaped face can be paired with another.

According to Yang Yang et al., for faces fi and fj to be partners: 1. Face normals must be in opposite directions 2. Line connecting arc centers must be parallel to normals 3. Larger circular edges should be geometrically identical 4. Smaller circular edges should be geometrically identical

Parameters:
  • other – Another fan-shaped face to check pairing with

  • aag – The AttributedAdjacencyGraph for accessing face data

Returns:

True if faces can be paired

opposite_normal(other: FanShapedFace) bool#

Verify that two faces have the same but opposite normal vector.

Parameters:

other – other FanShapedFace.

Returns:

True if normals are opposite, False otherwise.

share_common_face(other: FanShapedFace, aag: AttributedAdjacencyGraph) bool#

Verify that two faces have the same common face.

Parameters:
  • other – other FanShapedFace.

  • aag – AttributedAdjacencyGraph containing corresponding faces.

Returns:

True if common face was found, False otherwise.

class volmdlr_tools.shapes.sheet_metal.SheetMetalShape(shape: Shape, aag: AttributedAdjacencyGraph, main_face_group_1: list[int], main_face_group_2: list[int], thickness_faces: list[int], thickness_components: list[set[int]] | list[ThicknessFaceChain], seed_face_id: int, opposite_face_id: int, name: str = '')#

Bases: RecognizedShape

Sheet metal shape abstraction.

Represents a classified sheet metal part and knows how to extract sheet-metal-specific features like thickness, sides, and contours.

This class is the result of SheetMetalRecognizer.recognize() and contains all the information needed to query features and parameters of the sheet metal.

property boundary_chain: ThicknessFaceChain#

Get the boundary thickness face chain object.

Returns the ThicknessFaceChain classified as boundary based on range values.

Returns:

Boundary ThicknessFaceChain or None if not found.

extract_features() dict#

Extract all sheet metal features at once.

Returns:

Dictionary containing all extracted features

get_boundary_thickness_shell() Shell | None#

Get boundary thickness facecc chain as a single Shell.

Creates a shell from all boundary thickness faces (outer boundary faces). Uses the cached boundary_thickness_face_chain property.

Returns:

Shell containing all boundary thickness faces, or None if creation fails

get_internal_thickness_shells() list[Shell]#

Get internal thickness faces as a list of Shells.

Creates a shell for each connected component of internal thickness faces (faces around holes, cutouts, and other internal features). Uses the cached internal_thickness_faces property.

Returns:

List of shells, one for each internal thickness component

get_side_1_aag() AttributedAdjacencyGraph | None#

Create AAG for side 1 from its shell.

Returns:

AttributedAdjacencyGraph for side 1, or None if creation fails

get_side_1_areas() dict[int, float]#

Get areas for all faces in side 1.

Returns:

Dictionary mapping face IDs to their areas

get_side_1_contours() dict#

Get contours for side 1.

Uses cached contours if available, otherwise computes and caches them.

Returns:

Dictionary containing outer and inner contours

get_side_1_shell() Shell | None#

Get side 1 as a Shell.

Returns:

Shell containing all faces from side 1, or None if creation fails

get_side_1_total_area() float#

Get total area of side 1.

Sums the areas of all faces in side 1.

Returns:

Total area of side 1

Return type:

float

get_side_2_aag() AttributedAdjacencyGraph | None#

Create AAG for side 2 from its shell.

Returns:

AttributedAdjacencyGraph for side 2, or None if creation fails

get_side_2_areas() dict[int, float]#

Get areas for all faces in side 2.

Returns:

Dictionary mapping face IDs to their areas

get_side_2_contours() dict#

Get contours for side 2.

Uses cached contours if available, otherwise computes and caches them.

Returns:

Dictionary containing outer and inner contours

get_side_2_shell() Shell | None#

Get side 2 as a Shell.

Returns:

Shell containing all faces from side 2, or None if creation fails

get_side_2_total_area() float#

Get total area of side 2.

Sums the areas of all faces in side 2.

Returns:

Total area of side 2

Return type:

float

get_thickness() float | None#

Calculate sheet metal thickness.

The rigorous method identifies boundary thickness faces (those connected to the outer contour) and measures the length of edges shared between them, which represents the actual sheet metal thickness. Falls back to seed-opposite distance if needed.

Returns:

Thickness value or None if calculation fails

get_thickness_aag() AttributedAdjacencyGraph | None#

Create AAG for thickness faces.

Returns:

AttributedAdjacencyGraph for thickness faces, or None if creation fails

get_thickness_faces_areas() dict[int, float]#

Get areas for all thickness faces.

Returns:

Dictionary mapping face IDs to their areas

get_thickness_faces_compound() Compound | None#

Get thickness faces as a Compound of shells.

Creates a compound containing the boundary thickness shell and all internal thickness shells.

Returns:

Compound of shells, or None if creation fails

property internal_chains: list[ThicknessFaceChain]#

Get all internal thickness face chain objects.

Returns list of ThicknessFaceChain objects classified as internal based on range values.

Returns:

List of internal ThicknessFaceChain objects

property main_faces: list[int]#

Get all main face IDs from both sides.

Combines face IDs from main_face_group_1 and main_face_group_2.

Returns:

List of all main face IDs

Return type:

list[int]

validate() bool#

Validate sheet metal structure.

Checks that removing thickness faces creates exactly two connected components (the two main sides).

Returns:

True if valid sheet metal structure, False otherwise

static validate_sheet_metal_structure(aag: AttributedAdjacencyGraph, thickness_faces: list[int], main_faces: list[int]) bool#

Validate sheet metal structure (static validation logic).

Checks that removing thickness faces creates exactly two connected components (the two main sides).

Parameters:
  • aag – The attributed adjacency graph

  • thickness_faces – List of thickness face IDs

  • main_faces – List of main face IDs

Returns:

True if valid sheet metal structure, False otherwise

class volmdlr_tools.shapes.sheet_metal.TFCGroup(thickness_face_chains: list[ThicknessFaceChain], name: str = '')#

Bases: DessiaObject

Group of ThicknessFaceChain objects for feature analysis.

A TFCGroup represents a collection of ThicknessFaceChain objects that are grouped together for feature recognition and property extraction. This class provides methods to aggregate fan-shaped faces, count parallel planar pairs, and extract properties for matching against feature classification rules (cut features, composite features, etc.).

extract_composite_feature_properties() dict[str, Any]#

Extract properties for matching against composite feature rules.

Properties correspond to Table 2 from Yang Yang et al. (2021): - internal_chains: Number of internal thickness face chains - boundary_subchains: Number of boundary sub-chains - fan_shaped_faces: Number of fan-shaped faces - fan_shaped_pairs: Number of fan-shaped face pairs - share_common_face: Do fan-shaped pairs share a common face? - opposite_normals: Are normals in opposite directions? - d1_greater_d2: Is flat part width > deformed part width?

Returns:

Dictionary of properties

Return type:

dict[str, Any]

extract_cut_feature_properties() dict[str, Any]#

Extract properties for matching against cut feature rules.

Properties correspond to Table 1 from Yang Yang et al. (2021): - type_of_chain: “Closed” or “Open” - total_faces: Total number of faces in chain - cylindrical_surfaces: Count of cylindrical faces - different_radius_values: Number of distinct radii in cylindrical faces - planar_surfaces: Count of planar faces - parallel_planar_pairs: Number of parallel planar face pairs

Returns:

Dictionary of properties

Return type:

dict

get_fan_shaped_faces() list[FanShapedFace]#

Get all fan-shaped faces from all thickness face chains in the group.

Aggregates fan-shaped faces from each ThicknessFaceChain in the group.

Returns:

List of all FanShapedFace objects from all chains

Return type:

list[FanShapedFace]

get_fan_shaped_pairs() list[tuple[FanShapedFace, FanShapedFace]]#

Get all fan-shaped face pairs from the group.

If the group contains only one ThicknessFaceChain, returns pairs from that chain. Otherwise, aggregates all fan-shaped faces from all chains and pairs them according to the pairing criteria (opposite normals, common face, etc.).

Returns:

List of tuples containing paired FanShapedFace objects

Return type:

list[tuple[FanShapedFace, FanShapedFace]]

property parallel_count: tuple[int, set[float]]#

Get the count of parallel planar pairs and their distances.

Returns a tuple containing: - The number of parallel planar face pairs - A set of distances between parallel pairs

Returns:

Tuple of (pair_count, distances_set)

Return type:

tuple[int, set[float]]

class volmdlr_tools.shapes.sheet_metal.ThicknessFaceChain(face_ids: list[int], aag: AttributedAdjacencyGraph, is_closed: bool | None = True, is_internal_chain: bool | None = False, is_fsf_neighbor: bool | None = False, name: str | None = None)#

Bases: DessiaObject

Base class representing a chain of thickness faces.

A thickness face chain is a group of connected thickness faces. According to Yang Yang et al. (2021), thickness face chains are the fundamental building blocks for sheet metal feature recognition.

property adjacency_map: dict[int, list[int]]#

Get adjacency relationships between faces in the chain.

Returns:

Dictionary mapping face_id -> list of adjacent face_ids in chain

all_angles_concave() bool#

Check if all angles between consecutive faces are concave.

Returns:

True if all angles are concave

Return type:

bool

all_angles_convex() bool#

Check if all angles between consecutive faces are convex.

Returns:

True if all angles are convex

Return type:

bool

property angles: dict#

Extract angle data between consecutive faces.

Returns:

Dictionary mapping (face_id1, face_id2) -> angle data

Return type:

dict

binary_pattern_contains(pattern: list[int]) bool#

Check if binary pattern contains the given pattern as a subsequence.

Parameters:

pattern (list[int]) – Pattern to find (e.g., [0, 1])

Returns:

True if pattern is found

Return type:

bool

static extract_deform_feature_properties(termination_criterion: int, inner_loop_shape: str) dict#

Extract properties for matching against deform feature rules.

Properties correspond to Table 3 from Yang Yang et al. (2021): - has_interconnected_faces: Are faces interconnected? - termination_criterion: Which criterion terminated extraction (1 or 2) - inner_loop_shape: Shape of the inner loop (e.g., “Circular”, “Rectangular”)

Parameters:
  • termination_criterion (int) – Termination criterion used (1 or 2)

  • inner_loop_shape (str) – Shape of the inner loop

Returns:

Dictionary of properties

Return type:

dict

extract_fsf_subchains() list[ThicknessFaceChain]#

Extract feature sub-chains from binary representation of fan-shaped faces.

According to Yang Yang et al. (Section 3.2.1), the binary matrix encodes fan-shaped face pairs where: - 0 = starting face of a pair - 1 = partner face of that pair

Returns:

List of sub-chains, where each sub-chain contains all face IDs (including non-fan-shaped faces) between the start and end

Return type:

list[list[int]]

property fan_shaped_faces_paths: dict[tuple[int, int], tuple[list[int], list[int]]]#

Get the fan-shaped faces paths dictionary.

Returns a copy of the paths dictionary to prevent external modification.

Returns:

Dictionary mapping face ID tuples to path tuples (shortest_path, longest_path)

Return type:

dict[tuple[int, int], tuple[list[int], list[int]]]

property fsf_binary_representation: list[list[int]]#

Generate binary representation matrices for fan shaped faces.

According to Yang Yang et al., the algorithm: 1. For each fan-shaped pair, find faces between them in both directions 2. Keep the shorter list for each pair 3. Select the longest of these shorter lists (ensures not starting in middle) 4. Create second list from remaining faces by traversing in opposite direction 5. Assign binary values: 0 for starting face, 1 for partner face

The binary patterns are used to classify bend/jog/lance features. Example patterns from paper (Fig. 6): - Matrix 1: [0 0 0 1 1 1 1] (contains pairs 1, 2, 3, 4) - Matrix 2: [0 0 1 1 0 1] (contains remaining pairs)

Returns:

List of binary matrices (typically 2, one for each direction)

get_concave_subchains() list[ThicknessFaceChain]#

Extract sub-chains with concave angles using the concavity method.

According to Yang Yang et al. (Section 3.2.2), concave angles indicate features like slots, notches, and corner reliefs. This method identifies consecutive faces connected by concave angles.

Returns:

List of ThicknessFaceChain sub-chains with concave angles

Return type:

list[ThicknessFaceChain]

get_convex_subchains() list[list[int]]#

Extract clip sub-chains using the convexity method.

Example from paper:

fi – fj – fk Where fj is a clip if both angles (fi-fj and fj-fk) are convex and within the range (π/2, π).

Returns:

List of clip sub-chains, where each sub-chain contains a single face ID

Return type:

list[list[int]]

get_fan_shaped_faces() list[FanShapedFace]#

Identify all fan-shaped faces in the chain.

According to Yang Yang et al., a fan-shaped thickness face: - Must be planar - Must have two concentric circular edges - Must have two thickness edges - Solid angles between edges must be < 180°

Returns:

List of FanShapedFace objects

get_fan_shaped_faces_path(key: tuple[int, int]) tuple[list[int], list[int]]#

Get the fan-shaped faces path for a given key.

Parameters:

key (tuple[int, int]) – Tuple of (start_face_id, end_face_id) identifying the path

Returns:

Tuple containing (shortest_path, longest_path) as lists of face IDs

Return type:

tuple[list]

Raises:

KeyError – If no path exists for the given key

get_fan_shaped_pairs(max_angle: float = 3.141592653589793) list[tuple[FanShapedFace, FanShapedFace]]#

Identify pairs of fan-shaped faces.

According to Yang Yang et al., fan-shaped faces form pairs that represent bend features. The pairing algorithm checks: 1. Normals in opposite directions 2. Arc centers connected by line parallel to normals 3. Circular edges are geometrically identical

Returns:

List of (face1, face2) pairs

get_main_fan_shaped_pair_lists() tuple[list[int], list[int]]#

Get the two main lists of fan-shaped faces for binary representation.

According to Yang Yang et al.: 1. For each pair, find the shorter path between them 2. Select the longest of these shorter paths (ensures not starting in middle) 3. Create second list from remaining faces in opposite direction

Returns:

Tuple of (first_list, second_list) of face IDs

get_range_values() tuple[float, float, float]#

Calculate range values for the chain.

Returns (X_range, Y_range, Z_range) where: X_range = X_max - X_min for all faces in chain

Used to classify boundary vs internal chains.

Returns:

Tuple of (x_range, y_range, z_range)

has_binary_pattern(pattern: list[int]) bool#

Check if binary pattern matches exactly.

Parameters:

pattern (list[int]) – Pattern to match (e.g., [0, 1] for bend)

Returns:

True if pattern matches

Return type:

bool

is_open_ended() bool#

Check if chain is open (not closed).

Returns:

True if open

Return type:

bool

is_single_face() bool#

Check if chain contains only a single face.

Returns:

True if only one face

Return type:

bool

is_small(max_faces: int = 3) bool#

Check if chain is small (few faces).

Parameters:

max_faces (int) – Maximum number of faces to be considered small

Returns:

True if face count <= max_faces

Return type:

bool

set_fan_shaped_faces(faces: list[FanShapedFace]) None#

Set the fan-shaped faces for this chain.

Parameters:

faces (list[FanShapedFace]) – List of FanShapedFace objects

Returns:

None

Return type:

None

set_fan_shaped_faces_path(key: tuple[int, int], value: tuple[list[int], list[int]]) None#

Set the fan-shaped faces path for a given key.

Parameters:
  • key (tuple[int, int]) – Tuple of (start_face_id, end_face_id) identifying the path

  • value (tuple[list[int], list[int]]) – Tuple containing (shortest_path, longest_path) as lists of face IDs

Returns:

None

Return type:

None

set_fan_shaped_pairs(face_pairs: list[tuple[FanShapedFace, FanShapedFace]]) None#

Set the fan-shaped face pairs for this chain.

Parameters:

face_pairs (list[tuple[FanShapedFace, FanShapedFace]]) – List of tuples containing paired FanShapedFace objects

Returns:

None

Return type:

None

property thickness: float | None#

Get thickness value for validating fan-shaped faces.

Calculates thickness by finding the length of common edges between neighboring faces in the chain. Returns the first non-zero edge length found.

Returns:

Thickness value or None if calculation fails

Return type:

Optional[float]

property thickness_shell: Shell#

Get the thickness shell for this chain.

Creates a Shell object from all faces in the chain. Caches the result for subsequent calls.

Returns:

Shell containing all faces in the chain

Return type:

shapes.Shell

verify_fan_shaped_pair_order(face1: FanShapedFace, face2: FanShapedFace) tuple[FanShapedFace, FanShapedFace]#

Verify and correct the order of fan-shaped face pairs.

Computes paths between the two faces and ensures they are ordered correctly based on their position in the chain. Stores the paths for later use.

Parameters:
Returns:

Tuple of (ordered_face1, ordered_face2)

Return type:

tuple[FanShapedFace, FanShapedFace]

volmdlr_tools.shapes.sheet_metal.are_faces_parallel(face1: Face, face2: Face, tolerance: float = 1e-06) bool#

Check if two faces are parallel.

Two faces are considered parallel if the vector connecting their centers is parallel to the normal of the first face (i.e., the dot product is approximately ±1).

Parameters:
  • face1 – First face to check

  • face2 – Second face to check

  • tolerance – Tolerance for parallel checks

Returns:

True if faces are parallel, False otherwise

Return type:

bool

volmdlr_tools.shapes.sheet_metal.get_face_normal(face: Shape) Vector3D#

Extract normal vector from a planar face.

Parameters:

face – Face object to extract normal from

Returns:

Normal vector as tuple (x, y, z) or None if extraction fails

Return type:

Optional[tuple[float, float, float]]

volmdlr_tools.shapes.sheet_metal.order_nodes_by_graph(nodes: list[int], subgraph: Graph) list[int]#

Orders a list of nodes according to their connectivity in the graph.

Works for both open paths and closed cycles.

Parameters:
  • nodes (list) – List of nodes to order

  • subgraph (networkx.Graph) – The graph containing the nodes

Returns:

Ordered list of nodes following the graph structure

Return type:

list

volmdlr_tools.shapes.bearing module#

Module dedicated to identifying bearings within an assembly.

class volmdlr_tools.shapes.bearing.Bearing(primitives: list[Shape], graph_assembly_repeating_elements_ids: list[int], graph_assembly_rings_ids: list[int], name: str = '')#

Bases: Compound

Bearing class.

class volmdlr_tools.shapes.bearing.BearingFinder(graph_assembly: GraphAssembly)#

Bases: object

Class to identify bearings within an assembly graph.

find_bearings(number_elements_define_bearing: int = 5) list[list[int]]#

Find all bearings in the assembly.

Returns:

list[list[str]]: List of bearing groups, where each group contains node IDs

of components that form a bearing.

Module contents#

Shape recognition and abstractions.