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.
Files changed (79) hide show
  1. topologicpy/Aperture.py +46 -0
  2. topologicpy/Cell.py +1780 -0
  3. topologicpy/CellComplex.py +791 -0
  4. topologicpy/Cluster.py +591 -0
  5. topologicpy/Color.py +157 -0
  6. topologicpy/Context.py +56 -0
  7. topologicpy/DGL.py +2661 -0
  8. topologicpy/Dictionary.py +470 -0
  9. topologicpy/Edge.py +855 -0
  10. topologicpy/EnergyModel.py +1052 -0
  11. topologicpy/Face.py +1810 -0
  12. topologicpy/Graph.py +3526 -0
  13. topologicpy/Graph_Export.py +858 -0
  14. topologicpy/Grid.py +338 -0
  15. topologicpy/Helper.py +182 -0
  16. topologicpy/Honeybee.py +424 -0
  17. topologicpy/Matrix.py +255 -0
  18. topologicpy/Neo4jGraph.py +311 -0
  19. topologicpy/Plotly.py +1396 -0
  20. topologicpy/Polyskel.py +524 -0
  21. topologicpy/Process.py +1368 -0
  22. topologicpy/SQL.py +48 -0
  23. topologicpy/Shell.py +1418 -0
  24. topologicpy/Speckle.py +433 -0
  25. topologicpy/Topology.py +5854 -0
  26. topologicpy/UnitTest.py +29 -0
  27. topologicpy/Vector.py +555 -0
  28. topologicpy/Vertex.py +714 -0
  29. topologicpy/Wire.py +2346 -0
  30. topologicpy/__init__.py +20 -0
  31. topologicpy/bin/linux/topologic/__init__.py +2 -0
  32. topologicpy/bin/linux/topologic/topologic.cpython-310-x86_64-linux-gnu.so +0 -0
  33. topologicpy/bin/linux/topologic/topologic.cpython-311-x86_64-linux-gnu.so +0 -0
  34. topologicpy/bin/linux/topologic/topologic.cpython-38-x86_64-linux-gnu.so +0 -0
  35. topologicpy/bin/linux/topologic/topologic.cpython-39-x86_64-linux-gnu.so +0 -0
  36. topologicpy/bin/linux/topologic.libs/libTKBO-6bdf205d.so.7.7.0 +0 -0
  37. topologicpy/bin/linux/topologic.libs/libTKBRep-2960a069.so.7.7.0 +0 -0
  38. topologicpy/bin/linux/topologic.libs/libTKBool-c44b74bd.so.7.7.0 +0 -0
  39. topologicpy/bin/linux/topologic.libs/libTKFillet-9a670ba0.so.7.7.0 +0 -0
  40. topologicpy/bin/linux/topologic.libs/libTKG2d-8f31849e.so.7.7.0 +0 -0
  41. topologicpy/bin/linux/topologic.libs/libTKG3d-4c6bce57.so.7.7.0 +0 -0
  42. topologicpy/bin/linux/topologic.libs/libTKGeomAlgo-26066fd9.so.7.7.0 +0 -0
  43. topologicpy/bin/linux/topologic.libs/libTKGeomBase-2116cabe.so.7.7.0 +0 -0
  44. topologicpy/bin/linux/topologic.libs/libTKMath-72572fa8.so.7.7.0 +0 -0
  45. topologicpy/bin/linux/topologic.libs/libTKMesh-2a060427.so.7.7.0 +0 -0
  46. topologicpy/bin/linux/topologic.libs/libTKOffset-6cab68ff.so.7.7.0 +0 -0
  47. topologicpy/bin/linux/topologic.libs/libTKPrim-eb1262b3.so.7.7.0 +0 -0
  48. topologicpy/bin/linux/topologic.libs/libTKShHealing-e67e5cc7.so.7.7.0 +0 -0
  49. topologicpy/bin/linux/topologic.libs/libTKTopAlgo-e4c96c33.so.7.7.0 +0 -0
  50. topologicpy/bin/linux/topologic.libs/libTKernel-fb7fe3b7.so.7.7.0 +0 -0
  51. topologicpy/bin/linux/topologic.libs/libgcc_s-32c1665e.so.1 +0 -0
  52. topologicpy/bin/linux/topologic.libs/libstdc++-672d7b41.so.6.0.30 +0 -0
  53. topologicpy/bin/windows/topologic/TKBO-f6b191de.dll +0 -0
  54. topologicpy/bin/windows/topologic/TKBRep-e56a600e.dll +0 -0
  55. topologicpy/bin/windows/topologic/TKBool-7b8d47ae.dll +0 -0
  56. topologicpy/bin/windows/topologic/TKFillet-0ddbf0a8.dll +0 -0
  57. topologicpy/bin/windows/topologic/TKG2d-2e2dee3d.dll +0 -0
  58. topologicpy/bin/windows/topologic/TKG3d-6674513d.dll +0 -0
  59. topologicpy/bin/windows/topologic/TKGeomAlgo-d240e370.dll +0 -0
  60. topologicpy/bin/windows/topologic/TKGeomBase-df87aba5.dll +0 -0
  61. topologicpy/bin/windows/topologic/TKMath-45bd625a.dll +0 -0
  62. topologicpy/bin/windows/topologic/TKMesh-d6e826b1.dll +0 -0
  63. topologicpy/bin/windows/topologic/TKOffset-79b9cc94.dll +0 -0
  64. topologicpy/bin/windows/topologic/TKPrim-aa430a86.dll +0 -0
  65. topologicpy/bin/windows/topologic/TKShHealing-bb48be89.dll +0 -0
  66. topologicpy/bin/windows/topologic/TKTopAlgo-7d0d1e22.dll +0 -0
  67. topologicpy/bin/windows/topologic/TKernel-08c8cfbb.dll +0 -0
  68. topologicpy/bin/windows/topologic/__init__.py +2 -0
  69. topologicpy/bin/windows/topologic/topologic.cp310-win_amd64.pyd +0 -0
  70. topologicpy/bin/windows/topologic/topologic.cp311-win_amd64.pyd +0 -0
  71. topologicpy/bin/windows/topologic/topologic.cp38-win_amd64.pyd +0 -0
  72. topologicpy/bin/windows/topologic/topologic.cp39-win_amd64.pyd +0 -0
  73. {topologicpy-0.4.8.dist-info → topologicpy-0.4.9.dist-info}/METADATA +1 -1
  74. topologicpy-0.4.9.dist-info/RECORD +77 -0
  75. topologicpy-0.4.9.dist-info/top_level.txt +1 -0
  76. topologicpy-0.4.8.dist-info/RECORD +0 -5
  77. topologicpy-0.4.8.dist-info/top_level.txt +0 -1
  78. {topologicpy-0.4.8.dist-info → topologicpy-0.4.9.dist-info}/LICENSE +0 -0
  79. {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)