topologicpy 0.7.94__py3-none-any.whl → 0.7.97__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
topologicpy/Graph.py CHANGED
@@ -750,102 +750,6 @@ class Graph:
750
750
  _ = graph.AllPaths(vertexA, vertexB, True, timeLimit, paths) # Hook to Core
751
751
  return paths
752
752
 
753
- @staticmethod
754
- def AreIsomorphic(graphA, graphB, maxIterations=10, silent=False):
755
- """
756
- Tests if the two input graphs are isomorphic according to the Weisfeiler Lehman graph isomorphism test. See https://en.wikipedia.org/wiki/Weisfeiler_Leman_graph_isomorphism_test
757
-
758
- Parameters
759
- ----------
760
- graphA : topologic_core.Graph
761
- The first input graph.
762
- graphB : topologic_core.Graph
763
- The second input graph.
764
- maxIterations : int , optional
765
- This number limits the number of iterations to prevent the function from running indefinitely, particularly for very large or complex graphs.
766
- silent : bool , optional
767
- If set to True, no error and warning messages are printed. Otherwise, they are. The default is False.
768
-
769
- Returns
770
- -------
771
- bool
772
- True if the two input graphs are isomorphic. False otherwise
773
-
774
- """
775
-
776
- from topologicpy.Topology import Topology
777
-
778
- def weisfeiler_lehman_test(graph1, graph2, max_iterations=10):
779
- """
780
- Test if two graphs are isomorphic using the Weisfeiler-Leman (WL) algorithm with early stopping.
781
-
782
- Parameters:
783
- graph1 (dict): Adjacency list representation of the first graph.
784
- graph2 (dict): Adjacency list representation of the second graph.
785
- max_iterations (int): Maximum WL iterations allowed (default is 10).
786
-
787
- Returns:
788
- bool: True if the graphs are WL-isomorphic, False otherwise.
789
- """
790
-
791
- def wl_iteration(labels, graph):
792
- """Perform one WL iteration and return updated labels."""
793
- new_labels = {}
794
- for node in graph:
795
- neighborhood_labels = sorted([labels[neighbor] for neighbor in graph[node]])
796
- new_labels[node] = (labels[node], tuple(neighborhood_labels))
797
- unique_labels = {}
798
- count = 0
799
- for node in sorted(new_labels):
800
- if new_labels[node] not in unique_labels:
801
- unique_labels[new_labels[node]] = count
802
- count += 1
803
- new_labels[node] = unique_labels[new_labels[node]]
804
- return new_labels
805
-
806
- # Initialize labels
807
- labels1 = {node: 1 for node in graph1}
808
- labels2 = {node: 1 for node in graph2}
809
-
810
- for i in range(max_iterations):
811
- # Perform WL iteration for both graphs
812
- new_labels1 = wl_iteration(labels1, graph1)
813
- new_labels2 = wl_iteration(labels2, graph2)
814
-
815
- # Check if the label distributions match
816
- if sorted(new_labels1.values()) != sorted(new_labels2.values()):
817
- return False
818
-
819
- # Check for stability (early stopping)
820
- if new_labels1 == labels1 and new_labels2 == labels2:
821
- break
822
-
823
- # Update labels for next iteration
824
- labels1, labels2 = new_labels1, new_labels2
825
-
826
- return True
827
-
828
- if not Topology.IsInstance(graphA, "Graph") and not Topology.IsInstance(graphB, "Graph"):
829
- if not silent:
830
- print("Graph.AreIsomorphic - Error: The input graph parameters are not valid graphs. Returning None.")
831
- return None
832
- if not Topology.IsInstance(graphA, "Graph"):
833
- if not silent:
834
- print("Graph.AreIsomorphic - Error: The input graphA parameter is not a valid graph. Returning None.")
835
- return None
836
- if not Topology.IsInstance(graphB, "Graph"):
837
- if not silent:
838
- print("Graph.AreIsomorphic - Error: The input graphB parameter is not a valid graph. Returning None.")
839
- return None
840
- if maxIterations <= 0:
841
- if not silent:
842
- print("Graph.AreIsomorphic - Error: The input maxIterations parameter is not within a valid range. Returning None.")
843
- return None
844
-
845
- g1 = Graph.AdjacencyDictionary(graphA)
846
- g2 = Graph.AdjacencyDictionary(graphB)
847
- return weisfeiler_lehman_test(g1, g2, max_iterations=maxIterations)
848
-
849
753
  @staticmethod
