topologicpy 0.5.4__py3-none-any.whl → 0.5.6__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/Cell.py CHANGED
@@ -18,22 +18,6 @@ import topologic
18
18
  from topologicpy.Wire import Wire
19
19
  from topologicpy.Topology import Topology
20
20
  import math
21
- import os
22
- import warnings
23
-
24
- try:
25
- import numpy as np
26
- except:
27
- print("Cell - Installing required numpy library.")
28
- try:
29
- os.system("pip install numpy")
30
- except:
31
- os.system("pip install numpy --user")
32
- try:
33
- import numpy as np
34
- print("Cell - numpy library installed correctly.")
35
- except:
36
- warnings.warn("Cell - Error: Could not import numpy.")
37
21
 
38
22
  class Cell(Topology):
39
23
  @staticmethod
@@ -226,15 +210,9 @@ class Cell(Topology):
226
210
  The created offset topology. WARNING: This method may fail to create a cell if the offset creates self-intersecting faces. Always check the type being returned by this method.
227
211
 
228
212
  """
229
- from topologicpy.Vertex import Vertex
230
- from topologicpy.Wire import Wire
231
213
  from topologicpy.Face import Face
232
- from topologicpy.Cluster import Cluster
233
- from topologicpy.Helper import Helper
234
214
  from topologicpy.Topology import Topology
235
215
  from topologicpy.Vector import Vector
236
- from operator import add
237
- import numpy as np
238
216
 
239
217
  vertices = Topology.Vertices(cell)
240
218
  new_vertices = []
@@ -922,7 +900,6 @@ class Cell(Topology):
922
900
  from topologicpy.Vector import Vector
923
901
  from topologicpy.Aperture import Aperture
924
902
  from topologicpy.Topology import Topology
925
- from numpy import arctan, pi, signbit, arctan2, rad2deg
926
903
 
927
904
  def angleCode(f, up, tiltAngle):
928
905
  dirA = Face.NormalAtParameters(f)
@@ -464,7 +464,6 @@ class CellComplex(Topology):
464
464
  from topologicpy.Vector import Vector
465
465
  from topologicpy.Aperture import Aperture
466
466
  from topologicpy.Topology import Topology
467
- from numpy import arctan, pi, signbit, arctan2, rad2deg
468
467
 
469
468
  def angleCode(f, up, tiltAngle):
470
469
  dirA = Face.NormalAtParameters(f)
@@ -1102,8 +1101,6 @@ class CellComplex(Topology):
1102
1101
  if len(vertices) < 1:
1103
1102
  print("CellComplex.Voronoi - Error: The input vertices parame ter does not contain any vertices that are inside the input cell parameter. Returning None.")
1104
1103
  return None
1105
- #cell_vertices = Topology.Vertices(cell)
1106
- #all_vertices = cell_vertices + vertices
1107
1104
  voronoi_points = np.array([Vertex.Coordinates(v) for v in vertices])
1108
1105
  cluster = fracture_with_voronoi(voronoi_points)
1109
1106
  if cluster == None:
topologicpy/Face.py CHANGED
@@ -484,7 +484,7 @@ class Face(Topology):
484
484
  return None
485
485
 
486
486
  @staticmethod
487
- def ByVertices(vertices: list) -> topologic.Face:
487
+ def ByVertices(vertices: list, tolerance: float = 0.0001) -> topologic.Face:
488
488
 
489
489
  """
490
490
  Creates a face from the input list of vertices.
@@ -493,6 +493,8 @@ class Face(Topology):
493
493
  ----------
494
494
  vertices : list
495
495
  The input list of vertices.
496
+ tolerance : float , optional
497
+ The desired tolerance. The default is 0.0001.
496
498
 
497
499
  Returns
498
500
  -------
@@ -509,12 +511,12 @@ class Face(Topology):
509
511
  if len(vertexList) < 3:
510
512
  return None
511
513
 
512
- w = Wire.ByVertices(vertexList)
513
- f = Face.ByWire(w)
514
+ w = Wire.ByVertices(vertexList, tolerance=tolerance)
515
+ f = Face.ByWire(w, tolerance=tolerance)
514
516
  return f
515
517
 
516
518
  @staticmethod
