topologicpy 0.4.8__py3-none-any.whl → 0.4.9__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- topologicpy/Aperture.py +46 -0
- topologicpy/Cell.py +1780 -0
- topologicpy/CellComplex.py +791 -0
- topologicpy/Cluster.py +591 -0
- topologicpy/Color.py +157 -0
- topologicpy/Context.py +56 -0
- topologicpy/DGL.py +2661 -0
- topologicpy/Dictionary.py +470 -0
- topologicpy/Edge.py +855 -0
- topologicpy/EnergyModel.py +1052 -0
- topologicpy/Face.py +1810 -0
- topologicpy/Graph.py +3526 -0
- topologicpy/Graph_Export.py +858 -0
- topologicpy/Grid.py +338 -0
- topologicpy/Helper.py +182 -0
- topologicpy/Honeybee.py +424 -0
- topologicpy/Matrix.py +255 -0
- topologicpy/Neo4jGraph.py +311 -0
- topologicpy/Plotly.py +1396 -0
- topologicpy/Polyskel.py +524 -0
- topologicpy/Process.py +1368 -0
- topologicpy/SQL.py +48 -0
- topologicpy/Shell.py +1418 -0
- topologicpy/Speckle.py +433 -0
- topologicpy/Topology.py +5854 -0
- topologicpy/UnitTest.py +29 -0
- topologicpy/Vector.py +555 -0
- topologicpy/Vertex.py +714 -0
- topologicpy/Wire.py +2346 -0
- topologicpy/__init__.py +20 -0
- topologicpy/bin/linux/topologic/__init__.py +2 -0
- topologicpy/bin/linux/topologic/topologic.cpython-310-x86_64-linux-gnu.so +0 -0
- topologicpy/bin/linux/topologic/topologic.cpython-311-x86_64-linux-gnu.so +0 -0
- topologicpy/bin/linux/topologic/topologic.cpython-38-x86_64-linux-gnu.so +0 -0
- topologicpy/bin/linux/topologic/topologic.cpython-39-x86_64-linux-gnu.so +0 -0
- topologicpy/bin/linux/topologic.libs/libTKBO-6bdf205d.so.7.7.0 +0 -0
- topologicpy/bin/linux/topologic.libs/libTKBRep-2960a069.so.7.7.0 +0 -0
- topologicpy/bin/linux/topologic.libs/libTKBool-c44b74bd.so.7.7.0 +0 -0
- topologicpy/bin/linux/topologic.libs/libTKFillet-9a670ba0.so.7.7.0 +0 -0
- topologicpy/bin/linux/topologic.libs/libTKG2d-8f31849e.so.7.7.0 +0 -0
- topologicpy/bin/linux/topologic.libs/libTKG3d-4c6bce57.so.7.7.0 +0 -0
- topologicpy/bin/linux/topologic.libs/libTKGeomAlgo-26066fd9.so.7.7.0 +0 -0
- topologicpy/bin/linux/topologic.libs/libTKGeomBase-2116cabe.so.7.7.0 +0 -0
- topologicpy/bin/linux/topologic.libs/libTKMath-72572fa8.so.7.7.0 +0 -0
- topologicpy/bin/linux/topologic.libs/libTKMesh-2a060427.so.7.7.0 +0 -0
- topologicpy/bin/linux/topologic.libs/libTKOffset-6cab68ff.so.7.7.0 +0 -0
- topologicpy/bin/linux/topologic.libs/libTKPrim-eb1262b3.so.7.7.0 +0 -0
- topologicpy/bin/linux/topologic.libs/libTKShHealing-e67e5cc7.so.7.7.0 +0 -0
- topologicpy/bin/linux/topologic.libs/libTKTopAlgo-e4c96c33.so.7.7.0 +0 -0
- topologicpy/bin/linux/topologic.libs/libTKernel-fb7fe3b7.so.7.7.0 +0 -0
- topologicpy/bin/linux/topologic.libs/libgcc_s-32c1665e.so.1 +0 -0
- topologicpy/bin/linux/topologic.libs/libstdc++-672d7b41.so.6.0.30 +0 -0
- topologicpy/bin/windows/topologic/TKBO-f6b191de.dll +0 -0
- topologicpy/bin/windows/topologic/TKBRep-e56a600e.dll +0 -0
- topologicpy/bin/windows/topologic/TKBool-7b8d47ae.dll +0 -0
- topologicpy/bin/windows/topologic/TKFillet-0ddbf0a8.dll +0 -0
- topologicpy/bin/windows/topologic/TKG2d-2e2dee3d.dll +0 -0
- topologicpy/bin/windows/topologic/TKG3d-6674513d.dll +0 -0
- topologicpy/bin/windows/topologic/TKGeomAlgo-d240e370.dll +0 -0
- topologicpy/bin/windows/topologic/TKGeomBase-df87aba5.dll +0 -0
- topologicpy/bin/windows/topologic/TKMath-45bd625a.dll +0 -0
- topologicpy/bin/windows/topologic/TKMesh-d6e826b1.dll +0 -0
- topologicpy/bin/windows/topologic/TKOffset-79b9cc94.dll +0 -0
- topologicpy/bin/windows/topologic/TKPrim-aa430a86.dll +0 -0
- topologicpy/bin/windows/topologic/TKShHealing-bb48be89.dll +0 -0
- topologicpy/bin/windows/topologic/TKTopAlgo-7d0d1e22.dll +0 -0
- topologicpy/bin/windows/topologic/TKernel-08c8cfbb.dll +0 -0
- topologicpy/bin/windows/topologic/__init__.py +2 -0
- topologicpy/bin/windows/topologic/topologic.cp310-win_amd64.pyd +0 -0
- topologicpy/bin/windows/topologic/topologic.cp311-win_amd64.pyd +0 -0
- topologicpy/bin/windows/topologic/topologic.cp38-win_amd64.pyd +0 -0
- topologicpy/bin/windows/topologic/topologic.cp39-win_amd64.pyd +0 -0
- {topologicpy-0.4.8.dist-info → topologicpy-0.4.9.dist-info}/METADATA +1 -1
- topologicpy-0.4.9.dist-info/RECORD +77 -0
- topologicpy-0.4.9.dist-info/top_level.txt +1 -0
- topologicpy-0.4.8.dist-info/RECORD +0 -5
- topologicpy-0.4.8.dist-info/top_level.txt +0 -1
- {topologicpy-0.4.8.dist-info → topologicpy-0.4.9.dist-info}/LICENSE +0 -0
- {topologicpy-0.4.8.dist-info → topologicpy-0.4.9.dist-info}/WHEEL +0 -0
topologicpy/Graph.py
ADDED
|
@@ -0,0 +1,3526 @@
|
|
|
1
|
+
import topologicpy
|
|
2
|
+
import topologic
|
|
3
|
+
from topologicpy.Dictionary import Dictionary
|
|
4
|
+
from topologicpy.Topology import Topology
|
|
5
|
+
from topologicpy.Aperture import Aperture
|
|
6
|
+
import random
|
|
7
|
+
import time
|
|
8
|
+
|
|
9
|
+
class Graph:
|
|
10
|
+
@staticmethod
|
|
11
|
+
def AdjacencyMatrix(graph, tolerance=0.0001):
|
|
12
|
+
"""
|
|
13
|
+
Returns the adjacency matrix of the input Graph. See https://en.wikipedia.org/wiki/Adjacency_matrix.
|
|
14
|
+
|
|
15
|
+
Parameters
|
|
16
|
+
----------
|
|
17
|
+
graph : topologic.Graph
|
|
18
|
+
The input graph.
|
|
19
|
+
tolerance : float , optional
|
|
20
|
+
The desired tolerance. The default is 0.0001.
|
|
21
|
+
|
|
22
|
+
Returns
|
|
23
|
+
-------
|
|
24
|
+
list
|
|
25
|
+
The adjacency matrix.
|
|
26
|
+
|
|
27
|
+
"""
|
|
28
|
+
from topologicpy.Vertex import Vertex
|
|
29
|
+
from topologicpy.Topology import Topology
|
|
30
|
+
if not isinstance(graph, topologic.Graph):
|
|
31
|
+
return None
|
|
32
|
+
|
|
33
|
+
vertices = Graph.Vertices(graph)
|
|
34
|
+
order = len(vertices)
|
|
35
|
+
matrix = []
|
|
36
|
+
for i in range(order):
|
|
37
|
+
tempRow = []
|
|
38
|
+
for j in range(order):
|
|
39
|
+
tempRow.append(0)
|
|
40
|
+
matrix.append(tempRow)
|
|
41
|
+
for i in range(order):
|
|
42
|
+
adjVertices = Graph.AdjacentVertices(graph, vertices[i])
|
|
43
|
+
for adjVertex in adjVertices:
|
|
44
|
+
adjIndex = Vertex.Index(vertex=adjVertex, vertices=vertices, strict=True, tolerance=0.01)
|
|
45
|
+
if not adjIndex == None:
|
|
46
|
+
matrix[i][adjIndex] = 1
|
|
47
|
+
return matrix
|
|
48
|
+
@staticmethod
|
|
49
|
+
def AdjacencyList(graph, tolerance=0.0001):
|
|
50
|
+
"""
|
|
51
|
+
Returns the adjacency list of the input Graph. See https://en.wikipedia.org/wiki/Adjacency_list.
|
|
52
|
+
|
|
53
|
+
Parameters
|
|
54
|
+
----------
|
|
55
|
+
graph : topologic.Graph
|
|
56
|
+
The input graph.
|
|
57
|
+
tolerance : float , optional
|
|
58
|
+
The desired tolerance. The default is 0.0001.
|
|
59
|
+
|
|
60
|
+
Returns
|
|
61
|
+
-------
|
|
62
|
+
list
|
|
63
|
+
The adjacency list.
|
|
64
|
+
"""
|
|
65
|
+
from topologicpy.Vertex import Vertex
|
|
66
|
+
from topologicpy.Topology import Topology
|
|
67
|
+
if not isinstance(graph, topologic.Graph):
|
|
68
|
+
return None
|
|
69
|
+
vertices = Graph.Vertices(graph)
|
|
70
|
+
order = len(vertices)
|
|
71
|
+
adjList = []
|
|
72
|
+
for i in range(order):
|
|
73
|
+
tempRow = []
|
|
74
|
+
v = Graph.NearestVertex(graph, vertices[i])
|
|
75
|
+
adjVertices = Graph.AdjacentVertices(graph, v)
|
|
76
|
+
for adjVertex in adjVertices:
|
|
77
|
+
adjIndex = Vertex.Index(vertex=adjVertex, vertices=vertices, strict=True, tolerance=tolerance)
|
|
78
|
+
if not adjIndex == None:
|
|
79
|
+
tempRow.append(adjIndex)
|
|
80
|
+
tempRow.sort()
|
|
81
|
+
adjList.append(tempRow)
|
|
82
|
+
return adjList
|
|
83
|
+
|
|
84
|
+
@staticmethod
|
|
85
|
+
def AddEdge(graph, edge, tolerance=0.0001):
|
|
86
|
+
"""
|
|
87
|
+
Adds the input edge to the input Graph.
|
|
88
|
+
|
|
89
|
+
Parameters
|
|
90
|
+
----------
|
|
91
|
+
graph : topologic.Graph
|
|
92
|
+
The input graph.
|
|
93
|
+
edges : topologic.Edge
|
|
94
|
+
The input edge.
|
|
95
|
+
tolerance : float , optional
|
|
96
|
+
The desired tolerance. The default is 0.0001.
|
|
97
|
+
|
|
98
|
+
Returns
|
|
99
|
+
-------
|
|
100
|
+
topologic.Graph
|
|
101
|
+
The input graph with the input edge added to it.
|
|
102
|
+
|
|
103
|
+
"""
|
|
104
|
+
from topologicpy.Vertex import Vertex
|
|
105
|
+
from topologicpy.Edge import Edge
|
|
106
|
+
from topologicpy.Dictionary import Dictionary
|
|
107
|
+
from topologicpy.Topology import Topology
|
|
108
|
+
|
|
109
|
+
def addIfUnique(graph_vertices, vertex, tolerance):
|
|
110
|
+
unique = True
|
|
111
|
+
returnVertex = vertex
|
|
112
|
+
for gv in graph_vertices:
|
|
113
|
+
if (Vertex.Distance(vertex, gv) < tolerance):
|
|
114
|
+
gd = Topology.Dictionary(gv)
|
|
115
|
+
vd = Topology.Dictionary(vertex)
|
|
116
|
+
gk = gd.Keys()
|
|
117
|
+
vk = vd.Keys()
|
|
118
|
+
d = None
|
|
119
|
+
if (len(gk) > 0) and (len(vk) > 0):
|
|
120
|
+
d = Dictionary.ByMergedDictionaries([gd, vd])
|
|
121
|
+
elif (len(gk) > 0) and (len(vk) < 1):
|
|
122
|
+
d = gd
|
|
123
|
+
elif (len(gk) < 1) and (len(vk) > 0):
|
|
124
|
+
d = vd
|
|
125
|
+
if d:
|
|
126
|
+
_ = Topology.SetDictionary(gv,d)
|
|
127
|
+
unique = False
|
|
128
|
+
returnVertex = gv
|
|
129
|
+
break
|
|
130
|
+
if unique:
|
|
131
|
+
graph_vertices.append(vertex)
|
|
132
|
+
return [graph_vertices, returnVertex]
|
|
133
|
+
|
|
134
|
+
if not isinstance(graph, topologic.Graph):
|
|
135
|
+
return None
|
|
136
|
+
if not isinstance(edge, topologic.Edge):
|
|
137
|
+
return None
|
|
138
|
+
graph_vertices = Graph.Vertices(graph)
|
|
139
|
+
graph_edges = Graph.Edges(graph, graph_vertices, tolerance)
|
|
140
|
+
vertices = Edge.Vertices(edge)
|
|
141
|
+
new_vertices = []
|
|
142
|
+
for vertex in vertices:
|
|
143
|
+
graph_vertices, nv = addIfUnique(graph_vertices, vertex, tolerance)
|
|
144
|
+
new_vertices.append(nv)
|
|
145
|
+
new_edge = Edge.ByVertices([new_vertices[0], new_vertices[1]])
|
|
146
|
+
_ = Topology.SetDictionary(new_edge, Topology.Dictionary(edge))
|
|
147
|
+
graph_edges.append(new_edge)
|
|
148
|
+
new_graph = Graph.ByVerticesEdges(graph_vertices, graph_edges)
|
|
149
|
+
return new_graph
|
|
150
|
+
|
|
151
|
+
@staticmethod
|
|
152
|
+
def AddVertex(graph, vertex, tolerance=0.0001):
|
|
153
|
+
"""
|
|
154
|
+
Adds the input vertex to the input graph.
|
|
155
|
+
|
|
156
|
+
Parameters
|
|
157
|
+
----------
|
|
158
|
+
graph : topologic.Graph
|
|
159
|
+
The input graph.
|
|
160
|
+
vertex : topologic.Vertex
|
|
161
|
+
The input vertex.
|
|
162
|
+
tolerance : float , optional
|
|
163
|
+
The desired tolerance. The default is 0.0001.
|
|
164
|
+
|
|
165
|
+
Returns
|
|
166
|
+
-------
|
|
167
|
+
topologic.Graph
|
|
168
|
+
The input graph with the input vertex added to it.
|
|
169
|
+
|
|
170
|
+
"""
|
|
171
|
+
if not isinstance(graph, topologic.Graph):
|
|
172
|
+
return None
|
|
173
|
+
if not isinstance(vertex, topologic.Vertex):
|
|
174
|
+
return None
|
|
175
|
+
_ = graph.AddVertices([vertex], tolerance)
|
|
176
|
+
return graph
|
|
177
|
+
|
|
178
|
+
@staticmethod
|
|
179
|
+
def AddVertices(graph, vertices, tolerance=0.0001):
|
|
180
|
+
"""
|
|
181
|
+
Adds the input vertex to the input graph.
|
|
182
|
+
|
|
183
|
+
Parameters
|
|
184
|
+
----------
|
|
185
|
+
graph : topologic.Graph
|
|
186
|
+
The input graph.
|
|
187
|
+
vertices : list
|
|
188
|
+
The input list of vertices.
|
|
189
|
+
tolerance : float , optional
|
|
190
|
+
The desired tolerance. The default is 0.0001.
|
|
191
|
+
|
|
192
|
+
Returns
|
|
193
|
+
-------
|
|
194
|
+
topologic.Graph
|
|
195
|
+
The input graph with the input vertex added to it.
|
|
196
|
+
|
|
197
|
+
"""
|
|
198
|
+
if not isinstance(graph, topologic.Graph):
|
|
199
|
+
return None
|
|
200
|
+
if not isinstance(vertices, list):
|
|
201
|
+
return None
|
|
202
|
+
vertices = [v for v in vertices if isinstance(v, topologic.Vertex)]
|
|
203
|
+
if len(vertices) < 1:
|
|
204
|
+
return None
|
|
205
|
+
_ = graph.AddVertices(vertices, tolerance)
|
|
206
|
+
return graph
|
|
207
|
+
|
|
208
|
+
@staticmethod
|
|
209
|
+
def AdjacentVertices(graph, vertex):
|
|
210
|
+
"""
|
|
211
|
+
Returns the list of vertices connected to the input vertex.
|
|
212
|
+
|
|
213
|
+
Parameters
|
|
214
|
+
----------
|
|
215
|
+
graph : topologic.Graph
|
|
216
|
+
The input graph.
|
|
217
|
+
vertex : topologic.Vertex
|
|
218
|
+
the input vertex.
|
|
219
|
+
|
|
220
|
+
Returns
|
|
221
|
+
-------
|
|
222
|
+
list
|
|
223
|
+
The list of adjacent vertices.
|
|
224
|
+
|
|
225
|
+
"""
|
|
226
|
+
vertices = []
|
|
227
|
+
_ = graph.AdjacentVertices(vertex, vertices)
|
|
228
|
+
return list(vertices)
|
|
229
|
+
|
|
230
|
+
@staticmethod
|
|
231
|
+
def AllPaths(graph, vertexA, vertexB, timeLimit=10):
|
|
232
|
+
"""
|
|
233
|
+
Returns all the paths that connect the input vertices within the allowed time limit in seconds.
|
|
234
|
+
|
|
235
|
+
Parameters
|
|
236
|
+
----------
|
|
237
|
+
graph : topologic.Graph
|
|
238
|
+
The input graph.
|
|
239
|
+
vertexA : topologic.Vertex
|
|
240
|
+
The first input vertex.
|
|
241
|
+
vertexB : topologic.Vertex
|
|
242
|
+
The second input vertex.
|
|
243
|
+
timeLimit : int , optional
|
|
244
|
+
The time limit in second. The default is 10 seconds.
|
|
245
|
+
|
|
246
|
+
Returns
|
|
247
|
+
-------
|
|
248
|
+
list
|
|
249
|
+
The list of all paths (wires) found within the time limit.
|
|
250
|
+
|
|
251
|
+
"""
|
|
252
|
+
paths = []
|
|
253
|
+
_ = graph.AllPaths(vertexA, vertexB, True, timeLimit, paths)
|
|
254
|
+
return paths
|
|
255
|
+
|
|
256
|
+
@staticmethod
|
|
257
|
+
def BetweenessCentrality(graph, vertices=None, sources=None, destinations=None, tolerance=0.001):
|
|
258
|
+
"""
|
|
259
|
+
Returns the betweeness centrality measure of the input list of vertices within the input graph. The order of the returned list is the same as the order of the input list of vertices. If no vertices are specified, the betweeness centrality of all the vertices in the input graph is computed. See https://en.wikipedia.org/wiki/Centrality.
|
|
260
|
+
|
|
261
|
+
Parameters
|
|
262
|
+
----------
|
|
263
|
+
graph : topologic.Graph
|
|
264
|
+
The input graph.
|
|
265
|
+
vertices : list , optional
|
|
266
|
+
The input list of vertices. The default is None which means all vertices in the input graph are considered.
|
|
267
|
+
sources : list , optional
|
|
268
|
+
The input list of source vertices. The default is None which means all vertices in the input graph are considered.
|
|
269
|
+
destinations : list , optional
|
|
270
|
+
The input list of destination vertices. The default is None which means all vertices in the input graph are considered.
|
|
271
|
+
tolerance : float , optional
|
|
272
|
+
The desired tolerance. The default is 0.0001.
|
|
273
|
+
|
|
274
|
+
Returns
|
|
275
|
+
-------
|
|
276
|
+
list
|
|
277
|
+
The betweeness centrality of the input list of vertices within the input graph. The values are in the range 0 to 1.
|
|
278
|
+
|
|
279
|
+
"""
|
|
280
|
+
from topologicpy.Vertex import Vertex
|
|
281
|
+
import sys
|
|
282
|
+
import subprocess
|
|
283
|
+
|
|
284
|
+
def betweeness(vertices, topologies, tolerance=0.001):
|
|
285
|
+
returnList = [0] * len(vertices)
|
|
286
|
+
for topology in topologies:
|
|
287
|
+
t_vertices = Topology.Vertices(topology)
|
|
288
|
+
for t_v in t_vertices:
|
|
289
|
+
index = Vertex.Index(t_v, vertices, strict=False, tolerance=tolerance)
|
|
290
|
+
if not index == None:
|
|
291
|
+
returnList[index] = returnList[index]+1
|
|
292
|
+
return returnList
|
|
293
|
+
|
|
294
|
+
try:
|
|
295
|
+
from tqdm.auto import tqdm
|
|
296
|
+
except:
|
|
297
|
+
call = [sys.executable, '-m', 'pip', 'install', 'tqdm', '-t', sys.path[0]]
|
|
298
|
+
subprocess.run(call)
|
|
299
|
+
try:
|
|
300
|
+
from tqdm.auto import tqdm
|
|
301
|
+
except:
|
|
302
|
+
print("DGL - Error: Could not import tqdm")
|
|
303
|
+
|
|
304
|
+
if not isinstance(graph, topologic.Graph):
|
|
305
|
+
return None
|
|
306
|
+
graphVertices = Graph.Vertices(graph)
|
|
307
|
+
if not isinstance(vertices, list):
|
|
308
|
+
vertices = graphVertices
|
|
309
|
+
else:
|
|
310
|
+
vertices = [v for v in vertices if isinstance(v, topologic.Vertex)]
|
|
311
|
+
if len(vertices) < 1:
|
|
312
|
+
return None
|
|
313
|
+
if not isinstance(sources, list):
|
|
314
|
+
sources = graphVertices
|
|
315
|
+
else:
|
|
316
|
+
sources = [v for v in sources if isinstance(v, topologic.Vertex)]
|
|
317
|
+
if len(sources) < 1:
|
|
318
|
+
return None
|
|
319
|
+
if not isinstance(destinations, list):
|
|
320
|
+
destinations = graphVertices
|
|
321
|
+
else:
|
|
322
|
+
destinations = [v for v in destinations if isinstance(v, topologic.Vertex)]
|
|
323
|
+
if len(destinations) < 1:
|
|
324
|
+
return None
|
|
325
|
+
|
|
326
|
+
paths = []
|
|
327
|
+
try:
|
|
328
|
+
for so in tqdm(sources, desc="Computing Shortest Paths", leave=False):
|
|
329
|
+
v1 = Graph.NearestVertex(graph, so)
|
|
330
|
+
for si in destinations:
|
|
331
|
+
v2 = Graph.NearestVertex(graph, si)
|
|
332
|
+
if not v1 == v2:
|
|
333
|
+
path = Graph.ShortestPath(graph, v1, v2)
|
|
334
|
+
if path:
|
|
335
|
+
paths.append(path)
|
|
336
|
+
except:
|
|
337
|
+
for so in sources:
|
|
338
|
+
v1 = Graph.NearestVertex(graph, so)
|
|
339
|
+
for si in destinations:
|
|
340
|
+
v2 = Graph.NearestVertex(graph, si)
|
|
341
|
+
if not v1 == v2:
|
|
342
|
+
path = Graph.ShortestPath(graph, v1, v2)
|
|
343
|
+
if path:
|
|
344
|
+
paths.append(path)
|
|
345
|
+
|
|
346
|
+
#Topology.Show(cluster)
|
|
347
|
+
values = betweeness(vertices, paths, tolerance=tolerance)
|
|
348
|
+
minValue = min(values)
|
|
349
|
+
maxValue = max(values)
|
|
350
|
+
size = maxValue - minValue
|
|
351
|
+
values = [(v-minValue)/size for v in values]
|
|
352
|
+
return values
|
|
353
|
+
|
|
354
|
+
|
|
355
|
+
@staticmethod
|
|
356
|
+
def ByDGCNNFile(file, key):
|
|
357
|
+
"""
|
|
358
|
+
Creates a graph from a DGCNN File.
|
|
359
|
+
|
|
360
|
+
Parameters
|
|
361
|
+
----------
|
|
362
|
+
file : file object
|
|
363
|
+
The input file.
|
|
364
|
+
key : str
|
|
365
|
+
The desired key for storing the node label.
|
|
366
|
+
|
|
367
|
+
Returns
|
|
368
|
+
-------
|
|
369
|
+
dict
|
|
370
|
+
A dictionary with the graphs and labels. The keys are 'graphs' and 'labels'.
|
|
371
|
+
|
|
372
|
+
"""
|
|
373
|
+
def verticesByCoordinates(x_coords, y_coords):
|
|
374
|
+
vertices = []
|
|
375
|
+
for i in range(len(x_coords)):
|
|
376
|
+
vertices.append(topologic.Vertex.ByCoordinates(x_coords[i], y_coords[i], 0))
|
|
377
|
+
return vertices
|
|
378
|
+
|
|
379
|
+
if not file:
|
|
380
|
+
return None
|
|
381
|
+
graphs = []
|
|
382
|
+
labels = []
|
|
383
|
+
lines = file.readlines()
|
|
384
|
+
n_graphs = int(lines[0])
|
|
385
|
+
index = 1
|
|
386
|
+
for i in range(n_graphs):
|
|
387
|
+
edges = []
|
|
388
|
+
line = lines[index].split()
|
|
389
|
+
n_nodes = int(line[0])
|
|
390
|
+
graph_label = int(line[1])
|
|
391
|
+
labels.append(graph_label)
|
|
392
|
+
index+=1
|
|
393
|
+
x_coordinates = random.sample(range(0, n_nodes), n_nodes)
|
|
394
|
+
y_coordinates = random.sample(range(0, n_nodes), n_nodes)
|
|
395
|
+
vertices = verticesByCoordinates(x_coordinates, y_coordinates)
|
|
396
|
+
for j in range(n_nodes):
|
|
397
|
+
line = lines[index+j].split()
|
|
398
|
+
node_label = int(line[0])
|
|
399
|
+
node_dict = Dictionary.DictionaryByKeysValues([key], [node_label])
|
|
400
|
+
Topology.TopologySetDictionary(vertices[j], node_dict)
|
|
401
|
+
for j in range(n_nodes):
|
|
402
|
+
line = lines[index+j].split()
|
|
403
|
+
sv = vertices[j]
|
|
404
|
+
adj_vertices = line[2:]
|
|
405
|
+
for adj_vertex in adj_vertices:
|
|
406
|
+
ev = vertices[int(adj_vertex)]
|
|
407
|
+
e = topologic.Edge.ByStartVertexEndVertex(sv, ev)
|
|
408
|
+
edges.append(e)
|
|
409
|
+
index+=n_nodes
|
|
410
|
+
graphs.append(topologic.Graph.ByVerticesEdges(vertices, edges))
|
|
411
|
+
file.close()
|
|
412
|
+
return {'graphs':graphs, 'labels':labels}
|
|
413
|
+
|
|
414
|
+
@staticmethod
|
|
415
|
+
def ByTopology(topology, direct=True, directApertures=False, viaSharedTopologies=False, viaSharedApertures=False, toExteriorTopologies=False, toExteriorApertures=False, toContents=False, toOutposts=False, idKey="TOPOLOGIC_ID", outpostsKey="outposts", useInternalVertex=True, storeBRep=False, tolerance=0.0001):
|
|
416
|
+
"""
|
|
417
|
+
Creates a graph.See https://en.wikipedia.org/wiki/Graph_(discrete_mathematics).
|
|
418
|
+
|
|
419
|
+
Parameters
|
|
420
|
+
----------
|
|
421
|
+
topology : topologic.Topology
|
|
422
|
+
The input topology.
|
|
423
|
+
direct : bool , optional
|
|
424
|
+
If set to True, connect the subtopologies directly with a single edge. The default is True.
|
|
425
|
+
directApertures : bool , optional
|
|
426
|
+
If set to True, connect the subtopologies directly with a single edge if they share one or more apertures. The default is False.
|
|
427
|
+
viaSharedTopologies : bool , optional
|
|
428
|
+
If set to True, connect the subtopologies via their shared topologies. The default is False.
|
|
429
|
+
viaSharedApertures : bool , optional
|
|
430
|
+
If set to True, connect the subtopologies via their shared apertures. The default is False.
|
|
431
|
+
toExteriorTopologies : bool , optional
|
|
432
|
+
If set to True, connect the subtopologies to their exterior topologies. The default is False.
|
|
433
|
+
toExteriorApertures : bool , optional
|
|
434
|
+
If set to True, connect the subtopologies to their exterior apertures. The default is False.
|
|
435
|
+
toContents : bool , optional
|
|
436
|
+
If set to True, connect the subtopologies to their contents. The default is False.
|
|
437
|
+
toOutposts : bool , optional
|
|
438
|
+
If set to True, connect the topology to the list specified in its outposts. The default is False.
|
|
439
|
+
idKey : str , optional
|
|
440
|
+
The key to use to find outpost by ID. It is case insensitive. The default is "TOPOLOGIC_ID".
|
|
441
|
+
outpostsKey : str , optional
|
|
442
|
+
The key to use to find the list of outposts. It is case insensitive. The default is "outposts".
|
|
443
|
+
useInternalVertex : bool , optional
|
|
444
|
+
If set to True, use an internal vertex to represent the subtopology. Otherwise, use its centroid. The default is False.
|
|
445
|
+
storeBRep : bool , optional
|
|
446
|
+
If set to True, store the BRep of the subtopology in its representative vertex. The default is False.
|
|
447
|
+
tolerance : float , optional
|
|
448
|
+
The desired tolerance. The default is 0.0001.
|
|
449
|
+
|
|
450
|
+
Returns
|
|
451
|
+
-------
|
|
452
|
+
topologic.Graph
|
|
453
|
+
The created graph.
|
|
454
|
+
|
|
455
|
+
"""
|
|
456
|
+
from topologicpy.Dictionary import Dictionary
|
|
457
|
+
from topologicpy.Cluster import Cluster
|
|
458
|
+
from topologicpy.Topology import Topology
|
|
459
|
+
|
|
460
|
+
def mergeDictionaries(sources):
|
|
461
|
+
if isinstance(sources, list) == False:
|
|
462
|
+
sources = [sources]
|
|
463
|
+
sinkKeys = []
|
|
464
|
+
sinkValues = []
|
|
465
|
+
d = sources[0].GetDictionary()
|
|
466
|
+
if d != None:
|
|
467
|
+
stlKeys = d.Keys()
|
|
468
|
+
if len(stlKeys) > 0:
|
|
469
|
+
sinkKeys = d.Keys()
|
|
470
|
+
sinkValues = Dictionary.Values(d)
|
|
471
|
+
for i in range(1,len(sources)):
|
|
472
|
+
d = sources[i].GetDictionary()
|
|
473
|
+
if d == None:
|
|
474
|
+
continue
|
|
475
|
+
stlKeys = d.Keys()
|
|
476
|
+
if len(stlKeys) > 0:
|
|
477
|
+
sourceKeys = d.Keys()
|
|
478
|
+
for aSourceKey in sourceKeys:
|
|
479
|
+
if aSourceKey not in sinkKeys:
|
|
480
|
+
sinkKeys.append(aSourceKey)
|
|
481
|
+
sinkValues.append("")
|
|
482
|
+
for i in range(len(sourceKeys)):
|
|
483
|
+
index = sinkKeys.index(sourceKeys[i])
|
|
484
|
+
sourceValue = Dictionary.ValueAtKey(d, sourceKeys[i])
|
|
485
|
+
if sourceValue != None:
|
|
486
|
+
if sinkValues[index] != "":
|
|
487
|
+
if isinstance(sinkValues[index], list):
|
|
488
|
+
sinkValues[index].append(sourceValue)
|
|
489
|
+
else:
|
|
490
|
+
sinkValues[index] = [sinkValues[index], sourceValue]
|
|
491
|
+
else:
|
|
492
|
+
sinkValues[index] = sourceValue
|
|
493
|
+
if len(sinkKeys) > 0 and len(sinkValues) > 0:
|
|
494
|
+
return Dictionary.ByKeysValues(sinkKeys, sinkValues)
|
|
495
|
+
return None
|
|
496
|
+
|
|
497
|
+
def mergeDictionaries2(sources):
|
|
498
|
+
if isinstance(sources, list) == False:
|
|
499
|
+
sources = [sources]
|
|
500
|
+
sinkKeys = []
|
|
501
|
+
sinkValues = []
|
|
502
|
+
d = sources[0]
|
|
503
|
+
if d != None:
|
|
504
|
+
stlKeys = d.Keys()
|
|
505
|
+
if len(stlKeys) > 0:
|
|
506
|
+
sinkKeys = d.Keys()
|
|
507
|
+
sinkValues = Dictionary.Values(d)
|
|
508
|
+
for i in range(1,len(sources)):
|
|
509
|
+
d = sources[i]
|
|
510
|
+
if d == None:
|
|
511
|
+
continue
|
|
512
|
+
stlKeys = d.Keys()
|
|
513
|
+
if len(stlKeys) > 0:
|
|
514
|
+
sourceKeys = d.Keys()
|
|
515
|
+
for aSourceKey in sourceKeys:
|
|
516
|
+
if aSourceKey not in sinkKeys:
|
|
517
|
+
sinkKeys.append(aSourceKey)
|
|
518
|
+
sinkValues.append("")
|
|
519
|
+
for i in range(len(sourceKeys)):
|
|
520
|
+
index = sinkKeys.index(sourceKeys[i])
|
|
521
|
+
sourceValue = Dictionary.ValueAtKey(d, sourceKeys[i])
|
|
522
|
+
if sourceValue != None:
|
|
523
|
+
if sinkValues[index] != "":
|
|
524
|
+
if isinstance(sinkValues[index], list):
|
|
525
|
+
sinkValues[index].append(sourceValue)
|
|
526
|
+
else:
|
|
527
|
+
sinkValues[index] = [sinkValues[index], sourceValue]
|
|
528
|
+
else:
|
|
529
|
+
sinkValues[index] = sourceValue
|
|
530
|
+
if len(sinkKeys) > 0 and len(sinkValues) > 0:
|
|
531
|
+
return Dictionary.ByKeysValues(sinkKeys, sinkValues)
|
|
532
|
+
return None
|
|
533
|
+
|
|
534
|
+
def outpostsByID(topologies, ids, idKey="TOPOLOGIC_ID"):
|
|
535
|
+
returnList = []
|
|
536
|
+
idList = []
|
|
537
|
+
for t in topologies:
|
|
538
|
+
d = Topology.Dictionary(t)
|
|
539
|
+
keys = Dictionary.Keys(d)
|
|
540
|
+
k = None
|
|
541
|
+
for key in keys:
|
|
542
|
+
if key.lower() == idKey.lower():
|
|
543
|
+
k = key
|
|
544
|
+
if k:
|
|
545
|
+
id = Dictionary.ValueAtKey(d, k)
|
|
546
|
+
else:
|
|
547
|
+
id = ""
|
|
548
|
+
idList.append(id)
|
|
549
|
+
for id in ids:
|
|
550
|
+
try:
|
|
551
|
+
index = idList.index(id)
|
|
552
|
+
except:
|
|
553
|
+
index = None
|
|
554
|
+
if index:
|
|
555
|
+
returnList.append(topologies[index])
|
|
556
|
+
return returnList
|
|
557
|
+
|
|
558
|
+
def processCellComplex(item):
|
|
559
|
+
topology, others, outpostsKey, idKey, direct, directApertures, viaSharedTopologies, viaSharedApertures, toExteriorTopologies, toExteriorApertures, toContents, toOutposts, useInternalVertex, storeBRep, tolerance = item
|
|
560
|
+
edges = []
|
|
561
|
+
vertices = []
|
|
562
|
+
cellmat = []
|
|
563
|
+
if direct == True:
|
|
564
|
+
cells = []
|
|
565
|
+
_ = topology.Cells(None, cells)
|
|
566
|
+
# Create a matrix of zeroes
|
|
567
|
+
for i in range(len(cells)):
|
|
568
|
+
cellRow = []
|
|
569
|
+
for j in range(len(cells)):
|
|
570
|
+
cellRow.append(0)
|
|
571
|
+
cellmat.append(cellRow)
|
|
572
|
+
for i in range(len(cells)):
|
|
573
|
+
for j in range(len(cells)):
|
|
574
|
+
if (i != j) and cellmat[i][j] == 0:
|
|
575
|
+
cellmat[i][j] = 1
|
|
576
|
+
cellmat[j][i] = 1
|
|
577
|
+
sharedt = Topology.SharedFaces(cells[i], cells[j])
|
|
578
|
+
if len(sharedt) > 0:
|
|
579
|
+
if useInternalVertex == True:
|
|
580
|
+
v1 = topologic.CellUtility.InternalVertex(cells[i], tolerance)
|
|
581
|
+
v2 = topologic.CellUtility.InternalVertex(cells[j], tolerance)
|
|
582
|
+
else:
|
|
583
|
+
v1 = cells[i].CenterOfMass()
|
|
584
|
+
v2 = cells[j].CenterOfMass()
|
|
585
|
+
e = topologic.Edge.ByStartVertexEndVertex(v1, v2)
|
|
586
|
+
mDict = mergeDictionaries(sharedt)
|
|
587
|
+
keys = (Dictionary.Keys(mDict) or [])+["relationship"]
|
|
588
|
+
values = (Dictionary.Values(mDict) or [])+["Direct"]
|
|
589
|
+
mDict = Dictionary.ByKeysValues(keys, values)
|
|
590
|
+
if mDict:
|
|
591
|
+
e.SetDictionary(mDict)
|
|
592
|
+
edges.append(e)
|
|
593
|
+
if directApertures == True:
|
|
594
|
+
cellmat = []
|
|
595
|
+
cells = []
|
|
596
|
+
_ = topology.Cells(None, cells)
|
|
597
|
+
# Create a matrix of zeroes
|
|
598
|
+
for i in range(len(cells)):
|
|
599
|
+
cellRow = []
|
|
600
|
+
for j in range(len(cells)):
|
|
601
|
+
cellRow.append(0)
|
|
602
|
+
cellmat.append(cellRow)
|
|
603
|
+
for i in range(len(cells)):
|
|
604
|
+
for j in range(len(cells)):
|
|
605
|
+
if (i != j) and cellmat[i][j] == 0:
|
|
606
|
+
cellmat[i][j] = 1
|
|
607
|
+
cellmat[j][i] = 1
|
|
608
|
+
sharedt = Topology.SharedFaces(cells[i], cells[j])
|
|
609
|
+
if len(sharedt) > 0:
|
|
610
|
+
apertureExists = False
|
|
611
|
+
for x in sharedt:
|
|
612
|
+
apList = []
|
|
613
|
+
_ = x.Apertures(apList)
|
|
614
|
+
if len(apList) > 0:
|
|
615
|
+
apTopList = []
|
|
616
|
+
for ap in apList:
|
|
617
|
+
apTopList.append(ap.Topology())
|
|
618
|
+
apertureExists = True
|
|
619
|
+
break
|
|
620
|
+
if apertureExists:
|
|
621
|
+
if useInternalVertex == True:
|
|
622
|
+
v1 = topologic.CellUtility.InternalVertex(cells[i], tolerance)
|
|
623
|
+
v2 = topologic.CellUtility.InternalVertex(cells[j], tolerance)
|
|
624
|
+
else:
|
|
625
|
+
v1 = cells[i].CenterOfMass()
|
|
626
|
+
v2 = cells[j].CenterOfMass()
|
|
627
|
+
e = topologic.Edge.ByStartVertexEndVertex(v1, v2)
|
|
628
|
+
mDict = mergeDictionaries(apTopList)
|
|
629
|
+
if mDict:
|
|
630
|
+
e.SetDictionary(mDict)
|
|
631
|
+
edges.append(e)
|
|
632
|
+
if toOutposts and others:
|
|
633
|
+
d = Topology.Dictionary(topology)
|
|
634
|
+
keys = Dictionary.Keys(d)
|
|
635
|
+
k = None
|
|
636
|
+
for key in keys:
|
|
637
|
+
if key.lower() == outpostsKey.lower():
|
|
638
|
+
k = key
|
|
639
|
+
if k:
|
|
640
|
+
ids = Dictionary.ValueAtKey(k)
|
|
641
|
+
outposts = outpostsByID(others, ids, idKey)
|
|
642
|
+
else:
|
|
643
|
+
outposts = []
|
|
644
|
+
for outpost in outposts:
|
|
645
|
+
if useInternalVertex == True:
|
|
646
|
+
vop = Topology.InternalVertex(outpost, tolerance)
|
|
647
|
+
vcc = Topology.InternalVertex(topology, tolerance)
|
|
648
|
+
else:
|
|
649
|
+
vop = Topology.CenterOfMass(outpost)
|
|
650
|
+
vcc = Topology.CenterOfMass(topology)
|
|
651
|
+
d1 = Topology.Dictionary(vcc)
|
|
652
|
+
if storeBRep:
|
|
653
|
+
d2 = Dictionary.ByKeysValues(["brep", "brepType", "brepTypeString"], [Topology.String(topology), Topology.Type(topology), Topology.TypeAsString(topology)])
|
|
654
|
+
d3 = mergeDictionaries2([d1, d2])
|
|
655
|
+
_ = vcc.SetDictionary(d3)
|
|
656
|
+
else:
|
|
657
|
+
_ = vcc.SetDictionary(d1)
|
|
658
|
+
vertices.append(vcc)
|
|
659
|
+
tempe = topologic.Edge.ByStartVertexEndVertex(vcc, vop)
|
|
660
|
+
tempd = Dictionary.ByKeysValues(["relationship"],["To Outposts"])
|
|
661
|
+
_ = tempe.SetDictionary(tempd)
|
|
662
|
+
edges.append(tempe)
|
|
663
|
+
|
|
664
|
+
|
|
665
|
+
cells = []
|
|
666
|
+
_ = topology.Cells(None, cells)
|
|
667
|
+
if (viaSharedTopologies == True) or (viaSharedApertures == True) or (toExteriorTopologies == True) or (toExteriorApertures == True) or (toContents == True):
|
|
668
|
+
for aCell in cells:
|
|
669
|
+
if useInternalVertex == True:
|
|
670
|
+
vCell = topologic.CellUtility.InternalVertex(aCell, tolerance)
|
|
671
|
+
else:
|
|
672
|
+
vCell = aCell.CenterOfMass()
|
|
673
|
+
d1 = aCell.GetDictionary()
|
|
674
|
+
if storeBRep:
|
|
675
|
+
d2 = Dictionary.ByKeysValues(["brep", "brepType", "brepTypeString"], [Topology.String(aCell), Topology.Type(aCell), Topology.TypeAsString(aCell)])
|
|
676
|
+
d3 = mergeDictionaries2([d1, d2])
|
|
677
|
+
_ = vCell.SetDictionary(d3)
|
|
678
|
+
else:
|
|
679
|
+
_ = vCell.SetDictionary(d1)
|
|
680
|
+
vertices.append(vCell)
|
|
681
|
+
faces = []
|
|
682
|
+
_ = aCell.Faces(None, faces)
|
|
683
|
+
sharedTopologies = []
|
|
684
|
+
exteriorTopologies = []
|
|
685
|
+
sharedApertures = []
|
|
686
|
+
exteriorApertures = []
|
|
687
|
+
contents = []
|
|
688
|
+
_ = aCell.Contents(contents)
|
|
689
|
+
for aFace in faces:
|
|
690
|
+
cells = []
|
|
691
|
+
_ = aFace.Cells(topology, cells)
|
|
692
|
+
if len(cells) > 1:
|
|
693
|
+
sharedTopologies.append(aFace)
|
|
694
|
+
apertures = []
|
|
695
|
+
_ = aFace.Apertures(apertures)
|
|
696
|
+
for anAperture in apertures:
|
|
697
|
+
sharedApertures.append(anAperture)
|
|
698
|
+
else:
|
|
699
|
+
exteriorTopologies.append(aFace)
|
|
700
|
+
apertures = []
|
|
701
|
+
_ = aFace.Apertures(apertures)
|
|
702
|
+
for anAperture in apertures:
|
|
703
|
+
exteriorApertures.append(anAperture)
|
|
704
|
+
if viaSharedTopologies:
|
|
705
|
+
for sharedTopology in sharedTopologies:
|
|
706
|
+
if useInternalVertex == True:
|
|
707
|
+
vst = Topology.InternalVertex(sharedTopology, tolerance)
|
|
708
|
+
else:
|
|
709
|
+
vst = sharedTopology.CenterOfMass()
|
|
710
|
+
d1 = sharedTopology.GetDictionary()
|
|
711
|
+
if storeBRep:
|
|
712
|
+
d2 = Dictionary.ByKeysValues(["brep", "brepType", "brepTypeString"], [Topology.String(sharedTopology), Topology.Type(sharedTopology), Topology.TypeAsString(sharedTopology)])
|
|
713
|
+
d3 = mergeDictionaries2([d1, d2])
|
|
714
|
+
_ = vst.SetDictionary(d3)
|
|
715
|
+
else:
|
|
716
|
+
_ = vst.SetDictionary(d1)
|
|
717
|
+
vertices.append(vst)
|
|
718
|
+
tempe = topologic.Edge.ByStartVertexEndVertex(vCell, vst)
|
|
719
|
+
tempd = Dictionary.ByKeysValues(["relationship"],["Via Shared Topologies"])
|
|
720
|
+
_ = tempe.SetDictionary(tempd)
|
|
721
|
+
edges.append(tempe)
|
|
722
|
+
if toContents:
|
|
723
|
+
contents = []
|
|
724
|
+
_ = sharedTopology.Contents(contents)
|
|
725
|
+
for content in contents:
|
|
726
|
+
if useInternalVertex == True:
|
|
727
|
+
vst2 = Topology.InternalVertex(content, tolerance)
|
|
728
|
+
else:
|
|
729
|
+
vst2 = content.CenterOfMass()
|
|
730
|
+
d1 = content.GetDictionary()
|
|
731
|
+
vst2 = topologic.Vertex.ByCoordinates(vst2.X(), vst2.Y(), vst2.Z())
|
|
732
|
+
if storeBRep:
|
|
733
|
+
d2 = Dictionary.ByKeysValues(["brep", "brepType", "brepTypeString"], [Topology.String(content), Topology.Type(content), Topology.TypeAsString(content)])
|
|
734
|
+
d3 = mergeDictionaries2([d1, d2])
|
|
735
|
+
_ = vst2.SetDictionary(d3)
|
|
736
|
+
else:
|
|
737
|
+
_ = vst2.SetDictionary(d1)
|
|
738
|
+
vertices.append(vst2)
|
|
739
|
+
tempe = topologic.Edge.ByStartVertexEndVertex(vst, vst2)
|
|
740
|
+
tempd = Dictionary.ByKeysValues(["relationship"],["To Contents"])
|
|
741
|
+
_ = tempe.SetDictionary(tempd)
|
|
742
|
+
edges.append(tempe)
|
|
743
|
+
if viaSharedApertures:
|
|
744
|
+
for sharedAperture in sharedApertures:
|
|
745
|
+
if useInternalVertex == True:
|
|
746
|
+
vst = Topology.InternalVertex(sharedAperture.Topology(), tolerance)
|
|
747
|
+
else:
|
|
748
|
+
vst = sharedAperture.Topology().CenterOfMass()
|
|
749
|
+
d1 = sharedAperture.Topology().GetDictionary()
|
|
750
|
+
if storeBRep:
|
|
751
|
+
d2 = Dictionary.ByKeysValues(["brep", "brepType", "brepTypeString"], [Topology.String(sharedAperture), Topology.Type(sharedAperture), Topology.TypeAsString(sharedAperture)])
|
|
752
|
+
d3 = mergeDictionaries2([d1, d2])
|
|
753
|
+
_ = vst.SetDictionary(d3)
|
|
754
|
+
else:
|
|
755
|
+
_ = vst.SetDictionary(d1)
|
|
756
|
+
vst = topologic.Vertex.ByCoordinates(vst.X()+(tolerance*100), vst.Y()+(tolerance*100), vst.Z()+(tolerance*100))
|
|
757
|
+
vertices.append(vst)
|
|
758
|
+
tempe = topologic.Edge.ByStartVertexEndVertex(vCell, vst)
|
|
759
|
+
tempd = Dictionary.ByKeysValues(["relationship"],["Via Shared Apertures"])
|
|
760
|
+
_ = tempe.SetDictionary(tempd)
|
|
761
|
+
edges.append(tempe)
|
|
762
|
+
if toExteriorTopologies:
|
|
763
|
+
for exteriorTopology in exteriorTopologies:
|
|
764
|
+
if useInternalVertex == True:
|
|
765
|
+
vst = Topology.InternalVertex(exteriorTopology, tolerance)
|
|
766
|
+
else:
|
|
767
|
+
vst = exteriorTopology.CenterOfMass()
|
|
768
|
+
_ = vst.SetDictionary(exteriorTopology.GetDictionary())
|
|
769
|
+
d1 = exteriorTopology.GetDictionary()
|
|
770
|
+
if storeBRep:
|
|
771
|
+
d2 = Dictionary.ByKeysValues(["brep", "brepType", "brepTypeString"], [Topology.String(exteriorTopology), Topology.Type(exteriorTopology), Topology.TypeAsString(exteriorTopology)])
|
|
772
|
+
d3 = mergeDictionaries2([d1, d2])
|
|
773
|
+
_ = vst.SetDictionary(d3)
|
|
774
|
+
else:
|
|
775
|
+
_ = vst.SetDictionary(d1)
|
|
776
|
+
vertices.append(vst)
|
|
777
|
+
tempe = topologic.Edge.ByStartVertexEndVertex(vCell, vst)
|
|
778
|
+
tempd = Dictionary.ByKeysValues(["relationship"],["To Exterior Topologies"])
|
|
779
|
+
_ = tempe.SetDictionary(tempd)
|
|
780
|
+
edges.append(tempe)
|
|
781
|
+
if toContents:
|
|
782
|
+
contents = []
|
|
783
|
+
_ = exteriorTopology.Contents(contents)
|
|
784
|
+
for content in contents:
|
|
785
|
+
if useInternalVertex == True:
|
|
786
|
+
vst2 = Topology.InternalVertex(content, tolerance)
|
|
787
|
+
else:
|
|
788
|
+
vst2 = content.CenterOfMass()
|
|
789
|
+
d1 = content.GetDictionary()
|
|
790
|
+
vst2 = topologic.Vertex.ByCoordinates(vst2.X()+(tolerance*100), vst2.Y()+(tolerance*100), vst2.Z()+(tolerance*100))
|
|
791
|
+
if storeBRep:
|
|
792
|
+
d2 = Dictionary.ByKeysValues(["brep", "brepType", "brepTypeString"], [Topology.String(content), Topology.Type(content), Topology.TypeAsString(content)])
|
|
793
|
+
d3 = mergeDictionaries2([d1, d2])
|
|
794
|
+
_ = vst2.SetDictionary(d3)
|
|
795
|
+
else:
|
|
796
|
+
_ = vst2.SetDictionary(d1)
|
|
797
|
+
vertices.append(vst2)
|
|
798
|
+
tempe = topologic.Edge.ByStartVertexEndVertex(vst, vst2)
|
|
799
|
+
tempd = Dictionary.ByKeysValues(["relationship"],["To Contents"])
|
|
800
|
+
_ = tempe.SetDictionary(tempd)
|
|
801
|
+
edges.append(tempe)
|
|
802
|
+
if toExteriorApertures:
|
|
803
|
+
for exteriorAperture in exteriorApertures:
|
|
804
|
+
extTop = exteriorAperture.Topology()
|
|
805
|
+
if useInternalVertex == True:
|
|
806
|
+
vst = Topology.InternalVertex(extTop, tolerance)
|
|
807
|
+
else:
|
|
808
|
+
vst = exteriorAperture.Topology().CenterOfMass()
|
|
809
|
+
d1 = exteriorAperture.Topology().GetDictionary()
|
|
810
|
+
vst = topologic.Vertex.ByCoordinates(vst.X()+(tolerance*100), vst.Y()+(tolerance*100), vst.Z()+(tolerance*100))
|
|
811
|
+
if storeBRep:
|
|
812
|
+
d2 = Dictionary.ByKeysValues(["brep", "brepType", "brepTypeString"], [Topology.String(exteriorAperture), Topology.Type(exteriorAperture), Topology.TypeAsString(exteriorAperture)])
|
|
813
|
+
d3 = mergeDictionaries2([d1, d2])
|
|
814
|
+
_ = vst.SetDictionary(d3)
|
|
815
|
+
else:
|
|
816
|
+
_ = vst.SetDictionary(d1)
|
|
817
|
+
vertices.append(vst)
|
|
818
|
+
tempe = topologic.Edge.ByStartVertexEndVertex(vCell, vst)
|
|
819
|
+
tempd = Dictionary.ByKeysValues(["relationship"],["To Exterior Apertures"])
|
|
820
|
+
_ = tempe.SetDictionary(tempd)
|
|
821
|
+
edges.append(tempe)
|
|
822
|
+
if toContents:
|
|
823
|
+
contents = []
|
|
824
|
+
_ = aCell.Contents(contents)
|
|
825
|
+
for content in contents:
|
|
826
|
+
if useInternalVertex == True:
|
|
827
|
+
vst = Topology.InternalVertex(content, tolerance)
|
|
828
|
+
else:
|
|
829
|
+
vst = content.CenterOfMass()
|
|
830
|
+
vst = topologic.Vertex.ByCoordinates(vst.X()+(tolerance*100), vst.Y()+(tolerance*100), vst.Z()+(tolerance*100))
|
|
831
|
+
d1 = content.GetDictionary()
|
|
832
|
+
if storeBRep:
|
|
833
|
+
d2 = Dictionary.ByKeysValues(["brep", "brepType", "brepTypeString"], [Topology.String(content), Topology.Type(content), Topology.TypeAsString(content)])
|
|
834
|
+
d3 = mergeDictionaries2([d1, d2])
|
|
835
|
+
_ = vst.SetDictionary(d3)
|
|
836
|
+
else:
|
|
837
|
+
_ = vst.SetDictionary(d1)
|
|
838
|
+
vertices.append(vst)
|
|
839
|
+
tempe = topologic.Edge.ByStartVertexEndVertex(vCell, vst)
|
|
840
|
+
tempd = Dictionary.ByKeysValues(["relationship"],["To Contents"])
|
|
841
|
+
_ = tempe.SetDictionary(tempd)
|
|
842
|
+
edges.append(tempe)
|
|
843
|
+
|
|
844
|
+
for aCell in cells:
|
|
845
|
+
if useInternalVertex == True:
|
|
846
|
+
vCell = topologic.CellUtility.InternalVertex(aCell, tolerance)
|
|
847
|
+
else:
|
|
848
|
+
vCell = aCell.CenterOfMass()
|
|
849
|
+
d1 = aCell.GetDictionary()
|
|
850
|
+
if storeBRep:
|
|
851
|
+
d2 = Dictionary.ByKeysValues(["brep", "brepType", "brepTypeString"], [Topology.String(aCell), Topology.Type(aCell), Topology.TypeAsString(aCell)])
|
|
852
|
+
d3 = mergeDictionaries2([d1, d2])
|
|
853
|
+
_ = vCell.SetDictionary(d3)
|
|
854
|
+
else:
|
|
855
|
+
_ = vCell.SetDictionary(d1)
|
|
856
|
+
vertices.append(vCell)
|
|
857
|
+
return [vertices,edges]
|
|
858
|
+
|
|
859
|
+
def processCell(item):
|
|
860
|
+
topology, others, outpostsKey, idKey, direct, directApertures, viaSharedTopologies, viaSharedApertures, toExteriorTopologies, toExteriorApertures, toContents, toOutposts, useInternalVertex, storeBRep, tolerance = item
|
|
861
|
+
vertices = []
|
|
862
|
+
edges = []
|
|
863
|
+
|
|
864
|
+
if useInternalVertex == True:
|
|
865
|
+
vCell = topologic.CellUtility.InternalVertex(topology, tolerance)
|
|
866
|
+
else:
|
|
867
|
+
vCell = topology.CenterOfMass()
|
|
868
|
+
d1 = topology.GetDictionary()
|
|
869
|
+
if storeBRep:
|
|
870
|
+
d2 = Dictionary.ByKeysValues(["brep", "brepType", "brepTypeString"], [Topology.String(topology), Topology.Type(topology), Topology.TypeAsString(topology)])
|
|
871
|
+
d3 = mergeDictionaries2([d1, d2])
|
|
872
|
+
_ = vCell.SetDictionary(d3)
|
|
873
|
+
else:
|
|
874
|
+
_ = vCell.SetDictionary(d1)
|
|
875
|
+
vertices.append(vCell)
|
|
876
|
+
|
|
877
|
+
if toOutposts and others:
|
|
878
|
+
d = Topology.Dictionary(topology)
|
|
879
|
+
keys = Dictionary.Keys(d)
|
|
880
|
+
k = None
|
|
881
|
+
for key in keys:
|
|
882
|
+
if key.lower() == outpostsKey.lower():
|
|
883
|
+
k = key
|
|
884
|
+
if k:
|
|
885
|
+
ids = Dictionary.ValueAtKey(d, k)
|
|
886
|
+
outposts = outpostsByID(others, ids, idKey)
|
|
887
|
+
else:
|
|
888
|
+
outposts = []
|
|
889
|
+
for outpost in outposts:
|
|
890
|
+
if useInternalVertex == True:
|
|
891
|
+
vop = Topology.InternalVertex(outpost, tolerance)
|
|
892
|
+
else:
|
|
893
|
+
vop = Topology.CenterOfMass(outpost)
|
|
894
|
+
tempe = topologic.Edge.ByStartVertexEndVertex(vCell, vop)
|
|
895
|
+
tempd = Dictionary.ByKeysValues(["relationship"],["To Outposts"])
|
|
896
|
+
_ = tempe.SetDictionary(tempd)
|
|
897
|
+
edges.append(tempe)
|
|
898
|
+
if (toExteriorTopologies == True) or (toExteriorApertures == True) or (toContents == True):
|
|
899
|
+
faces = []
|
|
900
|
+
_ = topology.Faces(None, faces)
|
|
901
|
+
exteriorTopologies = []
|
|
902
|
+
exteriorApertures = []
|
|
903
|
+
for aFace in faces:
|
|
904
|
+
exteriorTopologies.append(aFace)
|
|
905
|
+
apertures = []
|
|
906
|
+
_ = aFace.Apertures(apertures)
|
|
907
|
+
for anAperture in apertures:
|
|
908
|
+
exteriorApertures.append(anAperture)
|
|
909
|
+
if toExteriorTopologies:
|
|
910
|
+
for exteriorTopology in exteriorTopologies:
|
|
911
|
+
if useInternalVertex == True:
|
|
912
|
+
vst = Topology.InternalVertex(exteriorTopology, tolerance)
|
|
913
|
+
else:
|
|
914
|
+
vst = exteriorTopology.CenterOfMass()
|
|
915
|
+
d1 = exteriorTopology.GetDictionary()
|
|
916
|
+
if storeBRep:
|
|
917
|
+
d2 = Dictionary.ByKeysValues(["brep", "brepType", "brepTypeString"], [Topology.String(exteriorTopology), Topology.Type(exteriorTopology), Topology.TypeAsString(exteriorTopology)])
|
|
918
|
+
d3 = mergeDictionaries2([d1, d2])
|
|
919
|
+
_ = vst.SetDictionary(d3)
|
|
920
|
+
else:
|
|
921
|
+
_ = vst.SetDictionary(d1)
|
|
922
|
+
vertices.append(vst)
|
|
923
|
+
tempe = topologic.Edge.ByStartVertexEndVertex(vCell, vst)
|
|
924
|
+
tempd = Dictionary.ByKeysValues(["relationship"],["To Exterior Topologies"])
|
|
925
|
+
_ = tempe.SetDictionary(tempd)
|
|
926
|
+
edges.append(tempe)
|
|
927
|
+
if toContents:
|
|
928
|
+
contents = []
|
|
929
|
+
_ = exteriorTopology.Contents(contents)
|
|
930
|
+
for content in contents:
|
|
931
|
+
if useInternalVertex == True:
|
|
932
|
+
vst2 = Topology.InternalVertex(content, tolerance)
|
|
933
|
+
else:
|
|
934
|
+
vst2 = content.CenterOfMass()
|
|
935
|
+
vst2 = topologic.Vertex.ByCoordinates(vst2.X()+(tolerance*100), vst2.Y()+(tolerance*100), vst2.Z()+(tolerance*100))
|
|
936
|
+
d1 = content.GetDictionary()
|
|
937
|
+
if storeBRep:
|
|
938
|
+
d2 = Dictionary.ByKeysValues(["brep", "brepType", "brepTypeString"], [Topology.String(content), Topology.Type(content), Topology.TypeAsString(content)])
|
|
939
|
+
d3 = mergeDictionaries2([d1, d2])
|
|
940
|
+
_ = vst2.SetDictionary(d3)
|
|
941
|
+
else:
|
|
942
|
+
_ = vst2.SetDictionary(d1)
|
|
943
|
+
vertices.append(vst2)
|
|
944
|
+
tempe = topologic.Edge.ByStartVertexEndVertex(vst, vst2)
|
|
945
|
+
tempd = Dictionary.ByKeysValues(["relationship"],["To Contents"])
|
|
946
|
+
_ = tempe.SetDictionary(tempd)
|
|
947
|
+
edges.append(tempe)
|
|
948
|
+
if toExteriorApertures:
|
|
949
|
+
for exteriorAperture in exteriorApertures:
|
|
950
|
+
extTop = exteriorAperture.Topology()
|
|
951
|
+
if useInternalVertex == True:
|
|
952
|
+
vst = Topology.InternalVertex(extTop, tolerance)
|
|
953
|
+
else:
|
|
954
|
+
vst = exteriorAperture.Topology().CenterOfMass()
|
|
955
|
+
d1 = exteriorAperture.Topology().GetDictionary()
|
|
956
|
+
vst = topologic.Vertex.ByCoordinates(vst.X()+(tolerance*100), vst.Y()+(tolerance*100), vst.Z()+(tolerance*100))
|
|
957
|
+
if storeBRep:
|
|
958
|
+
d2 = Dictionary.ByKeysValues(["brep", "brepType", "brepTypeString"], [Topology.String(Aperture.Topology(exteriorAperture)), Topology.Type(Aperture.Topology(exteriorAperture)), Topology.TypeAsString(Aperture.Topology(exteriorAperture))])
|
|
959
|
+
d3 = mergeDictionaries2([d1, d2])
|
|
960
|
+
_ = vst.SetDictionary(d3)
|
|
961
|
+
else:
|
|
962
|
+
_ = vst.SetDictionary(d1)
|
|
963
|
+
vertices.append(vst)
|
|
964
|
+
tempe = topologic.Edge.ByStartVertexEndVertex(vCell, vst)
|
|
965
|
+
tempd = Dictionary.ByKeysValues(["relationship"],["To Exterior Apertures"])
|
|
966
|
+
_ = tempe.SetDictionary(tempd)
|
|
967
|
+
edges.append(tempe)
|
|
968
|
+
if toContents:
|
|
969
|
+
contents = []
|
|
970
|
+
_ = topology.Contents(contents)
|
|
971
|
+
for content in contents:
|
|
972
|
+
if useInternalVertex == True:
|
|
973
|
+
vst = Topology.InternalVertex(content, tolerance)
|
|
974
|
+
else:
|
|
975
|
+
vst = content.CenterOfMass()
|
|
976
|
+
vst = topologic.Vertex.ByCoordinates(vst.X()+(tolerance*100), vst.Y()+(tolerance*100), vst.Z()+(tolerance*100))
|
|
977
|
+
d1 = content.GetDictionary()
|
|
978
|
+
if storeBRep:
|
|
979
|
+
d2 = Dictionary.ByKeysValues(["brep", "brepType", "brepTypeString"], [Topology.String(content), Topology.Type(content), Topology.TypeAsString(content)])
|
|
980
|
+
d3 = mergeDictionaries2([d1, d2])
|
|
981
|
+
_ = vst.SetDictionary(d3)
|
|
982
|
+
else:
|
|
983
|
+
_ = vst.SetDictionary(d1)
|
|
984
|
+
vertices.append(vst)
|
|
985
|
+
tempe = topologic.Edge.ByStartVertexEndVertex(vCell, vst)
|
|
986
|
+
tempd = Dictionary.ByKeysValues(["relationship"],["To Contents"])
|
|
987
|
+
_ = tempe.SetDictionary(tempd)
|
|
988
|
+
edges.append(tempe)
|
|
989
|
+
return [vertices, edges]
|
|
990
|
+
|
|
991
|
+
def processShell(item):
|
|
992
|
+
topology, others, outpostsKey, idKey, direct, directApertures, viaSharedTopologies, viaSharedApertures, toExteriorTopologies, toExteriorApertures, toContents, toOutposts, useInternalVertex, storeBRep, tolerance = item
|
|
993
|
+
graph = None
|
|
994
|
+
edges = []
|
|
995
|
+
vertices = []
|
|
996
|
+
facemat = []
|
|
997
|
+
if direct == True:
|
|
998
|
+
topFaces = []
|
|
999
|
+
_ = topology.Faces(None, topFaces)
|
|
1000
|
+
# Create a matrix of zeroes
|
|
1001
|
+
for i in range(len(topFaces)):
|
|
1002
|
+
faceRow = []
|
|
1003
|
+
for j in range(len(topFaces)):
|
|
1004
|
+
faceRow.append(0)
|
|
1005
|
+
facemat.append(faceRow)
|
|
1006
|
+
for i in range(len(topFaces)):
|
|
1007
|
+
for j in range(len(topFaces)):
|
|
1008
|
+
if (i != j) and facemat[i][j] == 0:
|
|
1009
|
+
facemat[i][j] = 1
|
|
1010
|
+
facemat[j][i] = 1
|
|
1011
|
+
sharedt = Topology.SharedEdges(topFaces[i], topFaces[j])
|
|
1012
|
+
if len(sharedt) > 0:
|
|
1013
|
+
if useInternalVertex == True:
|
|
1014
|
+
v1 = topologic.FaceUtility.InternalVertex(topFaces[i], tolerance)
|
|
1015
|
+
v2 = topologic.FaceUtility.InternalVertex(topFaces[j], tolerance)
|
|
1016
|
+
else:
|
|
1017
|
+
v1 = topFaces[i].CenterOfMass()
|
|
1018
|
+
v2 = topFaces[j].CenterOfMass()
|
|
1019
|
+
e = topologic.Edge.ByStartVertexEndVertex(v1, v2)
|
|
1020
|
+
mDict = mergeDictionaries(sharedt)
|
|
1021
|
+
if mDict:
|
|
1022
|
+
e.SetDictionary(mDict)
|
|
1023
|
+
edges.append(e)
|
|
1024
|
+
if directApertures == True:
|
|
1025
|
+
facemat = []
|
|
1026
|
+
topFaces = []
|
|
1027
|
+
_ = topology.Faces(None, topFaces)
|
|
1028
|
+
# Create a matrix of zeroes
|
|
1029
|
+
for i in range(len(topFaces)):
|
|
1030
|
+
faceRow = []
|
|
1031
|
+
for j in range(len(topFaces)):
|
|
1032
|
+
faceRow.append(0)
|
|
1033
|
+
facemat.append(faceRow)
|
|
1034
|
+
for i in range(len(topFaces)):
|
|
1035
|
+
for j in range(len(topFaces)):
|
|
1036
|
+
if (i != j) and facemat[i][j] == 0:
|
|
1037
|
+
facemat[i][j] = 1
|
|
1038
|
+
facemat[j][i] = 1
|
|
1039
|
+
sharedt = Topology.SharedEdges(topFaces[i], topFaces[j])
|
|
1040
|
+
if len(sharedt) > 0:
|
|
1041
|
+
apertureExists = False
|
|
1042
|
+
for x in sharedt:
|
|
1043
|
+
apList = []
|
|
1044
|
+
_ = x.Apertures(apList)
|
|
1045
|
+
if len(apList) > 0:
|
|
1046
|
+
apertureExists = True
|
|
1047
|
+
break
|
|
1048
|
+
if apertureExists:
|
|
1049
|
+
apTopList = []
|
|
1050
|
+
for ap in apList:
|
|
1051
|
+
apTopList.append(ap.Topology())
|
|
1052
|
+
if useInternalVertex == True:
|
|
1053
|
+
v1 = topologic.FaceUtility.InternalVertex(topFaces[i], tolerance)
|
|
1054
|
+
v2 = topologic.FaceUtility.InternalVertex(topFaces[j], tolerance)
|
|
1055
|
+
else:
|
|
1056
|
+
v1 = topFaces[i].CenterOfMass()
|
|
1057
|
+
v2 = topFaces[j].CenterOfMass()
|
|
1058
|
+
e = topologic.Edge.ByStartVertexEndVertex(v1, v2)
|
|
1059
|
+
mDict = mergeDictionaries(apTopList)
|
|
1060
|
+
if mDict:
|
|
1061
|
+
e.SetDictionary(mDict)
|
|
1062
|
+
edges.append(e)
|
|
1063
|
+
|
|
1064
|
+
topFaces = []
|
|
1065
|
+
_ = topology.Faces(None, topFaces)
|
|
1066
|
+
if (viaSharedTopologies == True) or (viaSharedApertures == True) or (toExteriorTopologies == True) or (toExteriorApertures == True) or (toContents == True):
|
|
1067
|
+
for aFace in topFaces:
|
|
1068
|
+
if useInternalVertex == True:
|
|
1069
|
+
vFace = topologic.FaceUtility.InternalVertex(aFace, tolerance)
|
|
1070
|
+
else:
|
|
1071
|
+
vFace = aFace.CenterOfMass()
|
|
1072
|
+
_ = vFace.SetDictionary(aFace.GetDictionary())
|
|
1073
|
+
vertices.append(vFace)
|
|
1074
|
+
fEdges = []
|
|
1075
|
+
_ = aFace.Edges(None, fEdges)
|
|
1076
|
+
sharedTopologies = []
|
|
1077
|
+
exteriorTopologies = []
|
|
1078
|
+
sharedApertures = []
|
|
1079
|
+
exteriorApertures = []
|
|
1080
|
+
for anEdge in fEdges:
|
|
1081
|
+
faces = []
|
|
1082
|
+
_ = anEdge.Faces(topology, faces)
|
|
1083
|
+
if len(faces) > 1:
|
|
1084
|
+
sharedTopologies.append(anEdge)
|
|
1085
|
+
apertures = []
|
|
1086
|
+
_ = anEdge.Apertures(apertures)
|
|
1087
|
+
for anAperture in apertures:
|
|
1088
|
+
sharedApertures.append(anAperture)
|
|
1089
|
+
else:
|
|
1090
|
+
exteriorTopologies.append(anEdge)
|
|
1091
|
+
apertures = []
|
|
1092
|
+
_ = anEdge.Apertures(apertures)
|
|
1093
|
+
for anAperture in apertures:
|
|
1094
|
+
exteriorApertures.append(anAperture)
|
|
1095
|
+
if viaSharedTopologies:
|
|
1096
|
+
for sharedTopology in sharedTopologies:
|
|
1097
|
+
if useInternalVertex == True:
|
|
1098
|
+
vst = Topology.InternalVertex(sharedTopology, tolerance)
|
|
1099
|
+
else:
|
|
1100
|
+
vst = sharedTopology.CenterOfMass()
|
|
1101
|
+
d1 = sharedTopology.GetDictionary()
|
|
1102
|
+
if storeBRep:
|
|
1103
|
+
d2 = Dictionary.ByKeysValues(["brep", "brepType", "brepTypeString"], [Topology.String(sharedTopology), Topology.Type(sharedTopology), Topology.TypeAsString(sharedTopology)])
|
|
1104
|
+
d3 = mergeDictionaries2([d1, d2])
|
|
1105
|
+
_ = vst.SetDictionary(d3)
|
|
1106
|
+
else:
|
|
1107
|
+
_ = vst.SetDictionary(d1)
|
|
1108
|
+
vertices.append(vst)
|
|
1109
|
+
tempe = topologic.Edge.ByStartVertexEndVertex(vFace, vst)
|
|
1110
|
+
tempd = Dictionary.ByKeysValues(["relationship"],["Via Shared Topologies"])
|
|
1111
|
+
_ = tempe.SetDictionary(tempd)
|
|
1112
|
+
edges.append(tempe)
|
|
1113
|
+
if toContents:
|
|
1114
|
+
contents = []
|
|
1115
|
+
_ = sharedTopology.Contents(contents)
|
|
1116
|
+
for content in contents:
|
|
1117
|
+
if useInternalVertex == True:
|
|
1118
|
+
vst2 = Topology.InternalVertex(content, tolerance)
|
|
1119
|
+
else:
|
|
1120
|
+
vst2 = content.CenterOfMass()
|
|
1121
|
+
vst2 = topologic.Vertex.ByCoordinates(vst2.X()+(tolerance*100), vst2.Y()+(tolerance*100), vst2.Z()+(tolerance*100))
|
|
1122
|
+
d1 = content.GetDictionary()
|
|
1123
|
+
if storeBRep:
|
|
1124
|
+
d2 = Dictionary.ByKeysValues(["brep", "brepType", "brepTypeString"], [Topology.String(content), Topology.Type(content), Topology.TypeAsString(content)])
|
|
1125
|
+
d3 = mergeDictionaries2([d1, d2])
|
|
1126
|
+
_ = vst2.SetDictionary(d3)
|
|
1127
|
+
else:
|
|
1128
|
+
_ = vst2.SetDictionary(d1)
|
|
1129
|
+
vertices.append(vst2)
|
|
1130
|
+
tempe = topologic.Edge.ByStartVertexEndVertex(vst, vst2)
|
|
1131
|
+
tempd = Dictionary.ByKeysValues(["relationship"],["To Contents"])
|
|
1132
|
+
_ = tempe.SetDictionary(tempd)
|
|
1133
|
+
edges.append(tempe)
|
|
1134
|
+
if viaSharedApertures:
|
|
1135
|
+
for sharedAperture in sharedApertures:
|
|
1136
|
+
if useInternalVertex == True:
|
|
1137
|
+
vst = Topology.InternalVertex(sharedAperture.Topology(), tolerance)
|
|
1138
|
+
else:
|
|
1139
|
+
vst = sharedAperture.Topology().CenterOfMass()
|
|
1140
|
+
d1 = sharedAperture.Topology().GetDictionary()
|
|
1141
|
+
vst = topologic.Vertex.ByCoordinates(vst.X()+(tolerance*100), vst.Y()+(tolerance*100), vst.Z()+(tolerance*100))
|
|
1142
|
+
if storeBRep:
|
|
1143
|
+
d2 = Dictionary.ByKeysValues(["brep", "brepType", "brepTypeString"], [Topology.String(Aperture.Topology(sharedAperture)), Topology.Type(Aperture.Topology(sharedAperture)), Topology.TypeAsString(Aperture.Topology(sharedAperture))])
|
|
1144
|
+
d3 = mergeDictionaries2([d1, d2])
|
|
1145
|
+
_ = vst.SetDictionary(d3)
|
|
1146
|
+
else:
|
|
1147
|
+
_ = vst.SetDictionary(d1)
|
|
1148
|
+
vertices.append(vst)
|
|
1149
|
+
tempe = topologic.Edge.ByStartVertexEndVertex(vFace, vst)
|
|
1150
|
+
tempd = Dictionary.ByKeysValues(["relationship"],["Via Shared Apertures"])
|
|
1151
|
+
_ = tempe.SetDictionary(tempd)
|
|
1152
|
+
edges.append(tempe)
|
|
1153
|
+
if toExteriorTopologies:
|
|
1154
|
+
for exteriorTopology in exteriorTopologies:
|
|
1155
|
+
if useInternalVertex == True:
|
|
1156
|
+
vst = Topology.InternalVertex(exteriorTopology, tolerance)
|
|
1157
|
+
else:
|
|
1158
|
+
vst = exteriorTopology.CenterOfMass()
|
|
1159
|
+
d1 = exteriorTopology.GetDictionary()
|
|
1160
|
+
if storeBRep:
|
|
1161
|
+
d2 = Dictionary.ByKeysValues(["brep", "brepType", "brepTypeString"], [Topology.String(exteriorTopology), Topology.Type(exteriorTopology), Topology.TypeAsString(exteriorTopology)])
|
|
1162
|
+
d3 = mergeDictionaries2([d1, d2])
|
|
1163
|
+
_ = vst.SetDictionary(d3)
|
|
1164
|
+
else:
|
|
1165
|
+
_ = vst.SetDictionary(d1)
|
|
1166
|
+
vertices.append(vst)
|
|
1167
|
+
tempe = topologic.Edge.ByStartVertexEndVertex(vFace, vst)
|
|
1168
|
+
tempd = Dictionary.ByKeysValues(["relationship"],["To Exterior Apertures"])
|
|
1169
|
+
_ = tempe.SetDictionary(tempd)
|
|
1170
|
+
edges.append(tempe)
|
|
1171
|
+
if toContents:
|
|
1172
|
+
contents = []
|
|
1173
|
+
_ = exteriorTopology.Contents(contents)
|
|
1174
|
+
for content in contents:
|
|
1175
|
+
if useInternalVertex == True:
|
|
1176
|
+
vst2 = Topology.InternalVertex(content, tolerance)
|
|
1177
|
+
else:
|
|
1178
|
+
vst2 = content.CenterOfMass()
|
|
1179
|
+
vst2 = topologic.Vertex.ByCoordinates(vst2.X()+(tolerance*100), vst2.Y()+(tolerance*100), vst2.Z()+(tolerance*100))
|
|
1180
|
+
d1 = content.GetDictionary()
|
|
1181
|
+
if storeBRep:
|
|
1182
|
+
d2 = Dictionary.ByKeysValues(["brep", "brepType", "brepTypeString"], [Topology.String(content), Topology.Type(content), Topology.TypeAsString(content)])
|
|
1183
|
+
d3 = mergeDictionaries2([d1, d2])
|
|
1184
|
+
_ = vst2.SetDictionary(d3)
|
|
1185
|
+
else:
|
|
1186
|
+
_ = vst2.SetDictionary(d1)
|
|
1187
|
+
vertices.append(vst2)
|
|
1188
|
+
tempe = topologic.Edge.ByStartVertexEndVertex(vst, vst2)
|
|
1189
|
+
tempd = Dictionary.ByKeysValues(["relationship"],["To Contents"])
|
|
1190
|
+
_ = tempe.SetDictionary(tempd)
|
|
1191
|
+
edges.append(tempe)
|
|
1192
|
+
if toExteriorApertures:
|
|
1193
|
+
for exteriorAperture in exteriorApertures:
|
|
1194
|
+
extTop = exteriorAperture.Topology()
|
|
1195
|
+
if useInternalVertex == True:
|
|
1196
|
+
vst = Topology.InternalVertex(extTop, tolerance)
|
|
1197
|
+
else:
|
|
1198
|
+
vst = exteriorAperture.Topology().CenterOfMass()
|
|
1199
|
+
d1 = exteriorAperture.Topology().GetDictionary()
|
|
1200
|
+
vst = topologic.Vertex.ByCoordinates(vst.X()+(tolerance*100), vst.Y()+(tolerance*100), vst.Z()+(tolerance*100))
|
|
1201
|
+
if storeBRep:
|
|
1202
|
+
d2 = Dictionary.ByKeysValues(["brep", "brepType", "brepTypeString"], [Topology.String(Aperture.Topology(exteriorAperture)), Topology.Type(Aperture.Topology(exteriorAperture)), Topology.TypeAsString(Aperture.Topology(exteriorAperture))])
|
|
1203
|
+
d3 = mergeDictionaries2([d1, d2])
|
|
1204
|
+
_ = vst.SetDictionary(d3)
|
|
1205
|
+
else:
|
|
1206
|
+
_ = vst.SetDictionary(d1)
|
|
1207
|
+
vertices.append(vst)
|
|
1208
|
+
tempe = topologic.Edge.ByStartVertexEndVertex(vFace, vst)
|
|
1209
|
+
tempd = Dictionary.ByKeysValues(["relationship"],["To Exterior Apertures"])
|
|
1210
|
+
_ = tempe.SetDictionary(tempd)
|
|
1211
|
+
edges.append(tempe)
|
|
1212
|
+
if toContents:
|
|
1213
|
+
contents = []
|
|
1214
|
+
_ = aFace.Contents(contents)
|
|
1215
|
+
for content in contents:
|
|
1216
|
+
if useInternalVertex == True:
|
|
1217
|
+
vst = Topology.InternalVertex(content, tolerance)
|
|
1218
|
+
else:
|
|
1219
|
+
vst = content.CenterOfMass()
|
|
1220
|
+
vst = topologic.Vertex.ByCoordinates(vst.X()+(tolerance*100), vst.Y()+(tolerance*100), vst.Z()+(tolerance*100))
|
|
1221
|
+
d1 = content.GetDictionary()
|
|
1222
|
+
if storeBRep:
|
|
1223
|
+
d2 = Dictionary.ByKeysValues(["brep", "brepType", "brepTypeString"], [Topology.String(content), Topology.Type(content), Topology.TypeAsString(content)])
|
|
1224
|
+
d3 = mergeDictionaries2([d1, d2])
|
|
1225
|
+
_ = vst.SetDictionary(d3)
|
|
1226
|
+
else:
|
|
1227
|
+
_ = vst.SetDictionary(d1)
|
|
1228
|
+
vertices.append(vst)
|
|
1229
|
+
tempe = topologic.Edge.ByStartVertexEndVertex(vFace, vst)
|
|
1230
|
+
tempd = Dictionary.ByKeysValues(["relationship"],["To Contents"])
|
|
1231
|
+
_ = tempe.SetDictionary(tempd)
|
|
1232
|
+
edges.append(tempe)
|
|
1233
|
+
|
|
1234
|
+
for aFace in topFaces:
|
|
1235
|
+
if useInternalVertex == True:
|
|
1236
|
+
vFace = Topology.InternalVertex(aFace, tolerance)
|
|
1237
|
+
else:
|
|
1238
|
+
vFace = aFace.CenterOfMass()
|
|
1239
|
+
d1 = aFace.GetDictionary()
|
|
1240
|
+
if storeBRep:
|
|
1241
|
+
d2 = Dictionary.ByKeysValues(["brep", "brepType", "brepTypeString"], [Topology.String(aFace), Topology.Type(aFace), Topology.TypeAsString(aFace)])
|
|
1242
|
+
d3 = mergeDictionaries2([d1, d2])
|
|
1243
|
+
_ = vFace.SetDictionary(d3)
|
|
1244
|
+
else:
|
|
1245
|
+
_ = vFace.SetDictionary(d1)
|
|
1246
|
+
vertices.append(vFace)
|
|
1247
|
+
if toOutposts and others:
|
|
1248
|
+
d = Topology.Dictionary(topology)
|
|
1249
|
+
keys = Dictionary.Keys(d)
|
|
1250
|
+
k = None
|
|
1251
|
+
for key in keys:
|
|
1252
|
+
if key.lower() == outpostsKey.lower():
|
|
1253
|
+
k = key
|
|
1254
|
+
if k:
|
|
1255
|
+
ids = Dictionary.ValueAtKey(k)
|
|
1256
|
+
outposts = outpostsByID(others, ids, idKey)
|
|
1257
|
+
else:
|
|
1258
|
+
outposts = []
|
|
1259
|
+
for outpost in outposts:
|
|
1260
|
+
if useInternalVertex == True:
|
|
1261
|
+
vop = Topology.InternalVertex(outpost, tolerance)
|
|
1262
|
+
vcc = Topology.InternalVertex(topology, tolerance)
|
|
1263
|
+
else:
|
|
1264
|
+
vop = Topology.CenterOfMass(outpost)
|
|
1265
|
+
vcc = Topology.CenterOfMass(topology)
|
|
1266
|
+
d1 = Topology.Dictionary(vcc)
|
|
1267
|
+
if storeBRep:
|
|
1268
|
+
d2 = Dictionary.ByKeysValues(["brep", "brepType", "brepTypeString"], [Topology.String(topology), Topology.Type(topology), Topology.TypeAsString(topology)])
|
|
1269
|
+
d3 = mergeDictionaries2([d1, d2])
|
|
1270
|
+
_ = vcc.SetDictionary(d3)
|
|
1271
|
+
else:
|
|
1272
|
+
_ = vcc.SetDictionary(d1)
|
|
1273
|
+
vertices.append(vcc)
|
|
1274
|
+
tempe = topologic.Edge.ByStartVertexEndVertex(vcc, vop)
|
|
1275
|
+
tempd = Dictionary.ByKeysValues(["relationship"],["To Outposts"])
|
|
1276
|
+
_ = tempe.SetDictionary(tempd)
|
|
1277
|
+
edges.append(tempe)
|
|
1278
|
+
return [vertices, edges]
|
|
1279
|
+
|
|
1280
|
+
def processFace(item):
|
|
1281
|
+
topology, others, outpostsKey, idKey, direct, directApertures, viaSharedTopologies, viaSharedApertures, toExteriorTopologies, toExteriorApertures, toContents, toOutposts, useInternalVertex, storeBRep, tolerance = item
|
|
1282
|
+
graph = None
|
|
1283
|
+
vertices = []
|
|
1284
|
+
edges = []
|
|
1285
|
+
|
|
1286
|
+
if useInternalVertex == True:
|
|
1287
|
+
vFace = topologic.FaceUtility.InternalVertex(topology, tolerance)
|
|
1288
|
+
else:
|
|
1289
|
+
vFace = topology.CenterOfMass()
|
|
1290
|
+
d1 = topology.GetDictionary()
|
|
1291
|
+
if storeBRep:
|
|
1292
|
+
d2 = Dictionary.ByKeysValues(["brep", "brepType", "brepTypeString"], [Topology.String(topology), Topology.Type(topology), Topology.TypeAsString(topology)])
|
|
1293
|
+
d3 = mergeDictionaries2([d1, d2])
|
|
1294
|
+
_ = vFace.SetDictionary(d3)
|
|
1295
|
+
else:
|
|
1296
|
+
_ = vFace.SetDictionary(d1)
|
|
1297
|
+
vertices.append(vFace)
|
|
1298
|
+
if toOutposts and others:
|
|
1299
|
+
d = Topology.Dictionary(topology)
|
|
1300
|
+
keys = Dictionary.Keys(d)
|
|
1301
|
+
k = None
|
|
1302
|
+
for key in keys:
|
|
1303
|
+
if key.lower() == outpostsKey.lower():
|
|
1304
|
+
k = key
|
|
1305
|
+
if k:
|
|
1306
|
+
ids = Dictionary.ValueAtKey(d, k)
|
|
1307
|
+
outposts = outpostsByID(others, ids, idKey)
|
|
1308
|
+
else:
|
|
1309
|
+
outposts = []
|
|
1310
|
+
for outpost in outposts:
|
|
1311
|
+
if useInternalVertex == True:
|
|
1312
|
+
vop = Topology.InternalVertex(outpost, tolerance)
|
|
1313
|
+
else:
|
|
1314
|
+
vop = Topology.CenterOfMass(outpost)
|
|
1315
|
+
tempe = topologic.Edge.ByStartVertexEndVertex(vFace, vop)
|
|
1316
|
+
tempd = Dictionary.ByKeysValues(["relationship"],["To Outposts"])
|
|
1317
|
+
_ = tempe.SetDictionary(tempd)
|
|
1318
|
+
edges.append(tempe)
|
|
1319
|
+
if (toExteriorTopologies == True) or (toExteriorApertures == True) or (toContents == True):
|
|
1320
|
+
fEdges = []
|
|
1321
|
+
_ = topology.Edges(None, fEdges)
|
|
1322
|
+
exteriorTopologies = []
|
|
1323
|
+
exteriorApertures = []
|
|
1324
|
+
|
|
1325
|
+
for anEdge in fEdges:
|
|
1326
|
+
exteriorTopologies.append(anEdge)
|
|
1327
|
+
apertures = []
|
|
1328
|
+
_ = anEdge.Apertures(apertures)
|
|
1329
|
+
for anAperture in apertures:
|
|
1330
|
+
exteriorApertures.append(anAperture)
|
|
1331
|
+
if toExteriorTopologies:
|
|
1332
|
+
for exteriorTopology in exteriorTopologies:
|
|
1333
|
+
if useInternalVertex == True:
|
|
1334
|
+
vst = Topology.InternalVertex(exteriorTopology, tolerance)
|
|
1335
|
+
else:
|
|
1336
|
+
vst = exteriorTopology.CenterOfMass()
|
|
1337
|
+
d1 = exteriorTopology.GetDictionary()
|
|
1338
|
+
if storeBRep:
|
|
1339
|
+
d2 = Dictionary.ByKeysValues(["brep", "brepType", "brepTypeString"], [Topology.String(exteriorTopology), Topology.Type(exteriorTopology), Topology.TypeAsString(exteriorTopology)])
|
|
1340
|
+
d3 = mergeDictionaries2([d1, d2])
|
|
1341
|
+
_ = vst.SetDictionary(d3)
|
|
1342
|
+
else:
|
|
1343
|
+
_ = vst.SetDictionary(d1)
|
|
1344
|
+
vertices.append(vst)
|
|
1345
|
+
tempe = topologic.Edge.ByStartVertexEndVertex(vFace, vst)
|
|
1346
|
+
tempd = Dictionary.ByKeysValues(["relationship"],["To Exterior Topologies"])
|
|
1347
|
+
_ = tempe.SetDictionary(tempd)
|
|
1348
|
+
edges.append(tempe)
|
|
1349
|
+
if toContents:
|
|
1350
|
+
contents = []
|
|
1351
|
+
_ = exteriorTopology.Contents(contents)
|
|
1352
|
+
for content in contents:
|
|
1353
|
+
if useInternalVertex == True:
|
|
1354
|
+
vst2 = Topology.InternalVertex(content, tolerance)
|
|
1355
|
+
else:
|
|
1356
|
+
vst2 = content.CenterOfMass()
|
|
1357
|
+
vst2 = topologic.Vertex.ByCoordinates(vst2.X()+(tolerance*100), vst2.Y()+(tolerance*100), vst2.Z()+(tolerance*100))
|
|
1358
|
+
d1 = content.GetDictionary()
|
|
1359
|
+
if storeBRep:
|
|
1360
|
+
d2 = Dictionary.ByKeysValues(["brep", "brepType", "brepTypeString"], [Topology.String(content), Topology.Type(content), Topology.TypeAsString(content)])
|
|
1361
|
+
d3 = mergeDictionaries2([d1, d2])
|
|
1362
|
+
_ = vst2.SetDictionary(d3)
|
|
1363
|
+
else:
|
|
1364
|
+
_ = vst2.SetDictionary(d1)
|
|
1365
|
+
vertices.append(vst2)
|
|
1366
|
+
tempe = topologic.Edge.ByStartVertexEndVertex(vst, vst2)
|
|
1367
|
+
tempd = Dictionary.ByKeysValues(["relationship"],["To Contents"])
|
|
1368
|
+
_ = tempe.SetDictionary(tempd)
|
|
1369
|
+
edges.append(tempe)
|
|
1370
|
+
if toExteriorApertures:
|
|
1371
|
+
for exteriorAperture in exteriorApertures:
|
|
1372
|
+
extTop = exteriorAperture.Topology()
|
|
1373
|
+
if useInternalVertex == True:
|
|
1374
|
+
vst = Topology.InternalVertex(extTop, tolerance)
|
|
1375
|
+
else:
|
|
1376
|
+
vst = exteriorAperture.Topology().CenterOfMass()
|
|
1377
|
+
d1 = exteriorAperture.Topology().GetDictionary()
|
|
1378
|
+
vst = topologic.Vertex.ByCoordinates(vst.X()+(tolerance*100), vst.Y()+(tolerance*100), vst.Z()+(tolerance*100))
|
|
1379
|
+
if storeBRep:
|
|
1380
|
+
d2 = Dictionary.ByKeysValues(["brep", "brepType", "brepTypeString"], [Topology.String(Aperture.Topology(exteriorAperture)), Topology.Type(Aperture.Topology(exteriorAperture)), Topology.TypeAsString(Aperture.Topology(exteriorAperture))])
|
|
1381
|
+
d3 = mergeDictionaries2([d1, d2])
|
|
1382
|
+
_ = vst.SetDictionary(d3)
|
|
1383
|
+
else:
|
|
1384
|
+
_ = vst.SetDictionary(d1)
|
|
1385
|
+
vertices.append(vst)
|
|
1386
|
+
tempe = topologic.Edge.ByStartVertexEndVertex(vFace, vst)
|
|
1387
|
+
tempd = Dictionary.ByKeysValues(["relationship"],["To Exterior Apertures"])
|
|
1388
|
+
_ = tempe.SetDictionary(tempd)
|
|
1389
|
+
edges.append(tempe)
|
|
1390
|
+
if toContents:
|
|
1391
|
+
contents = []
|
|
1392
|
+
_ = topology.Contents(contents)
|
|
1393
|
+
for content in contents:
|
|
1394
|
+
if useInternalVertex == True:
|
|
1395
|
+
vst = Topology.InternalVertex(content, tolerance)
|
|
1396
|
+
else:
|
|
1397
|
+
vst = content.CenterOfMass()
|
|
1398
|
+
vst = topologic.Vertex.ByCoordinates(vst.X()+(tolerance*100), vst.Y()+(tolerance*100), vst.Z()+(tolerance*100))
|
|
1399
|
+
d1 = content.GetDictionary()
|
|
1400
|
+
if storeBRep:
|
|
1401
|
+
d2 = Dictionary.ByKeysValues(["brep", "brepType", "brepTypeString"], [Topology.String(content), Topology.Type(content), Topology.TypeAsString(content)])
|
|
1402
|
+
d3 = mergeDictionaries2([d1, d2])
|
|
1403
|
+
_ = vst.SetDictionary(d3)
|
|
1404
|
+
else:
|
|
1405
|
+
_ = vst.SetDictionary(d1)
|
|
1406
|
+
vertices.append(vst)
|
|
1407
|
+
tempe = topologic.Edge.ByStartVertexEndVertex(vFace, vst)
|
|
1408
|
+
tempd = Dictionary.ByKeysValues(["relationship"],["To Contents"])
|
|
1409
|
+
_ = tempe.SetDictionary(tempd)
|
|
1410
|
+
edges.append(tempe)
|
|
1411
|
+
return [vertices, edges]
|
|
1412
|
+
|
|
1413
|
+
def processWire(item):
|
|
1414
|
+
topology, others, outpostsKey, idKey, direct, directApertures, viaSharedTopologies, viaSharedApertures, toExteriorTopologies, toExteriorApertures, toContents, toOutposts, useInternalVertex, storeBRep, tolerance = item
|
|
1415
|
+
graph = None
|
|
1416
|
+
edges = []
|
|
1417
|
+
vertices = []
|
|
1418
|
+
edgemat = []
|
|
1419
|
+
if direct == True:
|
|
1420
|
+
topEdges = []
|
|
1421
|
+
_ = topology.Edges(None, topEdges)
|
|
1422
|
+
# Create a matrix of zeroes
|
|
1423
|
+
for i in range(len(topEdges)):
|
|
1424
|
+
edgeRow = []
|
|
1425
|
+
for j in range(len(topEdges)):
|
|
1426
|
+
edgeRow.append(0)
|
|
1427
|
+
edgemat.append(edgeRow)
|
|
1428
|
+
for i in range(len(topEdges)):
|
|
1429
|
+
for j in range(len(topEdges)):
|
|
1430
|
+
if (i != j) and edgemat[i][j] == 0:
|
|
1431
|
+
edgemat[i][j] = 1
|
|
1432
|
+
edgemat[j][i] = 1
|
|
1433
|
+
sharedt = Topology.SharedVertices(topEdges[i], topEdges[j])
|
|
1434
|
+
if len(sharedt) > 0:
|
|
1435
|
+
try:
|
|
1436
|
+
v1 = topologic.EdgeUtility.PointAtParameter(topEdges[i], 0.5)
|
|
1437
|
+
except:
|
|
1438
|
+
v1 = topEdges[j].CenterOfMass()
|
|
1439
|
+
try:
|
|
1440
|
+
v2 = topologic.EdgeUtility.PointAtParameter(topEdges[j], 0.5)
|
|
1441
|
+
except:
|
|
1442
|
+
v2 = topEdges[j].CenterOfMass()
|
|
1443
|
+
e = topologic.Edge.ByStartVertexEndVertex(v1, v2)
|
|
1444
|
+
mDict = mergeDictionaries(sharedt)
|
|
1445
|
+
if mDict:
|
|
1446
|
+
e.SetDictionary(mDict)
|
|
1447
|
+
edges.append(e)
|
|
1448
|
+
if directApertures == True:
|
|
1449
|
+
edgemat = []
|
|
1450
|
+
topEdges = []
|
|
1451
|
+
_ = topology.Edges(None, topEdges)
|
|
1452
|
+
# Create a matrix of zeroes
|
|
1453
|
+
for i in range(len(topEdges)):
|
|
1454
|
+
edgeRow = []
|
|
1455
|
+
for j in range(len(topEdges)):
|
|
1456
|
+
edgeRow.append(0)
|
|
1457
|
+
edgemat.append(edgeRow)
|
|
1458
|
+
for i in range(len(topEdges)):
|
|
1459
|
+
for j in range(len(topEdges)):
|
|
1460
|
+
if (i != j) and edgemat[i][j] == 0:
|
|
1461
|
+
edgemat[i][j] = 1
|
|
1462
|
+
edgemat[j][i] = 1
|
|
1463
|
+
sharedt = Topology.SharedVertices(topEdges[i], topEdges[j])
|
|
1464
|
+
if len(sharedt) > 0:
|
|
1465
|
+
apertureExists = False
|
|
1466
|
+
for x in sharedt:
|
|
1467
|
+
apList = []
|
|
1468
|
+
_ = x.Apertures(apList)
|
|
1469
|
+
if len(apList) > 0:
|
|
1470
|
+
apertureExists = True
|
|
1471
|
+
break
|
|
1472
|
+
if apertureExists:
|
|
1473
|
+
try:
|
|
1474
|
+
v1 = topologic.EdgeUtility.PointAtParameter(topEdges[i], 0.5)
|
|
1475
|
+
except:
|
|
1476
|
+
v1 = topEdges[j].CenterOfMass()
|
|
1477
|
+
try:
|
|
1478
|
+
v2 = topologic.EdgeUtility.PointAtParameter(topEdges[j], 0.5)
|
|
1479
|
+
except:
|
|
1480
|
+
v2 = topEdges[j].CenterOfMass()
|
|
1481
|
+
e = topologic.Edge.ByStartVertexEndVertex(v1, v2)
|
|
1482
|
+
apTopologies = []
|
|
1483
|
+
for ap in apList:
|
|
1484
|
+
apTopologies.append(ap.Topology())
|
|
1485
|
+
mDict = mergeDictionaries(apTopologies)
|
|
1486
|
+
if mDict:
|
|
1487
|
+
e.SetDictionary(mDict)
|
|
1488
|
+
edges.append(e)
|
|
1489
|
+
|
|
1490
|
+
topEdges = []
|
|
1491
|
+
_ = topology.Edges(None, topEdges)
|
|
1492
|
+
if (viaSharedTopologies == True) or (viaSharedApertures == True) or (toExteriorTopologies == True) or (toExteriorApertures == True) or (toContents == True):
|
|
1493
|
+
for anEdge in topEdges:
|
|
1494
|
+
try:
|
|
1495
|
+
vEdge = topologic.EdgeUtility.PointAtParameter(anEdge, 0.5)
|
|
1496
|
+
except:
|
|
1497
|
+
vEdge = anEdge.CenterOfMass()
|
|
1498
|
+
d1 = anEdge.GetDictionary()
|
|
1499
|
+
if storeBRep:
|
|
1500
|
+
d2 = Dictionary.ByKeysValues(["brep", "brepType", "brepTypeString"], [Topology.String(anEdge), Topology.Type(anEdge), Topology.TypeAsString(anEdge)])
|
|
1501
|
+
d3 = mergeDictionaries2([d1, d2])
|
|
1502
|
+
_ = vEdge.SetDictionary(d3)
|
|
1503
|
+
else:
|
|
1504
|
+
_ = vEdge.SetDictionary(d1)
|
|
1505
|
+
vertices.append(vEdge)
|
|
1506
|
+
eVertices = []
|
|
1507
|
+
_ = anEdge.Vertices(None, eVertices)
|
|
1508
|
+
sharedTopologies = []
|
|
1509
|
+
exteriorTopologies = []
|
|
1510
|
+
sharedApertures = []
|
|
1511
|
+
exteriorApertures = []
|
|
1512
|
+
contents = []
|
|
1513
|
+
_ = anEdge.Contents(contents)
|
|
1514
|
+
for aVertex in eVertices:
|
|
1515
|
+
tempEdges = []
|
|
1516
|
+
_ = aVertex.Edges(topology, tempEdges)
|
|
1517
|
+
if len(tempEdges) > 1:
|
|
1518
|
+
sharedTopologies.append(aVertex)
|
|
1519
|
+
apertures = []
|
|
1520
|
+
_ = aVertex.Apertures(apertures)
|
|
1521
|
+
for anAperture in apertures:
|
|
1522
|
+
sharedApertures.append(anAperture)
|
|
1523
|
+
else:
|
|
1524
|
+
exteriorTopologies.append(aVertex)
|
|
1525
|
+
apertures = []
|
|
1526
|
+
_ = aVertex.Apertures(apertures)
|
|
1527
|
+
for anAperture in apertures:
|
|
1528
|
+
exteriorApertures.append(anAperture)
|
|
1529
|
+
if viaSharedTopologies:
|
|
1530
|
+
for sharedTopology in sharedTopologies:
|
|
1531
|
+
vst = sharedTopology.CenterOfMass()
|
|
1532
|
+
d1 = sharedTopology.GetDictionary()
|
|
1533
|
+
if storeBRep:
|
|
1534
|
+
d2 = Dictionary.ByKeysValues(["brep", "brepType", "brepTypeString"], [Topology.String(sharedTopology), Topology.Type(sharedTopology), Topology.TypeAsString(sharedTopology)])
|
|
1535
|
+
d3 = mergeDictionaries2([d1, d2])
|
|
1536
|
+
_ = vst.SetDictionary(d3)
|
|
1537
|
+
else:
|
|
1538
|
+
_ = vst.SetDictionary(d1)
|
|
1539
|
+
vertices.append(vst)
|
|
1540
|
+
tempe = topologic.Edge.ByStartVertexEndVertex(vEdge, vst)
|
|
1541
|
+
tempd = Dictionary.ByKeysValues(["relationship"],["Via Shared Topologies"])
|
|
1542
|
+
_ = tempe.SetDictionary(tempd)
|
|
1543
|
+
edges.append(tempe)
|
|
1544
|
+
if toContents:
|
|
1545
|
+
contents = []
|
|
1546
|
+
_ = sharedTopology.Contents(contents)
|
|
1547
|
+
for content in contents:
|
|
1548
|
+
if useInternalVertex == True:
|
|
1549
|
+
vst2 = Topology.InternalVertex(content, tolerance)
|
|
1550
|
+
else:
|
|
1551
|
+
vst2 = content.CenterOfMass()
|
|
1552
|
+
vst2 = topologic.Vertex.ByCoordinates(vst2.X()+(tolerance*100), vst2.Y()+(tolerance*100), vst2.Z()+(tolerance*100))
|
|
1553
|
+
d1 = content.GetDictionary()
|
|
1554
|
+
if storeBRep:
|
|
1555
|
+
d2 = Dictionary.ByKeysValues(["brep", "brepType", "brepTypeString"], [Topology.String(content), Topology.Type(content), Topology.TypeAsString(content)])
|
|
1556
|
+
d3 = mergeDictionaries2([d1, d2])
|
|
1557
|
+
_ = vst2.SetDictionary(d3)
|
|
1558
|
+
else:
|
|
1559
|
+
_ = vst2.SetDictionary(d1)
|
|
1560
|
+
vertices.append(vst2)
|
|
1561
|
+
tempe = topologic.Edge.ByStartVertexEndVertex(vst, vst2)
|
|
1562
|
+
tempd = Dictionary.ByKeysValues(["relationship"],["To Contents"])
|
|
1563
|
+
_ = tempe.SetDictionary(tempd)
|
|
1564
|
+
edges.append(tempe)
|
|
1565
|
+
if viaSharedApertures:
|
|
1566
|
+
for sharedAperture in sharedApertures:
|
|
1567
|
+
if useInternalVertex == True:
|
|
1568
|
+
vst = Topology.InternalVertex(sharedAperture.Topology(), tolerance)
|
|
1569
|
+
else:
|
|
1570
|
+
vst = sharedAperture.Topology().CenterOfMass()
|
|
1571
|
+
d1 = sharedAperture.Topology().GetDictionary()
|
|
1572
|
+
vst = topologic.Vertex.ByCoordinates(vst.X()+(tolerance*100), vst.Y()+(tolerance*100), vst.Z()+(tolerance*100))
|
|
1573
|
+
if storeBRep:
|
|
1574
|
+
d2 = Dictionary.ByKeysValues(["brep", "brepType", "brepTypeString"], [Topology.String(Aperture.Topology(sharedAperture)), Topology.Type(Aperture.Topology(sharedAperture)), Topology.TypeAsString(Aperture.Topology(sharedAperture))])
|
|
1575
|
+
d3 = mergeDictionaries2([d1, d2])
|
|
1576
|
+
_ = vst.SetDictionary(d3)
|
|
1577
|
+
else:
|
|
1578
|
+
_ = vst.SetDictionary(d1)
|
|
1579
|
+
vertices.append(vst)
|
|
1580
|
+
tempe = topologic.Edge.ByStartVertexEndVertex(vEdge, vst)
|
|
1581
|
+
tempd = Dictionary.ByKeysValues(["relationship"],["Via Shared Apertures"])
|
|
1582
|
+
_ = tempe.SetDictionary(tempd)
|
|
1583
|
+
edges.append(tempe)
|
|
1584
|
+
if toExteriorTopologies:
|
|
1585
|
+
for exteriorTopology in exteriorTopologies:
|
|
1586
|
+
vst = exteriorTopology
|
|
1587
|
+
vertices.append(exteriorTopology)
|
|
1588
|
+
tempe = topologic.Edge.ByStartVertexEndVertex(vEdge, vst)
|
|
1589
|
+
tempd = Dictionary.ByKeysValues(["relationship"],["To Exterior Topologies"])
|
|
1590
|
+
_ = tempe.SetDictionary(tempd)
|
|
1591
|
+
edges.append(tempe)
|
|
1592
|
+
if toContents:
|
|
1593
|
+
contents = []
|
|
1594
|
+
_ = vst.Contents(contents)
|
|
1595
|
+
for content in contents:
|
|
1596
|
+
if useInternalVertex == True:
|
|
1597
|
+
vst2 = Topology.InternalVertex(content, tolerance)
|
|
1598
|
+
else:
|
|
1599
|
+
vst2 = content.CenterOfMass()
|
|
1600
|
+
vst2 = topologic.Vertex.ByCoordinates(vst2.X()+(tolerance*100), vst2.Y()+(tolerance*100), vst2.Z()+(tolerance*100))
|
|
1601
|
+
d1 = content.GetDictionary()
|
|
1602
|
+
if storeBRep:
|
|
1603
|
+
d2 = Dictionary.ByKeysValues(["brep", "brepType", "brepTypeString"], [Topology.String(content), Topology.Type(content), Topology.TypeAsString(content)])
|
|
1604
|
+
d3 = mergeDictionaries2([d1, d2])
|
|
1605
|
+
_ = vst2.SetDictionary(d3)
|
|
1606
|
+
else:
|
|
1607
|
+
_ = vst2.SetDictionary(d1)
|
|
1608
|
+
vertices.append(vst2)
|
|
1609
|
+
tempe = topologic.Edge.ByStartVertexEndVertex(vst, vst2)
|
|
1610
|
+
tempd = Dictionary.ByKeysValues(["relationship"],["To Contents"])
|
|
1611
|
+
_ = tempe.SetDictionary(tempd)
|
|
1612
|
+
edges.append(tempe)
|
|
1613
|
+
if toExteriorApertures:
|
|
1614
|
+
for exteriorAperture in exteriorApertures:
|
|
1615
|
+
extTop = exteriorAperture.Topology()
|
|
1616
|
+
if useInternalVertex == True:
|
|
1617
|
+
vst = Topology.InternalVertex(extTop, tolerance)
|
|
1618
|
+
else:
|
|
1619
|
+
vst = extTop.CenterOfMass()
|
|
1620
|
+
d1 = extTop.GetDictionary()
|
|
1621
|
+
vst = topologic.Vertex.ByCoordinates(vst.X()+(tolerance*100), vst.Y()+(tolerance*100), vst.Z()+(tolerance*100))
|
|
1622
|
+
if storeBRep:
|
|
1623
|
+
d2 = Dictionary.ByKeysValues(["brep", "brepType", "brepTypeString"], [Topology.String(extTop), Topology.Type(extTop), Topology.TypeAsString(extTop)])
|
|
1624
|
+
d3 = mergeDictionaries2([d1, d2])
|
|
1625
|
+
_ = vst.SetDictionary(d3)
|
|
1626
|
+
else:
|
|
1627
|
+
_ = vst.SetDictionary(d1)
|
|
1628
|
+
vertices.append(vst)
|
|
1629
|
+
tempe = topologic.Edge.ByStartVertexEndVertex(vEdge, vst)
|
|
1630
|
+
tempd = Dictionary.ByKeysValues(["relationship"],["To Exterior Apertures"])
|
|
1631
|
+
_ = tempe.SetDictionary(tempd)
|
|
1632
|
+
edges.append(tempe)
|
|
1633
|
+
if toContents:
|
|
1634
|
+
contents = []
|
|
1635
|
+
_ = anEdge.Contents(contents)
|
|
1636
|
+
for content in contents:
|
|
1637
|
+
if useInternalVertex == True:
|
|
1638
|
+
vst = Topology.InternalVertex(content, tolerance)
|
|
1639
|
+
else:
|
|
1640
|
+
vst = content.CenterOfMass()
|
|
1641
|
+
vst = topologic.Vertex.ByCoordinates(vst.X()+(tolerance*100), vst.Y()+(tolerance*100), vst.Z()+(tolerance*100))
|
|
1642
|
+
d1 = content.GetDictionary()
|
|
1643
|
+
vst = topologic.Vertex.ByCoordinates(vst.X(), vst.Y(), vst.Z())
|
|
1644
|
+
if storeBRep:
|
|
1645
|
+
d2 = Dictionary.ByKeysValues(["brep", "brepType", "brepTypeString"], [Topology.String(content), Topology.Type(content), Topology.TypeAsString(content)])
|
|
1646
|
+
d3 = mergeDictionaries2([d1, d2])
|
|
1647
|
+
_ = vst.SetDictionary(d3)
|
|
1648
|
+
else:
|
|
1649
|
+
_ = vst.SetDictionary(d1)
|
|
1650
|
+
vertices.append(vst)
|
|
1651
|
+
tempe = topologic.Edge.ByStartVertexEndVertex(vEdge, vst)
|
|
1652
|
+
tempd = Dictionary.ByKeysValues(["relationship"],["To Contents"])
|
|
1653
|
+
_ = tempe.SetDictionary(tempd)
|
|
1654
|
+
edges.append(tempe)
|
|
1655
|
+
for anEdge in topEdges:
|
|
1656
|
+
try:
|
|
1657
|
+
vEdge = topologic.EdgeUtility.PointAtParameter(anEdge, 0.5)
|
|
1658
|
+
except:
|
|
1659
|
+
vEdge = anEdge.CenterOfMass()
|
|
1660
|
+
d1 = anEdge.GetDictionary()
|
|
1661
|
+
if storeBRep:
|
|
1662
|
+
d2 = Dictionary.ByKeysValues(["brep", "brepType", "brepTypeString"], [Topology.String(anEdge), Topology.Type(anEdge), Topology.TypeAsString(anEdge)])
|
|
1663
|
+
d3 = mergeDictionaries2([d1, d2])
|
|
1664
|
+
_ = vEdge.SetDictionary(d3)
|
|
1665
|
+
else:
|
|
1666
|
+
_ = vEdge.SetDictionary(d1)
|
|
1667
|
+
vertices.append(vEdge)
|
|
1668
|
+
|
|
1669
|
+
if toOutposts and others:
|
|
1670
|
+
d = Topology.Dictionary(topology)
|
|
1671
|
+
keys = Dictionary.Keys(d)
|
|
1672
|
+
k = None
|
|
1673
|
+
for key in keys:
|
|
1674
|
+
if key.lower() == outpostsKey.lower():
|
|
1675
|
+
k = key
|
|
1676
|
+
if k:
|
|
1677
|
+
ids = Dictionary.ValueAtKey(k)
|
|
1678
|
+
outposts = outpostsByID(others, ids, idKey)
|
|
1679
|
+
else:
|
|
1680
|
+
outposts = []
|
|
1681
|
+
for outpost in outposts:
|
|
1682
|
+
if useInternalVertex == True:
|
|
1683
|
+
vop = Topology.InternalVertex(outpost, tolerance)
|
|
1684
|
+
vcc = Topology.InternalVertex(topology, tolerance)
|
|
1685
|
+
else:
|
|
1686
|
+
vop = Topology.CenterOfMass(outpost)
|
|
1687
|
+
vcc = Topology.CenterOfMass(topology)
|
|
1688
|
+
d1 = Topology.Dictionary(vcc)
|
|
1689
|
+
if storeBRep:
|
|
1690
|
+
d2 = Dictionary.ByKeysValues(["brep", "brepType", "brepTypeString"], [Topology.String(topology), Topology.Type(topology), Topology.TypeAsString(topology)])
|
|
1691
|
+
d3 = mergeDictionaries2([d1, d2])
|
|
1692
|
+
_ = vcc.SetDictionary(d3)
|
|
1693
|
+
else:
|
|
1694
|
+
_ = vcc.SetDictionary(d1)
|
|
1695
|
+
vertices.append(vcc)
|
|
1696
|
+
tempe = topologic.Edge.ByStartVertexEndVertex(vcc, vop)
|
|
1697
|
+
tempd = Dictionary.ByKeysValues(["relationship"],["To Outposts"])
|
|
1698
|
+
_ = tempe.SetDictionary(tempd)
|
|
1699
|
+
edges.append(tempe)
|
|
1700
|
+
|
|
1701
|
+
return [vertices, edges]
|
|
1702
|
+
|
|
1703
|
+
def processEdge(item):
|
|
1704
|
+
topology, others, outpostsKey, idKey, direct, directApertures, viaSharedTopologies, viaSharedApertures, toExteriorTopologies, toExteriorApertures, toContents, toOutposts, useInternalVertex, storeBRep, tolerance = item
|
|
1705
|
+
graph = None
|
|
1706
|
+
vertices = []
|
|
1707
|
+
edges = []
|
|
1708
|
+
|
|
1709
|
+
if useInternalVertex == True:
|
|
1710
|
+
try:
|
|
1711
|
+
vEdge = topologic.EdgeUtility.PointAtParameter(topology, 0.5)
|
|
1712
|
+
except:
|
|
1713
|
+
vEdge = topology.CenterOfMass()
|
|
1714
|
+
else:
|
|
1715
|
+
vEdge = topology.CenterOfMass()
|
|
1716
|
+
|
|
1717
|
+
d1 = vEdge.GetDictionary()
|
|
1718
|
+
if storeBRep:
|
|
1719
|
+
d2 = Dictionary.ByKeysValues(["brep", "brepType", "brepTypeString"], [Topology.String(topology), Topology.Type(topology), Topology.TypeAsString(topology)])
|
|
1720
|
+
d3 = mergeDictionaries2([d1, d2])
|
|
1721
|
+
_ = vEdge.SetDictionary(d3)
|
|
1722
|
+
else:
|
|
1723
|
+
_ = vEdge.SetDictionary(topology.GetDictionary())
|
|
1724
|
+
|
|
1725
|
+
vertices.append(vEdge)
|
|
1726
|
+
|
|
1727
|
+
if toOutposts and others:
|
|
1728
|
+
d = Topology.Dictionary(topology)
|
|
1729
|
+
keys = Dictionary.Keys(d)
|
|
1730
|
+
k = None
|
|
1731
|
+
for key in keys:
|
|
1732
|
+
if key.lower() == outpostsKey.lower():
|
|
1733
|
+
k = key
|
|
1734
|
+
if k:
|
|
1735
|
+
ids = Dictionary.ValueAtKey(d, k)
|
|
1736
|
+
outposts = outpostsByID(others, ids, idKey)
|
|
1737
|
+
else:
|
|
1738
|
+
outposts = []
|
|
1739
|
+
for outpost in outposts:
|
|
1740
|
+
if useInternalVertex == True:
|
|
1741
|
+
vop = Topology.InternalVertex(outpost, tolerance)
|
|
1742
|
+
else:
|
|
1743
|
+
vop = Topology.CenterOfMass(outpost)
|
|
1744
|
+
tempe = topologic.Edge.ByStartVertexEndVertex(vEdge, vop)
|
|
1745
|
+
tempd = Dictionary.ByKeysValues(["relationship"],["To Outposts"])
|
|
1746
|
+
_ = tempe.SetDictionary(tempd)
|
|
1747
|
+
edges.append(tempe)
|
|
1748
|
+
|
|
1749
|
+
if (toExteriorTopologies == True) or (toExteriorApertures == True) or (toContents == True):
|
|
1750
|
+
eVertices = []
|
|
1751
|
+
_ = topology.Vertices(None, eVertices)
|
|
1752
|
+
exteriorTopologies = []
|
|
1753
|
+
exteriorApertures = []
|
|
1754
|
+
for aVertex in eVertices:
|
|
1755
|
+
exteriorTopologies.append(aVertex)
|
|
1756
|
+
apertures = []
|
|
1757
|
+
_ = aVertex.Apertures(apertures)
|
|
1758
|
+
for anAperture in apertures:
|
|
1759
|
+
exteriorApertures.append(anAperture)
|
|
1760
|
+
if toExteriorTopologies:
|
|
1761
|
+
for exteriorTopology in exteriorTopologies:
|
|
1762
|
+
if useInternalVertex == True:
|
|
1763
|
+
vst = Topology.InternalVertex(exteriorTopology, tolerance)
|
|
1764
|
+
else:
|
|
1765
|
+
vst = exteriorTopology.CenterOfMass()
|
|
1766
|
+
d1 = exteriorTopology.GetDictionary()
|
|
1767
|
+
if storeBRep:
|
|
1768
|
+
d2 = Dictionary.ByKeysValues(["brep", "brepType", "brepTypeString"], [Topology.String(exteriorTopology), Topology.Type(exteriorTopology), Topology.TypeAsString(exteriorTopology)])
|
|
1769
|
+
d3 = mergeDictionaries2([d1, d2])
|
|
1770
|
+
_ = vst.SetDictionary(d3)
|
|
1771
|
+
else:
|
|
1772
|
+
_ = vst.SetDictionary(d1)
|
|
1773
|
+
vertices.append(vst)
|
|
1774
|
+
tempe = topologic.Edge.ByStartVertexEndVertex(vEdge, vst)
|
|
1775
|
+
tempd = Dictionary.ByKeysValues(["relationship"],["To Exterior Topologies"])
|
|
1776
|
+
_ = tempe.SetDictionary(tempd)
|
|
1777
|
+
edges.append(tempe)
|
|
1778
|
+
if toContents:
|
|
1779
|
+
contents = []
|
|
1780
|
+
_ = vst.Contents(contents)
|
|
1781
|
+
for content in contents:
|
|
1782
|
+
if useInternalVertex == True:
|
|
1783
|
+
vst2 = Topology.InternalVertex(content, tolerance)
|
|
1784
|
+
else:
|
|
1785
|
+
vst2 = content.CenterOfMass()
|
|
1786
|
+
vst2 = topologic.Vertex.ByCoordinates(vst2.X()+(tolerance*100), vst2.Y()+(tolerance*100), vst2.Z()+(tolerance*100))
|
|
1787
|
+
d1 = content.GetDictionary()
|
|
1788
|
+
if storeBRep:
|
|
1789
|
+
d2 = Dictionary.ByKeysValues(["brep", "brepType", "brepTypeString"], [Topology.String(content), Topology.Type(content), Topology.TypeAsString(content)])
|
|
1790
|
+
d3 = mergeDictionaries2([d1, d2])
|
|
1791
|
+
_ = vst2.SetDictionary(d3)
|
|
1792
|
+
else:
|
|
1793
|
+
_ = vst2.SetDictionary(d1)
|
|
1794
|
+
vertices.append(vst2)
|
|
1795
|
+
tempe = topologic.Edge.ByStartVertexEndVertex(vst, vst2)
|
|
1796
|
+
tempd = Dictionary.ByKeysValues(["relationship"],["To Contents"])
|
|
1797
|
+
_ = tempe.SetDictionary(tempd)
|
|
1798
|
+
edges.append(tempe)
|
|
1799
|
+
if toExteriorApertures:
|
|
1800
|
+
for exteriorAperture in exteriorApertures:
|
|
1801
|
+
extTop = exteriorAperture.Topology()
|
|
1802
|
+
if useInternalVertex == True:
|
|
1803
|
+
vst = Topology.InternalVertex(extTop, tolerance)
|
|
1804
|
+
else:
|
|
1805
|
+
vst = exteriorAperture.Topology().CenterOfMass()
|
|
1806
|
+
d1 = exteriorAperture.Topology().GetDictionary()
|
|
1807
|
+
vst = topologic.Vertex.ByCoordinates(vst.X()+(tolerance*100), vst.Y()+(tolerance*100), vst.Z()+(tolerance*100))
|
|
1808
|
+
if storeBRep:
|
|
1809
|
+
d2 = Dictionary.ByKeysValues(["brep", "brepType", "brepTypeString"], [Topology.String(Aperture.Topology(exteriorAperture)), Topology.Type(Aperture.Topology(exteriorAperture)), Topology.TypeAsString(Aperture.Topology(exteriorAperture))])
|
|
1810
|
+
d3 = mergeDictionaries2([d1, d2])
|
|
1811
|
+
_ = vst.SetDictionary(d3)
|
|
1812
|
+
else:
|
|
1813
|
+
_ = vst.SetDictionary(d1)
|
|
1814
|
+
_ = vst.SetDictionary(exteriorAperture.Topology().GetDictionary())
|
|
1815
|
+
vertices.append(vst)
|
|
1816
|
+
tempe = topologic.Edge.ByStartVertexEndVertex(vEdge, vst)
|
|
1817
|
+
tempd = Dictionary.ByKeysValues(["relationship"],["To Exterior Apertures"])
|
|
1818
|
+
_ = tempe.SetDictionary(tempd)
|
|
1819
|
+
edges.append(tempe)
|
|
1820
|
+
|
|
1821
|
+
return [vertices, edges]
|
|
1822
|
+
|
|
1823
|
+
def processVertex(item):
|
|
1824
|
+
topology, others, outpostsKey, idKey, direct, directApertures, viaSharedTopologies, viaSharedApertures, toExteriorTopologies, toExteriorApertures, toContents, toOutposts, useInternalVertex, storeBRep, tolerance = item
|
|
1825
|
+
vertices = [topology]
|
|
1826
|
+
edges = []
|
|
1827
|
+
|
|
1828
|
+
if toContents:
|
|
1829
|
+
contents = []
|
|
1830
|
+
_ = topology.Contents(contents)
|
|
1831
|
+
for content in contents:
|
|
1832
|
+
if useInternalVertex == True:
|
|
1833
|
+
vst = Topology.InternalVertex(content, tolerance)
|
|
1834
|
+
else:
|
|
1835
|
+
vst = content.CenterOfMass()
|
|
1836
|
+
d1 = content.GetDictionary()
|
|
1837
|
+
vst = topologic.Vertex.ByCoordinates(vst.X()+(tolerance*100), vst.Y()+(tolerance*100), vst.Z()+(tolerance*100))
|
|
1838
|
+
if storeBRep:
|
|
1839
|
+
d2 = Dictionary.ByKeysValues(["brep", "brepType", "brepTypeString"], [Topology.String(content), Topology.Type(content), Topology.TypeAsString(content)])
|
|
1840
|
+
d3 = mergeDictionaries2([d1, d2])
|
|
1841
|
+
_ = vst.SetDictionary(d3)
|
|
1842
|
+
else:
|
|
1843
|
+
_ = vst.SetDictionary(d1)
|
|
1844
|
+
vertices.append(vst)
|
|
1845
|
+
tempe = topologic.Edge.ByStartVertexEndVertex(topology, vst)
|
|
1846
|
+
tempd = Dictionary.ByKeysValues(["relationship"],["To Contents"])
|
|
1847
|
+
_ = tempe.SetDictionary(tempd)
|
|
1848
|
+
edges.append(tempe)
|
|
1849
|
+
|
|
1850
|
+
if toOutposts and others:
|
|
1851
|
+
d = Topology.Dictionary(topology)
|
|
1852
|
+
keys = Dictionary.Keys(d)
|
|
1853
|
+
k = None
|
|
1854
|
+
for key in keys:
|
|
1855
|
+
if key.lower() == outpostsKey.lower():
|
|
1856
|
+
k = key
|
|
1857
|
+
if k:
|
|
1858
|
+
ids = Dictionary.ValueAtKey(d, k)
|
|
1859
|
+
outposts = outpostsByID(others, ids, idKey)
|
|
1860
|
+
else:
|
|
1861
|
+
outposts = []
|
|
1862
|
+
for outpost in outposts:
|
|
1863
|
+
if useInternalVertex == True:
|
|
1864
|
+
vop = Topology.InternalVertex(outpost, tolerance)
|
|
1865
|
+
else:
|
|
1866
|
+
vop = Topology.CenterOfMass(outpost)
|
|
1867
|
+
tempe = topologic.Edge.ByStartVertexEndVertex(topology, vop)
|
|
1868
|
+
tempd = Dictionary.ByKeysValues(["relationship"],["To Outposts"])
|
|
1869
|
+
_ = tempe.SetDictionary(tempd)
|
|
1870
|
+
edges.append(tempe)
|
|
1871
|
+
|
|
1872
|
+
return [vertices, edges]
|
|
1873
|
+
|
|
1874
|
+
|
|
1875
|
+
if not isinstance(topology, topologic.Topology):
|
|
1876
|
+
return None
|
|
1877
|
+
graph = None
|
|
1878
|
+
item = [topology, None, None, None, direct, directApertures, viaSharedTopologies, viaSharedApertures, toExteriorTopologies, toExteriorApertures, toContents, None, useInternalVertex, storeBRep, tolerance]
|
|
1879
|
+
vertices = []
|
|
1880
|
+
edges = []
|
|
1881
|
+
if isinstance(topology, topologic.CellComplex):
|
|
1882
|
+
vertices, edges = processCellComplex(item)
|
|
1883
|
+
elif isinstance(topology, topologic.Cell):
|
|
1884
|
+
vertices, edges = processCell(item)
|
|
1885
|
+
elif isinstance(topology, topologic.Shell):
|
|
1886
|
+
vertices, edges = processShell(item)
|
|
1887
|
+
elif isinstance(topology, topologic.Face):
|
|
1888
|
+
vertices, edges = processFace(item)
|
|
1889
|
+
elif isinstance(topology, topologic.Wire):
|
|
1890
|
+
vertices, edges = processWire(item)
|
|
1891
|
+
elif isinstance(topology, topologic.Edge):
|
|
1892
|
+
vertices, edges = processEdge(item)
|
|
1893
|
+
elif isinstance(topology, topologic.Vertex):
|
|
1894
|
+
vertices, edges = processVertex(item)
|
|
1895
|
+
elif isinstance(topology, topologic.Cluster):
|
|
1896
|
+
c_cellComplexes = Topology.CellComplexes(topology)
|
|
1897
|
+
c_cells = Cluster.FreeCells(topology)
|
|
1898
|
+
c_shells = Cluster.FreeShells(topology)
|
|
1899
|
+
c_faces = Cluster.FreeFaces(topology)
|
|
1900
|
+
c_wires = Cluster.FreeWires(topology)
|
|
1901
|
+
c_edges = Cluster.FreeEdges(topology)
|
|
1902
|
+
c_vertices = Cluster.FreeVertices(topology)
|
|
1903
|
+
others = c_cellComplexes+c_cells+c_shells+c_faces+c_wires+c_edges+c_vertices
|
|
1904
|
+
parameters = [others, outpostsKey, idKey, direct, directApertures, viaSharedTopologies, viaSharedApertures, toExteriorTopologies, toExteriorApertures, toContents, toOutposts, useInternalVertex, storeBRep, tolerance]
|
|
1905
|
+
|
|
1906
|
+
for t in c_cellComplexes:
|
|
1907
|
+
v, e = processCellComplex([t]+parameters)
|
|
1908
|
+
vertices += v
|
|
1909
|
+
edges += e
|
|
1910
|
+
for t in c_cells:
|
|
1911
|
+
v, e = processCell([t]+parameters)
|
|
1912
|
+
vertices += v
|
|
1913
|
+
edges += e
|
|
1914
|
+
for t in c_shells:
|
|
1915
|
+
v, e = processShell([t]+parameters)
|
|
1916
|
+
vertices += v
|
|
1917
|
+
edges += e
|
|
1918
|
+
for t in c_faces:
|
|
1919
|
+
v, e = processFace([t]+parameters)
|
|
1920
|
+
vertices += v
|
|
1921
|
+
edges += e
|
|
1922
|
+
for t in c_wires:
|
|
1923
|
+
v, e = processWire([t]+parameters)
|
|
1924
|
+
vertices += v
|
|
1925
|
+
edges += e
|
|
1926
|
+
for t in c_edges:
|
|
1927
|
+
v, e = processEdge([t]+parameters)
|
|
1928
|
+
vertices += v
|
|
1929
|
+
edges += e
|
|
1930
|
+
for t in c_vertices:
|
|
1931
|
+
v, e = processVertex([t]+parameters)
|
|
1932
|
+
vertices += v
|
|
1933
|
+
edges += e
|
|
1934
|
+
else:
|
|
1935
|
+
return None
|
|
1936
|
+
return topologic.Graph.ByVerticesEdges(vertices, edges)
|
|
1937
|
+
|
|
1938
|
+
@staticmethod
|
|
1939
|
+
def ByVerticesEdges(vertices, edges):
|
|
1940
|
+
"""
|
|
1941
|
+
Creates a graph from the input list of vertices and edges.
|
|
1942
|
+
|
|
1943
|
+
Parameters
|
|
1944
|
+
----------
|
|
1945
|
+
vertices : list
|
|
1946
|
+
The input list of vertices.
|
|
1947
|
+
edges : list
|
|
1948
|
+
The input list of edges.
|
|
1949
|
+
|
|
1950
|
+
Returns
|
|
1951
|
+
-------
|
|
1952
|
+
topologic.Graph
|
|
1953
|
+
The created graph.
|
|
1954
|
+
|
|
1955
|
+
"""
|
|
1956
|
+
|
|
1957
|
+
if not isinstance(vertices, list):
|
|
1958
|
+
return None
|
|
1959
|
+
if not isinstance(edges, list):
|
|
1960
|
+
return None
|
|
1961
|
+
vertices = [v for v in vertices if isinstance(v, topologic.Vertex)]
|
|
1962
|
+
edges = [e for e in edges if isinstance(e, topologic.Edge)]
|
|
1963
|
+
return topologic.Graph.ByVerticesEdges(vertices, edges)
|
|
1964
|
+
|
|
1965
|
+
@staticmethod
|
|
1966
|
+
def ClosenessCentrality(graph, vertices=None, tolerance = 0.0001):
|
|
1967
|
+
"""
|
|
1968
|
+
Return the closeness centrality measure of the input list of vertices within the input graph. The order of the returned list is the same as the order of the input list of vertices. If no vertices are specified, the closeness centrality of all the vertices in the input graph is computed. See https://en.wikipedia.org/wiki/Centrality.
|
|
1969
|
+
|
|
1970
|
+
Parameters
|
|
1971
|
+
----------
|
|
1972
|
+
graph : topologic.Graph
|
|
1973
|
+
The input graph.
|
|
1974
|
+
vertices : list , optional
|
|
1975
|
+
The input list of vertices. The default is None.
|
|
1976
|
+
tolerance : float , optional
|
|
1977
|
+
The desired tolerance. The default is 0.0001.
|
|
1978
|
+
|
|
1979
|
+
Returns
|
|
1980
|
+
-------
|
|
1981
|
+
list
|
|
1982
|
+
The closeness centrality of the input list of vertices within the input graph. The values are in the range 0 to 1.
|
|
1983
|
+
|
|
1984
|
+
"""
|
|
1985
|
+
import sys
|
|
1986
|
+
import subprocess
|
|
1987
|
+
|
|
1988
|
+
try:
|
|
1989
|
+
from tqdm.auto import tqdm
|
|
1990
|
+
except:
|
|
1991
|
+
call = [sys.executable, '-m', 'pip', 'install', 'tqdm', '-t', sys.path[0]]
|
|
1992
|
+
subprocess.run(call)
|
|
1993
|
+
try:
|
|
1994
|
+
from tqdm.auto import tqdm
|
|
1995
|
+
except:
|
|
1996
|
+
print("DGL - Error: Could not import tqdm")
|
|
1997
|
+
|
|
1998
|
+
if not isinstance(graph, topologic.Graph):
|
|
1999
|
+
return None
|
|
2000
|
+
graphVertices = Graph.Vertices(graph)
|
|
2001
|
+
if not isinstance(vertices, list):
|
|
2002
|
+
vertices = graphVertices
|
|
2003
|
+
else:
|
|
2004
|
+
vertices = [v for v in vertices if isinstance(v, topologic.Vertex)]
|
|
2005
|
+
if len(vertices) < 1:
|
|
2006
|
+
return None
|
|
2007
|
+
n = len(graphVertices)
|
|
2008
|
+
|
|
2009
|
+
returnList = []
|
|
2010
|
+
try:
|
|
2011
|
+
for va in tqdm(vertices, desc="Computing Closeness Centrality", leave=False):
|
|
2012
|
+
top_dist = 0
|
|
2013
|
+
for vb in graphVertices:
|
|
2014
|
+
if topologic.Topology.IsSame(va, vb):
|
|
2015
|
+
d = 0
|
|
2016
|
+
else:
|
|
2017
|
+
d = Graph.TopologicalDistance(graph, va, vb, tolerance)
|
|
2018
|
+
top_dist += d
|
|
2019
|
+
if top_dist == 0:
|
|
2020
|
+
returnList.append(0)
|
|
2021
|
+
else:
|
|
2022
|
+
returnList.append((n-1)/top_dist)
|
|
2023
|
+
except:
|
|
2024
|
+
print("Could not use tqdm")
|
|
2025
|
+
for va in vertices:
|
|
2026
|
+
top_dist = 0
|
|
2027
|
+
for vb in graphVertices:
|
|
2028
|
+
if topologic.Topology.IsSame(va, vb):
|
|
2029
|
+
d = 0
|
|
2030
|
+
else:
|
|
2031
|
+
d = Graph.TopologicalDistance(graph, va, vb, tolerance)
|
|
2032
|
+
top_dist += d
|
|
2033
|
+
if top_dist == 0:
|
|
2034
|
+
returnList.append(0)
|
|
2035
|
+
else:
|
|
2036
|
+
returnList.append((n-1)/top_dist)
|
|
2037
|
+
return returnList
|
|
2038
|
+
|
|
2039
|
+
@staticmethod
|
|
2040
|
+
def Connect(graph, verticesA, verticesB, tolerance=0.0001):
|
|
2041
|
+
"""
|
|
2042
|
+
Connects the two lists of input vertices.
|
|
2043
|
+
|
|
2044
|
+
Parameters
|
|
2045
|
+
----------
|
|
2046
|
+
graph : topologic.Graph
|
|
2047
|
+
The input graph.
|
|
2048
|
+
verticesA : list
|
|
2049
|
+
The first list of input vertices.
|
|
2050
|
+
verticesB : topologic.Vertex
|
|
2051
|
+
The second list of input vertices.
|
|
2052
|
+
tolerance : float , optional
|
|
2053
|
+
The desired tolerance. The default is 0.0001.
|
|
2054
|
+
|
|
2055
|
+
Returns
|
|
2056
|
+
-------
|
|
2057
|
+
topologic.Graph
|
|
2058
|
+
The input graph with the connected input vertices.
|
|
2059
|
+
|
|
2060
|
+
"""
|
|
2061
|
+
if not isinstance(verticesA, list):
|
|
2062
|
+
return None
|
|
2063
|
+
if not isinstance(verticesB, list):
|
|
2064
|
+
return None
|
|
2065
|
+
verticesA = [v for v in verticesA if isinstance(v, topologic.Vertex)]
|
|
2066
|
+
verticesB = [v for v in verticesB if isinstance(v, topologic.Vertex)]
|
|
2067
|
+
if len(verticesA) < 1:
|
|
2068
|
+
return None
|
|
2069
|
+
if len(verticesB) < 1:
|
|
2070
|
+
return None
|
|
2071
|
+
if not len(verticesA) == len(verticesB):
|
|
2072
|
+
return None
|
|
2073
|
+
_ = graph.Connect(verticesA, verticesB, tolerance)
|
|
2074
|
+
return graph
|
|
2075
|
+
|
|
2076
|
+
@staticmethod
|
|
2077
|
+
def ContainsEdge(graph, edge, tolerance=0.0001):
|
|
2078
|
+
"""
|
|
2079
|
+
Returns True if the input graph contains the input edge. Returns False otherwise.
|
|
2080
|
+
|
|
2081
|
+
Parameters
|
|
2082
|
+
----------
|
|
2083
|
+
graph : topologic.Graph
|
|
2084
|
+
The input graph.
|
|
2085
|
+
edge : topologic.Edge
|
|
2086
|
+
The input edge.
|
|
2087
|
+
tolerance : float , optional
|
|
2088
|
+
The desired tolerance. The default is 0.0001.
|
|
2089
|
+
|
|
2090
|
+
Returns
|
|
2091
|
+
-------
|
|
2092
|
+
bool
|
|
2093
|
+
True if the input graph contains the input edge. False otherwise.
|
|
2094
|
+
|
|
2095
|
+
"""
|
|
2096
|
+
if not isinstance(graph, topologic.Graph):
|
|
2097
|
+
return None
|
|
2098
|
+
if not isinstance(edge, topologic.Edge):
|
|
2099
|
+
return None
|
|
2100
|
+
return graph.ContainsEdge(edge, tolerance)
|
|
2101
|
+
|
|
2102
|
+
@staticmethod
|
|
2103
|
+
def ContainsVertex(graph, vertex, tolerance=0.0001):
|
|
2104
|
+
"""
|
|
2105
|
+
Returns True if the input graph contains the input Vertex. Returns False otherwise.
|
|
2106
|
+
|
|
2107
|
+
Parameters
|
|
2108
|
+
----------
|
|
2109
|
+
graph : topologic.Graph
|
|
2110
|
+
The input graph.
|
|
2111
|
+
vertex : topologic.Vertex
|
|
2112
|
+
The input Vertex.
|
|
2113
|
+
tolerance : float , optional
|
|
2114
|
+
Ther desired tolerance. The default is 0.0001.
|
|
2115
|
+
|
|
2116
|
+
Returns
|
|
2117
|
+
-------
|
|
2118
|
+
bool
|
|
2119
|
+
True if the input graph contains the input vertex. False otherwise.
|
|
2120
|
+
|
|
2121
|
+
"""
|
|
2122
|
+
if not isinstance(graph, topologic.Graph):
|
|
2123
|
+
return None
|
|
2124
|
+
if not isinstance(vertex, topologic.Vertex):
|
|
2125
|
+
return None
|
|
2126
|
+
return graph.ContainsVertex(vertex, tolerance)
|
|
2127
|
+
|
|
2128
|
+
@staticmethod
|
|
2129
|
+
def DegreeSequence(graph):
|
|
2130
|
+
"""
|
|
2131
|
+
Returns the degree sequence of the input graph. See https://mathworld.wolfram.com/DegreeSequence.html.
|
|
2132
|
+
|
|
2133
|
+
Parameters
|
|
2134
|
+
----------
|
|
2135
|
+
graph : topologic.Graph
|
|
2136
|
+
The input graph.
|
|
2137
|
+
|
|
2138
|
+
Returns
|
|
2139
|
+
-------
|
|
2140
|
+
list
|
|
2141
|
+
The degree sequence of the input graph.
|
|
2142
|
+
|
|
2143
|
+
"""
|
|
2144
|
+
sequence = []
|
|
2145
|
+
_ = graph.DegreeSequence(sequence)
|
|
2146
|
+
return sequence
|
|
2147
|
+
|
|
2148
|
+
@staticmethod
|
|
2149
|
+
def Density(graph):
|
|
2150
|
+
"""
|
|
2151
|
+
Returns the density of the input graph. See https://en.wikipedia.org/wiki/Dense_graph.
|
|
2152
|
+
|
|
2153
|
+
Parameters
|
|
2154
|
+
----------
|
|
2155
|
+
graph : topologic.Graph
|
|
2156
|
+
The input graph.
|
|
2157
|
+
|
|
2158
|
+
Returns
|
|
2159
|
+
-------
|
|
2160
|
+
float
|
|
2161
|
+
The density of the input graph.
|
|
2162
|
+
|
|
2163
|
+
"""
|
|
2164
|
+
if not isinstance(graph, topologic.Graph):
|
|
2165
|
+
return None
|
|
2166
|
+
return graph.Density()
|
|
2167
|
+
|
|
2168
|
+
@staticmethod
|
|
2169
|
+
def DepthMap(graph, vertices=None, tolerance=0.0001):
|
|
2170
|
+
"""
|
|
2171
|
+
Return the depth map of the input list of vertices within the input graph. The returned list contains the total of the topological distances of each vertex to every other vertex in the input graph. The order of the depth map list is the same as the order of the input list of vertices. If no vertices are specified, the depth map of all the vertices in the input graph is computed.
|
|
2172
|
+
|
|
2173
|
+
Parameters
|
|
2174
|
+
----------
|
|
2175
|
+
graph : topologic.Graph
|
|
2176
|
+
The input graph.
|
|
2177
|
+
vertices : list , optional
|
|
2178
|
+
The input list of vertices. The default is None.
|
|
2179
|
+
tolerance : float , optional
|
|
2180
|
+
The desired tolerance. The default is 0.0001.
|
|
2181
|
+
|
|
2182
|
+
Returns
|
|
2183
|
+
-------
|
|
2184
|
+
list
|
|
2185
|
+
The depth map of the input list of vertices within the input graph.
|
|
2186
|
+
|
|
2187
|
+
"""
|
|
2188
|
+
if not isinstance(graph, topologic.Graph):
|
|
2189
|
+
return None
|
|
2190
|
+
graphVertices = Graph.Vertices(graph)
|
|
2191
|
+
if not isinstance(vertices, list):
|
|
2192
|
+
vertices = graphVertices
|
|
2193
|
+
else:
|
|
2194
|
+
vertices = [v for v in vertices if isinstance(v, topologic.Vertex)]
|
|
2195
|
+
if len(vertices) < 1:
|
|
2196
|
+
return None
|
|
2197
|
+
depthMap = []
|
|
2198
|
+
for va in vertices:
|
|
2199
|
+
depth = 0
|
|
2200
|
+
for vb in graphVertices:
|
|
2201
|
+
if topologic.Topology.IsSame(va, vb):
|
|
2202
|
+
dist = 0
|
|
2203
|
+
else:
|
|
2204
|
+
dist = Graph.TopologicalDistance(graph, va, vb, tolerance)
|
|
2205
|
+
depth = depth + dist
|
|
2206
|
+
depthMap.append(depth)
|
|
2207
|
+
return depthMap
|
|
2208
|
+
|
|
2209
|
+
@staticmethod
|
|
2210
|
+
def Diameter(graph):
|
|
2211
|
+
"""
|
|
2212
|
+
Returns the diameter of the input graph. See https://mathworld.wolfram.com/GraphDiameter.html.
|
|
2213
|
+
|
|
2214
|
+
Parameters
|
|
2215
|
+
----------
|
|
2216
|
+
graph : topologic.Graph
|
|
2217
|
+
The input graph.
|
|
2218
|
+
|
|
2219
|
+
Returns
|
|
2220
|
+
-------
|
|
2221
|
+
int
|
|
2222
|
+
The diameter of the input graph.
|
|
2223
|
+
|
|
2224
|
+
"""
|
|
2225
|
+
if not isinstance(graph, topologic.Graph):
|
|
2226
|
+
return None
|
|
2227
|
+
return graph.Diameter()
|
|
2228
|
+
|
|
2229
|
+
@staticmethod
|
|
2230
|
+
def Distance(graph, vertexA, vertexB, tolerance=0.0001):
|
|
2231
|
+
"""
|
|
2232
|
+
Returns the shortest-path distance between the input vertices. See https://en.wikipedia.org/wiki/Distance_(graph_theory).
|
|
2233
|
+
|
|
2234
|
+
Parameters
|
|
2235
|
+
----------
|
|
2236
|
+
graph : topologic.Graph
|
|
2237
|
+
The input graph.
|
|
2238
|
+
vertexA : topologic.Vertex
|
|
2239
|
+
The first input vertex.
|
|
2240
|
+
vertexB : topologic.Vertex
|
|
2241
|
+
The second input vertex.
|
|
2242
|
+
tolerance : float , optional
|
|
2243
|
+
The desired tolerance. The default is 0.0001.
|
|
2244
|
+
|
|
2245
|
+
Returns
|
|
2246
|
+
-------
|
|
2247
|
+
int
|
|
2248
|
+
The shortest-path distance between the input vertices.
|
|
2249
|
+
|
|
2250
|
+
"""
|
|
2251
|
+
if not isinstance(graph, topologic.Graph):
|
|
2252
|
+
return None
|
|
2253
|
+
if not isinstance(vertexA, topologic.Vertex) or not isinstance(vertexB, topologic.Vertex):
|
|
2254
|
+
return None
|
|
2255
|
+
return graph.TopologicalDistance(vertexA, vertexB, tolerance)
|
|
2256
|
+
|
|
2257
|
+
@staticmethod
|
|
2258
|
+
def Edge(graph, vertexA, vertexB, tolerance=0.0001):
|
|
2259
|
+
"""
|
|
2260
|
+
Returns the edge in the input graph that connects in the input vertices.
|
|
2261
|
+
|
|
2262
|
+
Parameters
|
|
2263
|
+
----------
|
|
2264
|
+
graph : topologic.Graph
|
|
2265
|
+
The input graph.
|
|
2266
|
+
vertexA : topologic.Vertex
|
|
2267
|
+
The first input vertex.
|
|
2268
|
+
vertexB : topologic.Vertex
|
|
2269
|
+
The second input Vertex.
|
|
2270
|
+
tolerance : float , optional
|
|
2271
|
+
The desired tolerance. The default is 0.0001.
|
|
2272
|
+
|
|
2273
|
+
Returns
|
|
2274
|
+
-------
|
|
2275
|
+
topologic.Edge
|
|
2276
|
+
The edge in the input graph that connects the input vertices.
|
|
2277
|
+
|
|
2278
|
+
"""
|
|
2279
|
+
if not isinstance(graph, topologic.Graph):
|
|
2280
|
+
return None
|
|
2281
|
+
if not isinstance(vertexA, topologic.Vertex) or not isinstance(vertexB, topologic.Vertex):
|
|
2282
|
+
return None
|
|
2283
|
+
return graph.Edge(vertexA, vertexB, tolerance)
|
|
2284
|
+
|
|
2285
|
+
@staticmethod
|
|
2286
|
+
def Edges(graph, vertices=None, tolerance=0.0001):
|
|
2287
|
+
"""
|
|
2288
|
+
Returns the edges found in the input graph. If the input list of vertices is specified, this method returns the edges connected to this list of vertices. Otherwise, it returns all graph edges.
|
|
2289
|
+
|
|
2290
|
+
Parameters
|
|
2291
|
+
----------
|
|
2292
|
+
graph : topologic.Graph
|
|
2293
|
+
The input graph.
|
|
2294
|
+
vertices : list , optional
|
|
2295
|
+
An optional list of vertices to restrict the returned list of edges only to those connected to this list.
|
|
2296
|
+
tolerance : float , optional
|
|
2297
|
+
The desired tolerance. The default is 0.0001.
|
|
2298
|
+
|
|
2299
|
+
Returns
|
|
2300
|
+
-------
|
|
2301
|
+
list
|
|
2302
|
+
The list of edges in the graph.
|
|
2303
|
+
|
|
2304
|
+
"""
|
|
2305
|
+
if not isinstance(graph, topologic.Graph):
|
|
2306
|
+
return None
|
|
2307
|
+
if not vertices:
|
|
2308
|
+
edges = []
|
|
2309
|
+
_ = graph.Edges(edges, tolerance)
|
|
2310
|
+
return edges
|
|
2311
|
+
else:
|
|
2312
|
+
vertices = [v for v in vertices if isinstance(v, topologic.Vertex)]
|
|
2313
|
+
if len(vertices) > 0:
|
|
2314
|
+
edges = []
|
|
2315
|
+
_ = graph.Edges(vertices, tolerance, edges)
|
|
2316
|
+
return list(dict.fromkeys(edges)) # remove duplicates
|
|
2317
|
+
return []
|
|
2318
|
+
|
|
2319
|
+
@staticmethod
|
|
2320
|
+
def ExportToCSV_GC(graphs, graphLabels, graphsPath, edgesPath, nodesPath, graphIDHeader="graph_id", graphLabelHeader="label",graphNumNodesHeader="num_nodes",edgeSRCHeader="src", edgeDSTHeader="dst", edgeLabelHeader="label", edgeLabelKey="label", defaultEdgeLabel=0, nodeLabelHeader="label", nodeLabelKey="label", defaultNodeLabel=0, overwrite=False):
|
|
2321
|
+
"""
|
|
2322
|
+
Exports the input list of graphs into a set of CSV files compatible with DGL for Graph Classification.
|
|
2323
|
+
|
|
2324
|
+
Parameters
|
|
2325
|
+
----------
|
|
2326
|
+
graphs : list
|
|
2327
|
+
The input list of graphs.
|
|
2328
|
+
graphLabels : list
|
|
2329
|
+
The input list of graph labels. This must be list of ints where the minimum must be 0 and the maximum must be n where n is the number of graph categories.
|
|
2330
|
+
graphsPaths : str
|
|
2331
|
+
The desired path to the output graphs CSV file.
|
|
2332
|
+
edgesPath : str
|
|
2333
|
+
The desired path to the output edges CSV file.
|
|
2334
|
+
nodesPath : str
|
|
2335
|
+
The desired path to the output nodes CSV file.
|
|
2336
|
+
graphIDHeader : str , optional
|
|
2337
|
+
The desired graph ID column header. The default is "graph_id".
|
|
2338
|
+
graphLabelHeader : str , optional
|
|
2339
|
+
The desired graph label column header. The default is "label".
|
|
2340
|
+
graphNumNodesHeader : str , optional
|
|
2341
|
+
The desired graph number of nodes column header. The default is "num_nodes".
|
|
2342
|
+
edgeSRCHeader : str , optional
|
|
2343
|
+
The desired edge source column header. The default is "src".
|
|
2344
|
+
edgeDSTHeader : str , optional
|
|
2345
|
+
The desired edge destination column header. The default is "dst".
|
|
2346
|
+
nodeLabelHeader : str , optional
|
|
2347
|
+
The desired node label column header. The default is "label".
|
|
2348
|
+
nodeLabelKey : str , optional
|
|
2349
|
+
The node label dictionary key saved in each graph vertex. The default is "label".
|
|
2350
|
+
defaultNodeLabel : int , optional
|
|
2351
|
+
The default node label to use if no node label is found. The default is 0.
|
|
2352
|
+
overwrite : bool , optional
|
|
2353
|
+
If set to True, any existing files are overwritten. Otherwise, the input list of graphs is appended to the end of each file. The default is False.
|
|
2354
|
+
|
|
2355
|
+
Returns
|
|
2356
|
+
-------
|
|
2357
|
+
bool
|
|
2358
|
+
True if the graphs have been successfully exported. False otherwise.
|
|
2359
|
+
|
|
2360
|
+
"""
|
|
2361
|
+
from topologicpy.Vertex import Vertex
|
|
2362
|
+
from topologicpy.Helper import Helper
|
|
2363
|
+
from topologicpy.Dictionary import Dictionary
|
|
2364
|
+
from topologicpy.Topology import Topology
|
|
2365
|
+
import random
|
|
2366
|
+
import pandas as pd
|
|
2367
|
+
|
|
2368
|
+
if not isinstance(graphs, list):
|
|
2369
|
+
print("Graph.ExportToCSV - Error: The input list of graphs is not a list. Returning None.")
|
|
2370
|
+
return None
|
|
2371
|
+
|
|
2372
|
+
for graph_index, graph in enumerate(graphs):
|
|
2373
|
+
graph_label = graphLabels[graph_index]
|
|
2374
|
+
# Export Graph Properties
|
|
2375
|
+
vertices = Graph.Vertices(graph)
|
|
2376
|
+
# Shuffle the vertices
|
|
2377
|
+
vertices = random.sample(vertices, len(vertices))
|
|
2378
|
+
graph_num_nodes = len(vertices)
|
|
2379
|
+
if overwrite == False:
|
|
2380
|
+
graphs = pd.read_csv(graphsPath)
|
|
2381
|
+
max_id = max(list(graphs[graphIDHeader]))
|
|
2382
|
+
graph_id = max_id + graph_index + 1
|
|
2383
|
+
else:
|
|
2384
|
+
graph_id = graph_index
|
|
2385
|
+
data = [[graph_id], [graph_label], [graph_num_nodes]]
|
|
2386
|
+
data = Helper.Iterate(data)
|
|
2387
|
+
data = Helper.Transpose(data)
|
|
2388
|
+
df = pd.DataFrame(data, columns= [graphIDHeader, graphLabelHeader, graphNumNodesHeader])
|
|
2389
|
+
if overwrite == False:
|
|
2390
|
+
df.to_csv(graphsPath, mode='a', index = False, header=False)
|
|
2391
|
+
else:
|
|
2392
|
+
if graph_index == 0:
|
|
2393
|
+
df.to_csv(graphsPath, mode='w+', index = False, header=True)
|
|
2394
|
+
else:
|
|
2395
|
+
df.to_csv(graphsPath, mode='a', index = False, header=False)
|
|
2396
|
+
|
|
2397
|
+
# Export Edge Properties
|
|
2398
|
+
edge_src = []
|
|
2399
|
+
edge_dst = []
|
|
2400
|
+
edge_graph_id = [] #Repetitive list of graph_id for each edge
|
|
2401
|
+
node_data = []
|
|
2402
|
+
node_columns = [graphIDHeader, nodeLabelHeader, "X", "Y", "Z"]
|
|
2403
|
+
# All keys should be the same for all vertices, so we can get them from the first vertex
|
|
2404
|
+
d = Topology.Dictionary(vertices[0])
|
|
2405
|
+
keys = Dictionary.Keys(d)
|
|
2406
|
+
for key in keys:
|
|
2407
|
+
if key != nodeLabelKey: #We have already saved that in its own column
|
|
2408
|
+
node_columns.append(key)
|
|
2409
|
+
for i, v in enumerate(vertices):
|
|
2410
|
+
# Might as well get the node labels since we are iterating through the vertices
|
|
2411
|
+
d = Topology.Dictionary(v)
|
|
2412
|
+
vLabel = Dictionary.ValueAtKey(d, nodeLabelKey)
|
|
2413
|
+
if not(vLabel):
|
|
2414
|
+
vLabel = defaultNodeLabel
|
|
2415
|
+
single_node_data = [graph_id, vLabel, round(float(v.X()),5), round(float(v.Y()),5), round(float(v.Z()),5)]
|
|
2416
|
+
keys = d.Keys()
|
|
2417
|
+
for key in keys:
|
|
2418
|
+
if key != nodeLabelKey and (key in node_columns):
|
|
2419
|
+
value = Dictionary.ValueAtKey(d, key)
|
|
2420
|
+
if not value:
|
|
2421
|
+
value = 'None'
|
|
2422
|
+
single_node_data.append(value)
|
|
2423
|
+
node_data.append(single_node_data)
|
|
2424
|
+
av = Graph.AdjacentVertices(graph, v)
|
|
2425
|
+
for k in range(len(av)):
|
|
2426
|
+
vi = Vertex.Index(av[k], vertices)
|
|
2427
|
+
edge_graph_id.append(graph_id)
|
|
2428
|
+
edge_src.append(i)
|
|
2429
|
+
edge_dst.append(vi)
|
|
2430
|
+
data = [edge_graph_id, edge_src, edge_dst]
|
|
2431
|
+
data = Helper.Iterate(data)
|
|
2432
|
+
data = Helper.Transpose(data)
|
|
2433
|
+
df = pd.DataFrame(data, columns= [graphIDHeader, edgeSRCHeader, edgeDSTHeader])
|
|
2434
|
+
if overwrite == False:
|
|
2435
|
+
df.to_csv(edgesPath, mode='a', index = False, header=False)
|
|
2436
|
+
else:
|
|
2437
|
+
if graph_index == 0:
|
|
2438
|
+
df.to_csv(edgesPath, mode='w+', index = False, header=True)
|
|
2439
|
+
else:
|
|
2440
|
+
df.to_csv(edgesPath, mode='a', index = False, header=False)
|
|
2441
|
+
|
|
2442
|
+
# Export Node Properties
|
|
2443
|
+
df = pd.DataFrame(node_data, columns= node_columns)
|
|
2444
|
+
|
|
2445
|
+
if overwrite == False:
|
|
2446
|
+
df.to_csv(nodesPath, mode='a', index = False, header=False)
|
|
2447
|
+
else:
|
|
2448
|
+
if graph_index == 0:
|
|
2449
|
+
df.to_csv(nodesPath, mode='w+', index = False, header=True)
|
|
2450
|
+
else:
|
|
2451
|
+
df.to_csv(nodesPath, mode='a', index = False, header=False)
|
|
2452
|
+
return True
|
|
2453
|
+
|
|
2454
|
+
@staticmethod
|
|
2455
|
+
def ExportToCSV_NC(graphs, graphLabels, path, edgeFeaturesKeys=[], nodeFeaturesKeys=[], graphIDHeader="graph_id", graphLabelHeader="label",graphNumNodesHeader="num_nodes", edgeLabelKey="label", defaultEdgeLabel=0, edgeSRCHeader="src_id", edgeDSTHeader="dst_id", edgeLabelHeader="label", edgeFeaturesHeader="feat", nodeLabelKey="label", defaultNodeLabel=0, nodeIDHeader="node_id", nodeLabelHeader="label", nodeFeaturesHeader="feat", trainRatio=0.8, validateRatio=0.1, testRatio=0.1, overwrite=False):
|
|
2456
|
+
"""
|
|
2457
|
+
Exports the input list of graphs into a set of CSV files compatible with DGL for Graph Classification.
|
|
2458
|
+
|
|
2459
|
+
Parameters
|
|
2460
|
+
----------
|
|
2461
|
+
graphs : list
|
|
2462
|
+
The input list of graphs.
|
|
2463
|
+
graphLabels : list
|
|
2464
|
+
The input list of graph labels. This must be list of ints where the minimum must be 0 and the maximum must be n where n is the number of graph categories.
|
|
2465
|
+
path : str
|
|
2466
|
+
The desired path to the output folder where the graphs, edges, and nodes CSV files will be saved.
|
|
2467
|
+
edgeFeaturesKeys : list , optional
|
|
2468
|
+
The list of features keys saved in the dicitonaries of edges. The default is [].
|
|
2469
|
+
nodesFeaturesKeys : list , optional
|
|
2470
|
+
The list of features keys saved in the dicitonaries of nodes. The default is [].
|
|
2471
|
+
graphIDHeader : str , optional
|
|
2472
|
+
The desired graph ID column header. The default is "graph_id".
|
|
2473
|
+
graphLabelHeader : str , optional
|
|
2474
|
+
The desired graph label column header. The default is "label".
|
|
2475
|
+
graphNumNodesHeader : str , optional
|
|
2476
|
+
The desired graph number of nodes column header. The default is "num_nodes".
|
|
2477
|
+
edgeLabelKey : str , optional
|
|
2478
|
+
The edge label dictionary key saved in each graph vertex. The default is "label".
|
|
2479
|
+
defaultEdgeLabel : int , optional
|
|
2480
|
+
The default nodedge label to use if no edge label is found. The default is 0.
|
|
2481
|
+
edgeSRCHeader : str , optional
|
|
2482
|
+
The desired edge source column header. The default is "src".
|
|
2483
|
+
edgeDSTHeader : str , optional
|
|
2484
|
+
The desired edge destination column header. The default is "dst".
|
|
2485
|
+
edgeFeaturesHeader : str , optional
|
|
2486
|
+
The desired edge features column header. The default is "feat".
|
|
2487
|
+
nodeLabelKey : str , optional
|
|
2488
|
+
The node label dictionary key saved in each graph vertex. The default is "label".
|
|
2489
|
+
defaultNodeLabel : int , optional
|
|
2490
|
+
The default node label to use if no node label is found. The default is 0.
|
|
2491
|
+
nodeIDHeader : str , optional
|
|
2492
|
+
The desired node ID column header. The default is "node_id".
|
|
2493
|
+
nodeLabelHeader : str , optional
|
|
2494
|
+
The desired node label column header. The default is "label".
|
|
2495
|
+
nodeFeaturesHeader : str , optional
|
|
2496
|
+
The desired node features column header. The default is "feat".
|
|
2497
|
+
trainRatio : float , optional
|
|
2498
|
+
The desired ratio of the data to use for training. The number must be between 0 and 1. The default is 0.8 which means 80% of the data will be used for training.
|
|
2499
|
+
validateRatio : float , optional
|
|
2500
|
+
The desired ratio of the data to use for validation. The number must be between 0 and 1. The default is 0.1 which means 10% of the data will be used for validation.
|
|
2501
|
+
testRatio : float , optional
|
|
2502
|
+
The desired ratio of the data to use for testing. The number must be between 0 and 1. The default is 0.1 which means 10% of the data will be used for testing.
|
|
2503
|
+
overwrite : bool , optional
|
|
2504
|
+
If set to True, any existing files are overwritten. Otherwise, the input list of graphs is appended to the end of each file. The default is False.
|
|
2505
|
+
|
|
2506
|
+
Returns
|
|
2507
|
+
-------
|
|
2508
|
+
bool
|
|
2509
|
+
True if the graphs have been successfully exported. False otherwise.
|
|
2510
|
+
|
|
2511
|
+
"""
|
|
2512
|
+
|
|
2513
|
+
|
|
2514
|
+
from topologicpy.Vertex import Vertex
|
|
2515
|
+
from topologicpy.Helper import Helper
|
|
2516
|
+
from topologicpy.Dictionary import Dictionary
|
|
2517
|
+
from topologicpy.Topology import Topology
|
|
2518
|
+
import os
|
|
2519
|
+
import math
|
|
2520
|
+
import random
|
|
2521
|
+
import pandas as pd
|
|
2522
|
+
|
|
2523
|
+
if not isinstance(graphs, list):
|
|
2524
|
+
print("Graph.ExportToCSV - Error: The input list of graphs is not a list. Returning None.")
|
|
2525
|
+
return None
|
|
2526
|
+
if abs(trainRatio + validateRatio + testRatio - 1) > 0.001:
|
|
2527
|
+
print("Graph.ExportToCSV - Error: The train, validate, test ratios do not add up to 1. Returning None")
|
|
2528
|
+
return None
|
|
2529
|
+
for graph_index, graph in enumerate(graphs):
|
|
2530
|
+
graph_label = graphLabels[graph_index]
|
|
2531
|
+
# Export Graph Properties
|
|
2532
|
+
vertices = Graph.Vertices(graph)
|
|
2533
|
+
# Shuffle the vertices
|
|
2534
|
+
vertices = random.sample(vertices, len(vertices))
|
|
2535
|
+
train_max = math.floor(float(len(vertices))*trainRatio)
|
|
2536
|
+
validate_max = math.floor(float(len(vertices))*validateRatio)
|
|
2537
|
+
test_max = len(vertices) - train_max - validate_max
|
|
2538
|
+
graph_num_nodes = len(vertices)
|
|
2539
|
+
if overwrite == False:
|
|
2540
|
+
graphs = pd.read_csv(os.path.join(path,"graphs.csv"))
|
|
2541
|
+
max_id = max(list(graphs[graphIDHeader]))
|
|
2542
|
+
graph_id = max_id + graph_index + 1
|
|
2543
|
+
else:
|
|
2544
|
+
graph_id = graph_index
|
|
2545
|
+
data = [[graph_id], [graph_label], [graph_num_nodes]]
|
|
2546
|
+
data = Helper.Iterate(data)
|
|
2547
|
+
data = Helper.Transpose(data)
|
|
2548
|
+
df = pd.DataFrame(data, columns= [graphIDHeader, graphLabelHeader, graphNumNodesHeader])
|
|
2549
|
+
if overwrite == False:
|
|
2550
|
+
df.to_csv(os.path.join(path, "graphs.csv"), mode='a', index = False, header=False)
|
|
2551
|
+
else:
|
|
2552
|
+
if graph_index == 0:
|
|
2553
|
+
df.to_csv(os.path.join(path, "graphs.csv"), mode='w+', index = False, header=True)
|
|
2554
|
+
else:
|
|
2555
|
+
df.to_csv(os.path.join(path, "graphs.csv"), mode='a', index = False, header=False)
|
|
2556
|
+
|
|
2557
|
+
# Export Edge Properties
|
|
2558
|
+
edge_graph_id = [] #Repetitive list of graph_id for each edge
|
|
2559
|
+
edge_src = []
|
|
2560
|
+
edge_dst = []
|
|
2561
|
+
edge_lab = []
|
|
2562
|
+
edge_feat = []
|
|
2563
|
+
node_graph_id = [] #Repetitive list of graph_id for each vertex/node
|
|
2564
|
+
node_labels = []
|
|
2565
|
+
x_list = []
|
|
2566
|
+
y_list = []
|
|
2567
|
+
z_list = []
|
|
2568
|
+
node_data = []
|
|
2569
|
+
node_columns = [graphIDHeader, nodeIDHeader, nodeLabelHeader, "train_mask", "val_mask", "test_mask", nodeFeaturesHeader, "X", "Y", "Z"]
|
|
2570
|
+
# All keys should be the same for all vertices, so we can get them from the first vertex
|
|
2571
|
+
d = Topology.Dictionary(vertices[0])
|
|
2572
|
+
'''
|
|
2573
|
+
keys = d.Keys()
|
|
2574
|
+
for key in keys:
|
|
2575
|
+
if key != node_label_key: #We have already saved that in its own column
|
|
2576
|
+
node_columns.append(key)
|
|
2577
|
+
'''
|
|
2578
|
+
train = 0
|
|
2579
|
+
test = 0
|
|
2580
|
+
validate = 0
|
|
2581
|
+
|
|
2582
|
+
for i, v in enumerate(vertices):
|
|
2583
|
+
if train < train_max:
|
|
2584
|
+
train_mask = True
|
|
2585
|
+
validate_mask = False
|
|
2586
|
+
test_mask = False
|
|
2587
|
+
train = train + 1
|
|
2588
|
+
elif validate < validate_max:
|
|
2589
|
+
train_mask = False
|
|
2590
|
+
validate_mask = True
|
|
2591
|
+
test_mask = False
|
|
2592
|
+
validate = validate + 1
|
|
2593
|
+
elif test < test_max:
|
|
2594
|
+
train_mask = False
|
|
2595
|
+
validate_mask = False
|
|
2596
|
+
test_mask = True
|
|
2597
|
+
test = test + 1
|
|
2598
|
+
else:
|
|
2599
|
+
train_mask = True
|
|
2600
|
+
validate_mask = False
|
|
2601
|
+
test_mask = False
|
|
2602
|
+
train = train + 1
|
|
2603
|
+
# Might as well get the node labels since we are iterating through the vertices
|
|
2604
|
+
d = Topology.Dictionary(v)
|
|
2605
|
+
vLabel = Dictionary.ValueAtKey(d, nodeLabelKey)
|
|
2606
|
+
if vLabel == None:
|
|
2607
|
+
vLabel = defaultNodeLabel
|
|
2608
|
+
# Might as well get the features since we are iterating through the vertices
|
|
2609
|
+
features = ""
|
|
2610
|
+
node_features_keys = Helper.Flatten(nodeFeaturesKeys)
|
|
2611
|
+
for node_feature_key in node_features_keys:
|
|
2612
|
+
if len(features) > 0:
|
|
2613
|
+
features = features + ","+ str(round(float(Dictionary.ValueAtKey(d, node_feature_key)),5))
|
|
2614
|
+
else:
|
|
2615
|
+
features = str(round(float(Dictionary.ValueAtKey(d, node_feature_key)),5))
|
|
2616
|
+
single_node_data = [graph_id, i, vLabel, train_mask, validate_mask, test_mask, features, round(float(Vertex.X(v)),5), round(float(Vertex.Y(v)),5), round(float(Vertex.Z(v)),5)]
|
|
2617
|
+
node_data.append(single_node_data)
|
|
2618
|
+
av = Graph.AdjacentVertices(graph, v)
|
|
2619
|
+
for k in range(len(av)):
|
|
2620
|
+
vi = Vertex.Index(av[k], vertices)
|
|
2621
|
+
edge_graph_id.append(graph_id)
|
|
2622
|
+
edge_src.append(i)
|
|
2623
|
+
edge_dst.append(vi)
|
|
2624
|
+
edge = graph.Edge(v, av[k], 0.0001)
|
|
2625
|
+
ed = Topology.Dictionary(edge)
|
|
2626
|
+
edge_label = Dictionary.ValueAtKey(d, edgeLabelKey)
|
|
2627
|
+
if edge_label == None:
|
|
2628
|
+
edge_label = defaultEdgeLabel
|
|
2629
|
+
edge_lab.append(edge_label)
|
|
2630
|
+
edge_features = ""
|
|
2631
|
+
edge_features_keys = Helper.Flatten(edgeFeaturesKeys)
|
|
2632
|
+
for edge_feature_key in edge_features_keys:
|
|
2633
|
+
if len(edge_features) > 0:
|
|
2634
|
+
edge_features = edge_features + ","+ str(round(float(Dictionary.ValueAtKey(ed, edge_feature_key)),5))
|
|
2635
|
+
else:
|
|
2636
|
+
edge_features = str(round(float(Dictionary.ValueAtKey(ed, edge_feature_key)),5))
|
|
2637
|
+
edge_feat.append(edge_features)
|
|
2638
|
+
data = [edge_graph_id, edge_src, edge_dst, edge_lab, edge_feat]
|
|
2639
|
+
data = Helper.Iterate(data)
|
|
2640
|
+
data = Helper.Transpose(data)
|
|
2641
|
+
df = pd.DataFrame(data, columns= [graphIDHeader, edgeSRCHeader, edgeDSTHeader, edgeLabelHeader, edgeFeaturesHeader])
|
|
2642
|
+
if overwrite == False:
|
|
2643
|
+
df.to_csv(os.path.join(path, "edges.csv"), mode='a', index = False, header=False)
|
|
2644
|
+
else:
|
|
2645
|
+
if graph_index == 0:
|
|
2646
|
+
df.to_csv(os.path.join(path, "edges.csv"), mode='w+', index = False, header=True)
|
|
2647
|
+
else:
|
|
2648
|
+
df.to_csv(os.path.join(path, "edges.csv"), mode='a', index = False, header=False)
|
|
2649
|
+
|
|
2650
|
+
# Export Node Properties
|
|
2651
|
+
df = pd.DataFrame(node_data, columns= node_columns)
|
|
2652
|
+
|
|
2653
|
+
if overwrite == False:
|
|
2654
|
+
df.to_csv(os.path.join(path, "nodes.csv"), mode='a', index = False, header=False)
|
|
2655
|
+
else:
|
|
2656
|
+
if graph_index == 0:
|
|
2657
|
+
df.to_csv(os.path.join(path, "nodes.csv"), mode='w+', index = False, header=True)
|
|
2658
|
+
else:
|
|
2659
|
+
df.to_csv(os.path.join(path, "nodes.csv"), mode='a', index = False, header=False)
|
|
2660
|
+
# Write out the meta.yaml file
|
|
2661
|
+
yaml_file = open(os.path.join(path,"meta.yaml"), "w")
|
|
2662
|
+
yaml_file.write('dataset_name: topologic_dataset\nedge_data:\n- file_name: edges.csv\nnode_data:\n- file_name: nodes.csv\ngraph_data:\n file_name: graphs.csv')
|
|
2663
|
+
yaml_file.close()
|
|
2664
|
+
return True
|
|
2665
|
+
|
|
2666
|
+
@staticmethod
|
|
2667
|
+
def IsBipartite(graph, tolerance=0.0001):
|
|
2668
|
+
"""
|
|
2669
|
+
Returns True if the input graph is bipartite. Returns False otherwise. See https://en.wikipedia.org/wiki/Bipartite_graph.
|
|
2670
|
+
|
|
2671
|
+
Parameters
|
|
2672
|
+
----------
|
|
2673
|
+
graph : topologic.Graph
|
|
2674
|
+
The input graph.
|
|
2675
|
+
tolerance : float , optional
|
|
2676
|
+
The desired tolerance. The default is 0.0001.
|
|
2677
|
+
|
|
2678
|
+
Returns
|
|
2679
|
+
-------
|
|
2680
|
+
bool
|
|
2681
|
+
True if the input graph is complete. False otherwise
|
|
2682
|
+
|
|
2683
|
+
"""
|
|
2684
|
+
# From https://www.geeksforgeeks.org/bipartite-graph/
|
|
2685
|
+
# This code is contributed by divyesh072019.
|
|
2686
|
+
def isBipartite(V, adj):
|
|
2687
|
+
# vector to store colour of vertex
|
|
2688
|
+
# assigning all to -1 i.e. uncoloured
|
|
2689
|
+
# colours are either 0 or 1
|
|
2690
|
+
# for understanding take 0 as red and 1 as blue
|
|
2691
|
+
col = [-1]*(V)
|
|
2692
|
+
|
|
2693
|
+
# queue for BFS storing {vertex , colour}
|
|
2694
|
+
q = []
|
|
2695
|
+
|
|
2696
|
+
#loop incase graph is not connected
|
|
2697
|
+
for i in range(V):
|
|
2698
|
+
|
|
2699
|
+
# if not coloured
|
|
2700
|
+
if (col[i] == -1):
|
|
2701
|
+
|
|
2702
|
+
# colouring with 0 i.e. red
|
|
2703
|
+
q.append([i, 0])
|
|
2704
|
+
col[i] = 0
|
|
2705
|
+
|
|
2706
|
+
while len(q) != 0:
|
|
2707
|
+
p = q[0]
|
|
2708
|
+
q.pop(0)
|
|
2709
|
+
|
|
2710
|
+
# current vertex
|
|
2711
|
+
v = p[0]
|
|
2712
|
+
|
|
2713
|
+
# colour of current vertex
|
|
2714
|
+
c = p[1]
|
|
2715
|
+
|
|
2716
|
+
# traversing vertexes connected to current vertex
|
|
2717
|
+
for j in adj[v]:
|
|
2718
|
+
|
|
2719
|
+
# if already coloured with parent vertex color
|
|
2720
|
+
# then bipartite graph is not possible
|
|
2721
|
+
if (col[j] == c):
|
|
2722
|
+
return False
|
|
2723
|
+
|
|
2724
|
+
# if uncoloured
|
|
2725
|
+
if (col[j] == -1):
|
|
2726
|
+
|
|
2727
|
+
# colouring with opposite color to that of parent
|
|
2728
|
+
if c == 1:
|
|
2729
|
+
col[j] = 0
|
|
2730
|
+
else:
|
|
2731
|
+
col[j] = 1
|
|
2732
|
+
q.append([j, col[j]])
|
|
2733
|
+
|
|
2734
|
+
# if all vertexes are coloured such that
|
|
2735
|
+
# no two connected vertex have same colours
|
|
2736
|
+
return True
|
|
2737
|
+
if not isinstance(graph, topologic.Graph):
|
|
2738
|
+
return None
|
|
2739
|
+
order = Graph.Order(graph)
|
|
2740
|
+
adjList = Graph.AdjacencyList(graph, tolerance)
|
|
2741
|
+
return isBipartite(order, adjList)
|
|
2742
|
+
|
|
2743
|
+
@staticmethod
|
|
2744
|
+
def IsComplete(graph):
|
|
2745
|
+
"""
|
|
2746
|
+
Returns True if the input graph is complete. Returns False otherwise. See https://en.wikipedia.org/wiki/Complete_graph.
|
|
2747
|
+
|
|
2748
|
+
Parameters
|
|
2749
|
+
----------
|
|
2750
|
+
graph : topologic.Graph
|
|
2751
|
+
The input graph.
|
|
2752
|
+
|
|
2753
|
+
Returns
|
|
2754
|
+
-------
|
|
2755
|
+
bool
|
|
2756
|
+
True if the input graph is complete. False otherwise
|
|
2757
|
+
|
|
2758
|
+
"""
|
|
2759
|
+
if not isinstance(graph, topologic.Graph):
|
|
2760
|
+
return None
|
|
2761
|
+
return graph.IsComplete()
|
|
2762
|
+
|
|
2763
|
+
@staticmethod
|
|
2764
|
+
def IsErdoesGallai(graph, sequence):
|
|
2765
|
+
"""
|
|
2766
|
+
Returns True if the input sequence satisfies the Erdős–Gallai theorem. Returns False otherwise. See https://en.wikipedia.org/wiki/Erd%C5%91s%E2%80%93Gallai_theorem.
|
|
2767
|
+
|
|
2768
|
+
Parameters
|
|
2769
|
+
----------
|
|
2770
|
+
graph : topologic.Graph
|
|
2771
|
+
The input graph.
|
|
2772
|
+
sequence : list
|
|
2773
|
+
The input sequence.
|
|
2774
|
+
|
|
2775
|
+
Returns
|
|
2776
|
+
-------
|
|
2777
|
+
bool
|
|
2778
|
+
True if the input sequence satisfies the Erdős–Gallai theorem. False otherwise.
|
|
2779
|
+
|
|
2780
|
+
"""
|
|
2781
|
+
if not isinstance(graph, topologic.Graph):
|
|
2782
|
+
return None
|
|
2783
|
+
return graph.IsErdoesGallai(sequence)
|
|
2784
|
+
|
|
2785
|
+
@staticmethod
|
|
2786
|
+
def IsolatedVertices(graph):
|
|
2787
|
+
"""
|
|
2788
|
+
Returns the list of isolated vertices in the input graph.
|
|
2789
|
+
|
|
2790
|
+
Parameters
|
|
2791
|
+
----------
|
|
2792
|
+
graph : topologic.Graph
|
|
2793
|
+
The input graph.
|
|
2794
|
+
|
|
2795
|
+
Returns
|
|
2796
|
+
-------
|
|
2797
|
+
list
|
|
2798
|
+
The list of isolated vertices.
|
|
2799
|
+
|
|
2800
|
+
"""
|
|
2801
|
+
if not isinstance(graph, topologic.Graph):
|
|
2802
|
+
return None
|
|
2803
|
+
vertices = []
|
|
2804
|
+
_ = graph.IsolatedVertices(vertices)
|
|
2805
|
+
return vertices
|
|
2806
|
+
|
|
2807
|
+
@staticmethod
|
|
2808
|
+
def MaximumDelta(graph):
|
|
2809
|
+
"""
|
|
2810
|
+
Returns the maximum delta of the input graph. The maximum delta of a graph is the maximum degree of a vertex in the graph.
|
|
2811
|
+
|
|
2812
|
+
Parameters
|
|
2813
|
+
----------
|
|
2814
|
+
graph : topologic.Graph
|
|
2815
|
+
the input graph.
|
|
2816
|
+
|
|
2817
|
+
Returns
|
|
2818
|
+
-------
|
|
2819
|
+
int
|
|
2820
|
+
The maximum delta.
|
|
2821
|
+
|
|
2822
|
+
"""
|
|
2823
|
+
if not isinstance(graph, topologic.Graph):
|
|
2824
|
+
return None
|
|
2825
|
+
return graph.MaximumDelta()
|
|
2826
|
+
|
|
2827
|
+
@staticmethod
|
|
2828
|
+
def MinimumDelta(graph):
|
|
2829
|
+
"""
|
|
2830
|
+
Returns the minimum delta of the input graph. The minimum delta of a graph is the minimum degree of a vertex in the graph.
|
|
2831
|
+
|
|
2832
|
+
Parameters
|
|
2833
|
+
----------
|
|
2834
|
+
graph : topologic.Graph
|
|
2835
|
+
The input graph.
|
|
2836
|
+
|
|
2837
|
+
Returns
|
|
2838
|
+
-------
|
|
2839
|
+
int
|
|
2840
|
+
The minimum delta.
|
|
2841
|
+
|
|
2842
|
+
"""
|
|
2843
|
+
if not isinstance(graph, topologic.Graph):
|
|
2844
|
+
return None
|
|
2845
|
+
return graph.MinimumDelta()
|
|
2846
|
+
|
|
2847
|
+
@staticmethod
|
|
2848
|
+
def MinimumSpanningTree(graph, edgeKey=None, tolerance=0.0001):
|
|
2849
|
+
"""
|
|
2850
|
+
Returns the minimum spanning tree of the input graph. See https://en.wikipedia.org/wiki/Minimum_spanning_tree.
|
|
2851
|
+
|
|
2852
|
+
Parameters
|
|
2853
|
+
----------
|
|
2854
|
+
graph : topologic.Graph
|
|
2855
|
+
The input graph.
|
|
2856
|
+
edgeKey : string , optional
|
|
2857
|
+
If set, the value of the edgeKey will be used as the weight and the tree will minimize the weight. The value associated with the edgeKey must be numerical. If the key is not set, the edges will be sorted by their length. The default is None
|
|
2858
|
+
tolerance : float , optional
|
|
2859
|
+
The desired tolerance. The default is 0.0001.
|
|
2860
|
+
|
|
2861
|
+
Returns
|
|
2862
|
+
-------
|
|
2863
|
+
topologic.Graph
|
|
2864
|
+
The minimum spanning tree.
|
|
2865
|
+
|
|
2866
|
+
"""
|
|
2867
|
+
from topologicpy.Vertex import Vertex
|
|
2868
|
+
from topologicpy.Edge import Edge
|
|
2869
|
+
from topologicpy.Dictionary import Dictionary
|
|
2870
|
+
def vertexInList(vertex, vertexList, tolerance=0.0001):
|
|
2871
|
+
for v in vertexList:
|
|
2872
|
+
if Vertex.Distance(v, vertex) < tolerance:
|
|
2873
|
+
return True
|
|
2874
|
+
return False
|
|
2875
|
+
|
|
2876
|
+
edges = Graph.Edges(graph)
|
|
2877
|
+
vertices = Graph.Vertices(graph)
|
|
2878
|
+
values = []
|
|
2879
|
+
if isinstance(edgeKey, str):
|
|
2880
|
+
for edge in edges:
|
|
2881
|
+
d = Dictionary.Dictionary(edge)
|
|
2882
|
+
value = Dictionary.ValueAtKey(d, edgeKey)
|
|
2883
|
+
if not value or not isinstance(value, int) or not isinstance(value, float):
|
|
2884
|
+
return None
|
|
2885
|
+
values.append(value)
|
|
2886
|
+
else:
|
|
2887
|
+
for edge in edges:
|
|
2888
|
+
value = Edge.Length(edge)
|
|
2889
|
+
values.append(value)
|
|
2890
|
+
keydict = dict(zip(edges, values))
|
|
2891
|
+
edges.sort(key=keydict.get)
|
|
2892
|
+
mst = Graph.ByVerticesEdges(vertices,[])
|
|
2893
|
+
for edge in edges:
|
|
2894
|
+
sv = Edge.StartVertex(edge)
|
|
2895
|
+
ev = Edge.EndVertex(edge)
|
|
2896
|
+
if len(Graph.Vertices(mst)) > 0:
|
|
2897
|
+
if not Graph.Path(mst, Graph.NearestVertex(mst, sv), Graph.NearestVertex(mst, ev)):
|
|
2898
|
+
mst = Graph.AddEdge(mst, edge)
|
|
2899
|
+
return mst
|
|
2900
|
+
|
|
2901
|
+
@staticmethod
|
|
2902
|
+
def NearestVertex(graph, vertex):
|
|
2903
|
+
"""
|
|
2904
|
+
Returns the vertex in the input graph that is the nearest to the input vertex.
|
|
2905
|
+
|
|
2906
|
+
Parameters
|
|
2907
|
+
----------
|
|
2908
|
+
graph : topologic.Graph
|
|
2909
|
+
The input graph.
|
|
2910
|
+
vertex : topologic.Vertex
|
|
2911
|
+
The input vertex.
|
|
2912
|
+
|
|
2913
|
+
Returns
|
|
2914
|
+
-------
|
|
2915
|
+
topologic.Vertex
|
|
2916
|
+
The vertex in the input graph that is the nearest to the input vertex.
|
|
2917
|
+
|
|
2918
|
+
"""
|
|
2919
|
+
from topologicpy.Vertex import Vertex
|
|
2920
|
+
|
|
2921
|
+
if not isinstance(graph, topologic.Graph):
|
|
2922
|
+
return None
|
|
2923
|
+
if not isinstance(vertex, topologic.Vertex):
|
|
2924
|
+
return None
|
|
2925
|
+
vertices = Graph.Vertices(graph)
|
|
2926
|
+
nearestVertex = vertices[0]
|
|
2927
|
+
nearestDistance = Vertex.Distance(vertex, nearestVertex)
|
|
2928
|
+
for aGraphVertex in vertices:
|
|
2929
|
+
newDistance = Vertex.Distance(vertex, aGraphVertex)
|
|
2930
|
+
if newDistance < nearestDistance:
|
|
2931
|
+
nearestDistance = newDistance
|
|
2932
|
+
nearestVertex = aGraphVertex
|
|
2933
|
+
return nearestVertex
|
|
2934
|
+
|
|
2935
|
+
@staticmethod
|
|
2936
|
+
def NetworkXGraph(graph, tolerance=0.0001):
|
|
2937
|
+
"""
|
|
2938
|
+
converts the input graph into a NetworkX Graph. See http://networkx.org
|
|
2939
|
+
|
|
2940
|
+
Parameters
|
|
2941
|
+
----------
|
|
2942
|
+
graph : topologic.Graph
|
|
2943
|
+
The input graph.
|
|
2944
|
+
|
|
2945
|
+
Returns
|
|
2946
|
+
-------
|
|
2947
|
+
networkX Graph
|
|
2948
|
+
The created networkX Graph
|
|
2949
|
+
|
|
2950
|
+
"""
|
|
2951
|
+
from topologicpy.Vertex import Vertex
|
|
2952
|
+
from topologicpy.Edge import Edge
|
|
2953
|
+
from topologicpy.Topology import Topology
|
|
2954
|
+
from topologicpy.Dictionary import Dictionary
|
|
2955
|
+
import random
|
|
2956
|
+
import sys
|
|
2957
|
+
import subprocess
|
|
2958
|
+
if not isinstance(graph, topologic.Graph):
|
|
2959
|
+
return None
|
|
2960
|
+
try:
|
|
2961
|
+
import networkx as nx
|
|
2962
|
+
except:
|
|
2963
|
+
call = [sys.executable, '-m', 'pip', 'install', 'networkx', '-t', sys.path[0]]
|
|
2964
|
+
subprocess.run(call)
|
|
2965
|
+
try:
|
|
2966
|
+
import networkx as nx
|
|
2967
|
+
except:
|
|
2968
|
+
print("Graph.NetworkXGraph - ERROR: Could not import networkx. Returning None.")
|
|
2969
|
+
return None
|
|
2970
|
+
|
|
2971
|
+
nxGraph = nx.Graph()
|
|
2972
|
+
vertices = Graph.Vertices(graph)
|
|
2973
|
+
order = len(vertices)
|
|
2974
|
+
nodes = []
|
|
2975
|
+
for i in range(order):
|
|
2976
|
+
v = vertices[i]
|
|
2977
|
+
d = Topology.Dictionary(vertices[i])
|
|
2978
|
+
if d:
|
|
2979
|
+
keys = Dictionary.Keys(d)
|
|
2980
|
+
if not keys:
|
|
2981
|
+
keys = []
|
|
2982
|
+
values = Dictionary.Values(d)
|
|
2983
|
+
if not values:
|
|
2984
|
+
values = []
|
|
2985
|
+
keys += ["x","y","z"]
|
|
2986
|
+
import random
|
|
2987
|
+
values += [Vertex.X(v), Vertex.Y(v), Vertex.Z(v)]
|
|
2988
|
+
d = Dictionary.ByKeysValues(keys,values)
|
|
2989
|
+
pythonD = Dictionary.PythonDictionary(d)
|
|
2990
|
+
nodes.append((i, pythonD))
|
|
2991
|
+
else:
|
|
2992
|
+
nodes.append((i, {"name": str(i)}))
|
|
2993
|
+
nxGraph.add_nodes_from(nodes)
|
|
2994
|
+
for i in range(order):
|
|
2995
|
+
v = vertices[i]
|
|
2996
|
+
adjVertices = Graph.AdjacentVertices(graph, vertices[i])
|
|
2997
|
+
for adjVertex in adjVertices:
|
|
2998
|
+
adjIndex = Vertex.Index(vertex=adjVertex, vertices=vertices, strict=True, tolerance=tolerance)
|
|
2999
|
+
if not adjIndex == None:
|
|
3000
|
+
nxGraph.add_edge(i,adjIndex, length=(Vertex.Distance(v, adjVertex)))
|
|
3001
|
+
|
|
3002
|
+
pos=nx.spring_layout(nxGraph, k=0.2)
|
|
3003
|
+
nx.set_node_attributes(nxGraph, pos, "pos")
|
|
3004
|
+
return nxGraph
|
|
3005
|
+
|
|
3006
|
+
@staticmethod
|
|
3007
|
+
def Order(graph):
|
|
3008
|
+
"""
|
|
3009
|
+
Returns the graph order of the input graph. The graph order is its number of vertices
|
|
3010
|
+
|
|
3011
|
+
Parameters
|
|
3012
|
+
----------
|
|
3013
|
+
graph : topologic.Graph
|
|
3014
|
+
The input graph.
|
|
3015
|
+
|
|
3016
|
+
Returns
|
|
3017
|
+
-------
|
|
3018
|
+
int
|
|
3019
|
+
The number of vertices in the input graph
|
|
3020
|
+
|
|
3021
|
+
"""
|
|
3022
|
+
if not isinstance(graph, topologic.Graph):
|
|
3023
|
+
return None
|
|
3024
|
+
return len(Graph.Vertices(graph))
|
|
3025
|
+
|
|
3026
|
+
@staticmethod
|
|
3027
|
+
def Path(graph, vertexA, vertexB):
|
|
3028
|
+
"""
|
|
3029
|
+
Returns a path (wire) in the input graph that connects the input vertices.
|
|
3030
|
+
|
|
3031
|
+
Parameters
|
|
3032
|
+
----------
|
|
3033
|
+
graph : topologic.Graph
|
|
3034
|
+
The input graph.
|
|
3035
|
+
vertexA : topologic.Vertex
|
|
3036
|
+
The first input vertex.
|
|
3037
|
+
vertexB : topologic.Vertex
|
|
3038
|
+
The second input vertex.
|
|
3039
|
+
|
|
3040
|
+
Returns
|
|
3041
|
+
-------
|
|
3042
|
+
topologic.Wire
|
|
3043
|
+
The path (wire) in the input graph that connects the input vertices.
|
|
3044
|
+
|
|
3045
|
+
"""
|
|
3046
|
+
return graph.Path(vertexA, vertexB)
|
|
3047
|
+
|
|
3048
|
+
@staticmethod
|
|
3049
|
+
def RemoveEdge(graph, edge, tolerance=0.0001):
|
|
3050
|
+
"""
|
|
3051
|
+
Removes the input edge from the input graph.
|
|
3052
|
+
|
|
3053
|
+
Parameters
|
|
3054
|
+
----------
|
|
3055
|
+
graph : topologic.Graph
|
|
3056
|
+
The input graph.
|
|
3057
|
+
edge : topologic.Edge
|
|
3058
|
+
The input edge.
|
|
3059
|
+
tolerance : float , optional
|
|
3060
|
+
The desired tolerance. The default is 0.0001.
|
|
3061
|
+
|
|
3062
|
+
Returns
|
|
3063
|
+
-------
|
|
3064
|
+
topologic.Graph
|
|
3065
|
+
The input graph with the input edge removed.
|
|
3066
|
+
|
|
3067
|
+
"""
|
|
3068
|
+
if not isinstance(graph, topologic.Graph):
|
|
3069
|
+
return None
|
|
3070
|
+
if not isinstance(edge, topologic.Edge):
|
|
3071
|
+
return None
|
|
3072
|
+
_ = graph.RemoveEdges([edge], tolerance)
|
|
3073
|
+
return graph
|
|
3074
|
+
|
|
3075
|
+
@staticmethod
|
|
3076
|
+
def RemoveVertex(graph, vertex, tolerance=0.0001):
|
|
3077
|
+
"""
|
|
3078
|
+
Removes the input vertex from the input graph.
|
|
3079
|
+
|
|
3080
|
+
Parameters
|
|
3081
|
+
----------
|
|
3082
|
+
graph : topologic.Graph
|
|
3083
|
+
The input graph.
|
|
3084
|
+
vertex : topologic.Vertex
|
|
3085
|
+
The input vertex.
|
|
3086
|
+
tolerance : float , optional
|
|
3087
|
+
The desired tolerance. The default is 0.0001.
|
|
3088
|
+
|
|
3089
|
+
Returns
|
|
3090
|
+
-------
|
|
3091
|
+
topologic.Graph
|
|
3092
|
+
The input graph with the input vertex removed.
|
|
3093
|
+
|
|
3094
|
+
"""
|
|
3095
|
+
if not isinstance(graph, topologic.Graph):
|
|
3096
|
+
return None
|
|
3097
|
+
if not isinstance(vertex, topologic.Vertex):
|
|
3098
|
+
return None
|
|
3099
|
+
graphVertex = Graph.NearestVertex(graph, vertex)
|
|
3100
|
+
_ = graph.RemoveVertices([graphVertex])
|
|
3101
|
+
return graph
|
|
3102
|
+
|
|
3103
|
+
@staticmethod
|
|
3104
|
+
def ShortestPath(graph, vertexA, vertexB, vertexKey="", edgeKey="Length"):
|
|
3105
|
+
"""
|
|
3106
|
+
Returns the shortest path that connects the input vertices.
|
|
3107
|
+
|
|
3108
|
+
Parameters
|
|
3109
|
+
----------
|
|
3110
|
+
graph : topologic.Graph
|
|
3111
|
+
The input graph.
|
|
3112
|
+
vertexA : topologic.Vertex
|
|
3113
|
+
The first input vertex.
|
|
3114
|
+
vertexB : topologic.Vertex
|
|
3115
|
+
The second input vertex.
|
|
3116
|
+
vertexKey : string , optional
|
|
3117
|
+
The vertex key to minimise. If set the vertices dictionaries will be searched for this key and the associated value will be used to compute the shortest path that minimized the total value. The value must be numeric. The default is None.
|
|
3118
|
+
edgeKey : string , optional
|
|
3119
|
+
The edge key to minimise. If set the edges dictionaries will be searched for this key and the associated value will be used to compute the shortest path that minimized the total value. The value of the key must be numeric. If set to "length" (case insensitive), the shortest path by length is computed. The default is "length".
|
|
3120
|
+
|
|
3121
|
+
Returns
|
|
3122
|
+
-------
|
|
3123
|
+
topologic.Wire
|
|
3124
|
+
The shortest path between the input vertices.
|
|
3125
|
+
|
|
3126
|
+
"""
|
|
3127
|
+
if not isinstance(graph, topologic.Graph):
|
|
3128
|
+
return None
|
|
3129
|
+
if not isinstance(vertexA, topologic.Vertex):
|
|
3130
|
+
return None
|
|
3131
|
+
if not isinstance(vertexB, topologic.Vertex):
|
|
3132
|
+
return None
|
|
3133
|
+
if edgeKey:
|
|
3134
|
+
if edgeKey.lower() == "length":
|
|
3135
|
+
edgeKey = "Length"
|
|
3136
|
+
try:
|
|
3137
|
+
return graph.ShortestPath(vertexA, vertexB, vertexKey, edgeKey)
|
|
3138
|
+
except:
|
|
3139
|
+
return None
|
|
3140
|
+
|
|
3141
|
+
@staticmethod
|
|
3142
|
+
def ShortestPaths(graph, vertexA, vertexB, vertexKey="", edgeKey="length", timeLimit=10,
|
|
3143
|
+
pathLimit=10, tolerance=0.0001):
|
|
3144
|
+
"""
|
|
3145
|
+
Returns the shortest path that connects the input vertices.
|
|
3146
|
+
|
|
3147
|
+
Parameters
|
|
3148
|
+
----------
|
|
3149
|
+
graph : topologic.Graph
|
|
3150
|
+
The input graph.
|
|
3151
|
+
vertexA : topologic.Vertex
|
|
3152
|
+
The first input vertex.
|
|
3153
|
+
vertexB : topologic.Vertex
|
|
3154
|
+
The second input vertex.
|
|
3155
|
+
vertexKey : string , optional
|
|
3156
|
+
The vertex key to minimise. If set the vertices dictionaries will be searched for this key and the associated value will be used to compute the shortest path that minimized the total value. The value must be numeric. The default is None.
|
|
3157
|
+
edgeKey : string , optional
|
|
3158
|
+
The edge key to minimise. If set the edges dictionaries will be searched for this key and the associated value will be used to compute the shortest path that minimized the total value. The value of the key must be numeric. If set to "length" (case insensitive), the shortest path by length is computed. The default is "length".
|
|
3159
|
+
timeLimit : int , optional
|
|
3160
|
+
The search time limit in seconds. The default is 10 seconds
|
|
3161
|
+
pathLimit: int , optional
|
|
3162
|
+
The number of found paths limit. The default is 10 paths.
|
|
3163
|
+
|
|
3164
|
+
Returns
|
|
3165
|
+
-------
|
|
3166
|
+
topologic.Wire
|
|
3167
|
+
The list of shortest paths between the input vertices.
|
|
3168
|
+
|
|
3169
|
+
"""
|
|
3170
|
+
from topologicpy.Vertex import Vertex
|
|
3171
|
+
from topologicpy.Wire import Wire
|
|
3172
|
+
def nearestVertex(g, v, tolerance):
|
|
3173
|
+
vertices = Graph.Vertices(g)
|
|
3174
|
+
for aVertex in vertices:
|
|
3175
|
+
d = Vertex.Distance(v, aVertex)
|
|
3176
|
+
if d < tolerance:
|
|
3177
|
+
return aVertex
|
|
3178
|
+
return None
|
|
3179
|
+
|
|
3180
|
+
def isUnique(paths, wire):
|
|
3181
|
+
if len(paths) < 1:
|
|
3182
|
+
return True
|
|
3183
|
+
for aPath in paths:
|
|
3184
|
+
copyPath = topologic.Topology.DeepCopy(aPath)
|
|
3185
|
+
dif = copyPath.Difference(wire, False)
|
|
3186
|
+
if dif == None:
|
|
3187
|
+
return False
|
|
3188
|
+
return True
|
|
3189
|
+
|
|
3190
|
+
shortestPaths = []
|
|
3191
|
+
end = time.time() + timeLimit
|
|
3192
|
+
while time.time() < end and len(shortestPaths) < pathLimit:
|
|
3193
|
+
gsv = nearestVertex(graph, vertexA, tolerance)
|
|
3194
|
+
gev = nearestVertex(graph, vertexB, tolerance)
|
|
3195
|
+
if (graph != None):
|
|
3196
|
+
if edgeKey:
|
|
3197
|
+
if edgeKey.lower() == "length":
|
|
3198
|
+
edgeKey = "Length"
|
|
3199
|
+
wire = graph.ShortestPath(gsv,gev,vertexKey,edgeKey) # Find the first shortest path
|
|
3200
|
+
wireVertices = []
|
|
3201
|
+
flag = False
|
|
3202
|
+
try:
|
|
3203
|
+
wireVertices = Wire.Vertices(wire)
|
|
3204
|
+
flag = True
|
|
3205
|
+
except:
|
|
3206
|
+
flag = False
|
|
3207
|
+
if (flag):
|
|
3208
|
+
if isUnique(shortestPaths, wire):
|
|
3209
|
+
shortestPaths.append(wire)
|
|
3210
|
+
vertices = Graph.Vertices(graph)
|
|
3211
|
+
random.shuffle(vertices)
|
|
3212
|
+
edges = Graph.Edges(graph)
|
|
3213
|
+
graph = Graph.ByVerticesEdges(vertices, edges)
|
|
3214
|
+
return shortestPaths
|
|
3215
|
+
|
|
3216
|
+
@staticmethod
|
|
3217
|
+
def Show(graph, vertexColor="white", vertexSize=6, vertexLabelKey=None, vertexGroupKey=None, vertexGroups=[], showVertices=True, edgeColor="black", edgeWidth=1, edgeLabelKey=None, edgeGroupKey=None, edgeGroups=[], showEdges=True, renderer="notebook"):
|
|
3218
|
+
from topologicpy.Plotly import Plotly
|
|
3219
|
+
if not isinstance(graph, topologic.Graph):
|
|
3220
|
+
return None
|
|
3221
|
+
data= Plotly.DataByGraph(graph, vertexColor="white", vertexSize=vertexSize, vertexLabelKey=vertexLabelKey, vertexGroupKey=vertexGroupKey, vertexGroups=vertexGroups, showVertices=showVertices, edgeColor=edgeColor, edgeWidth=edgeWidth, edgeLabelKey=edgeLabelKey, edgeGroupKey=edgeGroupKey, edgeGroups=edgeGroups, showEdges=showEdges)
|
|
3222
|
+
fig = Plotly.FigureByData(data, color=vertexColor)
|
|
3223
|
+
Plotly.Show(fig, renderer=renderer)
|
|
3224
|
+
|
|
3225
|
+
@staticmethod
|
|
3226
|
+
def Size(graph):
|
|
3227
|
+
"""
|
|
3228
|
+
Returns the graph size of the input graph. The graph size is its number of edges
|
|
3229
|
+
|
|
3230
|
+
Parameters
|
|
3231
|
+
----------
|
|
3232
|
+
graph : topologic.Graph
|
|
3233
|
+
The input graph.
|
|
3234
|
+
|
|
3235
|
+
Returns
|
|
3236
|
+
-------
|
|
3237
|
+
int
|
|
3238
|
+
The number of edges in the input graph.
|
|
3239
|
+
|
|
3240
|
+
"""
|
|
3241
|
+
if not isinstance(graph, topologic.Graph):
|
|
3242
|
+
return None
|
|
3243
|
+
return len(Graph.Edges(graph))
|
|
3244
|
+
|
|
3245
|
+
@staticmethod
|
|
3246
|
+
def TopologicalDistance(graph, vertexA, vertexB, tolerance=0.0001):
|
|
3247
|
+
"""
|
|
3248
|
+
Returns the topological distance between the input vertices. See https://en.wikipedia.org/wiki/Distance_(graph_theory).
|
|
3249
|
+
|
|
3250
|
+
Parameters
|
|
3251
|
+
----------
|
|
3252
|
+
graph : topologic.Graph
|
|
3253
|
+
The input graph.
|
|
3254
|
+
vertexA : topologic.Vertex
|
|
3255
|
+
The first input vertex.
|
|
3256
|
+
vertexB : topologic.Vertex
|
|
3257
|
+
The second input vertex.
|
|
3258
|
+
tolerance : float , optional
|
|
3259
|
+
The desired tolerance. The default is 0.0001.
|
|
3260
|
+
|
|
3261
|
+
Returns
|
|
3262
|
+
-------
|
|
3263
|
+
int
|
|
3264
|
+
The topological distance between the input vertices.
|
|
3265
|
+
|
|
3266
|
+
"""
|
|
3267
|
+
return graph.TopologicalDistance(vertexA, vertexB, tolerance)
|
|
3268
|
+
|
|
3269
|
+
@staticmethod
|
|
3270
|
+
def Topology(graph):
|
|
3271
|
+
"""
|
|
3272
|
+
Returns the topology (cluster) of the input graph
|
|
3273
|
+
|
|
3274
|
+
Parameters
|
|
3275
|
+
----------
|
|
3276
|
+
graph : topologic.Graph
|
|
3277
|
+
The input graph.
|
|
3278
|
+
|
|
3279
|
+
Returns
|
|
3280
|
+
-------
|
|
3281
|
+
topologic.Cluster
|
|
3282
|
+
The topology of the input graph.
|
|
3283
|
+
|
|
3284
|
+
"""
|
|
3285
|
+
return graph.Topology()
|
|
3286
|
+
|
|
3287
|
+
@staticmethod
|
|
3288
|
+
def Tree(graph, vertex=None, tolerance=0.0001):
|
|
3289
|
+
"""
|
|
3290
|
+
Creates a tree graph version of the input graph rooted at the input vertex.
|
|
3291
|
+
|
|
3292
|
+
Parameters
|
|
3293
|
+
----------
|
|
3294
|
+
graph : topologic.Graph
|
|
3295
|
+
DESCRIPTION.
|
|
3296
|
+
vertex : topologic.Vertex , optional
|
|
3297
|
+
The input root vertex. If not set, the first vertex in the graph is set as the root vertex. The default is None.
|
|
3298
|
+
tolerance : float , optional
|
|
3299
|
+
The desired tolerance. The default is 0.0001.
|
|
3300
|
+
|
|
3301
|
+
Returns
|
|
3302
|
+
-------
|
|
3303
|
+
topologic.Graph
|
|
3304
|
+
The tree graph version of the input graph.
|
|
3305
|
+
|
|
3306
|
+
"""
|
|
3307
|
+
from topologicpy.Vertex import Vertex
|
|
3308
|
+
def vertexInList(vertex, vertexList):
|
|
3309
|
+
if vertex and vertexList:
|
|
3310
|
+
if isinstance(vertex, topologic.Vertex) and isinstance(vertexList, list):
|
|
3311
|
+
for i in range(len(vertexList)):
|
|
3312
|
+
if vertexList[i]:
|
|
3313
|
+
if isinstance(vertexList[i], topologic.Vertex):
|
|
3314
|
+
if topologic.Topology.IsSame(vertex, vertexList[i]):
|
|
3315
|
+
return True
|
|
3316
|
+
return False
|
|
3317
|
+
|
|
3318
|
+
def getChildren(vertex, parent, graph, vertices):
|
|
3319
|
+
children = []
|
|
3320
|
+
adjVertices = []
|
|
3321
|
+
if vertex:
|
|
3322
|
+
adjVertices = Graph.AdjacentVertices(graph, vertex)
|
|
3323
|
+
if parent == None:
|
|
3324
|
+
return adjVertices
|
|
3325
|
+
else:
|
|
3326
|
+
for aVertex in adjVertices:
|
|
3327
|
+
if (not vertexInList(aVertex, [parent])) and (not vertexInList(aVertex, vertices)):
|
|
3328
|
+
children.append(aVertex)
|
|
3329
|
+
return children
|
|
3330
|
+
|
|
3331
|
+
def buildTree(graph, dictionary, vertex, parent, tolerance=0.0001):
|
|
3332
|
+
vertices = dictionary['vertices']
|
|
3333
|
+
edges = dictionary['edges']
|
|
3334
|
+
if not vertexInList(vertex, vertices):
|
|
3335
|
+
vertices.append(vertex)
|
|
3336
|
+
if parent:
|
|
3337
|
+
edges.append(Graph.Edge(graph, parent, vertex, tolerance))
|
|
3338
|
+
if parent == None:
|
|
3339
|
+
parent = vertex
|
|
3340
|
+
children = getChildren(vertex, parent, graph, vertices)
|
|
3341
|
+
dictionary['vertices'] = vertices
|
|
3342
|
+
dictionary['edges'] = edges
|
|
3343
|
+
for child in children:
|
|
3344
|
+
dictionary = buildTree(graph, dictionary, child, vertex, tolerance)
|
|
3345
|
+
return dictionary
|
|
3346
|
+
|
|
3347
|
+
if not isinstance(graph, topologic.Graph):
|
|
3348
|
+
return None
|
|
3349
|
+
if not isinstance(vertex, topologic.Vertex):
|
|
3350
|
+
vertex = Graph.Vertices(graph)[0]
|
|
3351
|
+
else:
|
|
3352
|
+
vertex = Graph.NearestVertex(graph, vertex)
|
|
3353
|
+
dictionary = {'vertices':[], 'edges':[]}
|
|
3354
|
+
dictionary = buildTree(graph, dictionary, vertex, None, tolerance)
|
|
3355
|
+
return Graph.ByVerticesEdges(dictionary['vertices'], dictionary['edges'])
|
|
3356
|
+
|
|
3357
|
+
@staticmethod
|
|
3358
|
+
def VertexDegree(graph, vertex):
|
|
3359
|
+
"""
|
|
3360
|
+
Returns the degree of the input vertex. See https://en.wikipedia.org/wiki/Degree_(graph_theory).
|
|
3361
|
+
|
|
3362
|
+
Parameters
|
|
3363
|
+
----------
|
|
3364
|
+
graph : topologic.Graph
|
|
3365
|
+
The input graph.
|
|
3366
|
+
vertices : topologic.Vertex
|
|
3367
|
+
The input vertex.
|
|
3368
|
+
|
|
3369
|
+
Returns
|
|
3370
|
+
-------
|
|
3371
|
+
int
|
|
3372
|
+
The degree of the input vertex.
|
|
3373
|
+
|
|
3374
|
+
"""
|
|
3375
|
+
if not isinstance(graph, topologic.Graph):
|
|
3376
|
+
return None
|
|
3377
|
+
if not isinstance(vertex, topologic.Vertex):
|
|
3378
|
+
return None
|
|
3379
|
+
return graph.VertexDegree(vertex)
|
|
3380
|
+
|
|
3381
|
+
@staticmethod
|
|
3382
|
+
def Vertices(graph):
|
|
3383
|
+
"""
|
|
3384
|
+
Returns the list of vertices in the input graph.
|
|
3385
|
+
|
|
3386
|
+
Parameters
|
|
3387
|
+
----------
|
|
3388
|
+
graph : topologic.Graph
|
|
3389
|
+
The input graph.
|
|
3390
|
+
|
|
3391
|
+
Returns
|
|
3392
|
+
-------
|
|
3393
|
+
list
|
|
3394
|
+
The list of vertices in the input graph.
|
|
3395
|
+
|
|
3396
|
+
"""
|
|
3397
|
+
if not isinstance(graph, topologic.Graph):
|
|
3398
|
+
return None
|
|
3399
|
+
vertices = []
|
|
3400
|
+
if graph:
|
|
3401
|
+
try:
|
|
3402
|
+
_ = graph.Vertices(vertices)
|
|
3403
|
+
except:
|
|
3404
|
+
vertices = []
|
|
3405
|
+
return vertices
|
|
3406
|
+
|
|
3407
|
+
@staticmethod
|
|
3408
|
+
def VisibilityGraph(boundary, obstacles=None, viewpointsA=None, viewpointsB=None, tolerance=0.0001):
|
|
3409
|
+
"""
|
|
3410
|
+
Creates a 2D visibility graph.
|
|
3411
|
+
|
|
3412
|
+
Parameters
|
|
3413
|
+
----------
|
|
3414
|
+
boundary : topologic.Wire
|
|
3415
|
+
The input boundary. View edges will be clipped to this face.
|
|
3416
|
+
obstacles : list
|
|
3417
|
+
The input list of obstacles (wires).
|
|
3418
|
+
viewpointsA : list
|
|
3419
|
+
The first input list of viewpoints (vertices). Visibility edges will connect these veritces to viewpointsB.
|
|
3420
|
+
viewpointsB : list
|
|
3421
|
+
The input list of viewpoints (vertices). Visibility edges will connect these vertices to viewpointsA.
|
|
3422
|
+
tolerance : float , optional
|
|
3423
|
+
The desired tolerance. The default is 0.0001.
|
|
3424
|
+
|
|
3425
|
+
Returns
|
|
3426
|
+
-------
|
|
3427
|
+
topologic.Graph
|
|
3428
|
+
The visibility graph.
|
|
3429
|
+
|
|
3430
|
+
"""
|
|
3431
|
+
from topologicpy.Vertex import Vertex
|
|
3432
|
+
from topologicpy.Edge import Edge
|
|
3433
|
+
from topologicpy.Face import Face
|
|
3434
|
+
from topologicpy.Graph import Graph
|
|
3435
|
+
from topologicpy.Wire import Wire
|
|
3436
|
+
from topologicpy.Cluster import Cluster
|
|
3437
|
+
from topologicpy.Topology import Topology
|
|
3438
|
+
import sys
|
|
3439
|
+
import subprocess
|
|
3440
|
+
try:
|
|
3441
|
+
from tqdm.auto import tqdm
|
|
3442
|
+
except:
|
|
3443
|
+
call = [sys.executable, '-m', 'pip', 'install', 'tqdm', '-t', sys.path[0]]
|
|
3444
|
+
subprocess.run(call)
|
|
3445
|
+
try:
|
|
3446
|
+
from tqdm.auto import tqdm
|
|
3447
|
+
except:
|
|
3448
|
+
print("Graph.VisibilityGraph - Error: Could not import tqdm")
|
|
3449
|
+
|
|
3450
|
+
def addEdge(edge, edges, viewpointsA, viewpointsB, tolerance=0.0001):
|
|
3451
|
+
# Add edge to edges only if its end points are in vertices
|
|
3452
|
+
sv = Edge.StartVertex(edge)
|
|
3453
|
+
ev = Edge.EndVertex(edge)
|
|
3454
|
+
con1 = Vertex.Index(sv, viewpointsA, strict=False, tolerance=tolerance)
|
|
3455
|
+
con2 = Vertex.Index(ev, viewpointsB, strict=False, tolerance=tolerance)
|
|
3456
|
+
if con1 != None and con2 != None:
|
|
3457
|
+
edges.append(edge)
|
|
3458
|
+
return edges
|
|
3459
|
+
|
|
3460
|
+
if not isinstance(boundary, topologic.Wire):
|
|
3461
|
+
return None
|
|
3462
|
+
if not obstacles:
|
|
3463
|
+
obstacles = []
|
|
3464
|
+
obstacles = [x for x in obstacles if isinstance(x, topologic.Wire)]
|
|
3465
|
+
if not viewpointsA and not viewpointsB:
|
|
3466
|
+
viewpointsA = Wire.Vertices(boundary)
|
|
3467
|
+
for obstacle in obstacles:
|
|
3468
|
+
obstacleVertices = Wire.Vertices(obstacle)
|
|
3469
|
+
viewpointsA += obstacleVertices
|
|
3470
|
+
if not isinstance(viewpointsA, list):
|
|
3471
|
+
return None
|
|
3472
|
+
else:
|
|
3473
|
+
viewpointsA = [x for x in viewpointsA if isinstance(x, topologic.Vertex)]
|
|
3474
|
+
if not len(viewpointsA) > 0:
|
|
3475
|
+
return None
|
|
3476
|
+
if not isinstance(viewpointsB, list):
|
|
3477
|
+
viewpointsB = []
|
|
3478
|
+
else:
|
|
3479
|
+
viewpointsB = [x for x in viewpointsB if isinstance(x, topologic.Vertex)]
|
|
3480
|
+
|
|
3481
|
+
boundaryFace = Face.ByWires(boundary, obstacles)
|
|
3482
|
+
edges = []
|
|
3483
|
+
matrix = []
|
|
3484
|
+
if not viewpointsB:
|
|
3485
|
+
viewpointsB = viewpointsA
|
|
3486
|
+
for i in range(max(len(viewpointsA), len(viewpointsB))):
|
|
3487
|
+
tempRow = []
|
|
3488
|
+
for j in range(max(len(viewpointsA), len(viewpointsB))):
|
|
3489
|
+
tempRow.append(0)
|
|
3490
|
+
matrix.append(tempRow)
|
|
3491
|
+
try:
|
|
3492
|
+
for i in tqdm(range(len(viewpointsA)), desc="Computing Visibility Graph", leave=False):
|
|
3493
|
+
for j in range(len(viewpointsB)):
|
|
3494
|
+
if not Topology.IsSame(viewpointsA[i], viewpointsB[j]) and matrix[i][j] == 0:
|
|
3495
|
+
matrix[i][j] = 1
|
|
3496
|
+
matrix[j][i] = 1
|
|
3497
|
+
e = Edge.ByVertices([viewpointsA[i], viewpointsB[j]])
|
|
3498
|
+
if e:
|
|
3499
|
+
e = Topology.Boolean(e, boundaryFace, "intersect", False)
|
|
3500
|
+
if isinstance(e, topologic.Edge):
|
|
3501
|
+
edges = addEdge(e, edges, viewpointsA, viewpointsB, 0.0001)
|
|
3502
|
+
elif isinstance(e, topologic.Cluster):
|
|
3503
|
+
tempEdges = Cluster.Edges(e)
|
|
3504
|
+
if tempEdges:
|
|
3505
|
+
for tempEdge in tempEdges:
|
|
3506
|
+
edges = addEdge(tempEdge, edges, viewpointsA, viewpointsB, 0.0001)
|
|
3507
|
+
except:
|
|
3508
|
+
for i in range(len(viewpointsA)):
|
|
3509
|
+
for j in range(len(viewpointsB)):
|
|
3510
|
+
if not Topology.IsSame(viewpointsA[i], viewpointsB[j]) and matrix[i][j] == 0:
|
|
3511
|
+
matrix[i][j] = 1
|
|
3512
|
+
matrix[j][i] = 1
|
|
3513
|
+
e = Edge.ByVertices([viewpointsA[i], viewpointsB[j]])
|
|
3514
|
+
if e:
|
|
3515
|
+
e = Topology.Boolean(e, boundaryFace, "intersect", False)
|
|
3516
|
+
if isinstance(e, topologic.Edge):
|
|
3517
|
+
edges = addEdge(e, edges, viewpointsA, viewpointsB, 0.0001)
|
|
3518
|
+
elif isinstance(e, topologic.Cluster):
|
|
3519
|
+
tempEdges = Cluster.Edges(e)
|
|
3520
|
+
if tempEdges:
|
|
3521
|
+
for tempEdge in tempEdges:
|
|
3522
|
+
edges = addEdge(tempEdge, edges, viewpointsA, viewpointsB, 0.0001)
|
|
3523
|
+
cluster = Cluster.ByTopologies(viewpointsA+viewpointsB)
|
|
3524
|
+
cluster = Cluster.SelfMerge(cluster)
|
|
3525
|
+
viewpoints = Cluster.Vertices(cluster)
|
|
3526
|
+
return Graph.ByVerticesEdges(viewpoints, edges)
|