topologicpy 0.8.10__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/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 not isinstance(vertices, list):
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 not isinstance(normalize, bool):
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
- vertices = [v for v in vertices if Topology.IsInstance(v, "Vertex")]
305
- if len(vertices) < 2:
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 = vertices[0]
308
- v2 = vertices[-1]
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)
@@ -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). Returns False otherwise.
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). False otherwise.
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 angle between vectors is either 0 or 180 degrees
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 np.isclose(dot_product, 1.0) or np.isclose(dot_product, -1.0):
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. Returns False otherwise.
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 angle between vectors is either 0 or 180 degrees
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 np.isclose(dot_product, 1.0):
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
  """
topologicpy/Vertex.py CHANGED
@@ -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
  """
topologicpy/Wire.py CHANGED
@@ -3596,7 +3596,6 @@ class Wire():
3596
3596
  baseWire = Topology.Orient(baseWire, origin=origin, dirA=[0, 0, 1], dirB=direction)
3597
3597
  return baseWire
3598
3598
 
3599
-
3600
3599
  @staticmethod
3601
3600
  def RemoveCollinearEdges(wire, angTolerance: float = 0.1, tolerance: float = 0.0001, silent: bool = False):
3602
3601
  """
@@ -3690,124 +3689,6 @@ class Wire():
3690
3689
  else:
3691
3690
  return Topology.SelfMerge(Cluster.ByTopologies(processed_wires, silent=silent))
3692
3691
 
3693
- @staticmethod
3694
- def RemoveCollinearEdges_old(wire, angTolerance: float = 0.1, tolerance: float = 0.0001, silent: bool = False):
3695
- """
3696
- Removes any collinear edges in the input wire.
3697
-
3698
- Parameters
3699
- ----------
3700
- wire : topologic_core.Wire
3701
- The input wire.
3702
- angTolerance : float , optional
3703
- The desired angular tolerance. The default is 0.1.
3704
- tolerance : float , optional
3705
- The desired tolerance. The default is 0.0001.
3706
- silent : bool , optional
3707
- If set to True, no error and warning messages are printed. Otherwise, they are. The default is False.
3708
-
3709
- Returns
3710
- -------
3711
- topologic_core.Wire
3712
- The created wire without any collinear edges.
3713
-
3714
- """
3715
- from topologicpy.Vertex import Vertex
3716
- from topologicpy.Edge import Edge
3717
- from topologicpy.Cluster import Cluster
3718
- from topologicpy.Topology import Topology
3719
- import inspect
3720
-
3721
- def cleanup(wire, tolerance=0.0001):
3722
- vertices = Topology.Vertices(wire)
3723
- vertices = Vertex.Fuse(vertices, tolerance=tolerance)
3724
- edges = Topology.Edges(wire)
3725
- new_edges = []
3726
- for edge in edges:
3727
- sv = Edge.StartVertex(edge)
3728
- sv = vertices[Vertex.Index(sv, vertices, tolerance=tolerance)]
3729
- ev = Edge.EndVertex(edge)
3730
- ev = vertices[Vertex.Index(ev, vertices, tolerance=tolerance)]
3731
- if Vertex.Distance(sv, ev) > tolerance:
3732
- new_edges.append(Edge.ByVertices([sv,ev]))
3733
- if len(new_edges) > 0:
3734
- return Topology.SelfMerge(Cluster.ByTopologies(new_edges, silent=silent), tolerance=tolerance)
3735
- return wire
3736
-
3737
- def rce(wire, angTolerance=0.1):
3738
- if not Topology.IsInstance(wire, "Wire"):
3739
- return wire
3740
- final_wire = None
3741
- vertices = []
3742
- wire_verts = []
3743
- try:
3744
- vertices = Topology.Vertices(wire)
3745
- except:
3746
- return wire
3747
- for aVertex in vertices:
3748
- edges = []
3749
- _ = aVertex.Edges(wire, edges)
3750
- if len(edges) > 1:
3751
- if not Edge.IsCollinear(edges[0], edges[1], tolerance=tolerance):
3752
- wire_verts.append(aVertex)
3753
- else:
3754
- wire_verts.append(aVertex)
3755
- if len(wire_verts) > 2:
3756
- if wire.IsClosed():
3757
- final_wire = Wire.ByVertices(wire_verts, close=True, tolerance=tolerance)
3758
- else:
3759
- final_wire = Wire.ByVertices(wire_verts, close=False, tolerance=tolerance)
3760
- elif len(wire_verts) == 2:
3761
- final_wire = Edge.ByStartVertexEndVertex(wire_verts[0], wire_verts[1], tolerance=tolerance, silent=True)
3762
- return final_wire
3763
-
3764
- if Topology.IsInstance(wire, "cluster"):
3765
- wires = Topology.Wires(wire)
3766
- temp_wires = []
3767
- for w in wires:
3768
- temp_w = Wire.RemoveCollinearEdges(w)
3769
- if not temp_w == None:
3770
- temp_wires.append(temp_w)
3771
- if len(temp_wires) > 0:
3772
- result = Topology.SelfMerge(Cluster.ByTopologies(temp_w))
3773
- return result
3774
- if not Topology.IsInstance(wire, "Wire"):
3775
- if not silent:
3776
- print("Wire.RemoveCollinearEdges - Error: The input wire parameter is not a valid wire. Returning None.")
3777
- curframe = inspect.currentframe()
3778
- calframe = inspect.getouterframes(curframe, 2)
3779
- print('caller name:', calframe[1][3])
3780
- return None
3781
- new_wire = cleanup(wire, tolerance=tolerance)
3782
- if not Wire.IsManifold(new_wire):
3783
- wires = Wire.Split(new_wire)
3784
- else:
3785
- wires = [new_wire]
3786
- returnWires = []
3787
- for aWire in wires:
3788
- if not Topology.IsInstance(aWire, "Wire"):
3789
- returnWires.append(aWire)
3790
- else:
3791
- returnWires.append(rce(aWire, angTolerance=angTolerance))
3792
- if len(returnWires) == 1:
3793
- returnWire = returnWires[0]
3794
- if Topology.IsInstance(returnWire, "Edge"):
3795
- return Wire.ByEdges([returnWire], tolerance=tolerance)
3796
- elif Topology.IsInstance(returnWire, "Wire"):
3797
- return returnWire
3798
- else:
3799
- return wire
3800
- elif len(returnWires) > 1:
3801
- returnWire = Topology.SelfMerge(Cluster.ByTopologies(returnWires, silent=silent))
3802
- if Topology.IsInstance(returnWire, "Edge"):
3803
- return Wire.ByEdges([returnWire], tolerance=tolerance)
3804
- elif Topology.IsInstance(returnWire, "Wire"):
3805
- return returnWire
3806
- else:
3807
- return wire
3808
- else:
3809
- return wire
3810
-
3811
3692
  @staticmethod
3812
3693
  def Representation(wire, normalize: bool = True, rotate: bool = True, mantissa: int = 6, tolerance: float = 0.0001):
3813
3694
  """