517
- def ByVerticesCluster(cluster: topologic.Cluster) -> topologic.Face:
519
+ def ByVerticesCluster(cluster: topologic.Cluster, tolerance: float = 0.0001) -> topologic.Face:
518
520
  """
519
521
  Creates a face from the input cluster of vertices.
520
522
 
@@ -522,6 +524,8 @@ class Face(Topology):
522
524
  ----------
523
525
  cluster : topologic.Cluster
524
526
  The input cluster of vertices.
527
+ tolerance : float , optional
528
+ The desired tolerance. The default is 0.0001.
525
529
 
526
530
  Returns
527
531
  -------
@@ -533,7 +537,7 @@ class Face(Topology):
533
537
  if not isinstance(cluster, topologic.Cluster):
534
538
  return None
535
539
  vertices = Cluster.Vertices(cluster)
536
- return Face.ByVertices(vertices)
540
+ return Face.ByVertices(vertices, tolerance=tolerance)
537
541
 
538
542
  @staticmethod
539
543
  def ByWire(wire: topologic.Wire, tolerance: float = 0.0001, silent=False) -> topologic.Face:
@@ -1782,7 +1786,7 @@ class Face(Topology):
1782
1786
  return Face.ByWire(wire, tolerance=tolerance)
1783
1787
 
1784
1788
  @staticmethod
1785
- def Triangulate(face:topologic.Face, tolerance: float = 0.0001) -> list:
1789
+ def Triangulate(face:topologic.Face, mode: str = "classic", meshSize: float = None, tolerance: float = 0.0001) -> list:
1786
1790
  """
1787
1791
  Triangulates the input face and returns a list of faces.
1788
1792
 
@@ -1792,6 +1796,13 @@ class Face(Topology):
1792
1796
  The input face.
1793
1797
  tolerance : float , optional
1794
1798
  The desired tolerance. The default is 0.0001.
1799
+ mode : str , optional
1800
+ The desired mode of meshing. Two options are available: "classic" and "mesh". They are case insensitive.
1801
+ The "mesh" option uses the gmsh library.
1802
+ WARNING: The "mesh" option can be very time consuming and can create very heavy geometry.
1803
+ meshSize : float , optional
1804
+ The desired size of the mesh when using the "mesh" option. If set to None, it will be
1805
+ calculated automatically and set to 10% of the overall size of the face.
1795
1806
 
1796
1807
  Returns
1797
1808
  -------
@@ -1805,6 +1816,135 @@ class Face(Topology):
1805
1816
  from topologicpy.Topology import Topology
1806
1817
  from topologicpy.Dictionary import Dictionary
1807
1818
 