850
754
  def AverageClusteringCoefficient(graph, mantissa: int = 6, silent: bool = False):
851
755
  """
@@ -1345,7 +1249,7 @@ class Graph:
1345
1249
  graph : topologic_core.Graph
1346
1250
  The input graph.
1347
1251
  key : str , optional
1348
- The dictionary key under which to save the betweeness centrality score. The default is "betweenness_centrality".
1252
+ The dictionary key under which to store the betweeness centrality score. The default is "betweenness_centrality".
1349
1253
  mantissa : int , optional
1350
1254
  The desired length of the mantissa. The default is 6.
1351
1255
  tolerance : float , optional
@@ -1427,7 +1331,75 @@ class Graph:
1427
1331
  return_betweenness[int(i)] = v
1428
1332
 
1429
1333
  return return_betweenness
1430
-
1334
+
1335
+ @staticmethod
1336
+ def Bridges(graph, key: str = "bridge", silent: bool = False):
1337
+ """
1338
+ Returns the list of bridge edges in the input graph. See: https://en.wikipedia.org/wiki/Bridge_(graph_theory)
1339
+
1340
+ Parameters
1341
+ ----------
1342
+ graph : topologic_core.Graph
1343
+ The input graph.
1344
+ key : str , optional
1345
+ The edge dictionary key under which to store the bridge status. 0 means the edge is NOT a bridge. 1 means that the edge IS a bridge. The default is "bridge".
1346
+ silent : bool , optional
1347
+ If set to True, no error and warning messages are printed. Otherwise, they are. The default is False.
1348
+
1349
+ Returns
1350
+ -------
1351
+ list
1352
+ The list of bridge edges in the input graph.
1353
+
1354
+ """
1355
+ import os
1356
+ import warnings
1357
+ from topologicpy.Topology import Topology
1358
+ from topologicpy.Dictionary import Dictionary
1359
+
1360
+ try:
1361
+ import igraph as ig
1362
+ except:
1363
+ print("Graph.Bridges - Installing required pyhon-igraph library.")
1364
+ try:
1365
+ os.system("pip install python-igraph")
1366
+ except:
1367
+ os.system("pip install python-igraph --user")
1368
+ try:
1369
+ import igraph as ig
1370
+ print("Graph.Bridges - python-igraph library installed correctly.")
1371
+ except:
1372
+ warnings.warn("Graph.Bridges - Error: Could not import python-igraph. Please install manually.")
1373
+
1374
+ if not Topology.IsInstance(graph, "graph"):
1375
+ if not silent:
1376
+ print("Graph.Bridges - Error: The input graph parameter is not a valid topologic graph. Returning None")
1377
+ return None
1378
+
1379
+ edges = Graph.Edges(graph)
1380
+ if len(edges) < 1:
1381
+ return []
1382
+ if len(edges) == 1:
1383
+ d = Topology.Dictionary(edge)
1384
+ d = Dictionary.SetValueAtKey(d, key, 1)
1385
+ edge = Topology.SetDictionary(edge, d)
1386
+ return [edge]
1387
+ mesh_data = Graph.MeshData(graph)
1388
+ graph_edges = mesh_data['edges']
1389
+ ig_graph = ig.Graph(edges=graph_edges)
1390
+
1391
+ bridges = ig_graph.bridges()
1392
+ bridge_edges = []
1393
+ for i, edge in enumerate(edges):
1394
+ d = Topology.Dictionary(edge)
1395
+ if i in bridges:
1396
+ d = Dictionary.SetValueAtKey(d, key, 1)
1397
+ bridge_edges.append(edge)
1398
+ else:
1399
+ d = Dictionary.SetValueAtKey(d, key, 0)
1400
+ edge = Topology.SetDictionary(edge, d)
1401
+ return bridge_edges
1402
+
1431
1403
  @staticmethod
1432
1404
  def ByAdjacencyMatrixCSVPath(path: str, dictionaries: list = None, silent: bool = False):
1433
1405
  """
