Skip to content

Commit 2e25b9f

Browse files
authored
Merge pull request #252 from robin-oval/feature/explode
explode disconnected mesh and network elements
2 parents b2acc37 + 76a8282 commit 2e25b9f

File tree

4 files changed

+234
-1
lines changed

4 files changed

+234
-1
lines changed

src/compas/datastructures/mesh/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
from .bbox import *
1717
from .descent import *
1818
from .duality import *
19+
from .explode import *
1920
from .geodesics import *
2021
from .join import *
2122
from .laplacian import *
Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
from __future__ import print_function
2+
from __future__ import absolute_import
3+
from __future__ import division
4+
5+
from compas.topology import connected_components
6+
7+
__all__ = [
8+
'mesh_disconnected_vertices',
9+
'mesh_disconnected_faces',
10+
'mesh_explode',
11+
]
12+
13+
14+
def mesh_disconnected_vertices(mesh):
15+
"""Get the disconnected vertex groups in a mesh.
16+
17+
Parameters
18+
----------
19+
mesh : Mesh
20+
A mesh.
21+
22+
Returns
23+
-------
24+
parts : list
25+
The list of disconnected vertex groups.
26+
27+
"""
28+
29+
return connected_components(mesh.adjacency)
30+
31+
32+
def mesh_disconnected_faces(mesh):
33+
"""Get the disconnected face groups in a mesh.
34+
35+
Parameters
36+
----------
37+
mesh : Mesh
38+
A mesh.
39+
40+
Returns
41+
-------
42+
parts : list
43+
The list of disconnected face groups.
44+
45+
"""
46+
47+
parts = mesh_disconnected_vertices(mesh)
48+
49+
return [set([fkey for vkey in part for fkey in mesh.vertex_faces(vkey)]) for part in parts]
50+
51+
52+
def mesh_explode(mesh, cls=None):
53+
"""Explode a mesh into its disconnected parts.
54+
55+
Parameters
56+
----------
57+
mesh : Mesh
58+
A mesh.
59+
60+
Returns
61+
-------
62+
exploded_meshes : list
63+
The list of the meshes from the exploded mesh parts.
64+
65+
"""
66+
67+
if cls is None:
68+
cls = type(mesh)
69+
70+
parts = mesh_disconnected_faces(mesh)
71+
72+
exploded_meshes = []
73+
74+
for part in parts:
75+
76+
vertex_keys = list(set([vkey for fkey in part for vkey in mesh.face_vertices(fkey)]))
77+
vertices = [mesh.vertex_coordinates(vkey) for vkey in vertex_keys]
78+
79+
key_to_index = {vkey: i for i, vkey in enumerate(vertex_keys)}
80+
faces = [ [key_to_index[vkey] for vkey in mesh.face_vertices(fkey)] for fkey in part]
81+
82+
exploded_meshes.append(cls.from_vertices_and_faces(vertices, faces))
83+
84+
return exploded_meshes
85+
86+
87+
# ==============================================================================
88+
# Main
89+
# ==============================================================================
90+
91+
if __name__ == '__main__':
92+
93+
from compas.datastructures import Mesh
94+
95+
vertices = [
96+
[0.0, 0.0, 0.0],
97+
[1.0, 0.0, 0.0],
98+
[2.0, 0.0, 0.0],
99+
[2.0, 0.0, 0.0],
100+
[3.0, 0.0, 0.0],
101+
[0.0, 1.0, 0.0],
102+
[1.0, 1.0, 0.0],
103+
[2.0, 1.0, 0.0],
104+
[2.0, 1.0, 0.0],
105+
[3.0, 1.0, 0.0],
106+
]
107+
108+
faces = [
109+
[0, 1, 6, 5],
110+
[1, 2, 7, 6],
111+
[3, 4, 9, 8]
112+
]
113+
114+
mesh = Mesh.from_vertices_and_faces(vertices, faces)
115+
116+
print(mesh_disconnected_vertices(mesh))
117+
print(mesh_disconnected_faces(mesh))
118+
print(mesh_explode(mesh))

src/compas/datastructures/network/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,10 @@
88
from .combinatorics import *
99
from .complementarity import *
1010
from .duality import *
11+
from .explode import *
1112
from .parallelisation import *
1213
from ._planarity import *
1314
from .smoothing import *
1415
from .transformations import *
1516

16-
1717
__all__ = [name for name in dir() if not name.startswith('_')]
Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
from __future__ import print_function
2+
from __future__ import absolute_import
3+
from __future__ import division
4+
5+
from compas.topology import connected_components
6+
7+
__all__ = [
8+
'network_disconnected_vertices',
9+
'network_disconnected_edges',
10+
'network_explode'
11+
]
12+
13+
14+
def network_disconnected_vertices(network):
15+
"""Get the disconnected vertex groups in a network.
16+
17+
Parameters
18+
----------
19+
network : Network
20+
A network.
21+
22+
Returns
23+
-------
24+
list
25+
The list of disconnected vertex groups.
26+
27+
"""
28+
29+
return connected_components(network.adjacency)
30+
31+
32+
def network_disconnected_edges(network):
33+
"""Get the disconnected edge groups in a network.
34+
35+
Parameters
36+
----------
37+
network : Network
38+
A network.
39+
40+
Returns
41+
-------
42+
parts : list
43+
The list of disconnected edge groups.
44+
45+
"""
46+
47+
48+
parts = network_disconnected_vertices(network)
49+
50+
return [[(u, v) for u in part for v in network.vertex_neighbors(u) if u < v] for part in parts]
51+
52+
53+
def network_explode(network, cls=None):
54+
"""Explode a network into its disconnected parts.
55+
56+
Parameters
57+
----------
58+
network : Network
59+
A network.
60+
61+
Returns
62+
-------
63+
exploded_networks : list
64+
The list of the networks from the exploded network parts.
65+
66+
"""
67+
68+
if cls is None:
69+
cls = type(network)
70+
71+
parts = network_disconnected_edges(network)
72+
73+
exploded_networks = []
74+
75+
for part in parts:
76+
77+
vertex_keys = list(set([vkey for edge in part for vkey in edge]))
78+
vertices = [network.vertex_coordinates(vkey) for vkey in vertex_keys]
79+
80+
key_to_index = {vkey: i for i, vkey in enumerate(vertex_keys)}
81+
edges = [ (key_to_index[u], key_to_index[v]) for u, v in part]
82+
83+
exploded_networks.append(cls.from_vertices_and_edges(vertices, edges))
84+
85+
return exploded_networks
86+
87+
88+
# ==============================================================================
89+
# Main
90+
# ==============================================================================
91+
92+
if __name__ == "__main__":
93+
94+
from compas.datastructures import Network
95+
96+
vertices = [
97+
[0.0, 0.0, 0.0],
98+
[1.0, 0.0, 0.0],
99+
[2.0, 0.0, 0.0],
100+
[3.0, 0.0, 0.0],
101+
[4.0, 0.0, 0.0],
102+
]
103+
104+
edges = [
105+
(0, 1),
106+
(2, 3),
107+
(3, 4),
108+
]
109+
110+
network = Network.from_vertices_and_edges(vertices, edges)
111+
112+
print(network_disconnected_vertices(network))
113+
print(network_disconnected_edges(network))
114+
print(network_explode(network))

0 commit comments

Comments
 (0)