Rule Checking#
Verify geometric rules on assembly graphs, such as position constraints, distance thresholds, connection requirements, and proximity checks.
Note
Prerequisites: GraphAssembly
Tip
Tutorial Data File: test.stp
Position Rule#
Position Rule Check#
1"""Showcase of position rule checking using graph."""
2
3from pathlib import Path
4
5from volmdlr.model import VolumeModel
6
7from volmdlr_tools.graph.assembly import GraphAssembly
8
9STEP_FILE = Path(__file__).parent.parent.parent.parent.parent / "data" / "step" / "test.stp"
10
11# DEFINING OBJECTS
12volume_model = VolumeModel.from_step(str(STEP_FILE))
13# volume_model.display_3d()
14graph = GraphAssembly.from_volume_model(volume_model)
15# graph.plot()
16
17
18# RULE: Check that all the nuts are under the plate
19# Note: The plate is Solid named "PLATE" and the nuts are Solids named "NUT"
20TOLERANCE = 1e-6
21
22# Set the bounding box attribute for all the nodes that are Solid
23graph.set_nodes_attribute(
24 attribute="bounding_box",
25 attribute_function=lambda node: graph.get_shape(node).bounding_box,
26 filter_function=lambda node: graph[node]["class"] == "Solid",
27)
28
29# Retrieve the minimum altitude of the plate
30plate_id = next(iter(graph.get_nodes(filter_function=lambda node: graph[node]["name"] == "PLATE")))
31plate_min_altitude = graph[plate_id]["bounding_box"].zmin
32
33# Get the nodes with name "NUT" that are above the plate minimum altitude
34incorrect_nodes = graph.get_nodes(
35 filter_function=lambda node: graph[node]["name"] == "NUT"
36 and graph[node]["class"] == "Solid"
37 and graph[node]["bounding_box"].zmax - TOLERANCE > plate_min_altitude
38)
39
40if len(incorrect_nodes) == 0:
41 print("Rule #1: All the nuts are under the plate.")
42else:
43 print(f"Rule #1: The following nodes are above the plate: {incorrect_nodes.keys()}")
44 primitives = [graph.get_shape(node) for node in incorrect_nodes] + [graph.get_shape(plate_id)]
45 VolumeModel(primitives=primitives).display_3d()
Distance Rule#
Distance Rule Check#
1"""Showcase of distance rule checking using graph."""
2
3from pathlib import Path
4
5from volmdlr.model import VolumeModel
6
7from volmdlr_tools.graph.assembly import GraphAssembly
8
9STEP_FILE = Path(__file__).parent.parent.parent.parent.parent / "data" / "step" / "test.stp"
10
11# DEFINING OBJECTS
12volume_model = VolumeModel.from_step(str(STEP_FILE))
13# volume_model.display_3d()
14graph = GraphAssembly.from_volume_model(volume_model)
15# graph.plot()
16
17
18# RULE: Check if the bolts are at a minimum distance between each other
19# Note: The bolts are Solids named "BOLT"
20MIN_DISTANCE = 0.01
21
22# Create an edge between all the bolts
23graph.create_edges(filter_function=lambda edge: graph[edge[0]]["name"] == "BOLT" and graph[edge[1]]["name"] == "BOLT")
24
25# Set the distance attribute between all the bolts
26graph.set_edges_attribute(
27 attribute="distance",
28 attribute_function=lambda edge: graph.get_shape(edge[0]).distance(graph.get_shape(edge[1])),
29 filter_function=lambda edge: graph[edge[0]]["name"] == "BOLT" and graph[edge[1]]["name"] == "BOLT",
30)
31
32# Get the edges with distance less than 0.1
33incorrect_edges = graph.get_edges(
34 filter_function=lambda edge: graph[edge].get("distance") is not None # the distance attribute is set
35 and graph[edge]["distance"] < MIN_DISTANCE # the distance is less than MIN_DISTANCE
36 and graph[edge[0]]["name"] == "BOLT" # the first node is a BOLT
37 and graph[edge[1]]["name"] == "BOLT" # the second node is a BOLT
38)
39
40# Result
41if len(incorrect_edges) == 0:
42 print("Rule #2: All the bolts are at a minimum distance between each other.")
43else:
44 print(f"Rule #2: The following bolts are at a distance less than {MIN_DISTANCE} to another bolt: {incorrect_edges}")
45 primitives = [graph.get_shape(edge[0]) for edge in incorrect_edges] + [
46 graph.get_shape(edge[1]) for edge in incorrect_edges
47 ]
48 VolumeModel(primitives=primitives).display_3d()
Connection Rule#
Connection Rule Check#
1"""Showcase of connection rule checking using graph."""
2
3from pathlib import Path
4
5from volmdlr.model import VolumeModel
6
7from volmdlr_tools.graph.assembly import GraphAssembly
8
9STEP_FILE = Path(__file__).parent.parent.parent.parent.parent / "data" / "step" / "test.stp"
10
11# DEFINING OBJECTS
12volume_model = VolumeModel.from_step(str(STEP_FILE))
13# volume_model.display_3d()
14graph = GraphAssembly.from_volume_model(volume_model)
15# graph.plot()
16
17
18# RULE: Check that the rod is only connected to other solid with "Cylindrical" connection
19# Note: The rod is a unique Solid named "ROD"
20
21# Set the connection geometry attribute for all the edges between solids
22graph.set_connection_geometry()
23
24# Extract the edges with connection to the rod
25edges = graph.get_edges(
26 filter_function=lambda edge: (graph[edge[0]]["name"] == "ROD" or graph[edge[1]]["name"] == "ROD")
27 and graph[edge].get("connection") is not None
28)
29
30# Identify the edges that are not cylindrical connection
31for edge, attribute in edges.items():
32 shape1 = graph.get_shape(edge[0])
33 shape2 = graph.get_shape(edge[1])
34 connection_faces = [face for contact_pairs in attribute["connection"].contact_faces for face in contact_pairs]
35 vm = VolumeModel([shape1, shape2, *connection_faces]).display_3d()
36 for face in connection_faces:
37 print(f"{face.__class__.__name__} connection between {graph[edge[0]]['name']} and {graph[edge[1]]['name']}")
Proximity Rule#
Proximity Rule Check#
1"""Showcase of proximity rule checking using graph."""
2
3from pathlib import Path
4
5from volmdlr.model import VolumeModel
6
7from volmdlr_tools.graph.assembly import GraphAssembly
8
9STEP_FILE = Path(__file__).parent.parent.parent.parent.parent / "data" / "step" / "test.stp"
10
11# DEFINING OBJECTS
12volume_model = VolumeModel.from_step(str(STEP_FILE))
13# volume_model.display_3d()
14graph = GraphAssembly.from_volume_model(volume_model)
15# graph.plot()
16
17
18# RULE: The ROD should not have more than 4 solids at a given distance, and the plate should not be part of it
19# Note: The rod is a unique Solid named "ROD" and the plate is a Solid named "PLATE"
20PROXIMITY_DISTANCE = 0.01
21
22# Set the distance attribute for all the edges between solids
23graph.set_distance_attribute()
24
25# Extract the solid closer than PROXIMITY_DISTANCE to the rod
26edges = graph.get_edges(
27 filter_function=lambda edge: (graph[edge[0]]["name"] == "ROD" or graph[edge[1]]["name"] == "ROD")
28 and graph[edge].get("distance") is not None
29 and graph[edge]["distance"] < PROXIMITY_DISTANCE
30)
31
32# Create a subgraph with the rod and the solids at a given distance
33rod_proximity_graph = graph.subgraph(lambda node: node in [edge[0] for edge in edges] + [edge[1] for edge in edges])
34
35# Check if the rod is connected to more than 4 solids
36print(f"Rule #1: The rod is close to {rod_proximity_graph.n_nodes - 1} solids.")
37print(
38 f"Rule #2: The plate is near the rod: {len(rod_proximity_graph.get_nodes(filter_function=lambda node: graph[node]['name'] == 'PLATE')) > 0}"
39)
See Also#
GraphAssembly - GraphAssembly concepts and main features
Kinematics & Determinacy - Kinematic analysis of assemblies
Distance & Clearance - Distance and clearance computation