topologicpy 0.7.91__py3-none-any.whl → 0.7.93__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
@@ -264,7 +264,7 @@ class _DrawTree(object):
264
264
  return self.__str__()
265
265
 
266
266
  class Graph:
267
- def AdjacencyDictionary(graph, vertexLabelKey: str = "label", edgeKey: str = "Length", includeWeights: bool = False, reverse: bool = False, mantissa: int = 6):
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 "label".
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 BetweenessCentrality(graph, key: str = "betweeness_centrality", mantissa: int = 6, tolerance: float = 0.001, silent: bool = False):
1339
+ def BetweennessCentrality(graph, key: str = "betweenness_centrality", mantissa: int = 6, tolerance: float = 0.001, silent: bool = False):
1332
1340
  """
1333
- 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.
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 "betweneess_centrality".
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 betweeness centrality of the input list of vertices within the input graph. The values are in the range 0 to 1.
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 vertex_betweenness_centrality(graph, vertices):
1353
- """
1354
- Compute the betweenness centrality for vertices in the given TopologicPy graph.
1355
-
1356
- Args:
1357
- graph: The TopologicPy Graph object.
1358
-
1359
- Returns:
1360
- dict: A dictionary mapping each vertex to its betweenness centrality value.
1361
- """
1362
- from collections import defaultdict
1363
- n = len(vertices)
1364
- idList = []
1365
- vertex_map = {}
1366
- for i, v in enumerate(vertices):
1367
- d = Topology.Dictionary(v)
1368
- d = Dictionary.SetValueAtKey(d, "__id_", str(i))
1369
- v = Topology.SetDictionary(v, d)
1370
- idList.append(str(i))
1371
- vertex_map[str(i)] = v
1372
- if n < 2:
1373
- return {v: 0.0 for v in idList}
1374
- centrality = defaultdict(float)
1375
-
1376
- for source in idList:
1377
- stack, paths, sigma = [], {}, {v: 0.0 for v in idList}
1378
- sigma[source] = 1.0
1379
- paths[source] = []
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
- return vertex_betweenness_centrality(graph, vertices)
1435
-
1436
- @staticmethod
1437
- def BetweenessCentrality_old(graph, vertices=None, sources=None, destinations=None, key: str = "betweeness_centrality", mantissa: int = 6, tolerance: float = 0.001):
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(graph)
1411
+ betweenness = calculate_betweenness()
1412
+ for v in betweenness:
1413
+ betweenness[v] /= 2.0 # Each shortest path is counted twice
1440
1414
 
1441
- Parameters
1442
- ----------
1443
- graph : topologic_core.Graph
1444
- The input graph.
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
- if not isinstance(vertices, list):
1484
- vertices = graphVertices
1485
- else:
1486
- vertices = [v for v in vertices if Topology.IsInstance(v, "Vertex")]
1487
- if len(vertices) < 1:
1488
- print("Graph.BetweenessCentrality - Error: The input list of vertices does not contain valid vertices. Returning None.")
1489
- return None
1490
- if not isinstance(sources, list):
1491
- sources = graphVertices
1492
- else:
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 1s.
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 not adjacencyMatrix[i][j] == 0:
1639
- edges.append(Edge.ByVertices([vertices[i], vertices[j]]))
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
 
@@ -7094,7 +6992,6 @@ class Graph:
7094
6992
 
7095
6993
  # Compute positions based on layers
7096
6994
  for depth, nodes in layers.items():
7097
- print("depth:", depth)
7098
6995
  # Place nodes in a circular arrangement at each layer
7099
6996
  num_nodes = len(nodes)
7100
6997
  angle_step = 2 * np.pi / num_nodes if num_nodes > 0 else 0
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) or not isinstance(vectorB, 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 or Vector.Magnitude(vector=vectorB, 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.91'
1
+ __version__ = '0.7.93'
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: topologicpy
3
- Version: 0.7.91
3
+ Version: 0.7.93
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=Qm0V17oeIlhr62faoYqJpNUMzAB5d0F-3zes4jCtRi8,460350
14
+ topologicpy/Graph.py,sha256=oA647-h9McD0jm2JDsLl0DV93k5ikk8tSGxptlRgL-s,455440
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=A1g83zDHep58iVPY8WQ8iHNrSOfGWFEzvVeDuMnjDNY,33078
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=em3O4PG8JKL9957EgCcS5zUXOhgyMhAa6bmjZHQ7UmE,23
32
- topologicpy-0.7.91.dist-info/LICENSE,sha256=FK0vJ73LuE8PYJAn7LutsReWR47-Ooovw2dnRe5yV6Q,681
33
- topologicpy-0.7.91.dist-info/METADATA,sha256=m96FnumZC4Hy2QqaPuRryOZron2mQdjkGJvv5HJs3kM,10513
34
- topologicpy-0.7.91.dist-info/WHEEL,sha256=PZUExdf71Ui_so67QXpySuHtCi3-J3wvF4ORK6k_S8U,91
35
- topologicpy-0.7.91.dist-info/top_level.txt,sha256=J30bDzW92Ob7hw3zA8V34Jlp-vvsfIkGzkr8sqvb4Uw,12
36
- topologicpy-0.7.91.dist-info/RECORD,,
31
+ topologicpy/version.py,sha256=YGFP4tn4z5Mf5ro4QfsCTEeqytKtxPWMh98e63Gjkcs,23
32
+ topologicpy-0.7.93.dist-info/LICENSE,sha256=FK0vJ73LuE8PYJAn7LutsReWR47-Ooovw2dnRe5yV6Q,681
33
+ topologicpy-0.7.93.dist-info/METADATA,sha256=sPeHRuueLmdH5UdS78oe6TriVvU3ZTxQcnvhxZ-4348,10513
34
+ topologicpy-0.7.93.dist-info/WHEEL,sha256=PZUExdf71Ui_so67QXpySuHtCi3-J3wvF4ORK6k_S8U,91
35
+ topologicpy-0.7.93.dist-info/top_level.txt,sha256=J30bDzW92Ob7hw3zA8V34Jlp-vvsfIkGzkr8sqvb4Uw,12
36
+ topologicpy-0.7.93.dist-info/RECORD,,