@@ -4410,7 +4382,7 @@ class Graph:
4410
4382
  vertices : list , optional
4411
4383
  The input list of vertices. The default is None.
4412
4384
  key : str , optional
4413
- The dictionary key under which to save the closeness centrality score. The default is "closeness_centrality".
4385
+ The dictionary key under which to store the closeness centrality score. The default is "closeness_centrality".
4414
4386
  mantissa : int , optional
4415
4387
  The desired length of the mantissa. The default is 6.
4416
4388
  tolerance : float , optional
@@ -4498,7 +4470,7 @@ class Graph:
4498
4470
  graph : topologicp.Graph
4499
4471
  The input topologic graph.
4500
4472
  key : str , optional
4501
- The dictionary key under which to save the closeness centrality score. The default is "community".
4473
+ The dictionary key under which to store the closeness centrality score. The default is "community".
4502
4474
  mantissa : int , optional
4503
4475
  The desired length of the mantissa. The default is 6.
4504
4476
  tolerance : float , optional
@@ -4517,37 +4489,39 @@ class Graph:
4517
4489
  import warnings
4518
4490
 
4519
4491
  try:
4520
- import community as community_louvain
4492
+ import igraph as ig
4521
4493
  except:
4522
- print("Graph.Community - Installing required pyhon-louvain library.")
4494
+ print("Graph.Community - Installing required pyhon-igraph library.")
4523
4495
  try:
4524
- os.system("pip install python-louvain")
4496
+ os.system("pip install python-igraph")
4525
4497
  except:
4526
- os.system("pip install python-louvain --user")
4498
+ os.system("pip install python-igraph --user")
4527
4499
  try:
4528
- import community as community_louvain
4529
- print("Graph.Community - python-louvain library installed correctly.")
4500
+ import igraph as ig
4501
+ print("Graph.Community - python-igraph library installed correctly.")
4530
4502
  except:
4531
- warnings.warn("Graph.Community - Error: Could not import python-louvain. Please install manually.")
4503
+ warnings.warn("Graph.Community - Error: Could not import python-igraph. Please install manually.")
4532
4504
 
4533
4505
  if not Topology.IsInstance(graph, "graph"):
4534
4506
  if not silent:
4535
4507
  print("Graph.Community - Error: The input graph parameter is not a valid topologic graph. Returning None")
4536
4508
  return None
4537
4509
 
4510
+ mesh_data = Graph.MeshData(graph)
4511
+ # Create an igraph graph from the edge list
4512
+ ig_graph = ig.Graph(edges=mesh_data['edges'])
4513
+
4514
+ # Detect communities using Louvain method
4515
+ communities = ig_graph.community_multilevel()
4516
+
4517
+ # Get the list of communities sorted same as vertices
4518
+ community_list = communities.membership
4538
4519
  vertices = Graph.Vertices(graph)
4539
- nx_graph = Graph.NetworkXGraph(graph, mantissa=mantissa, tolerance=tolerance)
4540
- # Apply the Louvain algorithm
4541
- partition = community_louvain.best_partition(nx_graph)
4542
- communities = []
4543
- # Add the partition value to each node's properties
4544
- for node, community_id in partition.items():
4545
- nx_graph.nodes[node][key] = community_id
4546
- d = Topology.Dictionary(vertices[node])
4547
- d = Dictionary.SetValueAtKey(d, key, community_id)
4548
- vertices[node] = Topology.SetDictionary(vertices[node], d)
4549
- communities.append(community_id)
4550
- return communities
4520
+ for i, v in enumerate(vertices):
4521
+ d = Topology.Dictionary(v)
4522
+ d = Dictionary.SetValueAtKey(d, key, community_list[i])
4523
+ v = Topology.SetDictionary(v, d)
4524
+ return community_list
4551
4525
 
4552
4526
  @staticmethod
4553
4527
  def Connect(graph, verticesA, verticesB, tolerance=0.0001):
