topologicpy 0.5.3__py3-none-any.whl → 0.5.5__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 +112 -135
- topologicpy/CellComplex.py +15 -18
- topologicpy/Cluster.py +3 -3
- topologicpy/Color.py +10 -10
- topologicpy/Edge.py +12 -9
- topologicpy/Face.py +189 -44
- topologicpy/Graph.py +639 -69
- topologicpy/Grid.py +9 -9
- topologicpy/Plotly.py +2025 -2025
- topologicpy/Shell.py +42 -43
- topologicpy/Speckle.py +1 -1
- topologicpy/Topology.py +99 -88
- topologicpy/Vector.py +36 -36
- topologicpy/Vertex.py +12 -12
- topologicpy/Wire.py +80 -76
- topologicpy/__init__.py +1 -1
- {topologicpy-0.5.3.dist-info → topologicpy-0.5.5.dist-info}/METADATA +2 -2
- {topologicpy-0.5.3.dist-info → topologicpy-0.5.5.dist-info}/RECORD +21 -21
- {topologicpy-0.5.3.dist-info → topologicpy-0.5.5.dist-info}/LICENSE +0 -0
- {topologicpy-0.5.3.dist-info → topologicpy-0.5.5.dist-info}/WHEEL +0 -0
- {topologicpy-0.5.3.dist-info → topologicpy-0.5.5.dist-info}/top_level.txt +0 -0
topologicpy/Face.py
CHANGED
@@ -230,7 +230,7 @@ class Face(Topology):
|
|
230
230
|
for z in range(za,zb,zc):
|
231
231
|
if flag:
|
232
232
|
break
|
233
|
-
t = Topology.Rotate(topology, origin=origin,
|
233
|
+
t = Topology.Rotate(topology, origin=origin, axis=[0, 0, 1], angle=z)
|
234
234
|
minX, minY, maxX, maxY = bb(t)
|
235
235
|
w = abs(maxX - minX)
|
236
236
|
l = abs(maxY - minY)
|
@@ -257,7 +257,7 @@ class Face(Topology):
|
|
257
257
|
|
258
258
|
baseWire = Wire.ByVertices([vb1, vb2, vb3, vb4], close=True)
|
259
259
|
baseFace = Face.ByWire(baseWire, tolerance=tolerance)
|
260
|
-
baseFace = Topology.Rotate(baseFace, origin=origin,
|
260
|
+
baseFace = Topology.Rotate(baseFace, origin=origin, axis=[0, 0, 1], angle=-best_z)
|
261
261
|
dictionary = Dictionary.ByKeysValues(["zrot"], [best_z])
|
262
262
|
baseFace = Topology.SetDictionary(baseFace, dictionary)
|
263
263
|
return baseFace
|
@@ -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:
|
@@ -705,7 +709,7 @@ class Face(Topology):
|
|
705
709
|
return Face.ByWires(externalBoundary, internalBoundaries, tolerance=tolerance, silent=silent)
|
706
710
|
|
707
711
|
@staticmethod
|
708
|
-
def NorthArrow(origin: topologic.Vertex = None, radius: float = 0.5, sides: int = 16, direction: list = [0,0,1], northAngle: float = 0.0,
|
712
|
+
def NorthArrow(origin: topologic.Vertex = None, radius: float = 0.5, sides: int = 16, direction: list = [0, 0, 1], northAngle: float = 0.0,
|
709
713
|
placement: str = "center", tolerance: float = 0.0001) -> topologic.Face:
|
710
714
|
"""
|
711
715
|
Creates a north arrow.
|
@@ -713,13 +717,13 @@ class Face(Topology):
|
|
713
717
|
Parameters
|
714
718
|
----------
|
715
719
|
origin : topologic.Vertex, optional
|
716
|
-
The location of the origin of the circle. The default is None which results in the circle being placed at (0,0,0).
|
720
|
+
The location of the origin of the circle. The default is None which results in the circle being placed at (0, 0, 0).
|
717
721
|
radius : float , optional
|
718
722
|
The radius of the circle. The default is 1.
|
719
723
|
sides : int , optional
|
720
724
|
The number of sides of the circle. The default is 16.
|
721
725
|
direction : list , optional
|
722
|
-
The vector representing the up direction of the circle. The default is [0,0,1].
|
726
|
+
The vector representing the up direction of the circle. The default is [0, 0, 1].
|
723
727
|
northAngle : float , optional
|
724
728
|
The angular offset in degrees from the positive Y axis direction. The angle is measured in a counter-clockwise fashion where 0 is positive Y, 90 is negative X, 180 is negative Y, and 270 is positive X.
|
725
729
|
placement : str , optional
|
@@ -738,11 +742,11 @@ class Face(Topology):
|
|
738
742
|
if not origin:
|
739
743
|
origin = Vertex.Origin()
|
740
744
|
|
741
|
-
c = Face.Circle(origin=origin, radius=radius, sides=sides, direction=[0,0,1], placement="center", tolerance=tolerance)
|
745
|
+
c = Face.Circle(origin=origin, radius=radius, sides=sides, direction=[0, 0, 1], placement="center", tolerance=tolerance)
|
742
746
|
r = Face.Rectangle(origin=origin, width=radius*0.01,length=radius*1.2, placement="lowerleft")
|
743
747
|
r = Topology.Translate(r, -0.005*radius,0,0)
|
744
748
|
arrow = Topology.Difference(c, r, tolerance=tolerance)
|
745
|
-
arrow = Topology.Rotate(arrow, Vertex.Origin(), 0,0,1,northAngle)
|
749
|
+
arrow = Topology.Rotate(arrow, origin=Vertex.Origin(), axis=[0, 0, 1], angle=northAngle)
|
746
750
|
if placement.lower() == "lowerleft":
|
747
751
|
arrow = Topology.Translate(arrow, radius, radius, 0)
|
748
752
|
elif placement.lower() == "upperleft":
|
@@ -756,7 +760,7 @@ class Face(Topology):
|
|
756
760
|
return arrow
|
757
761
|
|
758
762
|
@staticmethod
|
759
|
-
def Circle(origin: topologic.Vertex = None, radius: float = 0.5, sides: int = 16, fromAngle: float = 0.0, toAngle: float = 360.0, direction: list = [0,0,1],
|
763
|
+
def Circle(origin: topologic.Vertex = None, radius: float = 0.5, sides: int = 16, fromAngle: float = 0.0, toAngle: float = 360.0, direction: list = [0, 0, 1],
|
760
764
|
placement: str = "center", tolerance: float = 0.0001) -> topologic.Face:
|
761
765
|
"""
|
762
766
|
Creates a circle.
|
@@ -764,7 +768,7 @@ class Face(Topology):
|
|
764
768
|
Parameters
|
765
769
|
----------
|
766
770
|
origin : topologic.Vertex, optional
|
767
|
-
The location of the origin of the circle. The default is None which results in the circle being placed at (0,0,0).
|
771
|
+
The location of the origin of the circle. The default is None which results in the circle being placed at (0, 0, 0).
|
768
772
|
radius : float , optional
|
769
773
|
The radius of the circle. The default is 1.
|
770
774
|
sides : int , optional
|
@@ -774,7 +778,7 @@ class Face(Topology):
|
|
774
778
|
toAngle : float , optional
|
775
779
|
The angle in degrees at which to end creating the arc of the circle. The default is 360.
|
776
780
|
direction : list , optional
|
777
|
-
The vector representing the up direction of the circle. The default is [0,0,1].
|
781
|
+
The vector representing the up direction of the circle. The default is [0, 0, 1].
|
778
782
|
placement : str , optional
|
779
783
|
The description of the placement of the origin of the circle. This can be "center", "lowerleft", "upperleft", "lowerright", or "upperright". It is case insensitive. The default is "center".
|
780
784
|
tolerance : float , optional
|
@@ -880,19 +884,19 @@ class Face(Topology):
|
|
880
884
|
return edges
|
881
885
|
|
882
886
|
@staticmethod
|
883
|
-
def Einstein(origin: topologic.Vertex = None, radius: float = 0.5, direction: list = [0,0,1],
|
884
|
-
placement: str = "center", tolerance: float=0.0001) -> topologic.Face:
|
887
|
+
def Einstein(origin: topologic.Vertex = None, radius: float = 0.5, direction: list = [0, 0, 1],
|
888
|
+
placement: str = "center", tolerance: float = 0.0001) -> topologic.Face:
|
885
889
|
"""
|
886
890
|
Creates an aperiodic monotile, also called an 'einstein' tile (meaning one tile in German, not the name of the famous physist). See https://arxiv.org/abs/2303.10798
|
887
891
|
|
888
892
|
Parameters
|
889
893
|
----------
|
890
894
|
origin : topologic.Vertex , optional
|
891
|
-
The location of the origin of the tile. The default is None which results in the tiles first vertex being placed at (0,0,0).
|
895
|
+
The location of the origin of the tile. The default is None which results in the tiles first vertex being placed at (0, 0, 0).
|
892
896
|
radius : float , optional
|
893
897
|
The radius of the hexagon determining the size of the tile. The default is 0.5.
|
894
898
|
direction : list , optional
|
895
|
-
The vector representing the up direction of the ellipse. The default is [0,0,1].
|
899
|
+
The vector representing the up direction of the ellipse. The default is [0, 0, 1].
|
896
900
|
placement : str , optional
|
897
901
|
The description of the placement of the origin of the hexagon determining the location of the tile. This can be "center", or "lowerleft". It is case insensitive. The default is "center".
|
898
902
|
tolerance : float , optional
|
@@ -927,7 +931,8 @@ class Face(Topology):
|
|
927
931
|
internal boundaries (holes). For example: [[270,270,270,270], [[270,270,270,270],[300,300,300]]]. If not, the returned list will be
|
928
932
|
a simple list of interior angles of the external boundary. For example: [270,270,270,270]. Please note that that the interior angles of the
|
929
933
|
internal boundaries are considered to be those interior to the original face. Thus, they are exterior to the internal boundary.
|
930
|
-
|
934
|
+
mantissa : int , optional
|
935
|
+
The desired length of the mantissa. The default is 6.
|
931
936
|
Returns
|
932
937
|
-------
|
933
938
|
list
|
@@ -1054,7 +1059,7 @@ class Face(Topology):
|
|
1054
1059
|
return harmonizedFace
|
1055
1060
|
|
1056
1061
|
@staticmethod
|
1057
|
-
def InteriorAngles(face: topologic.Face, includeInternalBoundaries=False, mantissa: int = 6) -> list:
|
1062
|
+
def InteriorAngles(face: topologic.Face, includeInternalBoundaries: bool = False, mantissa: int = 6) -> list:
|
1058
1063
|
"""
|
1059
1064
|
Returns the interior angles of the input face in degrees. The face must be planar.
|
1060
1065
|
|
@@ -1068,7 +1073,8 @@ class Face(Topology):
|
|
1068
1073
|
internal boundaries (holes). For example: [[90,90,90,90], [[90,90,90,90],[60,60,60]]]. If not, the returned list will be
|
1069
1074
|
a simple list of interior angles of the external boundary. For example: [90,90,90,90]. Please note that that the interior angles of the
|
1070
1075
|
internal boundaries are considered to be those interior to the original face. Thus, they are exterior to the internal boundary.
|
1071
|
-
|
1076
|
+
mantissa : int , optional
|
1077
|
+
The desired length of the mantissa. The default is 6.
|
1072
1078
|
Returns
|
1073
1079
|
-------
|
1074
1080
|
list
|
@@ -1269,7 +1275,7 @@ class Face(Topology):
|
|
1269
1275
|
normal = Face.Normal(face)
|
1270
1276
|
flatFace = Topology.Flatten(face, origin=origin, direction=normal)
|
1271
1277
|
|
1272
|
-
# Create a Vertex at the world's origin (0,0,0)
|
1278
|
+
# Create a Vertex at the world's origin (0, 0, 0)
|
1273
1279
|
world_origin = Vertex.Origin()
|
1274
1280
|
|
1275
1281
|
faceEdges = Face.Edges(flatFace)
|
@@ -1592,20 +1598,20 @@ class Face(Topology):
|
|
1592
1598
|
return Face.Rectangle(origin=origin, width=width, length=length, direction = direction, placement=placement, tolerance=tolerance)
|
1593
1599
|
|
1594
1600
|
@staticmethod
|
1595
|
-
def Rectangle(origin: topologic.Vertex = None, width: float = 1.0, length: float = 1.0, direction: list = [0,0,1], placement: str = "center", tolerance: float = 0.0001) -> topologic.Face:
|
1601
|
+
def Rectangle(origin: topologic.Vertex = None, width: float = 1.0, length: float = 1.0, direction: list = [0, 0, 1], placement: str = "center", tolerance: float = 0.0001) -> topologic.Face:
|
1596
1602
|
"""
|
1597
1603
|
Creates a rectangle.
|
1598
1604
|
|
1599
1605
|
Parameters
|
1600
1606
|
----------
|
1601
1607
|
origin : topologic.Vertex, optional
|
1602
|
-
The location of the origin of the rectangle. The default is None which results in the rectangle being placed at (0,0,0).
|
1608
|
+
The location of the origin of the rectangle. The default is None which results in the rectangle being placed at (0, 0, 0).
|
1603
1609
|
width : float , optional
|
1604
1610
|
The width of the rectangle. The default is 1.0.
|
1605
1611
|
length : float , optional
|
1606
1612
|
The length of the rectangle. The default is 1.0.
|
1607
1613
|
direction : list , optional
|
1608
|
-
The vector representing the up direction of the rectangle. The default is [0,0,1].
|
1614
|
+
The vector representing the up direction of the rectangle. The default is [0, 0, 1].
|
1609
1615
|
placement : str , optional
|
1610
1616
|
The description of the placement of the origin of the rectangle. This can be "center", "lowerleft", "upperleft", "lowerright", "upperright". It is case insensitive. The default is "center".
|
1611
1617
|
tolerance : float , optional
|
@@ -1680,18 +1686,18 @@ class Face(Topology):
|
|
1680
1686
|
return Wire.Skeleton(face, tolerance=tolerance)
|
1681
1687
|
|
1682
1688
|
@staticmethod
|
1683
|
-
def Square(origin: topologic.Vertex = None, size: float = 1.0, direction: list = [0,0,1], placement: str = "center", tolerance: float = 0.0001) -> topologic.Face:
|
1689
|
+
def Square(origin: topologic.Vertex = None, size: float = 1.0, direction: list = [0, 0, 1], placement: str = "center", tolerance: float = 0.0001) -> topologic.Face:
|
1684
1690
|
"""
|
1685
1691
|
Creates a square.
|
1686
1692
|
|
1687
1693
|
Parameters
|
1688
1694
|
----------
|
1689
1695
|
origin : topologic.Vertex , optional
|
1690
|
-
The location of the origin of the square. The default is None which results in the square being placed at (0,0,0).
|
1696
|
+
The location of the origin of the square. The default is None which results in the square being placed at (0, 0, 0).
|
1691
1697
|
size : float , optional
|
1692
1698
|
The size of the square. The default is 1.0.
|
1693
1699
|
direction : list , optional
|
1694
|
-
The vector representing the up direction of the square. The default is [0,0,1].
|
1700
|
+
The vector representing the up direction of the square. The default is [0, 0, 1].
|
1695
1701
|
placement : str , optional
|
1696
1702
|
The description of the placement of the origin of the square. This can be "center", "lowerleft", "upperleft", "lowerright", or "upperright". It is case insensitive. The default is "center".
|
1697
1703
|
tolerance : float , optional
|
@@ -1706,14 +1712,14 @@ class Face(Topology):
|
|
1706
1712
|
return Face.Rectangle(origin=origin, width=size, length=size, direction=direction, placement=placement, tolerance=tolerance)
|
1707
1713
|
|
1708
1714
|
@staticmethod
|
1709
|
-
def Star(origin: topologic.Vertex = None, radiusA: float = 1.0, radiusB: float = 0.4, rays: int = 5, direction: list = [0,0,1], placement: str = "center", tolerance: float = 0.0001) -> topologic.Face:
|
1715
|
+
def Star(origin: topologic.Vertex = None, radiusA: float = 1.0, radiusB: float = 0.4, rays: int = 5, direction: list = [0, 0, 1], placement: str = "center", tolerance: float = 0.0001) -> topologic.Face:
|
1710
1716
|
"""
|
1711
1717
|
Creates a star.
|
1712
1718
|
|
1713
1719
|
Parameters
|
1714
1720
|
----------
|
1715
1721
|
origin : topologic.Vertex, optional
|
1716
|
-
The location of the origin of the star. The default is None which results in the star being placed at (0,0,0).
|
1722
|
+
The location of the origin of the star. The default is None which results in the star being placed at (0, 0, 0).
|
1717
1723
|
radiusA : float , optional
|
1718
1724
|
The outer radius of the star. The default is 1.0.
|
1719
1725
|
radiusB : float , optional
|
@@ -1721,7 +1727,7 @@ class Face(Topology):
|
|
1721
1727
|
rays : int , optional
|
1722
1728
|
The number of star rays. The default is 5.
|
1723
1729
|
direction : list , optional
|
1724
|
-
The vector representing the up direction of the star. The default is [0,0,1].
|
1730
|
+
The vector representing the up direction of the star. The default is [0, 0, 1].
|
1725
1731
|
placement : str , optional
|
1726
1732
|
The description of the placement of the origin of the star. This can be "center", "lowerleft", "upperleft", "lowerright", or "upperright". It is case insensitive. The default is "center".
|
1727
1733
|
tolerance : float , optional
|
@@ -1741,14 +1747,14 @@ class Face(Topology):
|
|
1741
1747
|
return Face.ByWire(wire, tolerance=tolerance)
|
1742
1748
|
|
1743
1749
|
@staticmethod
|
1744
|
-
def Trapezoid(origin: topologic.Vertex = None, widthA: float = 1.0, widthB: float = 0.75, offsetA: float = 0.0, offsetB: float = 0.0, length: float = 1.0, direction: list = [0,0,1], placement: str = "center", tolerance: float = 0.0001) -> topologic.Face:
|
1750
|
+
def Trapezoid(origin: topologic.Vertex = None, widthA: float = 1.0, widthB: float = 0.75, offsetA: float = 0.0, offsetB: float = 0.0, length: float = 1.0, direction: list = [0, 0, 1], placement: str = "center", tolerance: float = 0.0001) -> topologic.Face:
|
1745
1751
|
"""
|
1746
1752
|
Creates a trapezoid.
|
1747
1753
|
|
1748
1754
|
Parameters
|
1749
1755
|
----------
|
1750
1756
|
origin : topologic.Vertex, optional
|
1751
|
-
The location of the origin of the trapezoid. The default is None which results in the trapezoid being placed at (0,0,0).
|
1757
|
+
The location of the origin of the trapezoid. The default is None which results in the trapezoid being placed at (0, 0, 0).
|
1752
1758
|
widthA : float , optional
|
1753
1759
|
The width of the bottom edge of the trapezoid. The default is 1.0.
|
1754
1760
|
widthB : float , optional
|
@@ -1760,7 +1766,7 @@ class Face(Topology):
|
|
1760
1766
|
length : float , optional
|
1761
1767
|
The length of the trapezoid. The default is 1.0.
|
1762
1768
|
direction : list , optional
|
1763
|
-
The vector representing the up direction of the trapezoid. The default is [0,0,1].
|
1769
|
+
The vector representing the up direction of the trapezoid. The default is [0, 0, 1].
|
1764
1770
|
placement : str , optional
|
1765
1771
|
The description of the placement of the origin of the trapezoid. This can be "center", or "lowerleft". It is case insensitive. The default is "center".
|
1766
1772
|
tolerance : float , optional
|
@@ -1780,7 +1786,7 @@ class Face(Topology):
|
|
1780
1786
|
return Face.ByWire(wire, tolerance=tolerance)
|
1781
1787
|
|
1782
1788
|
@staticmethod
|
1783
|
-
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:
|
1784
1790
|
"""
|
1785
1791
|
Triangulates the input face and returns a list of faces.
|
1786
1792
|
|
@@ -1790,6 +1796,13 @@ class Face(Topology):
|
|
1790
1796
|
The input face.
|
1791
1797
|
tolerance : float , optional
|
1792
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.
|
1793
1806
|
|
1794
1807
|
Returns
|
1795
1808
|
-------
|
@@ -1803,6 +1816,135 @@ class Face(Topology):
|
|
1803
1816
|
from topologicpy.Topology import Topology
|
1804
1817
|
from topologicpy.Dictionary import Dictionary
|
1805
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
|
+
|
1806
1948
|
if not isinstance(face, topologic.Face):
|
1807
1949
|
print("Face.Triangulate - Error: The input face parameter is not a valid face. Returning None.")
|
1808
1950
|
return None
|
@@ -1812,14 +1954,17 @@ class Face(Topology):
|
|
1812
1954
|
origin = Topology.Centroid(face)
|
1813
1955
|
normal = Face.Normal(face)
|
1814
1956
|
flatFace = Topology.Flatten(face, origin=origin, direction=normal)
|
1815
|
-
|
1816
|
-
|
1817
|
-
|
1818
|
-
|
1819
|
-
|
1820
|
-
|
1821
|
-
|
1822
|
-
|
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
|
1823
1968
|
|
1824
1969
|
if len(shell_faces) < 1:
|
1825
1970
|
return []
|