topologicpy/version.py CHANGED
@@ -1 +1 @@
1
- __version__ = '0.8.10'
1
+ __version__ = '0.8.11'
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: topologicpy
3
- Version: 0.8.10
3
+ Version: 0.8.11
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
@@ -10,27 +10,27 @@ topologicpy/DGL.py,sha256=M_znFtyPBJJz-iXLYZs2wwBj24fhevIo739dGha0chM,139041
10
10
  topologicpy/Dictionary.py,sha256=t0O7Du-iPq46FyKqZfcjHfsUK1E8GS_e67R2V5cpkbw,33186
11
11
  topologicpy/Edge.py,sha256=yxkCVDYBflJNEYxnjMmlyvbkpg8TNy7y5bSH3yQ4jzs,71418
12
12
  topologicpy/EnergyModel.py,sha256=UoQ9Jm-hYsN383CbcLKw-y6BKitRHj0uyh84yQ-8ACg,53856
13
- topologicpy/Face.py,sha256=a6rPTdgf4yhoH29kwV_48U_XYtdvNWdHnkErmMBp2CU,180759
14
- topologicpy/Graph.py,sha256=6pRgWtkq9a5p7uXiPq2O4yMEJZG6H7A5wA44bjGOP3s,497470
13
+ topologicpy/Face.py,sha256=tn3PI-t9rXikgI1QMclw0PFwQ5vvyLi-wJKqZZZ9xmw,182755
14
+ topologicpy/Graph.py,sha256=hrJYK0CboyxNjCRLoc75PeQzf9uI64OVxDyevbJUlZg,498342
15
15
  topologicpy/Grid.py,sha256=2s9cSlWldivn1i9EUz4OOokJyANveqmRe_vR93CAndI,18245
16
16
  topologicpy/Helper.py,sha256=4H5KPiv_eiEs489UOOyGLe9RaeoZIfmMh3mk_YCHmXg,29100
17
17
  topologicpy/Honeybee.py,sha256=Y_El6M8x3ixvvIe_VcRiwj_4C89ZZg5_WlT7adbCkpw,21849
