topologicpy 0.8.31__py3-none-any.whl → 0.8.35__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 +1098 -10
- topologicpy/CellComplex.py +28 -1
- topologicpy/Dictionary.py +119 -0
- topologicpy/Edge.py +16 -0
- topologicpy/Face.py +319 -54
- topologicpy/Graph.py +2 -7
- topologicpy/Helper.py +52 -0
- topologicpy/Shell.py +119 -92
- topologicpy/Topology.py +189 -11
- topologicpy/Vertex.py +1 -1
- topologicpy/Wire.py +66 -31
- topologicpy/version.py +1 -1
- {topologicpy-0.8.31.dist-info → topologicpy-0.8.35.dist-info}/METADATA +1 -1
- {topologicpy-0.8.31.dist-info → topologicpy-0.8.35.dist-info}/RECORD +17 -17
- {topologicpy-0.8.31.dist-info → topologicpy-0.8.35.dist-info}/WHEEL +0 -0
- {topologicpy-0.8.31.dist-info → topologicpy-0.8.35.dist-info}/licenses/LICENSE +0 -0
- {topologicpy-0.8.31.dist-info → topologicpy-0.8.35.dist-info}/top_level.txt +0 -0
topologicpy/Shell.py
CHANGED
@@ -739,42 +739,6 @@ class Shell():
|
|
739
739
|
_ = shell.Faces(None, faces)
|
740
740
|
return faces
|
741
741
|
|
742
|
-
@staticmethod
|
743
|
-
def IsOnBoundary(shell, vertex, tolerance: float = 0.0001) -> bool:
|
744
|
-
"""
|
745
|
-
Returns True if the input vertex is on the boundary of the input shell. Returns False otherwise. On the boundary is defined as being on the boundary of one of the shell's external or internal boundaries
|
746
|
-
|
747
|
-
Parameters
|
748
|
-
----------
|
749
|
-
shell : topologic_core.Shell
|
750
|
-
The input shell.
|
751
|
-
vertex : topologic_core.Vertex
|
752
|
-
The input vertex.
|
753
|
-
tolerance : float , optional
|
754
|
-
The desired tolerance. The default is 0.0001.
|
755
|
-
|
756
|
-
Returns
|
757
|
-
-------
|
758
|
-
bool
|
759
|
-
Returns True if the input vertex is inside the input shell. Returns False otherwise.
|
760
|
-
|
761
|
-
"""
|
762
|
-
from topologicpy.Vertex import Vertex
|
763
|
-
from topologicpy.Topology import Topology
|
764
|
-
|
765
|
-
if not Topology.IsInstance(shell, "Shell"):
|
766
|
-
return None
|
767
|
-
if not Topology.IsInstance(vertex, "Vertex"):
|
768
|
-
return None
|
769
|
-
boundary = Shell.ExternalBoundary(shell, tolerance=tolerance)
|
770
|
-
if Vertex.IsInternal(vertex, boundary, tolerance=tolerance):
|
771
|
-
return True
|
772
|
-
internal_boundaries = Shell.InternalBoundaries(shell, tolerance=tolerance)
|
773
|
-
for ib in internal_boundaries:
|
774
|
-
if Vertex.IsInternal(vertex, ib, tolerance=tolerance):
|
775
|
-
return True
|
776
|
-
return False
|
777
|
-
|
778
742
|
@staticmethod
|
779
743
|
def HyperbolicParaboloidRectangularDomain(origin= None,
|
780
744
|
llVertex= None,
|
@@ -1097,6 +1061,41 @@ class Shell():
|
|
1097
1061
|
"""
|
1098
1062
|
return shell.IsClosed()
|
1099
1063
|
|
1064
|
+
@staticmethod
|
1065
|
+
def IsOnBoundary(shell, vertex, tolerance: float = 0.0001) -> bool:
|
1066
|
+
"""
|
1067
|
+
Returns True if the input vertex is on the boundary of the input shell. Returns False otherwise. On the boundary is defined as being on the boundary of one of the shell's external or internal boundaries
|
1068
|
+
|
1069
|
+
Parameters
|
1070
|
+
----------
|
1071
|
+
shell : topologic_core.Shell
|
1072
|
+
The input shell.
|
1073
|
+
vertex : topologic_core.Vertex
|
1074
|
+
The input vertex.
|
1075
|
+
tolerance : float , optional
|
1076
|
+
The desired tolerance. The default is 0.0001.
|
1077
|
+
|
1078
|
+
Returns
|
1079
|
+
-------
|
1080
|
+
bool
|
1081
|
+
Returns True if the input vertex is inside the input shell. Returns False otherwise.
|
1082
|
+
|
1083
|
+
"""
|
1084
|
+
from topologicpy.Vertex import Vertex
|
1085
|
+
from topologicpy.Topology import Topology
|
1086
|
+
|
1087
|
+
if not Topology.IsInstance(shell, "Shell"):
|
1088
|
+
return None
|
1089
|
+
if not Topology.IsInstance(vertex, "Vertex"):
|
1090
|
+
return None
|
1091
|
+
boundary = Shell.ExternalBoundary(shell, tolerance=tolerance)
|
1092
|
+
if Vertex.IsInternal(vertex, boundary, tolerance=tolerance):
|
1093
|
+
return True
|
1094
|
+
internal_boundaries = Shell.InternalBoundaries(shell, tolerance=tolerance)
|
1095
|
+
for ib in internal_boundaries:
|
1096
|
+
if Vertex.IsInternal(vertex, ib, tolerance=tolerance):
|
1097
|
+
return True
|
1098
|
+
return False
|
1100
1099
|
|
1101
1100
|
@staticmethod
|
1102
1101
|
def Paraboloid(origin= None, focalLength=0.125, width: float = 1, length: float = 1, uSides: int = 16, vSides: int = 16,
|
@@ -1644,62 +1643,6 @@ class Shell():
|
|
1644
1643
|
else:
|
1645
1644
|
return None
|
1646
1645
|
|
1647
|
-
def Skeleton(face, tolerance: float = 0.001):
|
1648
|
-
"""
|
1649
|
-
Creates a shell through a straight skeleton. This method is contributed by 高熙鹏 xipeng gao <gaoxipeng1998@gmail.com>
|
1650
|
-
This algorithm depends on the polyskel code which is included in the library. Polyskel code is found at: https://github.com/Botffy/polyskel
|
1651
|
-
|
1652
|
-
Parameters
|
1653
|
-
----------
|
1654
|
-
face : topologic_core.Face
|
1655
|
-
The input face.
|
1656
|
-
tolerance : float , optional
|
1657
|
-
The desired tolerance. The default is 0.001. (This is set to a larger number as it was found to work better)
|
1658
|
-
|
1659
|
-
Returns
|
1660
|
-
-------
|
1661
|
-
topologic_core.Shell
|
1662
|
-
The created straight skeleton.
|
1663
|
-
|
1664
|
-
"""
|
1665
|
-
from topologicpy.Wire import Wire
|
1666
|
-
from topologicpy.Face import Face
|
1667
|
-
from topologicpy.Topology import Topology
|
1668
|
-
import topologic_core as topologic
|
1669
|
-
import math
|
1670
|
-
|
1671
|
-
if not Topology.IsInstance(face, "Face"):
|
1672
|
-
return None
|
1673
|
-
roof = Wire.Skeleton(face, tolerance=tolerance)
|
1674
|
-
if not (Topology.IsInstance(roof, "Wire") or Topology.IsInstance(roof, "Cluster")):
|
1675
|
-
print("Shell.Skeleton - Error: Could not create base skeleton wire. Returning None.")
|
1676
|
-
return None
|
1677
|
-
br = Wire.BoundingRectangle(roof) #This works even if it is a Cluster not a Wire
|
1678
|
-
if not Topology.IsInstance(br, "Wire"):
|
1679
|
-
print("Shell.Skeleton - Error: Could not create a bounding rectangle wire. Returning None.")
|
1680
|
-
return None
|
1681
|
-
br = Topology.Scale(br, Topology.Centroid(br), 1.5, 1.5, 1)
|
1682
|
-
bf = Face.ByWire(br, tolerance=tolerance)
|
1683
|
-
if not Topology.IsInstance(bf, "Face"):
|
1684
|
-
print("Shell.Skeleton - Error: Could not create a bounding rectangle face. Returning None.")
|
1685
|
-
return None
|
1686
|
-
large_shell = Topology.Boolean(bf, roof, operation="slice", tolerance=tolerance)
|
1687
|
-
if not large_shell:
|
1688
|
-
return None
|
1689
|
-
faces = Topology.Faces(large_shell)
|
1690
|
-
if not faces:
|
1691
|
-
return None
|
1692
|
-
final_faces = []
|
1693
|
-
for f in faces:
|
1694
|
-
internalBoundaries = Face.InternalBoundaries(f)
|
1695
|
-
if len(internalBoundaries) == 0:
|
1696
|
-
final_faces.append(f)
|
1697
|
-
shell = Shell.ByFaces(final_faces, tolerance=tolerance)
|
1698
|
-
if not Topology.IsInstance(shell, "Shell"):
|
1699
|
-
print("Shell.Skeleton - Error: Could not create shell. Returning None.")
|
1700
|
-
return None
|
1701
|
-
return shell
|
1702
|
-
|
1703
1646
|
@staticmethod
|
1704
1647
|
def Simplify(shell, simplifyBoundary: bool = True, mantissa: int = 6, tolerance: float = 0.0001):
|
1705
1648
|
"""
|
@@ -1846,6 +1789,63 @@ class Shell():
|
|
1846
1789
|
final_result = Shell.ByFaces(final_faces, tolerance=tolerance)
|
1847
1790
|
return final_result
|
1848
1791
|
|
1792
|
+
@staticmethod
|
1793
|
+
def Skeleton(face, tolerance: float = 0.001):
|
1794
|
+
"""
|
1795
|
+
Creates a shell through a straight skeleton. This method is contributed by 高熙鹏 xipeng gao <gaoxipeng1998@gmail.com>
|
1796
|
+
This algorithm depends on the polyskel code which is included in the library. Polyskel code is found at: https://github.com/Botffy/polyskel
|
1797
|
+
|
1798
|
+
Parameters
|
1799
|
+
----------
|
1800
|
+
face : topologic_core.Face
|
1801
|
+
The input face.
|
1802
|
+
tolerance : float , optional
|
1803
|
+
The desired tolerance. The default is 0.001. (This is set to a larger number as it was found to work better)
|
1804
|
+
|
1805
|
+
Returns
|
1806
|
+
-------
|
1807
|
+
topologic_core.Shell
|
1808
|
+
The created straight skeleton.
|
1809
|
+
|
1810
|
+
"""
|
1811
|
+
from topologicpy.Wire import Wire
|
1812
|
+
from topologicpy.Face import Face
|
1813
|
+
from topologicpy.Topology import Topology
|
1814
|
+
import topologic_core as topologic
|
1815
|
+
import math
|
1816
|
+
|
1817
|
+
if not Topology.IsInstance(face, "Face"):
|
1818
|
+
return None
|
1819
|
+
roof = Wire.Skeleton(face, tolerance=tolerance)
|
1820
|
+
if not (Topology.IsInstance(roof, "Wire") or Topology.IsInstance(roof, "Cluster")):
|
1821
|
+
print("Shell.Skeleton - Error: Could not create base skeleton wire. Returning None.")
|
1822
|
+
return None
|
1823
|
+
br = Wire.BoundingRectangle(roof) #This works even if it is a Cluster not a Wire
|
1824
|
+
if not Topology.IsInstance(br, "Wire"):
|
1825
|
+
print("Shell.Skeleton - Error: Could not create a bounding rectangle wire. Returning None.")
|
1826
|
+
return None
|
1827
|
+
br = Topology.Scale(br, Topology.Centroid(br), 1.5, 1.5, 1)
|
1828
|
+
bf = Face.ByWire(br, tolerance=tolerance)
|
1829
|
+
if not Topology.IsInstance(bf, "Face"):
|
1830
|
+
print("Shell.Skeleton - Error: Could not create a bounding rectangle face. Returning None.")
|
1831
|
+
return None
|
1832
|
+
large_shell = Topology.Boolean(bf, roof, operation="slice", tolerance=tolerance)
|
1833
|
+
if not large_shell:
|
1834
|
+
return None
|
1835
|
+
faces = Topology.Faces(large_shell)
|
1836
|
+
if not faces:
|
1837
|
+
return None
|
1838
|
+
final_faces = []
|
1839
|
+
for f in faces:
|
1840
|
+
internalBoundaries = Face.InternalBoundaries(f)
|
1841
|
+
if len(internalBoundaries) == 0:
|
1842
|
+
final_faces.append(f)
|
1843
|
+
shell = Shell.ByFaces(final_faces, tolerance=tolerance)
|
1844
|
+
if not Topology.IsInstance(shell, "Shell"):
|
1845
|
+
print("Shell.Skeleton - Error: Could not create shell. Returning None.")
|
1846
|
+
return None
|
1847
|
+
return shell
|
1848
|
+
|
1849
1849
|
@staticmethod
|
1850
1850
|
def Square(origin= None, size: float = 1.0,
|
1851
1851
|
uSides: int = 2, vSides: int = 2, direction: list = [0, 0, 1],
|
@@ -1882,6 +1882,33 @@ class Shell():
|
|
1882
1882
|
uSides=uSides, vSides=vSides, direction=direction,
|
1883
1883
|
placement=placement, tolerance=tolerance)
|
1884
1884
|
|
1885
|
+
@staticmethod
|
1886
|
+
def _grow_connected_group(seed_idx, group_size, adjacency, visited_global):
|
1887
|
+
"""
|
1888
|
+
Attempts to grow a group of the given size starting from seed_idx using adjacency.
|
1889
|
+
Returns a list of indices if successful, else None.
|
1890
|
+
"""
|
1891
|
+
from collections import deque
|
1892
|
+
import random
|
1893
|
+
|
1894
|
+
group = [seed_idx]
|
1895
|
+
visited = set(group)
|
1896
|
+
queue = deque([seed_idx])
|
1897
|
+
|
1898
|
+
while queue and len(group) < group_size:
|
1899
|
+
current = queue.popleft()
|
1900
|
+
neighbors = adjacency.get(current, [])
|
1901
|
+
random.shuffle(neighbors)
|
1902
|
+
for neighbor in neighbors:
|
1903
|
+
if neighbor not in visited and neighbor not in visited_global:
|
1904
|
+
group.append(neighbor)
|
1905
|
+
visited.add(neighbor)
|
1906
|
+
queue.append(neighbor)
|
1907
|
+
if len(group) >= group_size:
|
1908
|
+
break
|
1909
|
+
|
1910
|
+
return group if len(group) == group_size else None
|
1911
|
+
|
1885
1912
|
@staticmethod
|
1886
1913
|
def Vertices(shell) -> list:
|
1887
1914
|
"""
|
topologicpy/Topology.py
CHANGED
@@ -7897,13 +7897,6 @@ class Topology():
|
|
7897
7897
|
calframe = inspect.getouterframes(curframe, 2)
|
7898
7898
|
print('caller name:', calframe[1][3])
|
7899
7899
|
return topology
|
7900
|
-
if len(dictionary.Keys()) < 1:
|
7901
|
-
if not silent:
|
7902
|
-
print("Topology.SetDictionary - Warning: the input dictionary parameter is empty. Returning original input.")
|
7903
|
-
curframe = inspect.currentframe()
|
7904
|
-
calframe = inspect.getouterframes(curframe, 2)
|
7905
|
-
print('caller name:', calframe[1][3])
|
7906
|
-
return topology
|
7907
7900
|
_ = topology.SetDictionary(dictionary)
|
7908
7901
|
return topology
|
7909
7902
|
|
@@ -8861,6 +8854,177 @@ class Topology():
|
|
8861
8854
|
pass
|
8862
8855
|
return returnTopology
|
8863
8856
|
|
8857
|
+
@staticmethod
|
8858
|
+
def SubCombinations(topology,
|
8859
|
+
subTopologyType=None,
|
8860
|
+
minSize: int = 2,
|
8861
|
+
maxSize: int = None,
|
8862
|
+
maxCombinations: int = 100,
|
8863
|
+
timeLimit: int = 10,
|
8864
|
+
removeCoplanarFaces: bool = False,
|
8865
|
+
removeCollinearEdges: bool = False,
|
8866
|
+
tolerance: float = 0.001,
|
8867
|
+
silent: bool = False):
|
8868
|
+
"""
|
8869
|
+
Creates connected sub-combination topologies of the input topology. Warning: This is prone to combinatorial explosion.
|
8870
|
+
|
8871
|
+
Parameters
|
8872
|
+
----------
|
8873
|
+
topology : topologic_core.Topology
|
8874
|
+
The input topology. This cannot be vertex or edge.
|
8875
|
+
subTopologyType : str , optional except when topology is a Cluster
|
8876
|
+
The type of subTopology to include in the combinations.
|
8877
|
+
If the input is a Cluster, you must specify the subTopologyType.
|
8878
|
+
The options are (case insensitive):
|
8879
|
+
- "CellComplex"
|
8880
|
+
- "Shell"
|
8881
|
+
- "Wire"
|
8882
|
+
If set to None, it will be set according to the input topology type as follows:
|
8883
|
+
- "Cluster" -> User-defined
|
8884
|
+
- "CellComplex" -> "CellComplexes"
|
8885
|
+
- "Cell" -> "Shells"
|
8886
|
+
- "Shell" -> "Shells"
|
8887
|
+
- "Face" -> "Wires"
|
8888
|
+
- "Wire" -> "Wires"
|
8889
|
+
- "Edge" -> None
|
8890
|
+
- "Vertex" -> None
|
8891
|
+
- "Graph" -> "Graphs"
|
8892
|
+
minSize : int , optional
|
8893
|
+
The minimum number of subtopologies to include in a combination. This number cannot be less than 2. The default is 2.
|
8894
|
+
maxSize : int , optional
|
8895
|
+
The maximum number of faces to include in a combinations. This number cannot be less than the number of subtopologies minus 1. The default is None which means the maximum will be set to the number of subtopologies minus 1.
|
8896
|
+
maxCombinations : int , optional
|
8897
|
+
The maximum number of combinations to create. The default is 100.
|
8898
|
+
timeLimit : int , optional
|
8899
|
+
The time limit in seconds. The default is 10 seconds. Note that this time limit only applies to creating the combination indices and not the actual Shells.
|
8900
|
+
removeCoplanarFaces : bool , optional
|
8901
|
+
If set to True, coplanar faces are removed. Otherwise they are not. The default is False.
|
8902
|
+
removeCollinearEdges : bool , optional
|
8903
|
+
If set to True, collinear edges are removed. Otherwise they are not. The default is False.
|
8904
|
+
tolerance : float , optional
|
8905
|
+
The desired tolerance. The default is 0.0001.
|
8906
|
+
silent : bool , optional
|
8907
|
+
If set to True, no error and warning messages are printed. Otherwise, they are. The default is False.
|
8908
|
+
|
8909
|
+
Returns
|
8910
|
+
-------
|
8911
|
+
list
|
8912
|
+
The list of created sub-combinations.
|
8913
|
+
|
8914
|
+
"""
|
8915
|
+
from topologicpy.Cluster import Cluster
|
8916
|
+
from topologicpy.Graph import Graph
|
8917
|
+
from topologicpy.Topology import Topology
|
8918
|
+
from topologicpy.Dictionary import Dictionary
|
8919
|
+
from topologicpy.Helper import Helper
|
8920
|
+
import random
|
8921
|
+
import time
|
8922
|
+
|
8923
|
+
if Topology.IsInstance(topology, "cluster") and subTopologyType is None:
|
8924
|
+
if not silent:
|
8925
|
+
print("Topology.SubCombinations - Error: The topology input parameter is a cluster but the subTopologyType is not specified. Returning None.")
|
8926
|
+
return None
|
8927
|
+
|
8928
|
+
if Topology.IsInstance(topology, "vertex") or Topology.IsInstance(topology, "edge"):
|
8929
|
+
if not silent:
|
8930
|
+
print("Topology.SubCombinations - Error: The topology input parameter cannot be a vertex or an edge. Returning None.")
|
8931
|
+
return None
|
8932
|
+
|
8933
|
+
mapping = {
|
8934
|
+
"cellcomplex": "cell",
|
8935
|
+
"cell": "face",
|
8936
|
+
"shell": "face",
|
8937
|
+
"face": "edge",
|
8938
|
+
"wire": "edge",
|
8939
|
+
"graph": "vertex"
|
8940
|
+
}
|
8941
|
+
|
8942
|
+
type_string = Topology.TypeAsString(topology).lower()
|
8943
|
+
if type_string not in mapping:
|
8944
|
+
if not silent:
|
8945
|
+
print(f"Topology.SubCombinations - Error: The input topology type ({type_string}) is not supported. Returning None.")
|
8946
|
+
return None
|
8947
|
+
|
8948
|
+
if subTopologyType is None:
|
8949
|
+
subTopologyType = mapping[type_string]
|
8950
|
+
subTopologyType = subTopologyType.lower()
|
8951
|
+
|
8952
|
+
if subTopologyType not in ["cell", "face", "edge", "vertex"]:
|
8953
|
+
if not silent:
|
8954
|
+
print(f"Topology.SubCombinations - Error: Unknown subTopologyType: {subTopologyType}. Returning None.")
|
8955
|
+
return None
|
8956
|
+
|
8957
|
+
if ((type_string in ["cell", "shell"]) and subTopologyType not in ["face", "edge"]) or \
|
8958
|
+
((type_string in ["wire", "face"]) and subTopologyType != "edge"):
|
8959
|
+
if not silent:
|
8960
|
+
print(f"Topology.SubCombinations - Error: The subTopology type {subTopologyType} is not appropriate for topology of type {type_string}. Returning None.")
|
8961
|
+
return None
|
8962
|
+
|
8963
|
+
all_subtopologies = Topology.SubTopologies(topology, subTopologyType=subTopologyType, silent=silent)
|
8964
|
+
num_subtopologies = len(all_subtopologies)
|
8965
|
+
if num_subtopologies < 2:
|
8966
|
+
if not silent:
|
8967
|
+
print("Topology.SubCombinations - Warning: Not enough subtopologies found. Returning empty list.")
|
8968
|
+
return []
|
8969
|
+
|
8970
|
+
indices = list(range(num_subtopologies))
|
8971
|
+
minSize = max(2, minSize)
|
8972
|
+
maxSize = num_subtopologies - 1 if maxSize is None else min(maxSize, num_subtopologies - 1)
|
8973
|
+
|
8974
|
+
subt_label_key = "__index__"
|
8975
|
+
all_subtopologies = [Topology.SetDictionary(subt, Dictionary.ByKeyValue(subt_label_key, i)) for i, subt in enumerate(all_subtopologies)]
|
8976
|
+
|
8977
|
+
group_sizes = list(range(minSize, maxSize + 1))
|
8978
|
+
num_sizes = len(group_sizes)
|
8979
|
+
per_size_combinations = maxCombinations // num_sizes
|
8980
|
+
per_size_time = timeLimit / num_sizes
|
8981
|
+
|
8982
|
+
adjacency = Dictionary.AdjacencyDictionary(topology, subTopologyType=subTopologyType, labelKey=subt_label_key, weightKey=None, includeWeights=False)
|
8983
|
+
|
8984
|
+
results = []
|
8985
|
+
seen_groups = set()
|
8986
|
+
|
8987
|
+
for group_size in reversed(group_sizes):
|
8988
|
+
size_start_time = time.time()
|
8989
|
+
remaining = per_size_combinations
|
8990
|
+
tries = 0
|
8991
|
+
max_tries = per_size_combinations * 10
|
8992
|
+
|
8993
|
+
while remaining > 0 and (time.time() - size_start_time) < per_size_time and tries < max_tries:
|
8994
|
+
random.shuffle(indices)
|
8995
|
+
for seed in indices:
|
8996
|
+
if (time.time() - size_start_time) > per_size_time:
|
8997
|
+
break
|
8998
|
+
group = Helper.Grow(seed, group_size, adjacency, visited_global=seen_groups)
|
8999
|
+
if group:
|
9000
|
+
key = tuple(sorted(group))
|
9001
|
+
if key not in seen_groups:
|
9002
|
+
tries += 1
|
9003
|
+
seen_groups.add(key)
|
9004
|
+
results.append(group)
|
9005
|
+
remaining -= 1
|
9006
|
+
if remaining <= 0 or tries >= max_tries:
|
9007
|
+
break
|
9008
|
+
|
9009
|
+
return_combinations = []
|
9010
|
+
for result in reversed(results):
|
9011
|
+
subtopologies = [all_subtopologies[i] for i in result]
|
9012
|
+
# Special case for graphs
|
9013
|
+
if Topology.IsInstance(topology, "Graph"):
|
9014
|
+
edges = Graph.Edges(topology, vertices = subtopologies)
|
9015
|
+
combination = Graph.ByVerticesEdges(subtopologies, edges)
|
9016
|
+
else:
|
9017
|
+
combination = Topology.SelfMerge(Cluster.ByTopologies(subtopologies), tolerance=tolerance)
|
9018
|
+
if removeCollinearEdges:
|
9019
|
+
if Topology.IsInstance(combination, "face") or Topology.IsInstance(combination, "wire"):
|
9020
|
+
combination = Topology.RemoveCollinearEdges(combination, tolerance=tolerance)
|
9021
|
+
if removeCoplanarFaces:
|
9022
|
+
if Topology.IsInstance(combination, "cellcomplex") or Topology.IsInstance(combination, "cell") or Topology.IsInstance(combination, "shell"):
|
9023
|
+
combination = Topology.RemoveCoplanarFaces(combination, tolerance=tolerance)
|
9024
|
+
return_combinations.append(combination)
|
9025
|
+
|
9026
|
+
return return_combinations
|
9027
|
+
|
8864
9028
|
@staticmethod
|
8865
9029
|
def Taper(topology, origin=None, ratioRange: list = [0, 1], triangulate: bool = False, mantissa: int = 6, tolerance: float = 0.0001):
|
8866
9030
|
"""
|
@@ -9188,7 +9352,7 @@ class Topology():
|
|
9188
9352
|
return Topology.SubTopologies(topology=topology, subTopologyType="cluster")
|
9189
9353
|
|
9190
9354
|
@staticmethod
|
9191
|
-
def SubTopologies(topology, subTopologyType="vertex"):
|
9355
|
+
def SubTopologies(topology, subTopologyType="vertex", silent: bool = False):
|
9192
9356
|
"""
|
9193
9357
|
Returns the subtopologies of the input topology as specified by the subTopologyType input string.
|
9194
9358
|
|
@@ -9198,7 +9362,8 @@ class Topology():
|
|
9198
9362
|
The input topology.
|
9199
9363
|
subTopologyType : str , optional
|
9200
9364
|
The requested subtopology type. This can be one of "vertex", "edge", "wire", "face", "shell", "cell", "cellcomplex", "cluster". It is case insensitive. The default is "vertex".
|
9201
|
-
|
9365
|
+
silent : bool , optional
|
9366
|
+
If set to True, no warnings or errors will be printed. The default is False.
|
9202
9367
|
Returns
|
9203
9368
|
-------
|
9204
9369
|
list
|
@@ -9206,15 +9371,28 @@ class Topology():
|
|
9206
9371
|
|
9207
9372
|
"""
|
9208
9373
|
from topologicpy.Face import Face
|
9374
|
+
from topologicpy.Graph import Graph
|
9209
9375
|
|
9210
|
-
if not Topology.IsInstance(topology, "Topology"):
|
9211
|
-
|
9376
|
+
if not Topology.IsInstance(topology, "Topology") and not Topology.IsInstance(topology, "Graph"):
|
9377
|
+
if not silent:
|
9378
|
+
print("Topology.SubTopologies - Error: the input topology parameter is not a valid topology. Returning None.")
|
9212
9379
|
return None
|
9213
9380
|
if Topology.TypeAsString(topology).lower() == subTopologyType.lower():
|
9214
9381
|
return [topology]
|
9215
9382
|
|
9216
9383
|
subTopologies = []
|
9217
9384
|
|
9385
|
+
# Special case for Graphs
|
9386
|
+
if Topology.IsInstance(topology, "graph"):
|
9387
|
+
if subTopologyType.lower() == "vertex":
|
9388
|
+
return Graph.Vertices(topology)
|
9389
|
+
elif subTopologyType.lower() == "edge":
|
9390
|
+
return Graph.Edges(topology)
|
9391
|
+
else:
|
9392
|
+
if not silent:
|
9393
|
+
print(f"Topology.SubTopologies - Error: the input subTopologyType parameter {subTopologyType} is not a valid subTopology of Graphs. Returning None.")
|
9394
|
+
return None
|
9395
|
+
|
9218
9396
|
# Spcecial case for faces to return vertices in CW/CCW order.
|
9219
9397
|
if Topology.IsInstance(topology, "face") and (subTopologyType.lower() == "vertex" or subTopologyType.lower() == "edge"):
|
9220
9398
|
wires = Face.Wires(topology)
|
topologicpy/Vertex.py
CHANGED
@@ -726,7 +726,7 @@ class Vertex():
|
|
726
726
|
return None
|
727
727
|
|
728
728
|
@staticmethod
|
729
|
-
def
|
729
|
+
def EnclosingCells(vertex, topology, exclusive: bool = True, mantissa: int = 6, tolerance: float = 0.0001) -> list:
|
730
730
|
"""
|
731
731
|
Returns the list of Cells found in the input topology that enclose the input vertex.
|
732
732
|
|