@@ -4608,7 +4582,7 @@ class Graph:
4608
4582
  vertices : list , optional
4609
4583
  The input list of vertices. The default is None.
4610
4584
  key : str , optional
4611
- The dictionary key under which to save the connectivity score. The default is "connectivity".
4585
+ The dictionary key under which to store the connectivity score. The default is "connectivity".
4612
4586
  edgeKey : str , optional
4613
4587
  If specified, the value in the connected edges' dictionary specified by the edgeKey string will be aggregated to calculate
4614
4588
  the vertex degree. If a numeric value cannot be retrieved from an edge, a value of 1 is used instead. This is used in weighted graphs.
@@ -4703,6 +4677,67 @@ class Graph:
4703
4677
  return None
4704
4678
  return graph.ContainsVertex(vertex, tolerance) # Hook to Core
4705
4679
 
4680
+ @staticmethod
4681
+ def CutVertices(graph, key: str = "cut", silent: bool = False):
4682
+ """
4683
+ Returns the list of cut vertices in the input graph. See: https://en.wikipedia.org/wiki/Bridge_(graph_theory)
4684
+
4685
+ Parameters
4686
+ ----------
4687
+ graph : topologic_core.Graph
4688
+ The input graph.
4689
+ key : str , optional
4690
+ The vertex dictionary key under which to store the cut status. 0 means the vertex is NOT a cut vertex. 1 means that the vertex IS a cut vertex. The default is "cut".
4691
+ silent : bool , optional
4692
+ If set to True, no error and warning messages are printed. Otherwise, they are. The default is False.
4693
+
4694
+ Returns
4695
+ -------
4696
+ list
4697
+ The list of bridge edges in the input graph.
4698
+
4699
+ """
4700
+ import os
4701
+ import warnings
4702
+ from topologicpy.Topology import Topology
4703
+ from topologicpy.Dictionary import Dictionary
4704
+
4705
+ try:
4706
+ import igraph as ig
4707
+ except:
4708
+ print("Graph.CutVertices - Installing required pyhon-igraph library.")
4709
+ try:
4710
+ os.system("pip install python-igraph")
4711
+ except:
4712
+ os.system("pip install python-igraph --user")
4713
+ try:
4714
+ import igraph as ig
4715
+ print("Graph.CutVertices - python-igraph library installed correctly.")
4716
+ except:
4717
+ warnings.warn("Graph.CutVertices - Error: Could not import python-igraph. Please install manually.")
4718
+
4719
+ if not Topology.IsInstance(graph, "graph"):
4720
+ if not silent:
4721
+ print("Graph.CutVertices - Error: The input graph parameter is not a valid topologic graph. Returning None")
4722
+ return None
4723
+
4724
+ vertices = Graph.Vertices(graph)
4725
+ mesh_data = Graph.MeshData(graph)
4726
+ graph_edges = mesh_data['edges']
4727
+ ig_graph = ig.Graph(edges=graph_edges)
4728
+ articulation_points = ig_graph.vs[ig_graph.articulation_points()]
4729
+ articulation_points_list = [v.index for v in articulation_points]
4730
+ cut_vertices = []
4731
+ for i, vertex in enumerate(vertices):
4732
+ d = Topology.Dictionary(vertex)
4733
+ if i in articulation_points_list:
4734
+ d = Dictionary.SetValueAtKey(d, key, 1)
4735
+ cut_vertices.append(vertex)
4736
+ else:
4737
+ d = Dictionary.SetValueAtKey(d, key, 0)
4738
+ vertex = Topology.SetDictionary(vertex, d)
4739
+
4740
+ return cut_vertices
4706
4741
 
4707
4742
  @staticmethod
4708
4743
  def Degree(graph, vertices=None, key: str = "degree", edgeKey: str = None, mantissa: int = 6, tolerance = 0.0001):
@@ -4716,7 +4751,7 @@ class Graph:
4716
4751
  vertices : list , optional
4717
4752
  The input list of vertices. The default is None.
4718
4753
  key : str , optional