18
- topologicpy/Matrix.py,sha256=ydw0EH4rZcGBFeLmBHPIyuk57DVKKL3M1GcArkFsYxM,10941
18
+ topologicpy/Matrix.py,sha256=mqcCk14kM9OOwJPwd9ce-8SFM0IxS3jYb2XpWhVjUAc,19503
19
19
  topologicpy/Neo4j.py,sha256=BKOF29fRgXmdpMGkrNzuYbyqgCJ6ElPPMYlfTxXiVbc,22392
20
- topologicpy/Plotly.py,sha256=xfd_c2Mcam5KP-gDD-esl42RVXW5TSJsUCCqhUg1VFk,115788
20
+ topologicpy/Plotly.py,sha256=RU_VioIRLGIYzwyKI9OQHOx9OxxGppdpagysgTbdxIE,115942
21
21
  topologicpy/Polyskel.py,sha256=DDUayC29LI1EkxdK09F0DgGyH-NCOU1LE3J2Imz0rEI,19832
22
22
  topologicpy/PyG.py,sha256=LU9LCCzjxGPUM31qbaJXZsTvniTtgugxJY7y612t4A4,109757
23
23
  topologicpy/Shell.py,sha256=--dJoSdz6BapxVEyG2DI0W5apO_xwLORj5qmR15yl2Y,87983
24
24
  topologicpy/Speckle.py,sha256=AlsGlSDuKRtX5jhVsPNSSjjbZis079HbUchDH_5RJmE,18187
25
25
  topologicpy/Sun.py,sha256=42tDWMYpwRG7Z2Qjtp94eRgBuqySq7k8TgNUZDK7QxQ,36837
26
- topologicpy/Topology.py,sha256=zFNNxiXRsDURF4FABfU3aG0mEp-qYYmxjADksYXRIgI,463941
27
- topologicpy/Vector.py,sha256=rwMKNJQs7SsWc7bhGuxHAjkJA8s0w46xnY0Xo2zOPR0,39590
28
- topologicpy/Vertex.py,sha256=70bee44uuf1d-uk3kL_pKPJKduJLdjve14mmLpcaT3s,78511
29
- topologicpy/Wire.py,sha256=CYd8M774E6Pv9vDIrOoKWV6nKo2tNOi3xREQL9WE808,233433
26
+ topologicpy/Topology.py,sha256=mhRKJlFJLe_IGxj_bQ5lbK277YKod7PLXWzZ2Suq8ng,465493
27
+ topologicpy/Vector.py,sha256=GkGt-aJ591IJ2IPffMAudvITLDPi2qZibZc4UAav6m8,42407
28
+ topologicpy/Vertex.py,sha256=xr8KSgKnx-hgVp-eIvMPAKRv04R-wk-_4zc57xVyEqE,80793
29
+ topologicpy/Wire.py,sha256=x7tOeR1o5qi5cXp_d9JrQrSXfYztCWiBC1OnVl6Yp7A,228463
30
30
  topologicpy/__init__.py,sha256=vlPCanUbxe5NifC4pHcnhSzkmmYcs_UrZrTlVMsxcFs,928
31
- topologicpy/version.py,sha256=xfh7QQ1d8queik59T_oYOabvDZyIi-O8o2ByZ-QACcQ,23
32
- topologicpy-0.8.10.dist-info/LICENSE,sha256=FK0vJ73LuE8PYJAn7LutsReWR47-Ooovw2dnRe5yV6Q,681
33
- topologicpy-0.8.10.dist-info/METADATA,sha256=MDU41HIFzabAK1nEmY8rsdZDpwG3vwgBi7PMc9Tzp_Y,10513
34
- topologicpy-0.8.10.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
35
- topologicpy-0.8.10.dist-info/top_level.txt,sha256=J30bDzW92Ob7hw3zA8V34Jlp-vvsfIkGzkr8sqvb4Uw,12
36
- topologicpy-0.8.10.dist-info/RECORD,,
31
+ topologicpy/version.py,sha256=37n3GuNviuek888I4WoUQ7KvWprxXex9ltIoHwZWFxM,23
32
+ topologicpy-0.8.11.dist-info/LICENSE,sha256=FK0vJ73LuE8PYJAn7LutsReWR47-Ooovw2dnRe5yV6Q,681
33
+ topologicpy-0.8.11.dist-info/METADATA,sha256=_ggJ77QM3ok-OsVcQdXNC6Er-VH_AuQg3tZroNFpyYk,10513
34
+ topologicpy-0.8.11.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
35
+ topologicpy-0.8.11.dist-info/top_level.txt,sha256=J30bDzW92Ob7hw3zA8V34Jlp-vvsfIkGzkr8sqvb4Uw,12
36
+ topologicpy-0.8.11.dist-info/RECORD,,