topologicpy 0.8.9__py3-none-any.whl → 0.8.11__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/BVH.py +1 -1
- topologicpy/Cell.py +2 -2
- topologicpy/CellComplex.py +2 -2
- topologicpy/Edge.py +23 -23
- topologicpy/Face.py +61 -6
- topologicpy/Graph.py +221 -222
- topologicpy/Helper.py +55 -0
- topologicpy/Matrix.py +211 -5
- topologicpy/Plotly.py +8 -9
- topologicpy/Polyskel.py +3 -3
- topologicpy/Shell.py +4 -4
- topologicpy/Topology.py +350 -406
- topologicpy/Vector.py +84 -35
- topologicpy/Vertex.py +63 -6
- topologicpy/Wire.py +26 -145
- topologicpy/version.py +1 -1
- {topologicpy-0.8.9.dist-info → topologicpy-0.8.11.dist-info}/METADATA +1 -1
- topologicpy-0.8.11.dist-info/RECORD +36 -0
- topologicpy-0.8.9.dist-info/RECORD +0 -36
- {topologicpy-0.8.9.dist-info → topologicpy-0.8.11.dist-info}/LICENSE +0 -0
- {topologicpy-0.8.9.dist-info → topologicpy-0.8.11.dist-info}/WHEEL +0 -0
- {topologicpy-0.8.9.dist-info → topologicpy-0.8.11.dist-info}/top_level.txt +0 -0
topologicpy/Vector.py
CHANGED
@@ -275,13 +275,13 @@ class Vector(list):
|
|
275
275
|
return [x, y, z]
|
276
276
|
|
277
277
|
@staticmethod
|
278
|
-
def ByVertices(vertices, normalize: bool = True, mantissa: int = 6):
|
278
|
+
def ByVertices(*vertices, normalize: bool = True, mantissa: int = 6, silent: bool = False):
|
279
279
|
"""
|
280
280
|
Creates a vector by the specified input list of vertices.
|
281
281
|
|
282
282
|
Parameters
|
283
283
|
----------
|
284
|
-
vertices : list
|
284
|
+
*vertices : list
|
285
285
|
The the input list of topologic vertices. The first element in the list is considered the start vertex. The last element in the list is considered the end vertex.
|
286
286
|
normalize : bool , optional
|
287
287
|
If set to True, the resulting vector is normalized (i.e. its length is set to 1)
|
@@ -296,16 +296,59 @@ class Vector(list):
|
|
296
296
|
"""
|
297
297
|
from topologicpy.Vertex import Vertex
|
298
298
|
from topologicpy.Topology import Topology
|
299
|
+
from topologicpy.Helper import Helper
|
300
|
+
import inspect
|
299
301
|
|
300
|
-
if
|
302
|
+
if len(vertices) == 0:
|
303
|
+
if not silent:
|
304
|
+
print("Vector.ByVertices - Error: The input vertices parameter is an empty list. Returning None.")
|
305
|
+
curframe = inspect.currentframe()
|
306
|
+
calframe = inspect.getouterframes(curframe, 2)
|
307
|
+
print('caller name:', calframe[1][3])
|
301
308
|
return None
|
302
|
-
if
|
309
|
+
if len(vertices) == 1:
|
310
|
+
vertices = vertices[0]
|
311
|
+
if isinstance(vertices, list):
|
312
|
+
if len(vertices) == 0:
|
313
|
+
if not silent:
|
314
|
+
print("Vector.ByVertices - Error: The input vertices parameter is an empty list. Returning None.")
|
315
|
+
curframe = inspect.currentframe()
|
316
|
+
calframe = inspect.getouterframes(curframe, 2)
|
317
|
+
print('caller name:', calframe[1][3])
|
318
|
+
return None
|
319
|
+
else:
|
320
|
+
vertexList = [x for x in vertices if Topology.IsInstance(x, "Vertex")]
|
321
|
+
if len(vertexList) == 0:
|
322
|
+
if not silent:
|
323
|
+
print("Vector.ByVertices - Error: The input vertices parameter does not contain any valid vertices. Returning None.")
|
324
|
+
curframe = inspect.currentframe()
|
325
|
+
calframe = inspect.getouterframes(curframe, 2)
|
326
|
+
print('caller name:', calframe[1][3])
|
327
|
+
return None
|
328
|
+
else:
|
329
|
+
if not silent:
|
330
|
+
print("Vector.ByVertices - Warning: The input vertices parameter contains only one vertex. Returning None.")
|
331
|
+
curframe = inspect.currentframe()
|
332
|
+
calframe = inspect.getouterframes(curframe, 2)
|
333
|
+
print('caller name:', calframe[1][3])
|
334
|
+
return None
|
335
|
+
else:
|
336
|
+
vertexList = Helper.Flatten(list(vertices))
|
337
|
+
vertexList = [x for x in vertexList if Topology.IsInstance(x, "Vertex")]
|
338
|
+
if len(vertexList) == 0:
|
339
|
+
if not silent:
|
340
|
+
print("Vector.ByVertices - Error: The input parameters do not contain any valid vertices. Returning None.")
|
341
|
+
curframe = inspect.currentframe()
|
342
|
+
calframe = inspect.getouterframes(curframe, 2)
|
343
|
+
print('caller name:', calframe[1][3])
|
303
344
|
return None
|
304
|
-
|
305
|
-
if len(
|
345
|
+
|
346
|
+
if len(vertexList) < 2:
|
347
|
+
if not silent:
|
348
|
+
print("Vector.ByVertices - Error: The input parameters do not contain a minimum of two valid vertices. Returning None.")
|
306
349
|
return None
|
307
|
-
v1 =
|
308
|
-
v2 =
|
350
|
+
v1 = vertexList[0]
|
351
|
+
v2 = vertexList[-1]
|
309
352
|
vector = [Vertex.X(v2, mantissa=mantissa)-Vertex.X(v1, mantissa=mantissa), Vertex.Y(v2, mantissa=mantissa)-Vertex.Y(v1, mantissa=mantissa), Vertex.Z(v2, mantissa=mantissa)-Vertex.Z(v1, mantissa=mantissa)]
|
310
353
|
if normalize:
|
311
354
|
vector = Vector.Normalize(vector)
|
@@ -345,11 +388,11 @@ class Vector(list):
|
|
345
388
|
if not silent:
|
346
389
|
print("Vector.Coordinates - Error: The input vectorB parameter is not a valid vector. Returning Nonne.")
|
347
390
|
return None
|
348
|
-
if abs(vectorA[0])
|
391
|
+
if abs(vectorA[0]) <= tolerance and abs(vectorA[1]) <= tolerance:
|
349
392
|
if not silent:
|
350
393
|
print("Vector.CompassAngle - Error: The input vectorA parameter is vertical in the Z Axis. Returning Nonne.")
|
351
394
|
return None
|
352
|
-
if abs(vectorB[0])
|
395
|
+
if abs(vectorB[0]) <= tolerance and abs(vectorB[1]) <= tolerance:
|
353
396
|
if not silent:
|
354
397
|
print("Vector.CompassAngle - Error: The input vectorB parameter is vertical in the Z Axis. Returning Nonne.")
|
355
398
|
return None
|
@@ -404,7 +447,7 @@ class Vector(list):
|
|
404
447
|
x, y, z = vector
|
405
448
|
|
406
449
|
# Handle the origin
|
407
|
-
if abs(x)
|
450
|
+
if abs(x) <= tolerance and abs(y) <= tolerance and abs(z) <= tolerance:
|
408
451
|
return "Origin"
|
409
452
|
|
410
453
|
# Normalize vector to prevent magnitude bias
|
@@ -412,9 +455,9 @@ class Vector(list):
|
|
412
455
|
x, y, z = x / magnitude, y / magnitude, z / magnitude
|
413
456
|
|
414
457
|
# Apply tolerance to components
|
415
|
-
x = 0 if abs(x)
|
416
|
-
y = 0 if abs(y)
|
417
|
-
z = 0 if abs(z)
|
458
|
+
x = 0 if abs(x) <= tolerance else x
|
459
|
+
y = 0 if abs(y) <= tolerance else y
|
460
|
+
z = 0 if abs(z) <= tolerance else z
|
418
461
|
|
419
462
|
# Compass-based direction in the XY-plane
|
420
463
|
if x == 0 and y > 0:
|
@@ -553,18 +596,18 @@ class Vector(list):
|
|
553
596
|
if not silent:
|
554
597
|
print("Vector.Cross - Error: The input vectorB parameter is not a valid vector. Returning None.")
|
555
598
|
return None
|
556
|
-
if Vector.Magnitude(vector=vectorA, mantissa=mantissa)
|
599
|
+
if Vector.Magnitude(vector=vectorA, mantissa=mantissa) <= tolerance:
|
557
600
|
if not silent:
|
558
601
|
print("Vector.Cross - Error: The magnitude of the input vectorA parameter is less than the input tolerance parameter. Returning None.")
|
559
602
|
return None
|
560
|
-
if Vector.Magnitude(vector=vectorB, mantissa=mantissa)
|
603
|
+
if Vector.Magnitude(vector=vectorB, mantissa=mantissa) <= tolerance:
|
561
604
|
if not silent:
|
562
605
|
print("Vector.Cross - Error: The magnitude of the input vectorB parameter is less than the input tolerance parameter. Returning None.")
|
563
606
|
return None
|
564
607
|
vecA = np.array(vectorA)
|
565
608
|
vecB = np.array(vectorB)
|
566
609
|
vecC = list(np.cross(vecA, vecB))
|
567
|
-
if Vector.Magnitude(vecC)
|
610
|
+
if Vector.Magnitude(vecC) <= tolerance:
|
568
611
|
return [0, 0, 0]
|
569
612
|
return [round(vecC[0], mantissa), round(vecC[1], mantissa), round(vecC[2], mantissa)]
|
570
613
|
|
@@ -600,11 +643,11 @@ class Vector(list):
|
|
600
643
|
if not silent:
|
601
644
|
print("Vector.Dot - Error: The input vectorB parameter is not a valid vector. Returning None.")
|
602
645
|
return None
|
603
|
-
if Vector.Magnitude(vector=vectorA, mantissa=mantissa)
|
646
|
+
if Vector.Magnitude(vector=vectorA, mantissa=mantissa) <= tolerance:
|
604
647
|
if not silent:
|
605
648
|
print("Vector.Dot - Error: The magnitude of the input vectorA parameter is less than the input tolerance parameter. Returning None.")
|
606
649
|
return None
|
607
|
-
if Vector.Magnitude(vector=vectorB, mantissa=mantissa)
|
650
|
+
if Vector.Magnitude(vector=vectorB, mantissa=mantissa) <= tolerance:
|
608
651
|
if not silent:
|
609
652
|
print("Vector.Dot - Error: The magnitude of the input vectorB parameter is less than the input tolerance parameter. Returning None.")
|
610
653
|
return None
|
@@ -673,22 +716,26 @@ class Vector(list):
|
|
673
716
|
return False
|
674
717
|
|
675
718
|
@staticmethod
|
676
|
-
def IsCollinear(vectorA, vectorB):
|
719
|
+
def IsCollinear(vectorA, vectorB, tolerance=0.0001):
|
677
720
|
"""
|
678
|
-
Returns True if the input vectors are collinear (parallel or anti-parallel)
|
679
|
-
|
721
|
+
Returns True if the input vectors are collinear (parallel or anti-parallel)
|
722
|
+
within a given tolerance. Returns False otherwise.
|
723
|
+
|
680
724
|
Parameters
|
681
725
|
----------
|
682
726
|
vectorA : list
|
683
727
|
The first input vector.
|
684
728
|
vectorB : list
|
685
729
|
The second input vector.
|
730
|
+
tolerance : float, optional
|
731
|
+
The desired tolerance for determining collinearity. The default is 0.0001.
|
686
732
|
|
687
733
|
Returns
|
688
734
|
-------
|
689
735
|
bool
|
690
|
-
True if the input vectors are collinear (parallel or anti-parallel).
|
691
|
-
|
736
|
+
True if the input vectors are collinear (parallel or anti-parallel).
|
737
|
+
False otherwise.
|
738
|
+
|
692
739
|
"""
|
693
740
|
import numpy as np
|
694
741
|
|
@@ -700,17 +747,19 @@ class Vector(list):
|
|
700
747
|
vector1_norm = vector1 / np.linalg.norm(vector1)
|
701
748
|
vector2_norm = vector2 / np.linalg.norm(vector2)
|
702
749
|
|
703
|
-
# Check if the
|
750
|
+
# Check if the dot product is within the tolerance of 1.0 or -1.0
|
704
751
|
dot_product = np.dot(vector1_norm, vector2_norm)
|
705
|
-
if
|
752
|
+
if (1.0 - tolerance) <= dot_product <= (1.0 + tolerance) or \
|
753
|
+
(-1.0 - tolerance) <= dot_product <= (-1.0 + tolerance):
|
706
754
|
return True
|
707
755
|
else:
|
708
756
|
return False
|
709
757
|
|
710
758
|
@staticmethod
|
711
|
-
def IsParallel(vectorA, vectorB):
|
759
|
+
def IsParallel(vectorA, vectorB, tolerance=0.0001):
|
712
760
|
"""
|
713
|
-
Returns True if the input vectors are parallel
|
761
|
+
Returns True if the input vectors are parallel within a given tolerance.
|
762
|
+
Returns False otherwise.
|
714
763
|
|
715
764
|
Parameters
|
716
765
|
----------
|
@@ -718,12 +767,13 @@ class Vector(list):
|
|
718
767
|
The first input vector.
|
719
768
|
vectorB : list
|
720
769
|
The second input vector.
|
770
|
+
tolerance : float, optional
|
771
|
+
The desired tolerance for determining parallelism. The default is 0.0001.
|
721
772
|
|
722
773
|
Returns
|
723
774
|
-------
|
724
775
|
bool
|
725
776
|
True if the input vectors are parallel. False otherwise.
|
726
|
-
|
727
777
|
"""
|
728
778
|
import numpy as np
|
729
779
|
|
@@ -735,14 +785,13 @@ class Vector(list):
|
|
735
785
|
vector1_norm = vector1 / np.linalg.norm(vector1)
|
736
786
|
vector2_norm = vector2 / np.linalg.norm(vector2)
|
737
787
|
|
738
|
-
# Check if the
|
788
|
+
# Check if the dot product is within the tolerance of 1.0
|
739
789
|
dot_product = np.dot(vector1_norm, vector2_norm)
|
740
|
-
if
|
790
|
+
if (1.0 - tolerance) <= dot_product <= (1.0 + tolerance):
|
741
791
|
return True
|
742
792
|
else:
|
743
|
-
# Compute bisecting vector
|
744
793
|
return False
|
745
|
-
|
794
|
+
|
746
795
|
@staticmethod
|
747
796
|
def IsSame(vectorA, vectorB, tolerance=0.0001):
|
748
797
|
"""
|
@@ -763,7 +812,7 @@ class Vector(list):
|
|
763
812
|
True if the input vectors are the same. False otherwise.
|
764
813
|
|
765
814
|
"""
|
766
|
-
return all(abs(a - b)
|
815
|
+
return all(abs(a - b) <= tolerance for a, b in zip(vectorA, vectorB))
|
767
816
|
|
768
817
|
@staticmethod
|
769
818
|
def Length(vector, mantissa: int = 6):
|
@@ -825,7 +874,7 @@ class Vector(list):
|
|
825
874
|
The created vector that multiplies the input vector by the input magnitude.
|
826
875
|
|
827
876
|
"""
|
828
|
-
if abs(magnitude)
|
877
|
+
if abs(magnitude) <= tolerance:
|
829
878
|
return [0.0] * len(vector)
|
830
879
|
scaled_vector = [component * (magnitude) for component in vector]
|
831
880
|
return scaled_vector
|
topologicpy/Vertex.py
CHANGED
@@ -801,7 +801,7 @@ class Vertex():
|
|
801
801
|
|
802
802
|
other_vertex = vertices[i]
|
803
803
|
distance = np.linalg.norm(np.array(vertex) - np.array(other_vertex))
|
804
|
-
if distance
|
804
|
+
if distance <= tolerance:
|
805
805
|
# Choose the coordinate with the least amount of decimal points
|
806
806
|
if count_decimal_points(other_vertex) < count_decimal_points(fused_vertex):
|
807
807
|
fused_vertex = other_vertex
|
@@ -870,7 +870,7 @@ class Vertex():
|
|
870
870
|
incoming_edges = []
|
871
871
|
for edge in edges:
|
872
872
|
ev = Edge.EndVertex(edge)
|
873
|
-
if Vertex.Distance(vertex, ev)
|
873
|
+
if Vertex.Distance(vertex, ev) <= tolerance:
|
874
874
|
incoming_edges.append(edge)
|
875
875
|
return incoming_edges
|
876
876
|
|
@@ -911,7 +911,7 @@ class Vertex():
|
|
911
911
|
return i
|
912
912
|
else:
|
913
913
|
d = Vertex.Distance(vertex, vertices[i])
|
914
|
-
if d
|
914
|
+
if d <= tolerance:
|
915
915
|
return i
|
916
916
|
return None
|
917
917
|
|
@@ -967,7 +967,7 @@ class Vertex():
|
|
967
967
|
|
968
968
|
n_p = nearest_points[0]
|
969
969
|
n_d = n_p[0]
|
970
|
-
if n_d
|
970
|
+
if n_d <= tolerance:
|
971
971
|
return n_p[1]
|
972
972
|
|
973
973
|
# Calculate the weights for each nearest point based on inverse distance
|
@@ -1138,7 +1138,7 @@ class Vertex():
|
|
1138
1138
|
return None
|
1139
1139
|
|
1140
1140
|
if Topology.IsInstance(topology, "Vertex"):
|
1141
|
-
return Vertex.Distance(vertex, topology)
|
1141
|
+
return Vertex.Distance(vertex, topology) <= tolerance
|
1142
1142
|
elif Topology.IsInstance(topology, "Edge"):
|
1143
1143
|
try:
|
1144
1144
|
parameter = Edge.ParameterAtVertex(topology, vertex)
|
@@ -1502,7 +1502,7 @@ class Vertex():
|
|
1502
1502
|
outgoing_edges = []
|
1503
1503
|
for edge in edges:
|
1504
1504
|
sv = Edge.StartVertex(edge)
|
1505
|
-
if Vertex.Distance(vertex, sv)
|
1505
|
+
if Vertex.Distance(vertex, sv) <= tolerance:
|
1506
1506
|
outgoing_edges.append(edge)
|
1507
1507
|
return outgoing_edges
|
1508
1508
|
|
@@ -1806,6 +1806,63 @@ class Vertex():
|
|
1806
1806
|
separated_vertices[i] = Topology.SetDictionary(separated_vertices[i], d)
|
1807
1807
|
return separated_vertices
|
1808
1808
|
|
1809
|
+
@staticmethod
|
1810
|
+
def Transform(vertex, matrix, mantissa: int = 6, silent: bool = False):
|
1811
|
+
"""
|
1812
|
+
Transforms a 3D vertex using a 4x4 transformation matrix.
|
1813
|
+
|
1814
|
+
Parameters
|
1815
|
+
----------
|
1816
|
+
vertex : topologic_core.Vertex
|
1817
|
+
The input vertex
|
1818
|
+
matrix : list
|
1819
|
+
The 4x4 transformation matrix.
|
1820
|
+
mantissa : int , optional
|
1821
|
+
The desired length of the mantissa. The default is 6.
|
1822
|
+
silent : bool , optional
|
1823
|
+
If set to True, no error and warning messages are printed. Otherwise, they are. The default is False.
|
1824
|
+
|
1825
|
+
Returns
|
1826
|
+
-------
|
1827
|
+
topologic_core.Vertex
|
1828
|
+
The transformed vertex.
|
1829
|
+
"""
|
1830
|
+
from topologicpy.Topology import Topology
|
1831
|
+
|
1832
|
+
if not Topology.IsInstance(vertex, "vertex"):
|
1833
|
+
if not silent:
|
1834
|
+
print("Vertex.Transform - Error: The input vertex parameter is not a valid vertex. Returning None.")
|
1835
|
+
return None
|
1836
|
+
|
1837
|
+
if not isinstance(matrix, list):
|
1838
|
+
if not silent:
|
1839
|
+
print("Vertex.Transform - Error: The input matrix parameter is not a valid 4X4 matrix. Returning None.")
|
1840
|
+
return None
|
1841
|
+
|
1842
|
+
matrix = np.array(matrix) # Convert list to numpy array if necessary
|
1843
|
+
|
1844
|
+
# Check if the shape of the matrix is (4, 4)
|
1845
|
+
if not matrix.shape == (4, 4):
|
1846
|
+
if not silent:
|
1847
|
+
print("Vertex.Transform - Error: The input matrix parameter is not a valid 4X4 matrix. Returning None.")
|
1848
|
+
return None
|
1849
|
+
|
1850
|
+
# Convert the vertex to a 4D homogeneous coordinate
|
1851
|
+
coords = Vertex.Coordinates(vertex, mantissa=mantissa)
|
1852
|
+
homogeneous_coords= np.array([coords[0], coords[1], coords[2], 1.0])
|
1853
|
+
|
1854
|
+
# Perform matrix multiplication
|
1855
|
+
transformed_coords = np.dot(matrix, homogeneous_coords)
|
1856
|
+
|
1857
|
+
# Convert back to 3D by dividing by w
|
1858
|
+
if not np.isclose(transformed_coords[3], 0): # Avoid division by zero
|
1859
|
+
transformed_coords /= transformed_coords[3]
|
1860
|
+
|
1861
|
+
# Return the transformed (x', y', z') as a list
|
1862
|
+
coords = transformed_coords[:3].tolist()
|
1863
|
+
coords = [round(v, mantissa) for v in coords]
|
1864
|
+
return Vertex.ByCoordinates(coords)
|
1865
|
+
|
1809
1866
|
@staticmethod
|
1810
1867
|
def X(vertex, mantissa: int = 6) -> float:
|
1811
1868
|
"""
|