4719
- The dictionary key under which to save the closeness centrality score. The default is "degree".
4754
+ The dictionary key under which to store the closeness centrality score. The default is "degree".
4720
4755
  edgeKey : str , optional
4721
4756
  If specified, the value in the connected edges' dictionary specified by the edgeKey string will be aggregated to calculate
4722
4757
  the vertex degree. If a numeric value cannot be retrieved from an edge, a value of 1 is used instead. This is used in weighted graphs.
@@ -4872,7 +4907,7 @@ class Graph:
4872
4907
  vertices : list , optional
4873
4908
  The input list of vertices. The default is None.
4874
4909
  key : str , optional
4875
- The dictionary key under which to save the depth score. The default is "depth".
4910
+ The dictionary key under which to store the depth score. The default is "depth".
4876
4911
  type : str , optional
4877
4912
  The type of depth distance to calculate. The options are "topological" or "metric". The default is "topological". See https://www.spacesyntax.online/overview-2/analysis-of-spatial-relations/.
4878
4913
  mantissa : int , optional
@@ -6125,7 +6160,103 @@ class Graph:
6125
6160
  f.close()
6126
6161
  return False
6127
6162
  return False
6128
-
6163
+
6164
+ @staticmethod
6165
+ def IsIsomorphic(graphA, graphB, maxIterations=10, silent=False):
6166
+ """
6167
+ Tests if the two input graphs are isomorphic according to the Weisfeiler Lehman graph isomorphism test. See https://en.wikipedia.org/wiki/Weisfeiler_Leman_graph_isomorphism_test
6168
+
6169
+ Parameters
6170
+ ----------
6171
+ graphA : topologic_core.Graph
6172
+ The first input graph.
6173
+ graphB : topologic_core.Graph
6174
+ The second input graph.
6175
+ maxIterations : int , optional
6176
+ This number limits the number of iterations to prevent the function from running indefinitely, particularly for very large or complex graphs.
6177
+ silent : bool , optional
6178
+ If set to True, no error and warning messages are printed. Otherwise, they are. The default is False.
6179
+
6180
+ Returns
6181
+ -------
6182
+ bool
6183
+ True if the two input graphs are isomorphic. False otherwise
6184
+
6185
+ """
6186
+
6187
+ from topologicpy.Topology import Topology
6188
+
6189
+ def weisfeiler_lehman_test(graph1, graph2, max_iterations=10):
6190
+ """
6191
+ Test if two graphs are isomorphic using the Weisfeiler-Leman (WL) algorithm with early stopping.
6192
+
6193
+ Parameters:
6194
+ graph1 (dict): Adjacency list representation of the first graph.
6195
+ graph2 (dict): Adjacency list representation of the second graph.
6196
+ max_iterations (int): Maximum WL iterations allowed (default is 10).
6197
+
6198
+ Returns:
6199
+ bool: True if the graphs are WL-isomorphic, False otherwise.
6200
+ """
6201
+
6202
+ def wl_iteration(labels, graph):
6203
+ """Perform one WL iteration and return updated labels."""
6204
+ new_labels = {}
6205
+ for node in graph:
6206
+ neighborhood_labels = sorted([labels[neighbor] for neighbor in graph[node]])
6207
+ new_labels[node] = (labels[node], tuple(neighborhood_labels))
6208
+ unique_labels = {}
6209
+ count = 0
6210
+ for node in sorted(new_labels):
6211
+ if new_labels[node] not in unique_labels:
6212
+ unique_labels[new_labels[node]] = count
6213
+ count += 1
6214
+ new_labels[node] = unique_labels[new_labels[node]]
6215
+ return new_labels
6216
+
6217
+ # Initialize labels
6218
+ labels1 = {node: 1 for node in graph1}
6219
+ labels2 = {node: 1 for node in graph2}
6220
+
6221
+ for i in range(max_iterations):
6222
+ # Perform WL iteration for both graphs
6223
+ new_labels1 = wl_iteration(labels1, graph1)
6224
+ new_labels2 = wl_iteration(labels2, graph2)
6225
+
6226
+ # Check if the label distributions match
6227
+ if sorted(new_labels1.values()) != sorted(new_labels2.values()):
6228
+ return False
6229
+
6230
+ # Check for stability (early stopping)
6231
+ if new_labels1 == labels1 and new_labels2 == labels2:
6232
+ break
6233
+
6234
+ # Update labels for next iteration
6235
+ labels1, labels2 = new_labels1, new_labels2
6236
+
6237
+ return True
6238
+
6239
+ if not Topology.IsInstance(graphA, "Graph") and not Topology.IsInstance(graphB, "Graph"):
6240
+ if not silent:
6241
+ print("Graph.IsIsomorphic - Error: The input graph parameters are not valid graphs. Returning None.")
6242
+ return None
6243
+ if not Topology.IsInstance(graphA, "Graph"):
6244
+ if not silent:
6245
+ print("Graph.IsIsomorphic - Error: The input graphA parameter is not a valid graph. Returning None.")
6246
+ return None
6247
+ if not Topology.IsInstance(graphB, "Graph"):
6248
+ if not silent:
6249
+ print("Graph.IsIsomorphic - Error: The input graphB parameter is not a valid graph. Returning None.")
6250
+ return None
6251
+ if maxIterations <= 0:
6252
+ if not silent:
6253
+ print("Graph.IsIsomorphic - Error: The input maxIterations parameter is not within a valid range. Returning None.")
6254
+ return None
6255
+
6256
+ g1 = Graph.AdjacencyDictionary(graphA)
6257
+ g2 = Graph.AdjacencyDictionary(graphB)
6258
+ return weisfeiler_lehman_test(g1, g2, max_iterations=maxIterations)
6259
+
6129
6260
  @staticmethod
