topologicpy 0.8.30__py3-none-any.whl → 0.8.33__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 +5 -3
- topologicpy/CSG.py +1 -1
- topologicpy/Cell.py +1105 -12
- topologicpy/CellComplex.py +213 -1
- topologicpy/Cluster.py +4 -2
- topologicpy/Edge.py +61 -28
- topologicpy/Face.py +384 -101
- topologicpy/Graph.py +149 -2
- topologicpy/Plotly.py +0 -1
- topologicpy/ShapeGrammar.py +65 -6
- topologicpy/Topology.py +56 -416
- topologicpy/Vertex.py +1 -1
- topologicpy/Wire.py +95 -45
- topologicpy/version.py +1 -1
- {topologicpy-0.8.30.dist-info → topologicpy-0.8.33.dist-info}/METADATA +1 -1
- {topologicpy-0.8.30.dist-info → topologicpy-0.8.33.dist-info}/RECORD +19 -19
- {topologicpy-0.8.30.dist-info → topologicpy-0.8.33.dist-info}/WHEEL +1 -1
- {topologicpy-0.8.30.dist-info → topologicpy-0.8.33.dist-info}/licenses/LICENSE +0 -0
- {topologicpy-0.8.30.dist-info → topologicpy-0.8.33.dist-info}/top_level.txt +0 -0
topologicpy/CellComplex.py
CHANGED
@@ -48,6 +48,99 @@ except:
|
|
48
48
|
warnings.warn("CellComplex - Error: Could not import scipy.")
|
49
49
|
|
50
50
|
class CellComplex():
|
51
|
+
@staticmethod
|
52
|
+
def AdjacencyDictionary(cellComplex, cellLabelKey: str = None, faceKey: str = None, includeWeights: bool = False, reverse: bool = False, mantissa: int = 6, silent: bool = False):
|
53
|
+
"""
|
54
|
+
Returns the adjacency dictionary of the input Graph.
|
55
|
+
|
56
|
+
Parameters
|
57
|
+
----------
|
58
|
+
cellComplex : topologic_core.CellComplex
|
59
|
+
The input cellComplex.
|
60
|
+
cellLabelKey : str , optional
|
61
|
+
The returned cells are labelled according to the dictionary values stored under this key.
|
62
|
+
If the cellLabelKey does not exist, it will be created and the cells are labelled numerically and stored in the vertex dictionary under this key. The default is None.
|
63
|
+
faceKey : str , optional
|
64
|
+
If set, the faces' dictionaries will be searched for this key to set their weight. If the key is set to "Area" (case insensitive), the area of the shared faces will be used as its weight. If set to None, a weight of 1 will be used. The default is None.
|
65
|
+
includeWeights : bool , optional
|
66
|
+
If set to True, edge weights are included. Otherwise, they are not. The default is False.
|
67
|
+
reverse : bool , optional
|
68
|
+
If set to True, the cells are sorted in reverse order (only if cellLabelKey is set). Otherwise, they are not. The default is False.
|
69
|
+
|
70
|
+
silent : bool , optional
|
71
|
+
If set to True, no error and warning messages are printed. Otherwise, they are. The default is False.
|
72
|
+
|
73
|
+
Returns
|
74
|
+
-------
|
75
|
+
dict
|
76
|
+
The adjacency dictionary.
|
77
|
+
"""
|
78
|
+
from topologicpy.Face import Face
|
79
|
+
from topologicpy.Dictionary import Dictionary
|
80
|
+
from topologicpy.Topology import Topology
|
81
|
+
from topologicpy.Helper import Helper
|
82
|
+
|
83
|
+
if not Topology.IsInstance(cellComplex, "CellComplex"):
|
84
|
+
if not silent:
|
85
|
+
print("CellComplex.AdjacencyDictionary - Error: The input cellComplex input parameter is not a valid cellComplex. Returning None.")
|
86
|
+
return None
|
87
|
+
if cellLabelKey == None:
|
88
|
+
cellLabelKey = "__label__"
|
89
|
+
if not isinstance(cellLabelKey, str):
|
90
|
+
if not silent:
|
91
|
+
print("CellComplex.AdjacencyDictionary - Error: The input cellLabelKey is not a valid string. Returning None.")
|
92
|
+
return None
|
93
|
+
all_cells = Topology.Cells(cellComplex)
|
94
|
+
labels = []
|
95
|
+
n = max(len(str(len(all_cells))), 3)
|
96
|
+
for i, cell in enumerate(all_cells):
|
97
|
+
d = Topology.Dictionary(cell)
|
98
|
+
value = Dictionary.ValueAtKey(d, cellLabelKey)
|
99
|
+
if value == None:
|
100
|
+
value = str(i+1).zfill(n)
|
101
|
+
if d == None:
|
102
|
+
d = Dictionary.ByKeyValue(cellLabelKey, value)
|
103
|
+
else:
|
104
|
+
d = Dictionary.SetValueAtKey(d, cellLabelKey, value)
|
105
|
+
cell = Topology.SetDictionary(cell, d)
|
106
|
+
labels.append(value)
|
107
|
+
all_cells = Helper.Sort(all_cells, labels)
|
108
|
+
labels.sort()
|
109
|
+
order = len(all_cells)
|
110
|
+
adjDict = {}
|
111
|
+
for i in range(order):
|
112
|
+
cell = all_cells[i]
|
113
|
+
cell_label = labels[i]
|
114
|
+
adjCells = Topology.AdjacentTopologies(cell, hostTopology=cellComplex, topologyType="cell")
|
115
|
+
temp_list = []
|
116
|
+
for adjCell in adjCells:
|
117
|
+
adj_label = Dictionary.ValueAtKey(Topology.Dictionary(adjCell), cellLabelKey)
|
118
|
+
adj_index = labels.index(adj_label)
|
119
|
+
if includeWeights == True:
|
120
|
+
if faceKey == None:
|
121
|
+
weight = 1
|
122
|
+
elif "area" in faceKey.lower():
|
123
|
+
shared_topologies = Topology.SharedTopologies(cell, adjCell)
|
124
|
+
faces = shared_topologies.get("faces", [])
|
125
|
+
weight = sum([Face.Area(face, mantissa=mantissa) for face in faces])
|
126
|
+
else:
|
127
|
+
shared_topologies = Topology.SharedTopologies(cell, adjCell)
|
128
|
+
faces = shared_topologies.get("faces", [])
|
129
|
+
weight = sum([Dictionary.ValueAtKey(Topology.Dictionary(face),faceKey, 0) for face in faces])
|
130
|
+
if not adj_index == None:
|
131
|
+
temp_list.append((adj_label, weight))
|
132
|
+
else:
|
133
|
+
if not adj_index == None:
|
134
|
+
temp_list.append(adj_label)
|
135
|
+
temp_list.sort()
|
136
|
+
adjDict[cell_label] = temp_list
|
137
|
+
if cellLabelKey == "__label__": # This is label we added, so remove it
|
138
|
+
for cell in all_cells:
|
139
|
+
d = Topology.Dictionary(cell)
|
140
|
+
d = Dictionary.RemoveKey(d, cellLabelKey)
|
141
|
+
cell = Topology.SetDictionary(cell, d)
|
142
|
+
return adjDict
|
143
|
+
|
51
144
|
@staticmethod
|
52
145
|
def Box(origin= None,
|
53
146
|
width: float = 1.0, length: float = 1.0, height: float = 1.0,
|
@@ -159,7 +252,7 @@ class CellComplex():
|
|
159
252
|
if transferDictionaries == True:
|
160
253
|
for temp_cell in temp_cells:
|
161
254
|
v = Topology.InternalVertex(temp_cell, tolerance=tolerance)
|
162
|
-
enclosing_cells = Vertex.
|
255
|
+
enclosing_cells = Vertex.EnclosingCells(v, cluster)
|
163
256
|
dictionaries = [Topology.Dictionary(ec) for ec in enclosing_cells]
|
164
257
|
d = Dictionary.ByMergedDictionaries(dictionaries, silent=silent)
|
165
258
|
temp_cell = Topology.SetDictionary(temp_cell, d)
|
@@ -1050,6 +1143,125 @@ class CellComplex():
|
|
1050
1143
|
shells = Topology.Shells(cellComplex)
|
1051
1144
|
return shells
|
1052
1145
|
|
1146
|
+
|
1147
|
+
def _grow_connected_group(seed_idx, group_size, adjacency, visited_global):
|
1148
|
+
"""
|
1149
|
+
Attempts to grow a group of the given size starting from seed_idx using adjacency.
|
1150
|
+
Returns a list of indices if successful, else None.
|
1151
|
+
"""
|
1152
|
+
from collections import deque
|
1153
|
+
import random
|
1154
|
+
|
1155
|
+
group = [seed_idx]
|
1156
|
+
visited = set(group)
|
1157
|
+
queue = deque([seed_idx])
|
1158
|
+
|
1159
|
+
while queue and len(group) < group_size:
|
1160
|
+
current = queue.popleft()
|
1161
|
+
neighbors = adjacency.get(current, [])
|
1162
|
+
random.shuffle(neighbors)
|
1163
|
+
for neighbor in neighbors:
|
1164
|
+
if neighbor not in visited and neighbor not in visited_global:
|
1165
|
+
group.append(neighbor)
|
1166
|
+
visited.add(neighbor)
|
1167
|
+
queue.append(neighbor)
|
1168
|
+
if len(group) >= group_size:
|
1169
|
+
break
|
1170
|
+
|
1171
|
+
return group if len(group) == group_size else None
|
1172
|
+
|
1173
|
+
def SubCombinations(cellComplex,
|
1174
|
+
minCells: int = 2,
|
1175
|
+
maxCells: int = None,
|
1176
|
+
maxCombinations: int = 100,
|
1177
|
+
timeLimit: int = 10,
|
1178
|
+
silent: bool = False):
|
1179
|
+
"""
|
1180
|
+
Creates sub-combination cellComplexes of the input cellComplex. Warning: This is prone to combinatorial explosion.
|
1181
|
+
|
1182
|
+
Parameters
|
1183
|
+
----------
|
1184
|
+
cellComplex : topologic_core.cellComplex
|
1185
|
+
The input cellComplex
|
1186
|
+
minCells : int , optional
|
1187
|
+
The minimum number of cells to include in a combination. The default is 2.
|
1188
|
+
maxCells : int , optional
|
1189
|
+
The maximum number of cells to include in a combinations. The default is None which means the maximum will be set to the number of cells in the cellComplex minus 1.
|
1190
|
+
maxCombinations : int , optional
|
1191
|
+
The maximum number of combinations to create. The default is 100.
|
1192
|
+
timeLimit : int , optional
|
1193
|
+
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 CellComplexes.
|
1194
|
+
tolerance : float , optional
|
1195
|
+
The tolerance for computing if the input vertex is external to the input topology. The default is 0.0001.
|
1196
|
+
silent : bool , optional
|
1197
|
+
If set to True, no error and warning messages are printed. Otherwise, they are. The default is False.
|
1198
|
+
|
1199
|
+
Returns
|
1200
|
+
-------
|
1201
|
+
list
|
1202
|
+
The list of created CellComplex sub-combinations.
|
1203
|
+
|
1204
|
+
"""
|
1205
|
+
from topologicpy.Cluster import Cluster
|
1206
|
+
from topologicpy.Topology import Topology
|
1207
|
+
from topologicpy.Dictionary import Dictionary
|
1208
|
+
import random
|
1209
|
+
import time
|
1210
|
+
|
1211
|
+
if not Topology.IsInstance(cellComplex, "CellComplex"):
|
1212
|
+
if not silent:
|
1213
|
+
print("CellComplex.SubCombinations - Error: The cellComplex input parameter is not a valid cellComplex. Returning None.")
|
1214
|
+
return None
|
1215
|
+
|
1216
|
+
|
1217
|
+
start_time = time.time()
|
1218
|
+
all_cells = CellComplex.Cells(cellComplex)
|
1219
|
+
num_cells = len(all_cells)
|
1220
|
+
indices = list(range(num_cells))
|
1221
|
+
cell_label_key = "index"
|
1222
|
+
# 1. Assign a unique index to each cell's dictionary
|
1223
|
+
all_cells = [Topology.SetDictionary(cell, Dictionary.ByKeyValue(cell_label_key, i)) for i, cell in enumerate(all_cells)]
|
1224
|
+
if maxCells == None:
|
1225
|
+
maxCells = len(all_cells) - 1
|
1226
|
+
# 2. Allocate counts per group size
|
1227
|
+
group_sizes = list(range(minCells, maxCells + 1))
|
1228
|
+
combinations_per_size = maxCombinations // len(group_sizes)
|
1229
|
+
|
1230
|
+
# 3. Build adjacency dict
|
1231
|
+
adjacency = CellComplex.AdjacencyDictionary(cellComplex, cellLabelKey=cell_label_key, faceKey=None, includeWeights=False)
|
1232
|
+
|
1233
|
+
results = []
|
1234
|
+
seen_groups = set() # sets of sorted indices
|
1235
|
+
|
1236
|
+
# 4. Start from longest group size
|
1237
|
+
for group_size in reversed(group_sizes):
|
1238
|
+
remaining = combinations_per_size
|
1239
|
+
tries = 0
|
1240
|
+
max_tries = combinations_per_size * 10 # fallback guard
|
1241
|
+
while remaining > 0 and time.time() - start_time < timeLimit and tries < max_tries:
|
1242
|
+
random.shuffle(indices)
|
1243
|
+
for seed in indices:
|
1244
|
+
if time.time() - start_time > timeLimit:
|
1245
|
+
break
|
1246
|
+
group = CellComplex._grow_connected_group(seed, group_size, adjacency, visited_global=seen_groups)
|
1247
|
+
if group:
|
1248
|
+
key = tuple(sorted(group))
|
1249
|
+
if key not in seen_groups:
|
1250
|
+
tries += 1
|
1251
|
+
seen_groups.add(key)
|
1252
|
+
results.append(group)
|
1253
|
+
remaining -= 1
|
1254
|
+
if remaining <= 0 or tries >= max_tries:
|
1255
|
+
break
|
1256
|
+
# 5. Build CellComplex SubCombinations
|
1257
|
+
return_combinations = []
|
1258
|
+
for i, result in enumerate(reversed(results)):
|
1259
|
+
cells = [all_cells[i] for i in result]
|
1260
|
+
combination = Topology.SelfMerge(Cluster.ByTopologies(cells))
|
1261
|
+
if Topology.IsInstance(combination, "CellComplex"):
|
1262
|
+
return_combinations.append(combination)
|
1263
|
+
return return_combinations
|
1264
|
+
|
1053
1265
|
@staticmethod
|
1054
1266
|
def Tetrahedron(origin = None, length: float = 1, depth: int = 1, direction=[0,0,1], placement="center", mantissa: int = 6, tolerance: float = 0.0001, silent: bool = False):
|
1055
1267
|
"""
|
topologicpy/Cluster.py
CHANGED
@@ -1105,7 +1105,7 @@ class Cluster():
|
|
1105
1105
|
return Cluster.ByTopologies(cellComplexes+cells)
|
1106
1106
|
|
1107
1107
|
@staticmethod
|
1108
|
-
def MysticRose(wire= None, origin= None, radius: float = 0.5, sides: int = 16, perimeter: bool = True, direction: list = [0, 0, 1], placement:str = "center", tolerance: float = 0.0001):
|
1108
|
+
def MysticRose(wire= None, origin= None, radius: float = 0.5, sides: int = 16, perimeter: bool = True, direction: list = [0, 0, 1], placement:str = "center", tolerance: float = 0.0001, silent: bool = False):
|
1109
1109
|
"""
|
1110
1110
|
Creates a mystic rose.
|
1111
1111
|
|
@@ -1127,6 +1127,8 @@ class Cluster():
|
|
1127
1127
|
The description of the placement of the origin of the mystic rose. This can be "center", or "lowerleft". It is case insensitive. The default is "center".
|
1128
1128
|
tolerance : float , optional
|
1129
1129
|
The desired tolerance. The default is 0.0001.
|
1130
|
+
silent : bool , optional
|
1131
|
+
If set to True, no error and warning messages are printed. Otherwise, they are. The default is False.
|
1130
1132
|
|
1131
1133
|
Returns
|
1132
1134
|
-------
|
@@ -1153,7 +1155,7 @@ class Cluster():
|
|
1153
1155
|
if perimeter:
|
1154
1156
|
edges = Wire.Edges(wire)
|
1155
1157
|
for comb in combs:
|
1156
|
-
edges.append(Edge.ByVertices([vertices[comb[0]], vertices[comb[1]]], tolerance=tolerance))
|
1158
|
+
edges.append(Edge.ByVertices([vertices[comb[0]], vertices[comb[1]]], tolerance=tolerance, silent=silent))
|
1157
1159
|
return Cluster.ByTopologies(edges)
|
1158
1160
|
|
1159
1161
|
@staticmethod
|
topologicpy/Edge.py
CHANGED
@@ -114,7 +114,7 @@ class Edge():
|
|
114
114
|
return round(ang, mantissa)
|
115
115
|
|
116
116
|
@staticmethod
|
117
|
-
def Bisect(edgeA, edgeB, length: float = 1.0, placement: int = 0, tolerance: float = 0.0001):
|
117
|
+
def Bisect(edgeA, edgeB, length: float = 1.0, placement: int = 0, tolerance: float = 0.0001, silent: bool = False):
|
118
118
|
"""
|
119
119
|
Creates a bisecting edge between edgeA and edgeB.
|
120
120
|
|
@@ -134,6 +134,8 @@ class Edge():
|
|
134
134
|
If set to any number other than 0, 1, or 2, the bisecting edge centroid will be placed at the end vertex of the first edge. The default is 0.
|
135
135
|
tolerance : float , optional
|
136
136
|
The desired tolerance to decide if an Edge can be created. The default is 0.0001.
|
137
|
+
silent : bool , optional
|
138
|
+
If set to True, no error and warning messages are printed. Otherwise, they are. The default is False.
|
137
139
|
|
138
140
|
Returns
|
139
141
|
-------
|
@@ -171,29 +173,34 @@ class Edge():
|
|
171
173
|
return edge1, edge2
|
172
174
|
|
173
175
|
if not Topology.IsInstance(edgeA, "Edge"):
|
174
|
-
|
176
|
+
if not silent:
|
177
|
+
print("Edge.Bisect - Error: The input edgeA parameter is not a valid topologic edge. Returning None.")
|
175
178
|
return None
|
176
179
|
if not Topology.IsInstance(edgeB, "Edge"):
|
177
|
-
|
180
|
+
if not silent:
|
181
|
+
print("Edge.Bisect - Error: The input edgeB parameter is not a valid topologic edge. Returning None.")
|
178
182
|
return None
|
179
183
|
if Edge.Length(edgeA) <= tolerance:
|
180
|
-
|
184
|
+
if not silent:
|
185
|
+
print("Edge.Bisect - Error: The input edgeA parameter is shorter than the input tolerance parameter. Returning None.")
|
181
186
|
return None
|
182
187
|
if Edge.Length(edgeB) <= tolerance:
|
183
|
-
|
188
|
+
if not silent:
|
189
|
+
print("Edge.Bisect - Error: The input edgeB parameter is shorter than the input tolerance parameter. Returning None.")
|
184
190
|
return None
|
185
191
|
|
186
192
|
|
187
193
|
edge1, edge2 = process_edges(edgeA, edgeB, tolerance=tolerance)
|
188
194
|
if edge1 == None or edge2 == None:
|
189
|
-
|
195
|
+
if not silent:
|
196
|
+
print("Edge.Bisect - Error: The input edgeA and edgeB parameters do not share a vertex and thus cannot be bisected. Returning None.")
|
190
197
|
return None
|
191
198
|
sv = Edge.StartVertex(edge1)
|
192
199
|
dir1 = Edge.Direction(edge1)
|
193
200
|
dir2 = Edge.Direction(edge2)
|
194
201
|
bisecting_vector = Vector.Bisect(dir1, dir2)
|
195
202
|
ev = Topology.TranslateByDirectionDistance(sv, bisecting_vector, length)
|
196
|
-
bisecting_edge = Edge.ByVertices([sv, ev])
|
203
|
+
bisecting_edge = Edge.ByVertices([sv, ev], tolerance=tolerance, silent=silent)
|
197
204
|
if placement == 0:
|
198
205
|
bisecting_edge = Topology.TranslateByDirectionDistance(bisecting_edge, Vector.Reverse(bisecting_vector), length*0.5)
|
199
206
|
elif placement == 2:
|
@@ -299,29 +306,45 @@ class Edge():
|
|
299
306
|
"""
|
300
307
|
from topologicpy.Vertex import Vertex
|
301
308
|
from topologicpy.Topology import Topology
|
309
|
+
import inspect
|
302
310
|
|
303
311
|
edge = None
|
304
312
|
if not Topology.IsInstance(vertexA, "Vertex"):
|
305
313
|
if not silent:
|
306
314
|
print("Edge.ByStartVertexEndVertex - Error: The input vertexA parameter is not a valid topologic vertex. Returning None.")
|
315
|
+
curframe = inspect.currentframe()
|
316
|
+
calframe = inspect.getouterframes(curframe, 2)
|
317
|
+
print('caller name:', calframe[1][3])
|
307
318
|
return None
|
308
319
|
if not Topology.IsInstance(vertexB, "Vertex"):
|
309
320
|
if not silent:
|
310
321
|
print("Edge.ByStartVertexEndVertex - Error: The input vertexB parameter is not a valid topologic vertex. Returning None.")
|
322
|
+
curframe = inspect.currentframe()
|
323
|
+
calframe = inspect.getouterframes(curframe, 2)
|
324
|
+
print('caller name:', calframe[1][3])
|
311
325
|
return None
|
312
326
|
if Topology.IsSame(vertexA, vertexB):
|
313
327
|
if not silent:
|
314
328
|
print("Edge.ByStartVertexEndVertex - Error: The input vertexA and vertexB parameters are the same vertex. Returning None.")
|
329
|
+
curframe = inspect.currentframe()
|
330
|
+
calframe = inspect.getouterframes(curframe, 2)
|
331
|
+
print('caller name:', calframe[1][3])
|
315
332
|
return None
|
316
333
|
if Vertex.Distance(vertexA, vertexB) <= tolerance:
|
317
334
|
if not silent:
|
318
335
|
print("Edge.ByStartVertexEndVertex - Error: The distance between the input vertexA and vertexB parameters is less than the input tolerance. Returning None.")
|
336
|
+
curframe = inspect.currentframe()
|
337
|
+
calframe = inspect.getouterframes(curframe, 2)
|
338
|
+
print('caller name:', calframe[1][3])
|
319
339
|
return None
|
320
340
|
try:
|
321
341
|
edge = topologic.Edge.ByStartVertexEndVertex(vertexA, vertexB) # Hook to Core
|
322
342
|
except:
|
323
343
|
if not silent:
|
324
344
|
print("Edge.ByStartVertexEndVertex - Error: Could not create an edge. Returning None.")
|
345
|
+
curframe = inspect.currentframe()
|
346
|
+
calframe = inspect.getouterframes(curframe, 2)
|
347
|
+
print('caller name:', calframe[1][3])
|
325
348
|
edge = None
|
326
349
|
return edge
|
327
350
|
|
@@ -366,7 +389,7 @@ class Edge():
|
|
366
389
|
return None
|
367
390
|
|
368
391
|
endVertex = Topology.TranslateByDirectionDistance(origin, direction=direction[:3], distance=length)
|
369
|
-
edge = Edge.ByVertices(origin, endVertex, tolerance=tolerance)
|
392
|
+
edge = Edge.ByVertices(origin, endVertex, tolerance=tolerance, silent=silent)
|
370
393
|
return edge
|
371
394
|
|
372
395
|
@staticmethod
|
@@ -472,11 +495,11 @@ class Edge():
|
|
472
495
|
The first input edge. This edge will be extended to meet edgeB.
|
473
496
|
edgeB : topologic_core.Edge
|
474
497
|
The second input edge. This edge will be used to extend edgeA.
|
475
|
-
silent : bool , optional
|
476
|
-
If set to True, no error and warning messages are printed. Otherwise, they are. The default is False.
|
477
498
|
tolerance : float , optional
|
478
499
|
The desired tolerance. The default is 0.0001.
|
479
|
-
|
500
|
+
silent : bool , optional
|
501
|
+
If set to True, no error and warning messages are printed. Otherwise, they are. The default is False.
|
502
|
+
|
480
503
|
Returns
|
481
504
|
-------
|
482
505
|
topologic_core.Edge or topologic_core.Wire
|
@@ -496,7 +519,7 @@ class Edge():
|
|
496
519
|
distances.append(Vertex.Distance(pair[0], pair[1]))
|
497
520
|
v_list = Helper.Sort(v_list, distances)
|
498
521
|
closest_pair = v_list[0]
|
499
|
-
return_edge = Edge.ByVertices(closest_pair, silent=silent)
|
522
|
+
return_edge = Edge.ByVertices(closest_pair, tolerance=tolerance, silent=silent)
|
500
523
|
if return_edge == None:
|
501
524
|
if not silent:
|
502
525
|
print("Edge.ConnectToEdge - Warning: Could not connect the two edges. Returning None.")
|
@@ -617,7 +640,7 @@ class Edge():
|
|
617
640
|
|
618
641
|
|
619
642
|
@staticmethod
|
620
|
-
def Extend(edge, distance: float = 1.0, bothSides: bool = True, reverse: bool = False, tolerance: float = 0.0001):
|
643
|
+
def Extend(edge, distance: float = 1.0, bothSides: bool = True, reverse: bool = False, tolerance: float = 0.0001, silent: bool = False):
|
621
644
|
"""
|
622
645
|
Extends the input edge by the input distance.
|
623
646
|
|
@@ -633,6 +656,8 @@ class Edge():
|
|
633
656
|
If set to True, the edge will be extended from its start vertex. Otherwise, it will be extended from its end vertex. The default is False.
|
634
657
|
tolerance : float , optional
|
635
658
|
The desired tolerance. The default is 0.0001.
|
659
|
+
silent : bool , optional
|
660
|
+
If set to True, no error and warning messages are printed. Otherwise, they are. The default is False.
|
636
661
|
|
637
662
|
Returns
|
638
663
|
-------
|
@@ -659,7 +684,7 @@ class Edge():
|
|
659
684
|
else:
|
660
685
|
sve = Edge.StartVertex(edge)
|
661
686
|
eve = Edge.VertexByDistance(edge, distance=distance, origin=ev, tolerance=tolerance)
|
662
|
-
return Edge.ByVertices([sve, eve], tolerance=tolerance, silent=
|
687
|
+
return Edge.ByVertices([sve, eve], tolerance=tolerance, silent=silent)
|
663
688
|
|
664
689
|
@staticmethod
|
665
690
|
def ExtendToEdge(edgeA, edgeB, mantissa: int = 6, step: bool = True, tolerance: float = 0.0001, silent: bool = False):
|
@@ -728,14 +753,14 @@ class Edge():
|
|
728
753
|
|
729
754
|
d = max(d1, d2)*2
|
730
755
|
v2 = Topology.TranslateByDirectionDistance(v2, direction=edge_direction, distance=d)
|
731
|
-
new_edge = Edge.ByVertices(v1, v2)
|
756
|
+
new_edge = Edge.ByVertices([v1, v2], tolerance=tolerance, silent=silent)
|
732
757
|
|
733
758
|
svb = Edge.StartVertex(edgeB)
|
734
759
|
evb = Edge.EndVertex(edgeB)
|
735
760
|
|
736
761
|
intVertex = Topology.Intersect(new_edge, edgeB, tolerance=tolerance)
|
737
762
|
if intVertex:
|
738
|
-
return Edge.ByVertices([v1, intVertex], tolerance=tolerance, silent=
|
763
|
+
return Edge.ByVertices([v1, intVertex], tolerance=tolerance, silent=silent)
|
739
764
|
if not silent:
|
740
765
|
print("Edge.ExtendToEdge - Warning: The operation failed. Connecting the edges instead. Returning a Wire.")
|
741
766
|
return Edge.ConnectToEdge(edgeA, edgeB, tolerance=tolerance)
|
@@ -1323,7 +1348,7 @@ class Edge():
|
|
1323
1348
|
return normal_edge
|
1324
1349
|
|
1325
1350
|
@staticmethod
|
1326
|
-
def Normalize(edge, useEndVertex: bool = False, tolerance: float = 0.0001):
|
1351
|
+
def Normalize(edge, useEndVertex: bool = False, tolerance: float = 0.0001, silent: bool = False):
|
1327
1352
|
"""
|
1328
1353
|
Creates a normalized edge that has the same direction as the input edge, but a length of 1.
|
1329
1354
|
|
@@ -1335,6 +1360,8 @@ class Edge():
|
|
1335
1360
|
If True the normalized edge end vertex will be placed at the end vertex of the input edge. Otherwise, the normalized edge start vertex will be placed at the start vertex of the input edge. The default is False.
|
1336
1361
|
tolerance : float , optional
|
1337
1362
|
The desired tolerance. The default is 0.0001.
|
1363
|
+
silent : bool , optional
|
1364
|
+
If set to True, no error and warning messages are printed. Otherwise, they are. The default is False.
|
1338
1365
|
|
1339
1366
|
Returns
|
1340
1367
|
-------
|
@@ -1345,7 +1372,8 @@ class Edge():
|
|
1345
1372
|
from topologicpy.Topology import Topology
|
1346
1373
|
|
1347
1374
|
if not Topology.IsInstance(edge, "Edge"):
|
1348
|
-
|
1375
|
+
if not silent:
|
1376
|
+
print("Edge.Normalize - Error: The input edge parameter is not a valid topologic edge. Returning None.")
|
1349
1377
|
return None
|
1350
1378
|
if not useEndVertex:
|
1351
1379
|
sv = Edge.StartVertex(edge)
|
@@ -1353,7 +1381,7 @@ class Edge():
|
|
1353
1381
|
else:
|
1354
1382
|
sv = Edge.VertexByDistance(edge, 1.0, Edge.StartVertex(edge))
|
1355
1383
|
ev = Edge.EndVertex(edge)
|
1356
|
-
return Edge.ByVertices([sv, ev], tolerance=tolerance)
|
1384
|
+
return Edge.ByVertices([sv, ev], tolerance=tolerance, silent=silent)
|
1357
1385
|
|
1358
1386
|
@staticmethod
|
1359
1387
|
def ParameterAtVertex(edge, vertex, mantissa: int = 6, silent: bool = False) -> float:
|
@@ -1395,7 +1423,7 @@ class Edge():
|
|
1395
1423
|
return round(parameter, mantissa)
|
1396
1424
|
|
1397
1425
|
@staticmethod
|
1398
|
-
def Reverse(edge, tolerance: float = 0.0001):
|
1426
|
+
def Reverse(edge, tolerance: float = 0.0001, silent: bool = False):
|
1399
1427
|
"""
|
1400
1428
|
Creates an edge that has the reverse direction of the input edge.
|
1401
1429
|
|
@@ -1405,6 +1433,8 @@ class Edge():
|
|
1405
1433
|
The input edge.
|
1406
1434
|
tolerance : float , optional
|
1407
1435
|
The desired tolerance. The default is 0.0001.
|
1436
|
+
silent : bool , optional
|
1437
|
+
If set to True, no error and warning messages are printed. Otherwise, they are. The default is False.
|
1408
1438
|
|
1409
1439
|
Returns
|
1410
1440
|
-------
|
@@ -1415,9 +1445,10 @@ class Edge():
|
|
1415
1445
|
from topologicpy.Topology import Topology
|
1416
1446
|
|
1417
1447
|
if not Topology.IsInstance(edge, "Edge"):
|
1418
|
-
|
1448
|
+
if not silent:
|
1449
|
+
print("Edge.Reverse - Error: The input edge parameter is not a valid topologic edge. Returning None.")
|
1419
1450
|
return None
|
1420
|
-
return Edge.ByVertices([Edge.EndVertex(edge), Edge.StartVertex(edge)], tolerance=tolerance)
|
1451
|
+
return Edge.ByVertices([Edge.EndVertex(edge), Edge.StartVertex(edge)], tolerance=tolerance, silent=silent)
|
1421
1452
|
|
1422
1453
|
@staticmethod
|
1423
1454
|
def SetLength(edge , length: float = 1.0, bothSides: bool = True, reverse: bool = False, tolerance: float = 0.0001):
|
@@ -1482,7 +1513,7 @@ class Edge():
|
|
1482
1513
|
return vert
|
1483
1514
|
|
1484
1515
|
@staticmethod
|
1485
|
-
def Trim(edge, distance: float = 0.0, bothSides: bool = True, reverse: bool = False, tolerance: float = 0.0001):
|
1516
|
+
def Trim(edge, distance: float = 0.0, bothSides: bool = True, reverse: bool = False, tolerance: float = 0.0001, silent: bool = False):
|
1486
1517
|
"""
|
1487
1518
|
Trims the input edge by the input distance.
|
1488
1519
|
|
@@ -1498,6 +1529,8 @@ class Edge():
|
|
1498
1529
|
If set to True, the edge will be trimmed from its start vertex. Otherwise, it will be trimmed from its end vertex. The default is False.
|
1499
1530
|
tolerance : float , optional
|
1500
1531
|
The desired tolerance. The default is 0.0001.
|
1532
|
+
silent : bool , optional
|
1533
|
+
If set to True, no error and warning messages are printed. Otherwise, they are. The default is False.
|
1501
1534
|
|
1502
1535
|
Returns
|
1503
1536
|
-------
|
@@ -1527,7 +1560,7 @@ class Edge():
|
|
1527
1560
|
else:
|
1528
1561
|
sve = Edge.StartVertex(edge)
|
1529
1562
|
eve = Edge.VertexByDistance(edge, distance=-distance, origin=ev, tolerance=tolerance)
|
1530
|
-
return Edge.ByVertices([sve, eve], tolerance=tolerance, silent=
|
1563
|
+
return Edge.ByVertices([sve, eve], tolerance=tolerance, silent=silent)
|
1531
1564
|
|
1532
1565
|
@staticmethod
|
1533
1566
|
def TrimByEdge(edgeA, edgeB, reverse: bool = False, mantissa: int = 6, tolerance: float = 0.0001, silent: bool = False):
|
@@ -1587,9 +1620,9 @@ class Edge():
|
|
1587
1620
|
intVertex = None
|
1588
1621
|
if intVertex:
|
1589
1622
|
if reverse:
|
1590
|
-
return Edge.ByVertices([eva, intVertex], tolerance=tolerance, silent=
|
1623
|
+
return Edge.ByVertices([eva, intVertex], tolerance=tolerance, silent=silent)
|
1591
1624
|
else:
|
1592
|
-
return Edge.ByVertices([sva, intVertex], tolerance=tolerance, silent=
|
1625
|
+
return Edge.ByVertices([sva, intVertex], tolerance=tolerance, silent=silent)
|
1593
1626
|
else:
|
1594
1627
|
return None
|
1595
1628
|
|
@@ -1598,9 +1631,9 @@ class Edge():
|
|
1598
1631
|
intVertex = Topology.Intersect(edgeA, edgeB)
|
1599
1632
|
if intVertex and (Vertex.IsInternal(intVertex, edgeA)):
|
1600
1633
|
if reverse:
|
1601
|
-
return Edge.ByVertices([eva, intVertex], tolerance=tolerance, silent=
|
1634
|
+
return Edge.ByVertices([eva, intVertex], tolerance=tolerance, silent=slient)
|
1602
1635
|
else:
|
1603
|
-
return Edge.ByVertices([sva, intVertex], tolerance=tolerance, silent=
|
1636
|
+
return Edge.ByVertices([sva, intVertex], tolerance=tolerance, silent=silent)
|
1604
1637
|
return edgeA
|
1605
1638
|
|
1606
1639
|
@staticmethod
|