1819
+ # This function was contributed by Yidan Xue.
1820
+ def generate_gmsh(face, meshSize = None, tolerance = 0.0001):
1821
+ """
1822
+ Creates a gmsh of triangular meshes from the input face.
1823
+
1824
+ Parameters
1825
+ ----------
1826
+ face : topologic.Face
1827
+ The input face.
1828
+ meshSize : float , optional
1829
+ The desired mesh size.
1830
+ tolerance : float , optional
1831
+ The desired tolerance. The default is 0.0001.
1832
+
1833
+ Returns
1834
+ ----------
1835
+ topologic.Shell
1836
+ The shell of triangular meshes.
1837
+
1838
+ """
1839
+ import os
1840
+ import warnings
1841
+ try:
1842
+ import numpy as np
1843
+ except:
1844
+ print("Face.Triangulate - Warning: Installing required numpy library.")
1845
+ try:
1846
+ os.system("pip install numpy")
1847
+ except:
1848
+ os.system("pip install numpy --user")
1849
+ try:
1850
+ import numpy as np
1851
+ print("Face.Triangulate - Warning: numpy library installed correctly.")
1852
+ except:
1853
+ warnings.warn("Face.Triangulate - Error: Could not import numpy. Please try to install numpy manually. Returning None.")
1854
+ return None
1855
+ try:
1856
+ import gmsh
1857
+ except:
1858
+ print("Face.Triangulate - Warning: Installing required gmsh library.")
1859
+ try:
1860
+ os.system("pip install gmsh")
1861
+ except:
1862
+ os.system("pip install gmsh --user")
1863
+ try:
1864
+ import gmsh
1865
+ print("Face.Triangulate - Warning: gmsh library installed correctly.")
1866
+ except:
1867
+ warnings.warn("Face.Triangulate - Error: Could not import gmsh. Please try to install gmsh manually. Returning None.")
1868
+ return None
1869
+
1870
+ import topologic
1871
+ from topologicpy.Vertex import Vertex
1872
+ from topologicpy.Wire import Wire
1873
+ from topologicpy.Face import Face
1874
+
1875
+ if not isinstance(face, topologic.Face):
1876
+ print("Shell.ByMeshFace - Error: The input face parameter is not a valid face. Returning None.")
1877
+ return None
1878
+ if not meshSize:
1879
+ bounding_face = Face.BoundingRectangle(face)
1880
+ bounding_face_vertices = Face.Vertices(bounding_face)
1881
+ bounding_face_vertices_x = [Vertex.X(i) for i in bounding_face_vertices]
1882
+ bounding_face_vertices_y = [Vertex.Y(i) for i in bounding_face_vertices]
1883
+ width = max(bounding_face_vertices_x)-min(bounding_face_vertices_x)
1884
+ length = max(bounding_face_vertices_y)-min(bounding_face_vertices_y)
1885
+ meshSize = max([width,length])//10
1886
+
1887
+ gmsh.initialize()
1888
+ face_external_boundary = Face.ExternalBoundary(face)
1889
+ external_vertices = Wire.Vertices(face_external_boundary)
1890
+ external_vertex_number = len(external_vertices)
1891
+ for i in range(external_vertex_number):
1892
+ gmsh.model.geo.addPoint(Vertex.X(external_vertices[i]), Vertex.Y(external_vertices[i]), Vertex.Z(external_vertices[i]), meshSize, i+1)
1893
+ for i in range(external_vertex_number):
1894
+ if i < external_vertex_number-1:
1895
+ gmsh.model.geo.addLine(i+1, i+2, i+1)
1896
+ else:
1897
+ gmsh.model.geo.addLine(i+1, 1, i+1)
1898
+ gmsh.model.geo.addCurveLoop([i+1 for i in range(external_vertex_number)], 1)
1899
+ current_vertex_number = external_vertex_number
1900
+ current_edge_number = external_vertex_number
1901
+ current_wire_number = 1
1902
+
1903
+ face_internal_boundaries = Face.InternalBoundaries(face)
1904
+ if face_internal_boundaries:
1905
+ internal_face_number = len(face_internal_boundaries)
1906
+ for i in range(internal_face_number):
1907
+ face_internal_boundary = face_internal_boundaries[i]
1908
+ internal_vertices = Wire.Vertices(face_internal_boundary)
1909
+ internal_vertex_number = len(internal_vertices)
1910
+ for j in range(internal_vertex_number):
1911
+ gmsh.model.geo.addPoint(Vertex.X(internal_vertices[j]), Vertex.Y(internal_vertices[j]), Vertex.Z(internal_vertices[j]), meshSize, current_vertex_number+j+1)
1912
+ for j in range(internal_vertex_number):
1913
+ if j < internal_vertex_number-1:
1914
+ gmsh.model.geo.addLine(current_vertex_number+j+1, current_vertex_number+j+2, current_edge_number+j+1)
1915
+ else:
1916
+ gmsh.model.geo.addLine(current_vertex_number+j+1, current_vertex_number+1, current_edge_number+j+1)
1917
+ gmsh.model.geo.addCurveLoop([current_edge_number+i+1 for i in range(internal_vertex_number)], current_wire_number+1)
1918
+ current_vertex_number = current_vertex_number+internal_vertex_number
1919
+ current_edge_number = current_edge_number+internal_vertex_number
1920
+ current_wire_number = current_wire_number+1
1921
+
1922
+ gmsh.model.geo.addPlaneSurface([i+1 for i in range(current_wire_number)])
1923
+ gmsh.model.geo.synchronize()
1924
+
1925
+ gmsh.model.mesh.generate(2) # For a 2D mesh
1926
+ nodeTags, nodeCoords, nodeParams = gmsh.model.mesh.getNodes(-1, -1)
1927
+ elemTypes, elemTags, elemNodeTags = gmsh.model.mesh.getElements(-1, -1)
1928
+ gmsh.finalize()
1929
+
1930
+ vertex_number = len(nodeTags)
1931
+ vertices = []
1932
+ for i in range(vertex_number):
1933
+ vertices.append(Vertex.ByCoordinates(nodeCoords[3*i],nodeCoords[3*i+1],nodeCoords[3*i+2]))
1934
+
1935
+ faces = []
1936
+ for n in range(len(elemTypes)):
1937
+ vn = elemTypes[n]+1
1938
+ et = elemTags[n]
1939
+ ent = elemNodeTags[n]
1940
+ if vn==3:
1941
+ for i in range(len(et)):
1942
+ face_vertices = []
1943
+ for j in range(vn):
1944
+ face_vertices.append(vertices[np.where(nodeTags==ent[i*vn+j])[0][0]])
1945
+ faces.append(Face.ByVertices(face_vertices))
1946
+ return faces
1947
+
1808
1948
  if not isinstance(face, topologic.Face):
1809
1949
  print("Face.Triangulate - Error: The input face parameter is not a valid face. Returning None.")
1810
1950
  return None
@@ -1814,14 +1954,17 @@ class Face(Topology):
1814
1954
  origin = Topology.Centroid(face)
1815
1955
  normal = Face.Normal(face)
1816
1956
  flatFace = Topology.Flatten(face, origin=origin, direction=normal)
1817
-
1818
- shell_faces = []
1819
- for i in range(0,5,1):
1820
- try:
1821
- _ = topologic.FaceUtility.Triangulate(flatFace, float(i)*0.1, shell_faces)
1822
- break
1823
- except:
1824
- continue
1957
+
1958
+ if "mesh" in mode.lower():
1959
+ shell_faces = generate_gmsh(flatFace, meshSize = meshSize, tolerance = tolerance)
1960
+ else:
1961
+ shell_faces = []
1962
+ for i in range(0,5,1):
1963
+ try:
1964
+ _ = topologic.FaceUtility.Triangulate(flatFace, float(i)*0.1, shell_faces)
1965
+ break
1966
+ except:
1967
+ continue
1825
1968
 
1826
1969
  if len(shell_faces) < 1:
1827
1970
  return []