6130
6261
  def Reshape(graph,
6131
6262
  shape="spring 2D",
@@ -7765,7 +7896,7 @@ class Graph:
7765
7896
  vertices : list , optional
7766
7897
  The input list of vertices. If set to None, the local clustering coefficient of all vertices will be computed. The default is None.
7767
7898
  key : str , optional
7768
- The dictionary key under which to save the local clustering coefficient score. The default is "lcc".
7899
+ The dictionary key under which to store the local clustering coefficient score. The default is "lcc".
7769
7900
  mantissa : int , optional
7770
7901
  The desired length of the mantissa. The default is 6.
7771
7902
  tolerance : float , optional
@@ -8102,6 +8233,7 @@ class Graph:
8102
8233
 
8103
8234
  """
8104
8235
  from topologicpy.Vertex import Vertex
8236
+ from topologicpy.Edge import Edge
8105
8237
  from topologicpy.Dictionary import Dictionary
8106
8238
  from topologicpy.Topology import Topology
8107
8239
 
@@ -8116,8 +8248,8 @@ class Graph:
8116
8248
  m_edges = []
8117
8249
  e_dicts = []
8118
8250
  for g_edge in g_edges:
8119
- sv = g_edge.StartVertex()
8120
- ev = g_edge.EndVertex()
8251
+ sv = Edge.StartVertex(g_edge)
8252
+ ev = Edge.EndVertex(g_edge)
8121
8253
  si = Vertex.Index(sv, g_vertices, tolerance=tolerance)
8122
8254
  ei = Vertex.Index(ev, g_vertices, tolerance=tolerance)
8123
8255
  if (not si == None) and (not ei == None):
@@ -8421,11 +8553,11 @@ class Graph:
8421
8553
  graph : topologic_core.Graph
8422
8554
  The input graph.
8423
8555
  xKey : str , optional
8424
- The dictionary key under which to save the X-Coordinate of the vertex. The default is 'x'.
8556
+ The dictionary key under which to store the X-Coordinate of the vertex. The default is 'x'.
8425
8557
  yKey : str , optional
8426
- The dictionary key under which to save the Y-Coordinate of the vertex. The default is 'y'.
8558
+ The dictionary key under which to store the Y-Coordinate of the vertex. The default is 'y'.
8427
8559
  zKey : str , optional
8428
- The dictionary key under which to save the Z-Coordinate of the vertex. The default is 'z'.
8560
+ The dictionary key under which to store the Z-Coordinate of the vertex. The default is 'z'.
8429
8561
  mantissa : int , optional
8430
8562
  The desired length of the mantissa. The default is 6.
8431
8563
  tolerance : float , optional
@@ -8624,7 +8756,7 @@ class Graph:
8624
8756
  directed : bool , optional
8625
8757
  If set to True, the graph is considered as a directed graph. Otherwise, it will be considered as an undirected graph. The default is False.
8626
8758
  key : str , optional
8627
- The dictionary key under which to save the page_rank score. The default is "page_rank"
8759
+ The dictionary key under which to store the page_rank score. The default is "page_rank"
8628
8760
  mantissa : int , optional
8629
8761
  The desired length of the mantissa.
8630
8762
  tolerance : float , optional
topologicpy/Honeybee.py CHANGED
@@ -255,7 +255,7 @@ class Honeybee:
255
255
 
256
256
  def cellFloor(cell):
257
257
  faces = Topology.Faces(cell)
258
- c = [x.CenterOfMass().Z() for x in faces]
258
+ c = [Vertex.Z(Topology.CenterOfMass(x)) for x in faces]
259
259
  return round(min(c),2)
260
260
 
261
261
  def floorLevels(cells, min_difference):
topologicpy/Neo4j.py CHANGED
@@ -413,6 +413,7 @@ class Neo4j:
413
413
 
414
414
  """
415
415
  from topologicpy.Vertex import Vertex
416
+ from topologicpy.Edge import Edge
416
417
  from topologicpy.Graph import Graph
417
418
  from topologicpy.Topology import Topology
418
419
  from topologicpy.Dictionary import Dictionary
@@ -458,8 +459,8 @@ class Neo4j:
458
459
  nodes.append(n)
459
460
  for i in range(len(edges)):
460
461
  e = edges[i]
461
- sv = e.StartVertex()
462
- ev = e.EndVertex()
462
+ sv = Edge.StartVertex(e)
463
+ ev = Edge.EndVertex(e)
463
464
  sn = nodes[Vertex.Index(vertex=sv, vertices=vertices, strict=False, tolerance=tolerance)]
464
465
  en = nodes[Vertex.Index(vertex=ev, vertices=vertices, strict=False, tolerance=tolerance)]
465
466
  ed = Topology.Dictionary(e)
topologicpy/Shell.py CHANGED
@@ -432,17 +432,17 @@ class Shell():
432
432
  e3 = None
433
433
  e4 = None
434
434
  try:
435
- e3 = Edge.ByVertices([e1.StartVertex(), e2.StartVertex()], tolerance=tolerance, silent=silent)
435
+ e3 = Edge.ByVertices([Edge.StartVertex(e1), Edge.StartVertex(e2)], tolerance=tolerance, silent=silent)
436
436
  except:
437
- e4 = Edge.ByVertices([e1.EndVertex(), e2.EndVertex()], tolerance=tolerance, silent=silent)
437
+ e4 = Edge.ByVertices([Edge.EndVertex(e1), Edge.EndVertex(e2)], tolerance=tolerance, silent=silent)
438
438
  faces.append(Face.ByWire(Wire.ByEdges([e1, e2, e4], tolerance=tolerance), tolerance=tolerance))
439
439
  try:
440
- e4 = Edge.ByVertices([e1.EndVertex(), e2.EndVertex()], tolerance=tolerance, silent=silent)
440
+ e4 = Edge.ByVertices([Edge.EndVertex(e1), Edge.EndVertex(e2)], tolerance=tolerance, silent=silent)
441
441
  except:
442
- e3 = Edge.ByVertices([e1.StartVertex(), e2.StartVertex()], tolerance=tolerance, silent=silent)
442
+ e3 = Edge.ByVertices([Edge.StartVertex(e1), Edge.StartVertex(e2)], tolerance=tolerance, silent=silent)
443
443
  faces.append(Face.ByWire(Wire.ByEdges([e1, e2, e3],tolerance=tolerance), tolerance=tolerance))
444
444
  if e3 and e4:
445
- e5 = Edge.ByVertices([e1.StartVertex(), e2.EndVertex()], tolerance=tolerance, silent=silent)
445
+ e5 = Edge.ByVertices([Edge.StartVertex(e1), Edge.EndVertex(e2)], tolerance=tolerance, silent=silent)
446
446
  faces.append(Face.ByWire(Wire.ByEdges([e1, e5, e4], tolerance=tolerance), tolerance=tolerance))
447
447
  faces.append(Face.ByWire(Wire.ByEdges([e2, e5, e3], tolerance=tolerance), tolerance=tolerance))
448
448
  elif e3:
@@ -470,17 +470,17 @@ class Shell():
470
470
  e3 = None
471
471
  e4 = None
472
472
  try:
473
- e3 = Edge.ByVertices([e1.StartVertex(), e2.StartVertex()], tolerance=tolerance, silent=silent)
473
+ e3 = Edge.ByVertices([Edge.StartVertex(e1), Edge.StartVertex(e2)], tolerance=tolerance, silent=silent)
474
474
  except:
475
475
  try:
476
- e4 = Edge.ByVertices([e1.EndVertex(), e2.EndVertex()], tolerance=tolerance, silent=silent)
476
+ e4 = Edge.ByVertices([Edge.EndVertex(e1), Edge.EndVertex(e2)], tolerance=tolerance, silent=silent)
477
477
  except:
478
478
  pass
479
479
  try:
480
- e4 = Edge.ByVertices([e1.EndVertex(), e2.EndVertex()], tolerance=tolerance, silent=silent)
480
+ e4 = Edge.ByVertices([Edge.EndVertex(e1), Edge.EndVertex(e2)], tolerance=tolerance, silent=silent)
481
481
  except:
482
482
  try:
483
- e3 = Edge.ByVertices([e1.StartVertex(), e2.StartVertex()], tolerance=tolerance, silent=silent)
483
+ e3 = Edge.ByVertices([Edge.StartVertex(e1), Edge.StartVertex(e2)], tolerance=tolerance, silent=silent)
484
484
  except:
485
485
  pass
486
486
  if e3 and e4:
topologicpy/Topology.py CHANGED
@@ -4145,7 +4145,7 @@ class Topology():
4145
4145
  if not Topology.IsInstance(topology, "Topology"):
4146
4146
  print("Topology.CenterofMass - Error: the input topology parameter is not a valid topology. Returning None.")
4147
4147
  return None
4148
- return topology.CenterOfMass()
4148
+ return topology.CenterOfMass() # Hook to Core
4149
4149
 
4150
4150
  @staticmethod
4151
4151
  def Centroid(topology):
@@ -4169,8 +4169,8 @@ class Topology():
4169
4169
  print("Topology.Centroid - Error: the input topology parameter is not a valid topology. Returning None.")
4170
4170
  return None
4171
4171
  if Topology.IsInstance(topology, "Aperture"):
4172
- return Aperture.Topology(topology).Centroid()
4173
- return topology.Centroid()
4172
+ return Aperture.Topology(topology).Centroid() # Hook to Core
4173
+ return topology.Centroid() # Hook to Core
4174
4174
 
4175
4175
  @staticmethod
4176
4176
  def ClusterByKeys(topologies, *keys, silent=False):
@@ -6140,6 +6140,7 @@ class Topology():
6140
6140
 
6141
6141
  """
6142
6142
  from topologicpy.Vertex import Vertex
6143
+ from topologicpy.Edge import Edge
6143
6144
  from topologicpy.Face import Face
6144
6145
 
6145
6146
  vertices = []
@@ -6164,8 +6165,8 @@ class Topology():
6164
6165
  topEdges = Topology.Edges(topology)
6165
6166
  for anEdge in topEdges:
6166
6167
  e = []
6167
- sv = anEdge.StartVertex()
6168
- ev = anEdge.EndVertex()
6168
+ sv = Edge.StartVertex(anEdge)
6169
+ ev = Edge.EndVertex(anEdge)
6169
6170
  try:
6170
6171
  svIndex = vertices.index(Vertex.Coordinates(sv, mantissa=mantissa))
6171
6172
  except: