topologicpy 0.7.91__py3-none-any.whl → 0.7.92__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 +76 -178
- topologicpy/Vector.py +58 -42
- topologicpy/version.py +1 -1
- {topologicpy-0.7.91.dist-info → topologicpy-0.7.92.dist-info}/METADATA +1 -1
- {topologicpy-0.7.91.dist-info → topologicpy-0.7.92.dist-info}/RECORD +8 -8
- {topologicpy-0.7.91.dist-info → topologicpy-0.7.92.dist-info}/LICENSE +0 -0
- {topologicpy-0.7.91.dist-info → topologicpy-0.7.92.dist-info}/WHEEL +0 -0
- {topologicpy-0.7.91.dist-info → topologicpy-0.7.92.dist-info}/top_level.txt +0 -0
topologicpy/Graph.py
CHANGED
@@ -264,7 +264,7 @@ class _DrawTree(object):
|
|
264
264
|
return self.__str__()
|
265
265
|
|
266
266
|
class Graph:
|
267
|
-
def AdjacencyDictionary(graph, vertexLabelKey: str =
|
267
|
+
def AdjacencyDictionary(graph, vertexLabelKey: str = None, edgeKey: str = "Length", includeWeights: bool = False, reverse: bool = False, mantissa: int = 6):
|
268
268
|
"""
|
269
269
|
Returns the adjacency dictionary of the input Graph.
|
270
270
|
|
@@ -274,7 +274,7 @@ class Graph:
|
|
274
274
|
The input graph.
|
275
275
|
vertexLabelKey : str , optional
|
276
276
|
The returned vertices are labelled according to the dictionary values stored under this key.
|
277
|
-
If the vertexLabelKey does not exist, it will be created and the vertices are labelled numerically and stored in the vertex dictionary under this key. The default is
|
277
|
+
If the vertexLabelKey does not exist, it will be created and the vertices are labelled numerically and stored in the vertex dictionary under this key. The default is None.
|
278
278
|
edgeKey : str , optional
|
279
279
|
If set, the edges' dictionaries will be searched for this key to set their weight. If the key is set to "length" (case insensitive), the length of the edge will be used as its weight. If set to None, a weight of 1 will be used. The default is "Length".
|
280
280
|
includeWeights : bool , optional
|
@@ -298,6 +298,8 @@ class Graph:
|
|
298
298
|
if not Topology.IsInstance(graph, "Graph"):
|
299
299
|
print("Graph.AdjacencyDictionary - Error: The input graph is not a valid graph. Returning None.")
|
300
300
|
return None
|
301
|
+
if vertexLabelKey == None:
|
302
|
+
vertexLabelKey = "__label__"
|
301
303
|
if not isinstance(vertexLabelKey, str):
|
302
304
|
print("Graph.AdjacencyDictionary - Error: The input vertexLabelKey is not a valid string. Returning None.")
|
303
305
|
return None
|
@@ -353,6 +355,12 @@ class Graph:
|
|
353
355
|
temp_list.append(adjLabel)
|
354
356
|
temp_list.sort()
|
355
357
|
adjDict[vertex_label] = temp_list
|
358
|
+
if vertexLabelKey == "__label__": # This is label we added, so remove it
|
359
|
+
vertices = Graph.Vertices(graph)
|
360
|
+
for v in vertices:
|
361
|
+
d = Topology.Dictionary(v)
|
362
|
+
d = Dictionary.RemoveKey(d, vertexLabelKey)
|
363
|
+
v = Topology.SetDictionary(v, d)
|
356
364
|
return adjDict
|
357
365
|
|
358
366
|
@staticmethod
|
@@ -1328,16 +1336,16 @@ class Graph:
|
|
1328
1336
|
return bot_graph.serialize(format=format)
|
1329
1337
|
|
1330
1338
|
@staticmethod
|
1331
|
-
def
|
1339
|
+
def BetweennessCentrality(graph, key: str = "betweenness_centrality", mantissa: int = 6, tolerance: float = 0.001, silent: bool = False):
|
1332
1340
|
"""
|
1333
|
-
Returns the
|
1341
|
+
Returns the betweenness 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/Betweenness_centrality.
|
1334
1342
|
|
1335
1343
|
Parameters
|
1336
1344
|
----------
|
1337
1345
|
graph : topologic_core.Graph
|
1338
1346
|
The input graph.
|
1339
1347
|
key : str , optional
|
1340
|
-
The dictionary key under which to save the betweeness centrality score. The default is "
|
1348
|
+
The dictionary key under which to save the betweeness centrality score. The default is "betweenness_centrality".
|
1341
1349
|
mantissa : int , optional
|
1342
1350
|
The desired length of the mantissa. The default is 6.
|
1343
1351
|
tolerance : float , optional
|
@@ -1346,70 +1354,38 @@ class Graph:
|
|
1346
1354
|
Returns
|
1347
1355
|
-------
|
1348
1356
|
list
|
1349
|
-
The
|
1357
|
+
The betweenness centrality of the input list of vertices within the input graph. The values are in the range 0 to 1.
|
1350
1358
|
|
1351
1359
|
"""
|
1352
|
-
def
|
1353
|
-
|
1354
|
-
|
1355
|
-
|
1356
|
-
|
1357
|
-
|
1358
|
-
|
1359
|
-
|
1360
|
-
|
1361
|
-
|
1362
|
-
|
1363
|
-
|
1364
|
-
|
1365
|
-
|
1366
|
-
|
1367
|
-
|
1368
|
-
|
1369
|
-
|
1370
|
-
|
1371
|
-
|
1372
|
-
|
1373
|
-
|
1374
|
-
|
1375
|
-
|
1376
|
-
|
1377
|
-
|
1378
|
-
|
1379
|
-
|
1380
|
-
|
1381
|
-
queue = [source]
|
1382
|
-
while queue:
|
1383
|
-
v = queue.pop(0)
|
1384
|
-
stack.append(v)
|
1385
|
-
vertex = vertex_map[v]
|
1386
|
-
for neighbor in Graph.AdjacentVertices(graph, vertex):
|
1387
|
-
d = Topology.Dictionary(neighbor)
|
1388
|
-
neighbor_id = Dictionary.ValueAtKey(d, "__id_")
|
1389
|
-
if neighbor_id not in paths:
|
1390
|
-
queue.append(neighbor_id)
|
1391
|
-
paths[neighbor_id] = [v]
|
1392
|
-
elif v not in paths[neighbor_id]:
|
1393
|
-
paths[neighbor_id].append(v)
|
1394
|
-
sigma[neighbor_id] += sigma[v]
|
1395
|
-
|
1396
|
-
delta = {v: 0.0 for v in idList}
|
1397
|
-
while stack:
|
1398
|
-
w = stack.pop()
|
1399
|
-
for v in paths.get(w, []):
|
1400
|
-
delta[v] += (sigma[v] / sigma[w]) * (1 + delta[w])
|
1401
|
-
if w != source:
|
1402
|
-
centrality[w] += delta[w]
|
1403
|
-
# Normalize centrality values
|
1404
|
-
max_centrality = max([centrality[v] for v in idList])
|
1405
|
-
min_centrality = min([centrality[v] for v in idList])
|
1406
|
-
centrality = [round((centrality[v]-min_centrality)/max_centrality, mantissa) for v in idList]
|
1407
|
-
for i, v in enumerate(vertices):
|
1408
|
-
d = Topology.Dictionary(v)
|
1409
|
-
d = Dictionary.SetValueAtKey(d, "betweeness_centrality", centrality[i])
|
1410
|
-
d = Dictionary.RemoveKey(d, "__id_")
|
1411
|
-
v = Topology.SetDictionary(v, d)
|
1412
|
-
return centrality
|
1360
|
+
def bfs_paths(source):
|
1361
|
+
queue = [(source, [source])]
|
1362
|
+
while queue:
|
1363
|
+
(vertex, path) = queue.pop(0)
|
1364
|
+
for next in set(py_graph[vertex]) - set(path):
|
1365
|
+
queue.append((next, path + [next]))
|
1366
|
+
yield path + [next]
|
1367
|
+
|
1368
|
+
def shortest_paths_count(source):
|
1369
|
+
paths = list(bfs_paths(source))
|
1370
|
+
shortest_paths = {v: [] for v in py_graph}
|
1371
|
+
for path in paths:
|
1372
|
+
shortest_paths[path[-1]].append(path)
|
1373
|
+
return shortest_paths
|
1374
|
+
|
1375
|
+
def calculate_betweenness():
|
1376
|
+
betweenness = {v: 0.0 for v in py_graph}
|
1377
|
+
for s in py_graph:
|
1378
|
+
shortest_paths = shortest_paths_count(s)
|
1379
|
+
dependency = {v: 0.0 for v in py_graph}
|
1380
|
+
for t in py_graph:
|
1381
|
+
if t != s:
|
1382
|
+
for path in shortest_paths[t]:
|
1383
|
+
for v in path[1:-1]:
|
1384
|
+
dependency[v] += 1.0 / len(shortest_paths[t])
|
1385
|
+
for v in py_graph:
|
1386
|
+
if v != s:
|
1387
|
+
betweenness[v] += dependency[v]
|
1388
|
+
return betweenness
|
1413
1389
|
|
1414
1390
|
from topologicpy.Topology import Topology
|
1415
1391
|
from topologicpy.Dictionary import Dictionary
|
@@ -1431,115 +1407,26 @@ class Graph:
|
|
1431
1407
|
vertices[0] = Topology.SetDictionary(vertices[0], d)
|
1432
1408
|
return [1.0]
|
1433
1409
|
|
1434
|
-
|
1435
|
-
|
1436
|
-
|
1437
|
-
|
1438
|
-
"""
|
1439
|
-
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/Betweenness_centrality.
|
1410
|
+
py_graph = Graph.AdjacencyDictionary(g)
|
1411
|
+
betweenness = calculate_betweenness()
|
1412
|
+
for v in betweenness:
|
1413
|
+
betweenness[v] /= 2.0 # Each shortest path is counted twice
|
1440
1414
|
|
1441
|
-
|
1442
|
-
|
1443
|
-
|
1444
|
-
|
1445
|
-
vertices : list , optional
|
1446
|
-
The input list of vertices. The default is None which means all vertices in the input graph are considered.
|
1447
|
-
sources : list , optional
|
1448
|
-
The input list of source vertices. The default is None which means all vertices in the input graph are considered.
|
1449
|
-
destinations : list , optional
|
1450
|
-
The input list of destination vertices. The default is None which means all vertices in the input graph are considered.
|
1451
|
-
key : str , optional
|
1452
|
-
The dictionary key under which to save the betweeness centrality score. The default is "betweneess_centrality".
|
1453
|
-
mantissa : int , optional
|
1454
|
-
The desired length of the mantissa. The default is 6.
|
1455
|
-
tolerance : float , optional
|
1456
|
-
The desired tolerance. The default is 0.0001.
|
1457
|
-
|
1458
|
-
Returns
|
1459
|
-
-------
|
1460
|
-
list
|
1461
|
-
The betweeness centrality of the input list of vertices within the input graph. The values are in the range 0 to 1.
|
1462
|
-
|
1463
|
-
"""
|
1464
|
-
from topologicpy.Vertex import Vertex
|
1465
|
-
from topologicpy.Topology import Topology
|
1466
|
-
from topologicpy.Dictionary import Dictionary
|
1467
|
-
|
1468
|
-
def betweeness(vertices, topologies, tolerance=0.001):
|
1469
|
-
returnList = [0] * len(vertices)
|
1470
|
-
for topology in topologies:
|
1471
|
-
t_vertices = Topology.Vertices(topology)
|
1472
|
-
for t_v in t_vertices:
|
1473
|
-
index = Vertex.Index(t_v, vertices, strict=False, tolerance=tolerance)
|
1474
|
-
if not index == None:
|
1475
|
-
returnList[index] = returnList[index]+1
|
1476
|
-
return returnList
|
1477
|
-
|
1478
|
-
if not Topology.IsInstance(graph, "Graph"):
|
1479
|
-
print("Graph.BetweenessCentrality - Error: The input graph is not a valid graph. Returning None.")
|
1480
|
-
return None
|
1481
|
-
graphVertices = Graph.Vertices(graph)
|
1415
|
+
max_betweenness = max(betweenness.values())
|
1416
|
+
if max_betweenness > 0:
|
1417
|
+
for v in betweenness:
|
1418
|
+
betweenness[v] /= max_betweenness # Normalize to [0, 1]
|
1482
1419
|
|
1483
|
-
|
1484
|
-
|
1485
|
-
|
1486
|
-
|
1487
|
-
|
1488
|
-
|
1489
|
-
|
1490
|
-
|
1491
|
-
|
1492
|
-
|
1493
|
-
sources = [v for v in sources if Topology.IsInstance(v, "Vertex")]
|
1494
|
-
if len(sources) < 1:
|
1495
|
-
print("Graph.BetweenessCentrality - Error: The input list of sources does not contain valid vertices. Returning None.")
|
1496
|
-
return None
|
1497
|
-
if not isinstance(destinations, list):
|
1498
|
-
destinations = graphVertices
|
1499
|
-
else:
|
1500
|
-
destinations = [v for v in destinations if Topology.IsInstance(v, "Vertex")]
|
1501
|
-
if len(destinations) < 1:
|
1502
|
-
print("Graph.BetweenessCentrality - Error: The input list of destinations does not contain valid vertices. Returning None.")
|
1503
|
-
return None
|
1504
|
-
graphEdges = Graph.Edges(graph)
|
1505
|
-
if len(graphEdges) == 0:
|
1506
|
-
print("Graph.BetweenessCentrality - Warning: The input graph is a null graph.")
|
1507
|
-
scores = [0 for t in vertices]
|
1508
|
-
for i, v in enumerate(vertices):
|
1509
|
-
d = Topology.Dictionary(v)
|
1510
|
-
d = Dictionary.SetValueAtKey(d, key, scores[i])
|
1511
|
-
v = Topology.SetDictionary(v, d)
|
1512
|
-
return scores
|
1513
|
-
paths = []
|
1514
|
-
try:
|
1515
|
-
for so in tqdm(sources, desc="Computing Shortest Paths", leave=False):
|
1516
|
-
v1 = Graph.NearestVertex(graph, so)
|
1517
|
-
for si in destinations:
|
1518
|
-
v2 = Graph.NearestVertex(graph, si)
|
1519
|
-
if not v1 == v2:
|
1520
|
-
path = Graph.ShortestPath(graph, v1, v2)
|
1521
|
-
if path:
|
1522
|
-
paths.append(path)
|
1523
|
-
except:
|
1524
|
-
for so in sources:
|
1525
|
-
v1 = Graph.NearestVertex(graph, so)
|
1526
|
-
for si in destinations:
|
1527
|
-
v2 = Graph.NearestVertex(graph, si)
|
1528
|
-
if not v1 == v2:
|
1529
|
-
path = Graph.ShortestPath(graph, v1, v2)
|
1530
|
-
if path:
|
1531
|
-
paths.append(path)
|
1532
|
-
|
1533
|
-
scores = betweeness(vertices, paths, tolerance=tolerance)
|
1534
|
-
minValue = min(scores)
|
1535
|
-
maxValue = max(scores)
|
1536
|
-
size = maxValue - minValue
|
1537
|
-
scores = [round((v-minValue)/size, mantissa) for v in scores]
|
1538
|
-
for i, v in enumerate(vertices):
|
1539
|
-
d = Topology.Dictionary(v)
|
1540
|
-
d = Dictionary.SetValueAtKey(d, key, scores[i])
|
1541
|
-
v = Topology.SetDictionary(v, d)
|
1542
|
-
return scores
|
1420
|
+
|
1421
|
+
return_betweenness = [0]*len(vertices)
|
1422
|
+
for i, v in betweenness.items():
|
1423
|
+
vertex = vertices[int(i)]
|
1424
|
+
d = Topology.Dictionary(vertex)
|
1425
|
+
d = Dictionary.SetValueAtKey(d, key, round(v, mantissa))
|
1426
|
+
vertex = Topology.SetDictionary(vertex, d)
|
1427
|
+
return_betweenness[int(i)] = v
|
1428
|
+
|
1429
|
+
return return_betweenness
|
1543
1430
|
|
1544
1431
|
@staticmethod
|
1545
1432
|
def ByAdjacencyMatrixCSVPath(path: str, dictionaries: list = None, silent: bool = False):
|
@@ -1571,17 +1458,21 @@ class Graph:
|
|
1571
1458
|
return Graph.ByAdjacencyMatrix(adjacencyMatrix=adjacency_matrix, dictionaries=dictionaries, silent=silent)
|
1572
1459
|
|
1573
1460
|
@staticmethod
|
1574
|
-
def ByAdjacencyMatrix(adjacencyMatrix, dictionaries = None, xMin=-0.5, yMin=-0.5, zMin=-0.5, xMax=0.5, yMax=0.5, zMax=0.5, silent=False):
|
1461
|
+
def ByAdjacencyMatrix(adjacencyMatrix, dictionaries = None, edgeKeyFwd="weightFwd", edgeKeyBwd="weightBwd", xMin=-0.5, yMin=-0.5, zMin=-0.5, xMax=0.5, yMax=0.5, zMax=0.5, silent=False):
|
1575
1462
|
"""
|
1576
1463
|
Returns graphs according to the input folder path. This method assumes the CSV files follow DGL's schema.
|
1577
1464
|
|
1578
1465
|
Parameters
|
1579
1466
|
----------
|
1580
1467
|
adjacencyMatrix : list
|
1581
|
-
The adjacency matrix expressed as a nested list of 0s and
|
1468
|
+
The adjacency matrix expressed as a nested list of 0s and a number not 0 which represents the edge weight.
|
1582
1469
|
dictionaries : list , optional
|
1583
1470
|
A list of dictionaries to assign to the vertices of the graph. This list should be in
|
1584
1471
|
the same order and of the same length as the rows in the adjacency matrix.
|
1472
|
+
edgeKeyFwd : str , optional
|
1473
|
+
The dictionary key under which to store the edge weight value for forward edge. The default is "weight".
|
1474
|
+
edgeKeyBwd : str , optional
|
1475
|
+
The dictionary key under which to store the edge weight value for backward edge. The default is "weight".
|
1585
1476
|
xMin : float , optional
|
1586
1477
|
The desired minimum value to assign for a vertex's X coordinate. The default is -0.5.
|
1587
1478
|
yMin : float , optional
|
@@ -1606,6 +1497,7 @@ class Graph:
|
|
1606
1497
|
from topologicpy.Vertex import Vertex
|
1607
1498
|
from topologicpy.Edge import Edge
|
1608
1499
|
from topologicpy.Topology import Topology
|
1500
|
+
from topologicpy.Dictionary import Dictionary
|
1609
1501
|
import random
|
1610
1502
|
|
1611
1503
|
if not isinstance(adjacencyMatrix, list):
|
@@ -1632,11 +1524,17 @@ class Graph:
|
|
1632
1524
|
|
1633
1525
|
# Add edges based on the adjacency matrix
|
1634
1526
|
edges = []
|
1527
|
+
visited = []
|
1635
1528
|
for i in range(len(adjacencyMatrix)):
|
1636
1529
|
for j in range(len(adjacencyMatrix)):
|
1637
1530
|
if not i == j:
|
1638
|
-
if
|
1639
|
-
|
1531
|
+
if (adjacencyMatrix[i][j] != 0 or adjacencyMatrix[j][i] != 0) and not (i,j) in visited:
|
1532
|
+
edge = Edge.ByVertices([vertices[i], vertices[j]]) # Create only one edge
|
1533
|
+
d = Dictionary.ByKeysValues([edgeKeyFwd, edgeKeyBwd], [adjacencyMatrix[i][j], adjacencyMatrix[j][i]])
|
1534
|
+
edge = Topology.SetDictionary(edge, d)
|
1535
|
+
edges.append(edge)
|
1536
|
+
visited.append((i,j))
|
1537
|
+
visited.append((j,i))
|
1640
1538
|
|
1641
1539
|
return Graph.ByVerticesEdges(vertices, edges)
|
1642
1540
|
|
topologicpy/Vector.py
CHANGED
@@ -312,7 +312,7 @@ class Vector(list):
|
|
312
312
|
return vector
|
313
313
|
|
314
314
|
@staticmethod
|
315
|
-
def CompassAngle(vectorA, vectorB, mantissa=6, tolerance=0.0001):
|
315
|
+
def CompassAngle(vectorA, vectorB, mantissa: int = 6, tolerance: float = 0.0001, silent: bool = False):
|
316
316
|
"""
|
317
317
|
Returns the horizontal compass angle in degrees between the two input vectors. The angle is measured in clockwise fashion.
|
318
318
|
0 is along the positive Y-axis, 90 is along the positive X axis.
|
@@ -328,6 +328,8 @@ class Vector(list):
|
|
328
328
|
The length of the desired mantissa. The default is 6.
|
329
329
|
tolerance : float , optional
|
330
330
|
The desired tolerance. The default is 0.0001.
|
331
|
+
silent : bool , optional
|
332
|
+
If set to True, no error and warning messages are printed. Otherwise, they are. The default is False.
|
331
333
|
|
332
334
|
Returns
|
333
335
|
-------
|
@@ -335,9 +337,21 @@ class Vector(list):
|
|
335
337
|
The horizontal compass angle in degrees between the two input vectors.
|
336
338
|
|
337
339
|
"""
|
340
|
+
if not isinstance(vectorA, list):
|
341
|
+
if not silent:
|
342
|
+
print("Vector.Coordinates - Error: The input vectorA parameter is not a valid vector. Returning Nonne.")
|
343
|
+
return None
|
344
|
+
if not isinstance(vectorB, list):
|
345
|
+
if not silent:
|
346
|
+
print("Vector.Coordinates - Error: The input vectorB parameter is not a valid vector. Returning Nonne.")
|
347
|
+
return None
|
338
348
|
if abs(vectorA[0]) < tolerance and abs(vectorA[1]) < tolerance:
|
349
|
+
if not silent:
|
350
|
+
print("Vector.CompassAngle - Error: The input vectorA parameter is vertical in the Z Axis. Returning Nonne.")
|
339
351
|
return None
|
340
352
|
if abs(vectorB[0]) < tolerance and abs(vectorB[1]) < tolerance:
|
353
|
+
if not silent:
|
354
|
+
print("Vector.CompassAngle - Error: The input vectorB parameter is vertical in the Z Axis. Returning Nonne.")
|
341
355
|
return None
|
342
356
|
p1 = (vectorA[0], vectorA[1])
|
343
357
|
p2 = (vectorB[0], vectorB[1])
|
@@ -346,7 +360,7 @@ class Vector(list):
|
|
346
360
|
return round(rad2deg((ang1 - ang2) % (2 * pi)), mantissa)
|
347
361
|
|
348
362
|
@staticmethod
|
349
|
-
def Coordinates(vector, outputType="xyz", mantissa: int = 6):
|
363
|
+
def Coordinates(vector, outputType="xyz", mantissa: int = 6, silent: bool = False):
|
350
364
|
"""
|
351
365
|
Returns the coordinates of the input vector.
|
352
366
|
|
@@ -358,6 +372,8 @@ class Vector(list):
|
|
358
372
|
The desired output type. Could be any permutation or substring of "xyz" or the string "matrix". The default is "xyz". The input is case insensitive and the coordinates will be returned in the specified order.
|
359
373
|
mantissa : int , optional
|
360
374
|
The desired length of the mantissa. The default is 6.
|
375
|
+
silent : bool , optional
|
376
|
+
If set to True, no error and warning messages are printed. Otherwise, they are. The default is False.
|
361
377
|
|
362
378
|
Returns
|
363
379
|
-------
|
@@ -366,6 +382,8 @@ class Vector(list):
|
|
366
382
|
|
367
383
|
"""
|
368
384
|
if not isinstance(vector, list):
|
385
|
+
if not silent:
|
386
|
+
print("Vector.Coordinates - Error: The input vector parameter is not a valid vector. Returning None.")
|
369
387
|
return None
|
370
388
|
x = round(vector[0], mantissa)
|
371
389
|
y = round(vector[1], mantissa)
|
@@ -390,7 +408,7 @@ class Vector(list):
|
|
390
408
|
return output
|
391
409
|
|
392
410
|
@staticmethod
|
393
|
-
def Cross(vectorA, vectorB, mantissa=6, tolerance=0.0001):
|
411
|
+
def Cross(vectorA, vectorB, mantissa: int = 6, tolerance: float = 0.0001, silent: bool = False):
|
394
412
|
"""
|
395
413
|
Returns the cross product of the two input vectors. The resulting vector is perpendicular to the plane defined by the two input vectors.
|
396
414
|
|
@@ -404,6 +422,8 @@ class Vector(list):
|
|
404
422
|
The length of the desired mantissa. The default is 6.
|
405
423
|
tolerance : float, optional
|
406
424
|
the desired tolerance. The default is 0.0001.
|
425
|
+
silent : bool , optional
|
426
|
+
If set to True, no error and warning messages are printed. Otherwise, they are. The default is False.
|
407
427
|
|
408
428
|
Returns
|
409
429
|
-------
|
@@ -411,9 +431,21 @@ class Vector(list):
|
|
411
431
|
The vector representing the cross product of the two input vectors.
|
412
432
|
|
413
433
|
"""
|
414
|
-
if not isinstance(vectorA, list)
|
434
|
+
if not isinstance(vectorA, list):
|
435
|
+
if not silent:
|
436
|
+
print("Vector.Cross - Error: The input vectorA parameter is not a valid vector. Returning None.")
|
437
|
+
return None
|
438
|
+
if not isinstance(vectorB, list):
|
439
|
+
if not silent:
|
440
|
+
print("Vector.Cross - Error: The input vectorB parameter is not a valid vector. Returning None.")
|
415
441
|
return None
|
416
|
-
if Vector.Magnitude(vector=vectorA, mantissa=mantissa) < tolerance
|
442
|
+
if Vector.Magnitude(vector=vectorA, mantissa=mantissa) < tolerance:
|
443
|
+
if not silent:
|
444
|
+
print("Vector.Cross - Error: The magnitude of the input vectorA parameter is less than the input tolerance parameter. Returning None.")
|
445
|
+
return None
|
446
|
+
if Vector.Magnitude(vector=vectorB, mantissa=mantissa) < tolerance:
|
447
|
+
if not silent:
|
448
|
+
print("Vector.Cross - Error: The magnitude of the input vectorB parameter is less than the input tolerance parameter. Returning None.")
|
417
449
|
return None
|
418
450
|
vecA = np.array(vectorA)
|
419
451
|
vecB = np.array(vectorB)
|
@@ -423,7 +455,7 @@ class Vector(list):
|
|
423
455
|
return [round(vecC[0], mantissa), round(vecC[1], mantissa), round(vecC[2], mantissa)]
|
424
456
|
|
425
457
|
@staticmethod
|
426
|
-
def Dot(vectorA, vectorB, mantissa=6):
|
458
|
+
def Dot(vectorA, vectorB, mantissa: int = 6, tolerance: float = 0.0001, silent: bool = False):
|
427
459
|
"""
|
428
460
|
Returns the dot product of the two input vectors which is a measure of how much they are aligned.
|
429
461
|
|
@@ -435,6 +467,10 @@ class Vector(list):
|
|
435
467
|
The second vector.
|
436
468
|
mantissa : int, optional
|
437
469
|
The length of the desired mantissa. The default is 6.
|
470
|
+
tolerance : float, optional
|
471
|
+
the desired tolerance. The default is 0.0001.
|
472
|
+
silent : bool , optional
|
473
|
+
If set to True, no error and warning messages are printed. Otherwise, they are. The default is False.
|
438
474
|
|
439
475
|
Returns
|
440
476
|
-------
|
@@ -442,6 +478,22 @@ class Vector(list):
|
|
442
478
|
The vector representing the cross product of the two input vectors.
|
443
479
|
|
444
480
|
"""
|
481
|
+
if not isinstance(vectorA, list):
|
482
|
+
if not silent:
|
483
|
+
print("Vector.Dot - Error: The input vectorA parameter is not a valid vector. Returning None.")
|
484
|
+
return None
|
485
|
+
if not isinstance(vectorB, list):
|
486
|
+
if not silent:
|
487
|
+
print("Vector.Dot - Error: The input vectorB parameter is not a valid vector. Returning None.")
|
488
|
+
return None
|
489
|
+
if Vector.Magnitude(vector=vectorA, mantissa=mantissa) < tolerance:
|
490
|
+
if not silent:
|
491
|
+
print("Vector.Dot - Error: The magnitude of the input vectorA parameter is less than the input tolerance parameter. Returning None.")
|
492
|
+
return None
|
493
|
+
if Vector.Magnitude(vector=vectorB, mantissa=mantissa) < tolerance:
|
494
|
+
if not silent:
|
495
|
+
print("Vector.Dot - Error: The magnitude of the input vectorB parameter is less than the input tolerance parameter. Returning None.")
|
496
|
+
return None
|
445
497
|
return round(sum(a*b for a, b in zip(vectorA, vectorB)), mantissa)
|
446
498
|
|
447
499
|
@staticmethod
|
@@ -506,42 +558,6 @@ class Vector(list):
|
|
506
558
|
# Compute bisecting vector
|
507
559
|
return False
|
508
560
|
|
509
|
-
@staticmethod
|
510
|
-
def IsParallel(vectorA, vectorB):
|
511
|
-
"""
|
512
|
-
Returns True if the input vectors are parallel. Returns False otherwise.
|
513
|
-
|
514
|
-
Parameters
|
515
|
-
----------
|
516
|
-
vectorA : list
|
517
|
-
The first input vector.
|
518
|
-
vectorB : list
|
519
|
-
The second input vector.
|
520
|
-
|
521
|
-
Returns
|
522
|
-
-------
|
523
|
-
bool
|
524
|
-
True if the input vectors are parallel. False otherwise.
|
525
|
-
|
526
|
-
"""
|
527
|
-
import numpy as np
|
528
|
-
|
529
|
-
# Ensure vectors are numpy arrays
|
530
|
-
vector1 = np.array(vectorA)
|
531
|
-
vector2 = np.array(vectorB)
|
532
|
-
|
533
|
-
# Normalize input vectors
|
534
|
-
vector1_norm = vector1 / np.linalg.norm(vector1)
|
535
|
-
vector2_norm = vector2 / np.linalg.norm(vector2)
|
536
|
-
|
537
|
-
# Check if the angle between vectors is either 0 or 180 degrees
|
538
|
-
dot_product = np.dot(vector1_norm, vector2_norm)
|
539
|
-
if np.isclose(dot_product, 1.0):
|
540
|
-
return True
|
541
|
-
else:
|
542
|
-
# Compute bisecting vector
|
543
|
-
return False
|
544
|
-
|
545
561
|
@staticmethod
|
546
562
|
def IsCollinear(vectorA, vectorB):
|
547
563
|
"""
|
topologicpy/version.py
CHANGED
@@ -1 +1 @@
|
|
1
|
-
__version__ = '0.7.
|
1
|
+
__version__ = '0.7.92'
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: topologicpy
|
3
|
-
Version: 0.7.
|
3
|
+
Version: 0.7.92
|
4
4
|
Summary: An AI-Powered Spatial Modelling and Analysis Software Library for Architecture, Engineering, and Construction.
|
5
5
|
Author-email: Wassim Jabi <wassim.jabi@gmail.com>
|
6
6
|
License: AGPL v3 License
|
@@ -11,7 +11,7 @@ topologicpy/Dictionary.py,sha256=t0O7Du-iPq46FyKqZfcjHfsUK1E8GS_e67R2V5cpkbw,331
|
|
11
11
|
topologicpy/Edge.py,sha256=KWOJCkLDwCWyZJ5MKwDhT5umWwCYBHtLOz6ulHrSOfY,67205
|
12
12
|
topologicpy/EnergyModel.py,sha256=AqTtmXE35SxvRXhG3vYAQd7GQDW-6HtjYPHua6ME4Eg,53762
|
13
13
|
topologicpy/Face.py,sha256=2k1vSRK1M-s588RcqGHEalwIHJ9nT3qgx3pU4ktN0dU,150077
|
14
|
-
topologicpy/Graph.py,sha256=
|
14
|
+
topologicpy/Graph.py,sha256=LJek7dV9bq9uBf_2akAYrETjbSFfoPgLaMsHs4brvc4,455475
|
15
15
|
topologicpy/Grid.py,sha256=2s9cSlWldivn1i9EUz4OOokJyANveqmRe_vR93CAndI,18245
|
16
16
|
topologicpy/Helper.py,sha256=F3h4_qcOD_PHAoVe0tEbEE7_jYyVcaHjtwVs4QHOZuI,23978
|
17
17
|
topologicpy/Honeybee.py,sha256=HfTaEV1R8K1xOVQQy9sBOhBTF_ap8A2RxZOYhirp_Mw,21835
|
@@ -24,13 +24,13 @@ topologicpy/Shell.py,sha256=UdDz3zfIYmGRjoZIseviJ2cXNtR5Kx5tIsZLhWMyO_U,87906
|
|
24
24
|
topologicpy/Speckle.py,sha256=AlsGlSDuKRtX5jhVsPNSSjjbZis079HbUchDH_5RJmE,18187
|
25
25
|
topologicpy/Sun.py,sha256=42tDWMYpwRG7Z2Qjtp94eRgBuqySq7k8TgNUZDK7QxQ,36837
|
26
26
|
topologicpy/Topology.py,sha256=d99wryPPXvw7eRw12GVKV-DT6jhlmVq6GsMAjg-E-40,441693
|
27
|
-
topologicpy/Vector.py,sha256=
|
27
|
+
topologicpy/Vector.py,sha256=Cl7besf20cAGmyNPh-9gbFAHnRU5ZWSMChJ3VyFIDs4,35416
|
28
28
|
topologicpy/Vertex.py,sha256=sYWTbAHqKGRUAJRCIUqrCO_xFhvsXK09Sx7E4dafPLQ,73754
|
29
29
|
topologicpy/Wire.py,sha256=HjagWKoJb8Z3zhgOij_4k6ZnKIl5gk8LletHbsT1ZKU,190632
|
30
30
|
topologicpy/__init__.py,sha256=vlPCanUbxe5NifC4pHcnhSzkmmYcs_UrZrTlVMsxcFs,928
|
31
|
-
topologicpy/version.py,sha256=
|
32
|
-
topologicpy-0.7.
|
33
|
-
topologicpy-0.7.
|
34
|
-
topologicpy-0.7.
|
35
|
-
topologicpy-0.7.
|
36
|
-
topologicpy-0.7.
|
31
|
+
topologicpy/version.py,sha256=hEe71TmHDfYxdkk064adNlI0kHL1_wHg4VoGMKoeSWM,23
|
32
|
+
topologicpy-0.7.92.dist-info/LICENSE,sha256=FK0vJ73LuE8PYJAn7LutsReWR47-Ooovw2dnRe5yV6Q,681
|
33
|
+
topologicpy-0.7.92.dist-info/METADATA,sha256=t-giZYVXIF8phaA32BSO55_r4qGngtkKS_MMHUjD-aA,10513
|
34
|
+
topologicpy-0.7.92.dist-info/WHEEL,sha256=PZUExdf71Ui_so67QXpySuHtCi3-J3wvF4ORK6k_S8U,91
|
35
|
+
topologicpy-0.7.92.dist-info/top_level.txt,sha256=J30bDzW92Ob7hw3zA8V34Jlp-vvsfIkGzkr8sqvb4Uw,12
|
36
|
+
topologicpy-0.7.92.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|