topologicpy 0.6.3__py3-none-any.whl → 0.7.2__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/Aperture.py +12 -13
- topologicpy/Cell.py +234 -210
- topologicpy/CellComplex.py +130 -118
- topologicpy/Cluster.py +108 -91
- topologicpy/Context.py +11 -7
- topologicpy/DGL.py +1 -1
- topologicpy/Dictionary.py +55 -65
- topologicpy/Edge.py +217 -164
- topologicpy/EnergyModel.py +23 -24
- topologicpy/Face.py +526 -315
- topologicpy/Graph.py +437 -349
- topologicpy/Grid.py +40 -43
- topologicpy/Honeybee.py +1 -1
- topologicpy/Matrix.py +28 -27
- topologicpy/Neo4j.py +5 -5
- topologicpy/Plotly.py +135 -51
- topologicpy/Shell.py +160 -145
- topologicpy/Sun.py +17 -13
- topologicpy/Topology.py +544 -765
- topologicpy/Vector.py +4 -4
- topologicpy/Vertex.py +145 -126
- topologicpy/Wire.py +545 -328
- topologicpy/version.py +1 -1
- {topologicpy-0.6.3.dist-info → topologicpy-0.7.2.dist-info}/METADATA +1 -1
- topologicpy-0.7.2.dist-info/RECORD +33 -0
- topologicpy-0.6.3.dist-info/RECORD +0 -33
- {topologicpy-0.6.3.dist-info → topologicpy-0.7.2.dist-info}/LICENSE +0 -0
- {topologicpy-0.6.3.dist-info → topologicpy-0.7.2.dist-info}/WHEEL +0 -0
- {topologicpy-0.6.3.dist-info → topologicpy-0.7.2.dist-info}/top_level.txt +0 -0
topologicpy/Face.py
CHANGED
@@ -15,9 +15,6 @@
|
|
15
15
|
# this program. If not, see <https://www.gnu.org/licenses/>.
|
16
16
|
|
17
17
|
import topologic_core as topologic
|
18
|
-
from topologicpy.Vector import Vector
|
19
|
-
from topologicpy.Wire import Wire
|
20
|
-
from topologicpy.Topology import Topology
|
21
18
|
import math
|
22
19
|
import os
|
23
20
|
import warnings
|
@@ -36,33 +33,34 @@ except:
|
|
36
33
|
except:
|
37
34
|
warnings.warn("Face - Error: Could not import numpy.")
|
38
35
|
|
39
|
-
class Face(
|
36
|
+
class Face():
|
40
37
|
@staticmethod
|
41
|
-
def AddInternalBoundaries(face
|
38
|
+
def AddInternalBoundaries(face, wires: list):
|
42
39
|
"""
|
43
40
|
Adds internal boundaries (closed wires) to the input face. Internal boundaries are considered holes in the input face.
|
44
41
|
|
45
42
|
Parameters
|
46
43
|
----------
|
47
|
-
face :
|
44
|
+
face : topologic_core.Face
|
48
45
|
The input face.
|
49
46
|
wires : list
|
50
47
|
The input list of internal boundaries (closed wires).
|
51
48
|
|
52
49
|
Returns
|
53
50
|
-------
|
54
|
-
|
51
|
+
topologic_core.Face
|
55
52
|
The created face with internal boundaries added to it.
|
56
53
|
|
57
54
|
"""
|
55
|
+
from topologicpy.Topology import Topology
|
58
56
|
|
59
|
-
if not
|
57
|
+
if not Topology.IsInstance(face, "Face"):
|
60
58
|
print("Face.AddInternalBoundaries - Error: The input face parameter is not a valid topologic face. Returning None.")
|
61
59
|
return None
|
62
60
|
if not isinstance(wires, list):
|
63
61
|
print("Face.AddInternalBoundaries - Warning: The input wires parameter is not a valid list. Returning the input face.")
|
64
62
|
return face
|
65
|
-
wireList = [w for w in wires if
|
63
|
+
wireList = [w for w in wires if Topology.IsInstance(w, "Wire")]
|
66
64
|
if len(wireList) < 1:
|
67
65
|
print("Face.AddInternalBoundaries - Warning: The input wires parameter does not contain any valid wires. Returning the input face.")
|
68
66
|
return face
|
@@ -71,47 +69,49 @@ class Face(Topology):
|
|
71
69
|
_ = face.InternalBoundaries(faceibList)
|
72
70
|
for wire in wires:
|
73
71
|
faceibList.append(wire)
|
74
|
-
return
|
72
|
+
return Face.ByWires(faceeb, faceibList)
|
75
73
|
|
76
74
|
@staticmethod
|
77
|
-
def AddInternalBoundariesCluster(face
|
75
|
+
def AddInternalBoundariesCluster(face, cluster):
|
78
76
|
"""
|
79
77
|
Adds the input cluster of internal boundaries (closed wires) to the input face. Internal boundaries are considered holes in the input face.
|
80
78
|
|
81
79
|
Parameters
|
82
80
|
----------
|
83
|
-
face :
|
81
|
+
face : topologic_core.Face
|
84
82
|
The input face.
|
85
|
-
cluster :
|
83
|
+
cluster : topologic_core.Cluster
|
86
84
|
The input cluster of internal boundaries (topologic wires).
|
87
85
|
|
88
86
|
Returns
|
89
87
|
-------
|
90
|
-
|
88
|
+
topologic_core.Face
|
91
89
|
The created face with internal boundaries added to it.
|
92
90
|
|
93
91
|
"""
|
94
|
-
|
92
|
+
from topologicpy.Topology import Topology
|
93
|
+
|
94
|
+
if not Topology.IsInstance(face, "Face"):
|
95
95
|
print("Face.AddInternalBoundariesCluster - Warning: The input cluster parameter is not a valid cluster. Returning None.")
|
96
96
|
return None
|
97
97
|
if not cluster:
|
98
98
|
return face
|
99
|
-
if not
|
99
|
+
if not Topology.IsInstance(cluster, "Cluster"):
|
100
100
|
return face
|
101
101
|
wires = []
|
102
102
|
_ = cluster.Wires(None, wires)
|
103
103
|
return Face.AddInternalBoundaries(face, wires)
|
104
104
|
|
105
105
|
@staticmethod
|
106
|
-
def Angle(faceA
|
106
|
+
def Angle(faceA, faceB, mantissa: int = 6) -> float:
|
107
107
|
"""
|
108
108
|
Returns the angle in degrees between the two input faces.
|
109
109
|
|
110
110
|
Parameters
|
111
111
|
----------
|
112
|
-
faceA :
|
112
|
+
faceA : topologic_core.Face
|
113
113
|
The first input face.
|
114
|
-
faceB :
|
114
|
+
faceB : topologic_core.Face
|
115
115
|
The second input face.
|
116
116
|
mantissa : int , optional
|
117
117
|
The desired length of the mantissa. The default is 6.
|
@@ -123,10 +123,12 @@ class Face(Topology):
|
|
123
123
|
|
124
124
|
"""
|
125
125
|
from topologicpy.Vector import Vector
|
126
|
-
|
126
|
+
from topologicpy.Topology import Topology
|
127
|
+
|
128
|
+
if not Topology.IsInstance(faceA, "Face"):
|
127
129
|
print("Face.Angle - Warning: The input faceA parameter is not a valid topologic face. Returning None.")
|
128
130
|
return None
|
129
|
-
if not
|
131
|
+
if not Topology.IsInstance(faceB, "Face"):
|
130
132
|
print("Face.Angle - Warning: The input faceB parameter is not a valid topologic face. Returning None.")
|
131
133
|
return None
|
132
134
|
dirA = Face.NormalAtParameters(faceA, 0.5, 0.5, "xyz", 3)
|
@@ -134,13 +136,13 @@ class Face(Topology):
|
|
134
136
|
return round((Vector.Angle(dirA, dirB)), mantissa)
|
135
137
|
|
136
138
|
@staticmethod
|
137
|
-
def Area(face
|
139
|
+
def Area(face, mantissa: int = 6) -> float:
|
138
140
|
"""
|
139
141
|
Returns the area of the input face.
|
140
142
|
|
141
143
|
Parameters
|
142
144
|
----------
|
143
|
-
face :
|
145
|
+
face : topologic_core.Face
|
144
146
|
The input face.
|
145
147
|
mantissa : int , optional
|
146
148
|
The desired length of the mantissa. The default is 6.
|
@@ -151,24 +153,26 @@ class Face(Topology):
|
|
151
153
|
The area of the input face.
|
152
154
|
|
153
155
|
"""
|
154
|
-
|
156
|
+
from topologicpy.Topology import Topology
|
157
|
+
|
158
|
+
if not Topology.IsInstance(face, "Face"):
|
155
159
|
print("Face.Area - Warning: The input face parameter is not a valid topologic face. Returning None.")
|
156
160
|
return None
|
157
161
|
area = None
|
158
162
|
try:
|
159
|
-
area = round(topologic.FaceUtility.Area(face), mantissa)
|
163
|
+
area = round(topologic.FaceUtility.Area(face), mantissa) # Hook to Core
|
160
164
|
except:
|
161
165
|
area = None
|
162
166
|
return area
|
163
167
|
|
164
168
|
@staticmethod
|
165
|
-
def BoundingRectangle(topology
|
169
|
+
def BoundingRectangle(topology, optimize: int = 0, tolerance: float = 0.0001):
|
166
170
|
"""
|
167
171
|
Returns a face representing a bounding rectangle of the input topology. The returned face contains a dictionary with key "zrot" that represents rotations around the Z axis. If applied the resulting face will become axis-aligned.
|
168
172
|
|
169
173
|
Parameters
|
170
174
|
----------
|
171
|
-
topology :
|
175
|
+
topology : topologic_core.Topology
|
172
176
|
The input topology.
|
173
177
|
optimize : int , optional
|
174
178
|
If set to an integer from 1 (low optimization) to 10 (high optimization), the method will attempt to optimize the bounding rectangle so that it reduces its surface area. The default is 0 which will result in an axis-aligned bounding rectangle. The default is 0.
|
@@ -177,93 +181,20 @@ class Face(Topology):
|
|
177
181
|
|
178
182
|
Returns
|
179
183
|
-------
|
180
|
-
|
184
|
+
topologic_core.Face
|
181
185
|
The bounding rectangle of the input topology.
|
182
186
|
|
183
187
|
"""
|
184
188
|
from topologicpy.Wire import Wire
|
185
|
-
from topologicpy.Face import Face
|
186
|
-
from topologicpy.Cluster import Cluster
|
187
189
|
from topologicpy.Topology import Topology
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
y = []
|
194
|
-
for aVertex in vertices:
|
195
|
-
x.append(aVertex.X())
|
196
|
-
y.append(aVertex.Y())
|
197
|
-
minX = min(x)
|
198
|
-
minY = min(y)
|
199
|
-
maxX = max(x)
|
200
|
-
maxY = max(y)
|
201
|
-
return [minX, minY, maxX, maxY]
|
202
|
-
|
203
|
-
if not isinstance(topology, topologic.Topology):
|
204
|
-
print("Face.BoundingRectangle - Warning: The input topology parameter is not a valid topologic topology. Returning None.")
|
205
|
-
return None
|
206
|
-
vertices = Topology.SubTopologies(topology, subTopologyType="vertex")
|
207
|
-
topology = Cluster.ByTopologies(vertices)
|
208
|
-
boundingBox = bb(topology)
|
209
|
-
minX = boundingBox[0]
|
210
|
-
minY = boundingBox[1]
|
211
|
-
maxX = boundingBox[2]
|
212
|
-
maxY = boundingBox[3]
|
213
|
-
w = abs(maxX - minX)
|
214
|
-
l = abs(maxY - minY)
|
215
|
-
best_area = l*w
|
216
|
-
orig_area = best_area
|
217
|
-
best_z = 0
|
218
|
-
best_bb = boundingBox
|
219
|
-
origin = Topology.Centroid(topology)
|
220
|
-
optimize = min(max(optimize, 0), 10)
|
221
|
-
if optimize > 0:
|
222
|
-
factor = (round(((11 - optimize)/30 + 0.57), 2))
|
223
|
-
flag = False
|
224
|
-
for n in range(10,0,-1):
|
225
|
-
if flag:
|
226
|
-
break
|
227
|
-
za = n
|
228
|
-
zb = 90+n
|
229
|
-
zc = n
|
230
|
-
for z in range(za,zb,zc):
|
231
|
-
if flag:
|
232
|
-
break
|
233
|
-
t = Topology.Rotate(topology, origin=origin, axis=[0, 0, 1], angle=z)
|
234
|
-
minX, minY, maxX, maxY = bb(t)
|
235
|
-
w = abs(maxX - minX)
|
236
|
-
l = abs(maxY - minY)
|
237
|
-
area = l*w
|
238
|
-
if area < orig_area*factor:
|
239
|
-
best_area = area
|
240
|
-
best_z = z
|
241
|
-
best_bb = [minX, minY, maxX, maxY]
|
242
|
-
flag = True
|
243
|
-
break
|
244
|
-
if area < best_area:
|
245
|
-
best_area = area
|
246
|
-
best_z = z
|
247
|
-
best_bb = [minX, minY, maxX, maxY]
|
248
|
-
|
249
|
-
else:
|
250
|
-
best_bb = boundingBox
|
251
|
-
|
252
|
-
minX, minY, maxX, maxY = best_bb
|
253
|
-
vb1 = topologic.Vertex.ByCoordinates(minX, minY, 0)
|
254
|
-
vb2 = topologic.Vertex.ByCoordinates(maxX, minY, 0)
|
255
|
-
vb3 = topologic.Vertex.ByCoordinates(maxX, maxY, 0)
|
256
|
-
vb4 = topologic.Vertex.ByCoordinates(minX, maxY, 0)
|
257
|
-
|
258
|
-
baseWire = Wire.ByVertices([vb1, vb2, vb3, vb4], close=True)
|
259
|
-
baseFace = Face.ByWire(baseWire, tolerance=tolerance)
|
260
|
-
baseFace = Topology.Rotate(baseFace, origin=origin, axis=[0, 0, 1], angle=-best_z)
|
261
|
-
dictionary = Dictionary.ByKeysValues(["zrot"], [best_z])
|
262
|
-
baseFace = Topology.SetDictionary(baseFace, dictionary)
|
263
|
-
return baseFace
|
190
|
+
|
191
|
+
br_wire = Wire.BoundingRectangle(topology=topology, optimize=optimize, tolerance=tolerance)
|
192
|
+
br_face = Face.ByWire(br_wire)
|
193
|
+
br_face = Topology.SetDictionary(br_face, Topology.Dictionary(br_wire))
|
194
|
+
return br_face
|
264
195
|
|
265
196
|
@staticmethod
|
266
|
-
def ByEdges(edges: list, tolerance : float = 0.0001)
|
197
|
+
def ByEdges(edges: list, tolerance : float = 0.0001):
|
267
198
|
"""
|
268
199
|
Creates a face from the input list of edges.
|
269
200
|
|
@@ -276,44 +207,48 @@ class Face(Topology):
|
|
276
207
|
|
277
208
|
Returns
|
278
209
|
-------
|
279
|
-
face :
|
210
|
+
face : topologic_core.Face
|
280
211
|
The created face.
|
281
212
|
|
282
213
|
"""
|
283
214
|
from topologicpy.Wire import Wire
|
215
|
+
from topologicpy.Topology import Topology
|
216
|
+
|
284
217
|
if not isinstance(edges, list):
|
285
218
|
print("Face.ByEdges - Error: The input edges parameter is not a valid list. Returning None.")
|
286
219
|
return None
|
287
|
-
edges = [e for e in edges if
|
220
|
+
edges = [e for e in edges if Topology.IsInstance(e, "Edge")]
|
288
221
|
if len(edges) < 1:
|
289
222
|
print("Face.ByEdges - Error: The input edges parameter does not contain any valid edges. Returning None.")
|
290
223
|
return None
|
291
224
|
wire = Wire.ByEdges(edges, tolerance=tolerance)
|
292
|
-
if not
|
225
|
+
if not Topology.IsInstance(wire, "Wire"):
|
293
226
|
print("Face.ByEdges - Error: Could not create the required wire. Returning None.")
|
294
227
|
return None
|
295
228
|
return Face.ByWire(wire, tolerance=tolerance)
|
296
229
|
|
297
230
|
@staticmethod
|
298
|
-
def ByEdgesCluster(cluster
|
231
|
+
def ByEdgesCluster(cluster, tolerance: float = 0.0001):
|
299
232
|
"""
|
300
233
|
Creates a face from the input cluster of edges.
|
301
234
|
|
302
235
|
Parameters
|
303
236
|
----------
|
304
|
-
cluster :
|
237
|
+
cluster : topologic_core.Cluster
|
305
238
|
The input cluster of edges.
|
306
239
|
tolerance : float , optional
|
307
240
|
The desired tolerance. The default is 0.0001.
|
308
241
|
|
309
242
|
Returns
|
310
243
|
-------
|
311
|
-
face :
|
244
|
+
face : topologic_core.Face
|
312
245
|
The created face.
|
313
246
|
|
314
247
|
"""
|
315
248
|
from topologicpy.Cluster import Cluster
|
316
|
-
|
249
|
+
from topologicpy.Topology import Topology
|
250
|
+
|
251
|
+
if not Topology.IsInstance(cluster, "Cluster"):
|
317
252
|
print("Face.ByEdgesCluster - Warning: The input cluster parameter is not a valid topologic cluster. Returning None.")
|
318
253
|
return None
|
319
254
|
edges = Cluster.Edges(cluster)
|
@@ -323,15 +258,15 @@ class Face(Topology):
|
|
323
258
|
return Face.ByEdges(edges, tolerance=tolerance)
|
324
259
|
|
325
260
|
@staticmethod
|
326
|
-
def ByOffset(face
|
261
|
+
def ByOffset(face, offset: float = 1.0, miter: bool = False,
|
327
262
|
miterThreshold: float = None, offsetKey: str = None,
|
328
|
-
miterThresholdKey: str = None, step: bool = True, tolerance: float = 0.0001)
|
263
|
+
miterThresholdKey: str = None, step: bool = True, tolerance: float = 0.0001):
|
329
264
|
"""
|
330
265
|
Creates an offset face from the input face.
|
331
266
|
|
332
267
|
Parameters
|
333
268
|
----------
|
334
|
-
face :
|
269
|
+
face : topologic_core.Face
|
335
270
|
The input face.
|
336
271
|
offset : float , optional
|
337
272
|
The desired offset distance. The default is 1.0.
|
@@ -350,12 +285,14 @@ class Face(Topology):
|
|
350
285
|
|
351
286
|
Returns
|
352
287
|
-------
|
353
|
-
|
288
|
+
topologic_core.Face
|
354
289
|
The created face.
|
355
290
|
|
356
291
|
"""
|
357
292
|
from topologicpy.Wire import Wire
|
358
|
-
|
293
|
+
from topologicpy.Topology import Topology
|
294
|
+
|
295
|
+
if not Topology.IsInstance(face, "Face"):
|
359
296
|
print("Face.ByOffset - Warning: The input face parameter is not a valid toplogic face. Returning None.")
|
360
297
|
return None
|
361
298
|
eb = Face.Wire(face)
|
@@ -367,13 +304,13 @@ class Face(Topology):
|
|
367
304
|
return Face.ByWires(offset_external_boundary, offset_internal_boundaries, tolerance=tolerance)
|
368
305
|
|
369
306
|
@staticmethod
|
370
|
-
def ByShell(shell
|
307
|
+
def ByShell(shell, origin= None, angTolerance: float = 0.1, tolerance: float = 0.0001):
|
371
308
|
"""
|
372
309
|
Creates a face by merging the faces of the input shell.
|
373
310
|
|
374
311
|
Parameters
|
375
312
|
----------
|
376
|
-
shell :
|
313
|
+
shell : topologic_core.Shell
|
377
314
|
The input shell.
|
378
315
|
angTolerance : float , optional
|
379
316
|
The desired angular tolerance. The default is 0.1.
|
@@ -382,7 +319,7 @@ class Face(Topology):
|
|
382
319
|
|
383
320
|
Returns
|
384
321
|
-------
|
385
|
-
|
322
|
+
topologic_core.Face
|
386
323
|
The created face.
|
387
324
|
|
388
325
|
"""
|
@@ -400,29 +337,29 @@ class Face(Topology):
|
|
400
337
|
returnList.append(Wire.Planarize(aWire))
|
401
338
|
return returnList
|
402
339
|
|
403
|
-
if not
|
340
|
+
if not Topology.IsInstance(shell, "Shell"):
|
404
341
|
print("Face.ByShell - Error: The input shell parameter is not a valid toplogic shell. Returning None.")
|
405
342
|
return None
|
406
343
|
|
407
344
|
if origin == None:
|
408
345
|
origin = Topology.Centroid(shell)
|
409
|
-
if not
|
346
|
+
if not Topology.IsInstance(origin, "Vertex"):
|
410
347
|
print("Face.ByShell - Error: The input origin parameter is not a valid topologic vertex. Returning None.")
|
411
348
|
return None
|
412
349
|
|
413
350
|
# Try the simple method first
|
414
351
|
face = None
|
415
352
|
ext_boundary = Wire.RemoveCollinearEdges(Shell.ExternalBoundary(shell))
|
416
|
-
if
|
353
|
+
if Topology.IsInstance(ext_boundary, "Wire"):
|
417
354
|
face = Face.ByWire(ext_boundary)
|
418
|
-
elif
|
355
|
+
elif Topology.IsInstance(ext_boundary, "Cluster"):
|
419
356
|
wires = Topology.Wires(ext_boundary)
|
420
357
|
faces = [Face.ByWire(w) for w in wires]
|
421
358
|
areas = [Face.Area(f) for f in faces]
|
422
359
|
wires = Helper.Sort(wires, areas, reverseFlags=[True])
|
423
360
|
face = Face.ByWires(wires[0], wires[1:])
|
424
361
|
|
425
|
-
if
|
362
|
+
if Topology.IsInstance(face, "Face"):
|
426
363
|
return face
|
427
364
|
world_origin = Vertex.Origin()
|
428
365
|
planar_shell = Shell.Planarize(shell)
|
@@ -437,11 +374,11 @@ class Face(Topology):
|
|
437
374
|
planar_shell = Topology.SelfMerge(Topology.ReplaceVertices(planar_shell, verticesA=vertices, verticesB=new_vertices), tolerance=tolerance)
|
438
375
|
ext_boundary = Shell.ExternalBoundary(planar_shell, tolerance=tolerance)
|
439
376
|
ext_boundary = Topology.RemoveCollinearEdges(ext_boundary, angTolerance)
|
440
|
-
if not
|
377
|
+
if not Topology.IsInstance(ext_boundary, "Topology"):
|
441
378
|
print("Face.ByShell - Error: Could not derive the external boundary of the input shell parameter. Returning None.")
|
442
379
|
return None
|
443
380
|
|
444
|
-
if
|
381
|
+
if Topology.IsInstance(ext_boundary, "Wire"):
|
445
382
|
if not Topology.IsPlanar(ext_boundary, tolerance=tolerance):
|
446
383
|
ext_boundary = Wire.Planarize(ext_boundary, origin=origin, tolerance=tolerance)
|
447
384
|
ext_boundary = Topology.RemoveCollinearEdges(ext_boundary, angTolerance)
|
@@ -452,14 +389,14 @@ class Face(Topology):
|
|
452
389
|
except:
|
453
390
|
print("Face.ByShell - Error: The operation failed. Returning None.")
|
454
391
|
return None
|
455
|
-
elif
|
392
|
+
elif Topology.IsInstance(ext_boundary, "Cluster"): # The shell has holes.
|
456
393
|
wires = []
|
457
394
|
_ = ext_boundary.Wires(None, wires)
|
458
395
|
faces = []
|
459
396
|
areas = []
|
460
397
|
for wire in wires:
|
461
398
|
aFace = Face.ByWire(wire, tolerance=tolerance)
|
462
|
-
if not
|
399
|
+
if not Topology.IsInstance(aFace, "Face"):
|
463
400
|
print("Face.ByShell - Error: The operation failed. Returning None.")
|
464
401
|
return None
|
465
402
|
anArea = abs(Face.Area(aFace))
|
@@ -484,7 +421,7 @@ class Face(Topology):
|
|
484
421
|
return None
|
485
422
|
|
486
423
|
@staticmethod
|
487
|
-
def ByVertices(vertices: list, tolerance: float = 0.0001)
|
424
|
+
def ByVertices(vertices: list, tolerance: float = 0.0001):
|
488
425
|
|
489
426
|
"""
|
490
427
|
Creates a face from the input list of vertices.
|
@@ -498,7 +435,7 @@ class Face(Topology):
|
|
498
435
|
|
499
436
|
Returns
|
500
437
|
-------
|
501
|
-
|
438
|
+
topologic_core.Face
|
502
439
|
The created face.
|
503
440
|
|
504
441
|
"""
|
@@ -507,7 +444,7 @@ class Face(Topology):
|
|
507
444
|
|
508
445
|
if not isinstance(vertices, list):
|
509
446
|
return None
|
510
|
-
vertexList = [x for x in vertices if
|
447
|
+
vertexList = [x for x in vertices if Topology.IsInstance(x, "Vertex")]
|
511
448
|
if len(vertexList) < 3:
|
512
449
|
return None
|
513
450
|
|
@@ -516,37 +453,39 @@ class Face(Topology):
|
|
516
453
|
return f
|
517
454
|
|
518
455
|
@staticmethod
|
519
|
-
def ByVerticesCluster(cluster
|
456
|
+
def ByVerticesCluster(cluster, tolerance: float = 0.0001):
|
520
457
|
"""
|
521
458
|
Creates a face from the input cluster of vertices.
|
522
459
|
|
523
460
|
Parameters
|
524
461
|
----------
|
525
|
-
cluster :
|
462
|
+
cluster : topologic_core.Cluster
|
526
463
|
The input cluster of vertices.
|
527
464
|
tolerance : float , optional
|
528
465
|
The desired tolerance. The default is 0.0001.
|
529
466
|
|
530
467
|
Returns
|
531
468
|
-------
|
532
|
-
|
533
|
-
The
|
469
|
+
topologic_core.Face
|
470
|
+
The created face.
|
534
471
|
|
535
472
|
"""
|
536
473
|
from topologicpy.Cluster import Cluster
|
537
|
-
|
474
|
+
from topologicpy.Topology import Topology
|
475
|
+
|
476
|
+
if not Topology.IsInstance(cluster, "Cluster"):
|
538
477
|
return None
|
539
478
|
vertices = Cluster.Vertices(cluster)
|
540
479
|
return Face.ByVertices(vertices, tolerance=tolerance)
|
541
480
|
|
542
481
|
@staticmethod
|
543
|
-
def ByWire(wire
|
482
|
+
def ByWire(wire, tolerance: float = 0.0001, silent=False):
|
544
483
|
"""
|
545
484
|
Creates a face from the input closed wire.
|
546
485
|
|
547
486
|
Parameters
|
548
487
|
----------
|
549
|
-
wire :
|
488
|
+
wire : topologic_core.Wire
|
550
489
|
The input wire.
|
551
490
|
tolerance : float , optional
|
552
491
|
The desired tolerance. The default is 0.0001.
|
@@ -555,7 +494,7 @@ class Face(Topology):
|
|
555
494
|
|
556
495
|
Returns
|
557
496
|
-------
|
558
|
-
|
497
|
+
topologic_core.Face or list
|
559
498
|
The created face. If the wire is non-planar, the method will attempt to triangulate the wire and return a list of faces.
|
560
499
|
|
561
500
|
"""
|
@@ -571,11 +510,11 @@ class Face(Topology):
|
|
571
510
|
wire = Topology.RemoveCollinearEdges(wire)
|
572
511
|
vertices = Topology.Vertices(wire)
|
573
512
|
shell = Shell.Delaunay(vertices)
|
574
|
-
if
|
513
|
+
if Topology.IsInstance(shell, "Topology"):
|
575
514
|
return Topology.Faces(shell)
|
576
515
|
else:
|
577
516
|
return []
|
578
|
-
if not
|
517
|
+
if not Topology.IsInstance(wire, "Wire"):
|
579
518
|
if not silent:
|
580
519
|
print("Face.ByWire - Error: The input wire parameter is not a valid topologic wire. Returning None.")
|
581
520
|
return None
|
@@ -588,9 +527,9 @@ class Face(Topology):
|
|
588
527
|
wire = Topology.SelfMerge(Cluster.ByTopologies(edges), tolerance=tolerance)
|
589
528
|
vertices = Topology.Vertices(wire)
|
590
529
|
fList = []
|
591
|
-
if
|
530
|
+
if Topology.IsInstance(wire, "Wire"):
|
592
531
|
try:
|
593
|
-
fList = topologic.Face.ByExternalBoundary(wire)
|
532
|
+
fList = topologic.Face.ByExternalBoundary(wire) # Hook to Core
|
594
533
|
except:
|
595
534
|
if not silent:
|
596
535
|
print("Face.ByWire - Warning: Could not create face by external boundary. Trying other methods.")
|
@@ -608,7 +547,7 @@ class Face(Topology):
|
|
608
547
|
wire = Face.ExternalBoundary(f)
|
609
548
|
wire = Wire.Invert(wire)
|
610
549
|
try:
|
611
|
-
f = topologic.Face.ByExternalBoundary(wire)
|
550
|
+
f = topologic.Face.ByExternalBoundary(wire) # Hook to Core
|
612
551
|
returnList.append(f)
|
613
552
|
except:
|
614
553
|
pass
|
@@ -626,13 +565,13 @@ class Face(Topology):
|
|
626
565
|
return returnList
|
627
566
|
|
628
567
|
@staticmethod
|
629
|
-
def ByWires(externalBoundary
|
568
|
+
def ByWires(externalBoundary, internalBoundaries: list = [], tolerance: float = 0.0001, silent: bool = False):
|
630
569
|
"""
|
631
570
|
Creates a face from the input external boundary (closed wire) and the input list of internal boundaries (closed wires).
|
632
571
|
|
633
572
|
Parameters
|
634
573
|
----------
|
635
|
-
externalBoundary :
|
574
|
+
externalBoundary : topologic_core.Wire
|
636
575
|
The input external boundary.
|
637
576
|
internalBoundaries : list , optional
|
638
577
|
The input list of internal boundaries (closed wires). The default is an empty list.
|
@@ -643,11 +582,14 @@ class Face(Topology):
|
|
643
582
|
|
644
583
|
Returns
|
645
584
|
-------
|
646
|
-
|
585
|
+
topologic_core.Face
|
647
586
|
The created face.
|
648
587
|
|
649
588
|
"""
|
650
|
-
|
589
|
+
from topologicpy.Wire import Wire
|
590
|
+
from topologicpy.Topology import Topology
|
591
|
+
|
592
|
+
if not Topology.IsInstance(externalBoundary, "Wire"):
|
651
593
|
if not silent:
|
652
594
|
print("Face.ByWires - Error: The input externalBoundary parameter is not a valid topologic wire. Returning None.")
|
653
595
|
return None
|
@@ -655,10 +597,10 @@ class Face(Topology):
|
|
655
597
|
if not silent:
|
656
598
|
print("Face.ByWires - Error: The input externalBoundary parameter is not a closed topologic wire. Returning None.")
|
657
599
|
return None
|
658
|
-
ibList = [x for x in internalBoundaries if
|
600
|
+
ibList = [x for x in internalBoundaries if Topology.IsInstance(x, "Wire") and Wire.IsClosed(x)]
|
659
601
|
face = None
|
660
602
|
try:
|
661
|
-
face = topologic.Face.ByExternalInternalBoundaries(externalBoundary, ibList, tolerance)
|
603
|
+
face = topologic.Face.ByExternalInternalBoundaries(externalBoundary, ibList, tolerance) # Hook to Core
|
662
604
|
except:
|
663
605
|
if not silent:
|
664
606
|
print("Face.ByWires - Error: The operation failed. Returning None.")
|
@@ -667,15 +609,15 @@ class Face(Topology):
|
|
667
609
|
|
668
610
|
|
669
611
|
@staticmethod
|
670
|
-
def ByWiresCluster(externalBoundary
|
612
|
+
def ByWiresCluster(externalBoundary, internalBoundariesCluster = None, tolerance: float = 0.0001, silent: bool = False):
|
671
613
|
"""
|
672
614
|
Creates a face from the input external boundary (closed wire) and the input cluster of internal boundaries (closed wires).
|
673
615
|
|
674
616
|
Parameters
|
675
617
|
----------
|
676
|
-
externalBoundary
|
618
|
+
externalBoundary topologic_core.Wire
|
677
619
|
The input external boundary (closed wire).
|
678
|
-
internalBoundariesCluster :
|
620
|
+
internalBoundariesCluster : topologic_core.Cluster
|
679
621
|
The input cluster of internal boundaries (closed wires). The default is None.
|
680
622
|
tolerance : float , optional
|
681
623
|
The desired tolerance. The default is 0.0001.
|
@@ -684,13 +626,15 @@ class Face(Topology):
|
|
684
626
|
|
685
627
|
Returns
|
686
628
|
-------
|
687
|
-
|
629
|
+
topologic_core.Face
|
688
630
|
The created face.
|
689
631
|
|
690
632
|
"""
|
691
633
|
from topologicpy.Wire import Wire
|
692
634
|
from topologicpy.Cluster import Cluster
|
693
|
-
|
635
|
+
from topologicpy.Topology import Topology
|
636
|
+
|
637
|
+
if not Topology.IsInstance(externalBoundary, "Wire"):
|
694
638
|
if not silent:
|
695
639
|
print("Face.ByWiresCluster - Error: The input externalBoundary parameter is not a valid topologic wire. Returning None.")
|
696
640
|
return None
|
@@ -700,7 +644,7 @@ class Face(Topology):
|
|
700
644
|
return None
|
701
645
|
if not internalBoundariesCluster:
|
702
646
|
internalBoundaries = []
|
703
|
-
elif not
|
647
|
+
elif not Topology.IsInstance(internalBoundariesCluster, "Cluster"):
|
704
648
|
if not silent:
|
705
649
|
print("Face.ByWiresCluster - Error: The input internalBoundariesCluster parameter is not a valid topologic cluster. Returning None.")
|
706
650
|
return None
|
@@ -709,14 +653,14 @@ class Face(Topology):
|
|
709
653
|
return Face.ByWires(externalBoundary, internalBoundaries, tolerance=tolerance, silent=silent)
|
710
654
|
|
711
655
|
@staticmethod
|
712
|
-
def NorthArrow(origin
|
713
|
-
placement: str = "center", tolerance: float = 0.0001)
|
656
|
+
def NorthArrow(origin= None, radius: float = 0.5, sides: int = 16, direction: list = [0, 0, 1], northAngle: float = 0.0,
|
657
|
+
placement: str = "center", tolerance: float = 0.0001):
|
714
658
|
"""
|
715
659
|
Creates a north arrow.
|
716
660
|
|
717
661
|
Parameters
|
718
662
|
----------
|
719
|
-
origin :
|
663
|
+
origin : topologic_core.Vertex, optional
|
720
664
|
The location of the origin of the circle. The default is None which results in the circle being placed at (0, 0, 0).
|
721
665
|
radius : float , optional
|
722
666
|
The radius of the circle. The default is 1.
|
@@ -733,7 +677,7 @@ class Face(Topology):
|
|
733
677
|
|
734
678
|
Returns
|
735
679
|
-------
|
736
|
-
|
680
|
+
topologic_core.Face
|
737
681
|
The created circle.
|
738
682
|
|
739
683
|
"""
|
@@ -760,14 +704,14 @@ class Face(Topology):
|
|
760
704
|
return arrow
|
761
705
|
|
762
706
|
@staticmethod
|
763
|
-
def Circle(origin
|
764
|
-
placement: str = "center", tolerance: float = 0.0001)
|
707
|
+
def Circle(origin= None, radius: float = 0.5, sides: int = 16, fromAngle: float = 0.0, toAngle: float = 360.0, direction: list = [0, 0, 1],
|
708
|
+
placement: str = "center", tolerance: float = 0.0001):
|
765
709
|
"""
|
766
710
|
Creates a circle.
|
767
711
|
|
768
712
|
Parameters
|
769
713
|
----------
|
770
|
-
origin :
|
714
|
+
origin : topologic_core.Vertex, optional
|
771
715
|
The location of the origin of the circle. The default is None which results in the circle being placed at (0, 0, 0).
|
772
716
|
radius : float , optional
|
773
717
|
The radius of the circle. The default is 1.
|
@@ -786,24 +730,26 @@ class Face(Topology):
|
|
786
730
|
|
787
731
|
Returns
|
788
732
|
-------
|
789
|
-
|
733
|
+
topologic_core.Face
|
790
734
|
The created circle.
|
791
735
|
|
792
736
|
"""
|
793
737
|
from topologicpy.Wire import Wire
|
738
|
+
from topologicpy.Topology import Topology
|
739
|
+
|
794
740
|
wire = Wire.Circle(origin=origin, radius=radius, sides=sides, fromAngle=fromAngle, toAngle=toAngle, close=True, direction=direction, placement=placement, tolerance=tolerance)
|
795
|
-
if not
|
741
|
+
if not Topology.IsInstance(wire, "Wire"):
|
796
742
|
return None
|
797
743
|
return Face.ByWire(wire, tolerance=tolerance)
|
798
744
|
|
799
745
|
@staticmethod
|
800
|
-
def Compactness(face
|
746
|
+
def Compactness(face, mantissa: int = 6) -> float:
|
801
747
|
"""
|
802
748
|
Returns the compactness measure of the input face. See https://en.wikipedia.org/wiki/Compactness_measure_of_a_shape
|
803
749
|
|
804
750
|
Parameters
|
805
751
|
----------
|
806
|
-
face :
|
752
|
+
face : topologic_core.Face
|
807
753
|
The input face.
|
808
754
|
mantissa : int , optional
|
809
755
|
The desired length of the mantissa. The default is 6.
|
@@ -814,12 +760,14 @@ class Face(Topology):
|
|
814
760
|
The compactness measure of the input face.
|
815
761
|
|
816
762
|
"""
|
763
|
+
from topologicpy.Edge import Edge
|
764
|
+
|
817
765
|
exb = face.ExternalBoundary()
|
818
766
|
edges = []
|
819
767
|
_ = exb.Edges(None, edges)
|
820
768
|
perimeter = 0.0
|
821
769
|
for anEdge in edges:
|
822
|
-
perimeter = perimeter + abs(
|
770
|
+
perimeter = perimeter + abs(Edge.Length(anEdge))
|
823
771
|
area = abs(Face.Area(face))
|
824
772
|
compactness = 0
|
825
773
|
#From https://en.wikipedia.org/wiki/Compactness_measure_of_a_shape
|
@@ -832,13 +780,13 @@ class Face(Topology):
|
|
832
780
|
return round(compactness, mantissa)
|
833
781
|
|
834
782
|
@staticmethod
|
835
|
-
def CompassAngle(face
|
783
|
+
def CompassAngle(face, north: list = None, mantissa: int = 6) -> float:
|
836
784
|
"""
|
837
785
|
Returns the horizontal compass angle in degrees between the normal vector of the input face and the input vector. The angle is measured in counter-clockwise fashion. Only the first two elements of the vectors are considered.
|
838
786
|
|
839
787
|
Parameters
|
840
788
|
----------
|
841
|
-
face :
|
789
|
+
face : topologic_core.Face
|
842
790
|
The input face.
|
843
791
|
north : list , optional
|
844
792
|
The second vector representing the north direction. The default is the positive YAxis ([0,1,0]).
|
@@ -854,7 +802,9 @@ class Face(Topology):
|
|
854
802
|
|
855
803
|
"""
|
856
804
|
from topologicpy.Vector import Vector
|
857
|
-
|
805
|
+
from topologicpy.Topology import Topology
|
806
|
+
|
807
|
+
if not Topology.IsInstance(face, "Face"):
|
858
808
|
return None
|
859
809
|
if not north:
|
860
810
|
north = Vector.North()
|
@@ -862,13 +812,13 @@ class Face(Topology):
|
|
862
812
|
return Vector.CompassAngle(vectorA=dirA, vectorB=north, mantissa=mantissa)
|
863
813
|
|
864
814
|
@staticmethod
|
865
|
-
def Edges(face
|
815
|
+
def Edges(face) -> list:
|
866
816
|
"""
|
867
817
|
Returns the edges of the input face.
|
868
818
|
|
869
819
|
Parameters
|
870
820
|
----------
|
871
|
-
face :
|
821
|
+
face : topologic_core.Face
|
872
822
|
The input face.
|
873
823
|
|
874
824
|
Returns
|
@@ -877,21 +827,23 @@ class Face(Topology):
|
|
877
827
|
The list of edges.
|
878
828
|
|
879
829
|
"""
|
880
|
-
|
830
|
+
from topologicpy.Topology import Topology
|
831
|
+
|
832
|
+
if not Topology.IsInstance(face, "Face"):
|
881
833
|
return None
|
882
834
|
edges = []
|
883
835
|
_ = face.Edges(None, edges)
|
884
836
|
return edges
|
885
837
|
|
886
838
|
@staticmethod
|
887
|
-
def Einstein(origin
|
888
|
-
placement: str = "center", tolerance: float = 0.0001)
|
839
|
+
def Einstein(origin= None, radius: float = 0.5, direction: list = [0, 0, 1],
|
840
|
+
placement: str = "center", tolerance: float = 0.0001):
|
889
841
|
"""
|
890
842
|
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
|
891
843
|
|
892
844
|
Parameters
|
893
845
|
----------
|
894
|
-
origin :
|
846
|
+
origin : topologic_core.Vertex , optional
|
895
847
|
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).
|
896
848
|
radius : float , optional
|
897
849
|
The radius of the hexagon determining the size of the tile. The default is 0.5.
|
@@ -904,26 +856,27 @@ class Face(Topology):
|
|
904
856
|
|
905
857
|
Returns
|
906
858
|
--------
|
907
|
-
|
859
|
+
topologic_core.Face
|
908
860
|
The created Einstein tile.
|
909
861
|
|
910
862
|
"""
|
911
863
|
from topologicpy.Wire import Wire
|
864
|
+
from topologicpy.Topology import Topology
|
912
865
|
|
913
866
|
wire = Wire.Einstein(origin=origin, radius=radius, direction=direction, placement=placement)
|
914
|
-
if not
|
867
|
+
if not Topology.IsInstance(wire, "Wire"):
|
915
868
|
print("Face.Einstein - Error: Could not create base wire for the Einstein tile. Returning None.")
|
916
869
|
return None
|
917
870
|
return Face.ByWire(wire, tolerance=tolerance)
|
918
871
|
|
919
872
|
@staticmethod
|
920
|
-
def ExteriorAngles(face
|
873
|
+
def ExteriorAngles(face, includeInternalBoundaries=False, mantissa: int = 6) -> list:
|
921
874
|
"""
|
922
875
|
Returns the exterior angles of the input face in degrees. The face must be planar.
|
923
876
|
|
924
877
|
Parameters
|
925
878
|
----------
|
926
|
-
face :
|
879
|
+
face : topologic_core.Face
|
927
880
|
The input face.
|
928
881
|
includeInternalBoundaries : bool , optional
|
929
882
|
If set to True and if the face has internal boundaries (holes), the returned list will be a nested list where the first list is the list
|
@@ -940,8 +893,9 @@ class Face(Topology):
|
|
940
893
|
"""
|
941
894
|
|
942
895
|
from topologicpy.Wire import Wire
|
896
|
+
from topologicpy.Topology import Topology
|
943
897
|
|
944
|
-
if not
|
898
|
+
if not Topology.IsInstance(face, "Face"):
|
945
899
|
print("Face.ExteriorAngles - Error: The input face parameter is not a valid face. Returning None.")
|
946
900
|
return None
|
947
901
|
eb = Face.ExternalBoundary(face)
|
@@ -958,31 +912,43 @@ class Face(Topology):
|
|
958
912
|
return return_list
|
959
913
|
|
960
914
|
@staticmethod
|
961
|
-
def ExternalBoundary(face
|
915
|
+
def ExternalBoundary(face):
|
962
916
|
"""
|
963
917
|
Returns the external boundary (closed wire) of the input face.
|
964
918
|
|
965
919
|
Parameters
|
966
920
|
----------
|
967
|
-
face :
|
921
|
+
face : topologic_core.Face
|
968
922
|
The input face.
|
969
923
|
|
970
924
|
Returns
|
971
925
|
-------
|
972
|
-
|
926
|
+
topologic_core.Wire
|
973
927
|
The external boundary of the input face.
|
974
928
|
|
975
929
|
"""
|
976
|
-
|
930
|
+
from topologicpy.Vector import Vector
|
931
|
+
from topologicpy.Wire import Wire
|
932
|
+
from topologicpy.Topology import Topology
|
933
|
+
|
934
|
+
eb = face.ExternalBoundary()
|
935
|
+
f_dir = Face.Normal(face)
|
936
|
+
faceVertices = Topology.Vertices(eb)
|
937
|
+
temp_face = Face.ByWire(eb)
|
938
|
+
temp_dir = Face.Normal(temp_face)
|
939
|
+
if Vector.IsAntiParallel(f_dir, temp_dir):
|
940
|
+
faceVertices.reverse()
|
941
|
+
eb = Wire.ByVertices(faceVertices)
|
942
|
+
return eb
|
977
943
|
|
978
944
|
@staticmethod
|
979
|
-
def FacingToward(face
|
945
|
+
def FacingToward(face, direction: list = [0,0,-1], asVertex: bool = False, tolerance: float = 0.0001) -> bool:
|
980
946
|
"""
|
981
947
|
Returns True if the input face is facing toward the input direction.
|
982
948
|
|
983
949
|
Parameters
|
984
950
|
----------
|
985
|
-
face :
|
951
|
+
face : topologic_core.Face
|
986
952
|
The input face.
|
987
953
|
direction : list , optional
|
988
954
|
The input direction. The default is [0,0,-1].
|
@@ -997,8 +963,10 @@ class Face(Topology):
|
|
997
963
|
True if the face is facing toward the direction. False otherwise.
|
998
964
|
|
999
965
|
"""
|
1000
|
-
|
1001
|
-
|
966
|
+
from topologicpy.Vector import Vector
|
967
|
+
|
968
|
+
faceNormal = Face.Normal(face)
|
969
|
+
faceCenter = Face.VertexByParameters(face,0.5,0.5)
|
1002
970
|
cList = [faceCenter.X(), faceCenter.Y(), faceCenter.Z()]
|
1003
971
|
try:
|
1004
972
|
vList = [direction.X(), direction.Y(), direction.Z()]
|
@@ -1017,21 +985,80 @@ class Face(Topology):
|
|
1017
985
|
return False
|
1018
986
|
return True
|
1019
987
|
|
988
|
+
|
1020
989
|
@staticmethod
|
1021
|
-
def
|
990
|
+
def Fillet(face, radius: float = 0, radiusKey: str = None, tolerance: float = 0.0001, silent: bool = False):
|
991
|
+
"""
|
992
|
+
Fillets (rounds) the interior and exterior corners of the input face given the input radius. See https://en.wikipedia.org/wiki/Fillet_(mechanics)
|
993
|
+
|
994
|
+
Parameters
|
995
|
+
----------
|
996
|
+
face : topologic_core.Face
|
997
|
+
The input face.
|
998
|
+
radius : float
|
999
|
+
The desired radius of the fillet.
|
1000
|
+
radiusKey : str , optional
|
1001
|
+
If specified, the dictionary of the vertices will be queried for this key to specify the desired fillet radius. The default is None.
|
1002
|
+
tolerance : float , optional
|
1003
|
+
The desired tolerance. The default is 0.0001.
|
1004
|
+
silent : bool , optional
|
1005
|
+
If set to False, error and warning messages are printed. Otherwise, they are not. The default is False.
|
1006
|
+
|
1007
|
+
Returns
|
1008
|
+
-------
|
1009
|
+
topologic_core.Face
|
1010
|
+
The filleted face.
|
1011
|
+
|
1012
|
+
"""
|
1013
|
+
from topologicpy.Wire import Wire
|
1014
|
+
from topologicpy.Topology import Topology
|
1015
|
+
|
1016
|
+
if not Topology.IsInstance(face, "Face"):
|
1017
|
+
if not silent:
|
1018
|
+
print("Face.Fillet - Error: The input face parameter is not a valid face. Returning None.")
|
1019
|
+
return None
|
1020
|
+
|
1021
|
+
eb = Topology.Copy(Face.ExternalBoundary(face))
|
1022
|
+
ib_list = Face.InternalBoundaries(face)
|
1023
|
+
ib_list = [Topology.Copy(ib) for ib in ib_list]
|
1024
|
+
f_vertices = Face.Vertices(face)
|
1025
|
+
if isinstance(radiusKey, str):
|
1026
|
+
eb = Topology.TransferDictionariesBySelectors(eb, selectors=f_vertices, tranVertices=True)
|
1027
|
+
eb = Wire.Fillet(eb, radius=radius, radiusKey=radiusKey, tolerance=tolerance)
|
1028
|
+
if not Topology.IsInstance(eb, "Wire"):
|
1029
|
+
if not silent:
|
1030
|
+
print("Face.Fillet - Error: The operation failed. Returning None.")
|
1031
|
+
return None
|
1032
|
+
ib_wires = []
|
1033
|
+
for ib in ib_list:
|
1034
|
+
ib = Wire.ByVertices(Topology.Vertices(ib))
|
1035
|
+
ib = Wire.Reverse(ib)
|
1036
|
+
if isinstance(radiusKey, str):
|
1037
|
+
ib = Topology.TransferDictionariesBySelectors(ib, selectors=f_vertices, tranVertices=True)
|
1038
|
+
|
1039
|
+
ib_wire = Wire.Fillet(ib, radius=radius, radiusKey=radiusKey, tolerance=tolerance, silent=silent)
|
1040
|
+
if Topology.IsInstance(ib, "Wire"):
|
1041
|
+
ib_wires.append(ib_wire)
|
1042
|
+
else:
|
1043
|
+
if not silent:
|
1044
|
+
print("Face.Fillet - Error: The operation for one of the interior boundaries failed. Skipping.")
|
1045
|
+
return Face.ByWires(eb, ib_wires)
|
1046
|
+
|
1047
|
+
@staticmethod
|
1048
|
+
def Harmonize(face, tolerance: float = 0.0001):
|
1022
1049
|
"""
|
1023
1050
|
Returns a harmonized version of the input face such that the *u* and *v* origins are always in the upperleft corner.
|
1024
1051
|
|
1025
1052
|
Parameters
|
1026
1053
|
----------
|
1027
|
-
face :
|
1054
|
+
face : topologic_core.Face
|
1028
1055
|
The input face.
|
1029
1056
|
tolerance : float , optional
|
1030
1057
|
The desired tolerance. The default is 0.0001.
|
1031
1058
|
|
1032
1059
|
Returns
|
1033
1060
|
-------
|
1034
|
-
|
1061
|
+
topologic_core.Face
|
1035
1062
|
The harmonized face.
|
1036
1063
|
|
1037
1064
|
"""
|
@@ -1040,7 +1067,7 @@ class Face(Topology):
|
|
1040
1067
|
from topologicpy.Topology import Topology
|
1041
1068
|
from topologicpy.Dictionary import Dictionary
|
1042
1069
|
|
1043
|
-
if not
|
1070
|
+
if not Topology.IsInstance(face, "Face"):
|
1044
1071
|
print("Face.Harmonize - Error: The input face parameter is not a valid face. Returning None.")
|
1045
1072
|
return None
|
1046
1073
|
normal = Face.Normal(face)
|
@@ -1059,13 +1086,13 @@ class Face(Topology):
|
|
1059
1086
|
return harmonizedFace
|
1060
1087
|
|
1061
1088
|
@staticmethod
|
1062
|
-
def InteriorAngles(face
|
1089
|
+
def InteriorAngles(face, includeInternalBoundaries: bool = False, mantissa: int = 6) -> list:
|
1063
1090
|
"""
|
1064
1091
|
Returns the interior angles of the input face in degrees. The face must be planar.
|
1065
1092
|
|
1066
1093
|
Parameters
|
1067
1094
|
----------
|
1068
|
-
face :
|
1095
|
+
face : topologic_core.Face
|
1069
1096
|
The input face.
|
1070
1097
|
includeInternalBoundaries : bool , optional
|
1071
1098
|
If set to True and if the face has internal boundaries (holes), the returned list will be a nested list where the first list is the list
|
@@ -1080,10 +1107,10 @@ class Face(Topology):
|
|
1080
1107
|
list
|
1081
1108
|
The list of interior angles.
|
1082
1109
|
"""
|
1083
|
-
|
1084
1110
|
from topologicpy.Wire import Wire
|
1111
|
+
from topologicpy.Topology import Topology
|
1085
1112
|
|
1086
|
-
if not
|
1113
|
+
if not Topology.IsInstance(face, "Face"):
|
1087
1114
|
print("Face.InteriorAngles - Error: The input face parameter is not a valid face. Returning None.")
|
1088
1115
|
return None
|
1089
1116
|
eb = Face.ExternalBoundary(face)
|
@@ -1100,13 +1127,13 @@ class Face(Topology):
|
|
1100
1127
|
return return_list
|
1101
1128
|
|
1102
1129
|
@staticmethod
|
1103
|
-
def InternalBoundaries(face
|
1130
|
+
def InternalBoundaries(face) -> list:
|
1104
1131
|
"""
|
1105
1132
|
Returns the internal boundaries (closed wires) of the input face.
|
1106
1133
|
|
1107
1134
|
Parameters
|
1108
1135
|
----------
|
1109
|
-
face :
|
1136
|
+
face : topologic_core.Face
|
1110
1137
|
The input face.
|
1111
1138
|
|
1112
1139
|
Returns
|
@@ -1115,33 +1142,36 @@ class Face(Topology):
|
|
1115
1142
|
The list of internal boundaries (closed wires).
|
1116
1143
|
|
1117
1144
|
"""
|
1118
|
-
|
1145
|
+
from topologicpy.Topology import Topology
|
1146
|
+
|
1147
|
+
if not Topology.IsInstance(face, "Face"):
|
1119
1148
|
return None
|
1120
1149
|
wires = []
|
1121
1150
|
_ = face.InternalBoundaries(wires)
|
1122
1151
|
return list(wires)
|
1123
1152
|
|
1124
1153
|
@staticmethod
|
1125
|
-
def InternalVertex(face
|
1154
|
+
def InternalVertex(face, tolerance: float = 0.0001):
|
1126
1155
|
"""
|
1127
1156
|
Creates a vertex guaranteed to be inside the input face.
|
1128
1157
|
|
1129
1158
|
Parameters
|
1130
1159
|
----------
|
1131
|
-
face :
|
1160
|
+
face : topologic_core.Face
|
1132
1161
|
The input face.
|
1133
1162
|
tolerance : float , optional
|
1134
1163
|
The desired tolerance. The default is 0.0001.
|
1135
1164
|
|
1136
1165
|
Returns
|
1137
1166
|
-------
|
1138
|
-
|
1167
|
+
topologic_core.Vertex
|
1139
1168
|
The created vertex.
|
1140
1169
|
|
1141
1170
|
"""
|
1142
1171
|
from topologicpy.Vertex import Vertex
|
1143
1172
|
from topologicpy.Topology import Topology
|
1144
|
-
|
1173
|
+
|
1174
|
+
if not Topology.IsInstance(face, "Face"):
|
1145
1175
|
return None
|
1146
1176
|
v = Topology.Centroid(face)
|
1147
1177
|
if Vertex.IsInternal(v, face, tolerance=tolerance):
|
@@ -1152,30 +1182,31 @@ class Face(Topology):
|
|
1152
1182
|
v = Face.VertexByParameters(face, u, v)
|
1153
1183
|
if Vertex.IsInternal(v, face, tolerance=tolerance):
|
1154
1184
|
return v
|
1155
|
-
v = topologic.FaceUtility.InternalVertex(face, tolerance)
|
1185
|
+
v = topologic.FaceUtility.InternalVertex(face, tolerance) # Hook to Core
|
1156
1186
|
return v
|
1157
1187
|
|
1158
1188
|
@staticmethod
|
1159
|
-
def Invert(face
|
1189
|
+
def Invert(face, tolerance: float = 0.0001):
|
1160
1190
|
"""
|
1161
1191
|
Creates a face that is an inverse (mirror) of the input face.
|
1162
1192
|
|
1163
1193
|
Parameters
|
1164
1194
|
----------
|
1165
|
-
face :
|
1195
|
+
face : topologic_core.Face
|
1166
1196
|
The input face.
|
1167
1197
|
tolerance : float , optional
|
1168
1198
|
The desired tolerance. The default is 0.0001.
|
1169
1199
|
|
1170
1200
|
Returns
|
1171
1201
|
-------
|
1172
|
-
|
1202
|
+
topologic_core.Face
|
1173
1203
|
The inverted face.
|
1174
1204
|
|
1175
1205
|
"""
|
1176
1206
|
from topologicpy.Wire import Wire
|
1207
|
+
from topologicpy.Topology import Topology
|
1177
1208
|
|
1178
|
-
if not
|
1209
|
+
if not Topology.IsInstance(face, "Face"):
|
1179
1210
|
return None
|
1180
1211
|
eb = Face.ExternalBoundary(face)
|
1181
1212
|
vertices = Wire.Vertices(eb)
|
@@ -1189,15 +1220,15 @@ class Face(Topology):
|
|
1189
1220
|
return inverted_face
|
1190
1221
|
|
1191
1222
|
@staticmethod
|
1192
|
-
def IsCoplanar(faceA
|
1223
|
+
def IsCoplanar(faceA, faceB, tolerance: float = 0.0001) -> bool:
|
1193
1224
|
"""
|
1194
1225
|
Returns True if the two input faces are coplanar. Returns False otherwise.
|
1195
1226
|
|
1196
1227
|
Parameters
|
1197
1228
|
----------
|
1198
|
-
faceA :
|
1229
|
+
faceA : topologic_core.Face
|
1199
1230
|
The first input face.
|
1200
|
-
faceB :
|
1231
|
+
faceB : topologic_core.Face
|
1201
1232
|
The second input face
|
1202
1233
|
tolerance : float , optional
|
1203
1234
|
The desired tolerance. The deafault is 0.0001.
|
@@ -1213,24 +1244,112 @@ class Face(Topology):
|
|
1213
1244
|
True if the two input faces are coplanar. False otherwise.
|
1214
1245
|
|
1215
1246
|
"""
|
1216
|
-
|
1247
|
+
from topologicpy.Vector import Vector
|
1248
|
+
from topologicpy.Topology import Topology
|
1249
|
+
|
1250
|
+
if not Topology.IsInstance(faceA, "Face"):
|
1217
1251
|
print("Face.IsInide - Error: The input faceA parameter is not a valid topologic face. Returning None.")
|
1218
1252
|
return None
|
1219
|
-
if not
|
1253
|
+
if not Topology.IsInstance(faceB, "Face"):
|
1220
1254
|
print("Face.IsInide - Error: The input faceB parameter is not a valid topologic face. Returning None.")
|
1221
1255
|
return None
|
1222
1256
|
dirA = Face.NormalAtParameters(faceA, 0.5, 0.5, "xyz", 3)
|
1223
1257
|
dirB = Face.NormalAtParameters(faceB, 0.5, 0.5, "xyz", 3)
|
1224
1258
|
return Vector.IsCollinear(dirA, dirB)
|
1225
|
-
|
1259
|
+
|
1260
|
+
@staticmethod
|
1261
|
+
def Isovist(face, vertex, obstacles = None, fromAngle=0, toAngle=360, tolerance: float = 0.0001):
|
1262
|
+
"""
|
1263
|
+
Returns the face representing the isovist projection from the input viewpoint.
|
1264
|
+
This method assumes all input is in 2D. Z coordinates are ignored.
|
1265
|
+
|
1266
|
+
Parameters
|
1267
|
+
----------
|
1268
|
+
face : topologic_core.Face
|
1269
|
+
The face representing the boundary of the isovist.
|
1270
|
+
vertex : topologic_core.Vertex
|
1271
|
+
The vertex representing the location of the viewpoint of the isovist.
|
1272
|
+
obstacles : list , optional
|
1273
|
+
A list of wires representing the obstacles within the face. All obstacles are assumed to be within the
|
1274
|
+
boundary of the face.
|
1275
|
+
fromAngle : float , optional
|
1276
|
+
The angle in degrees from which to start creating the arc of the circle. The default is 0.
|
1277
|
+
0 is considered to be in the positive X-axis direction. 90 is considered to be in the
|
1278
|
+
positive Y-axis direction.
|
1279
|
+
toAngle : float , optional
|
1280
|
+
The angle in degrees at which to end creating the arc of the circle. The default is 360.
|
1281
|
+
Angles are measured in an anti-clockwise fashion.
|
1282
|
+
tolerance : float , optional:
|
1283
|
+
The desired tolerance. The default is 0.0001.
|
1284
|
+
|
1285
|
+
Returns
|
1286
|
+
-------
|
1287
|
+
topologic_core.Face
|
1288
|
+
The face representing the isovist projection from the input viewpoint.
|
1289
|
+
|
1290
|
+
"""
|
1291
|
+
from topologicpy.Vertex import Vertex
|
1292
|
+
from topologicpy.Edge import Edge
|
1293
|
+
from topologicpy.Wire import Wire
|
1294
|
+
from topologicpy.Face import Face
|
1295
|
+
from topologicpy.Shell import Shell
|
1296
|
+
from topologicpy.Cluster import Cluster
|
1297
|
+
from topologicpy.Topology import Topology
|
1298
|
+
|
1299
|
+
def vertexPartofFace(vertex, face, tolerance):
|
1300
|
+
vertices = []
|
1301
|
+
_ = face.Vertices(None, vertices)
|
1302
|
+
for v in vertices:
|
1303
|
+
if Vertex.Distance(vertex, v) < tolerance:
|
1304
|
+
return True
|
1305
|
+
return False
|
1306
|
+
|
1307
|
+
if not Topology.IsInstance(face, "Face"):
|
1308
|
+
print("Face.Isovist - Error: The input boundary parameter is not a valid Face. Returning None")
|
1309
|
+
return None
|
1310
|
+
if not Topology.IsInstance(vertex, "Vertex"):
|
1311
|
+
print("Face.Isovist - Error: The input viewPoint parameter is not a valid Vertex. Returning None")
|
1312
|
+
return None
|
1313
|
+
if isinstance(obstacles, list):
|
1314
|
+
obstacles = [obs for obs in obstacles if Topology.IsInstance(obs, "Wire")]
|
1315
|
+
for obs in obstacles:
|
1316
|
+
face = Topology.Difference(face, Face.ByWire(obs))
|
1317
|
+
targets = Topology.Vertices(face)
|
1318
|
+
distances = []
|
1319
|
+
for target in targets:
|
1320
|
+
distances.append(Vertex.Distance(vertex, target))
|
1321
|
+
distances.sort()
|
1322
|
+
max_d = distances[-1]*1.05
|
1323
|
+
edges = []
|
1324
|
+
for target in targets:
|
1325
|
+
e = Edge.ByVertices(vertex, target)
|
1326
|
+
e = Edge.SetLength(e, length=max_d, bothSides=False)
|
1327
|
+
edges.append(e)
|
1328
|
+
shell = Topology.Slice(face, Cluster.ByTopologies(edges))
|
1329
|
+
faces = Topology.Faces(shell)
|
1330
|
+
final_faces = []
|
1331
|
+
for face in faces:
|
1332
|
+
if vertexPartofFace(vertex, face, tolerance=0.001):
|
1333
|
+
final_faces.append(face)
|
1334
|
+
shell = Shell.ByFaces(final_faces)
|
1335
|
+
return_face = Topology.RemoveCoplanarFaces(shell)
|
1336
|
+
if abs(360 - toAngle - fromAngle) > tolerance:
|
1337
|
+
c = Wire.Circle(origin= vertex, radius=max_d, sides=180, fromAngle=fromAngle, toAngle=toAngle, close = False)
|
1338
|
+
e1 = Edge.ByVertices(Wire.StartVertex(c), vertex)
|
1339
|
+
e2 = Edge.ByVertices(Wire.EndVertex(c), vertex)
|
1340
|
+
edges = Topology.Edges(c) + [e1,e2]
|
1341
|
+
pie = Face.ByWire(Topology.SelfMerge(Cluster.ByTopologies(edges)))
|
1342
|
+
return_face = Topology.Intersect(pie, return_face)
|
1343
|
+
return return_face
|
1344
|
+
|
1226
1345
|
@staticmethod
|
1227
|
-
def MedialAxis(face
|
1346
|
+
def MedialAxis(face, resolution: int = 0, externalVertices: bool = False, internalVertices: bool = False, toLeavesOnly: bool = False, angTolerance: float = 0.1, tolerance: float = 0.0001):
|
1228
1347
|
"""
|
1229
1348
|
Returns a wire representing an approximation of the medial axis of the input topology. See https://en.wikipedia.org/wiki/Medial_axis.
|
1230
1349
|
|
1231
1350
|
Parameters
|
1232
1351
|
----------
|
1233
|
-
face :
|
1352
|
+
face : topologic_core.Face
|
1234
1353
|
The input face.
|
1235
1354
|
resolution : int , optional
|
1236
1355
|
The desired resolution of the solution (range is 0: standard resolution to 10: high resolution). This determines the density of the sampling along each edge. The default is 0.
|
@@ -1247,7 +1366,7 @@ class Face(Topology):
|
|
1247
1366
|
|
1248
1367
|
Returns
|
1249
1368
|
-------
|
1250
|
-
|
1369
|
+
topologic_core.Wire
|
1251
1370
|
The medial axis of the input face.
|
1252
1371
|
|
1253
1372
|
"""
|
@@ -1260,7 +1379,7 @@ class Face(Topology):
|
|
1260
1379
|
from topologicpy.Dictionary import Dictionary
|
1261
1380
|
|
1262
1381
|
def touchesEdge(vertex,edges, tolerance=0.0001):
|
1263
|
-
if not
|
1382
|
+
if not Topology.IsInstance(vertex, "Vertex"):
|
1264
1383
|
return False
|
1265
1384
|
for edge in edges:
|
1266
1385
|
u = Edge.ParameterAtVertex(edge, vertex, mantissa=6)
|
@@ -1313,13 +1432,13 @@ class Face(Topology):
|
|
1313
1432
|
theVertices = theVertices+extVertices
|
1314
1433
|
|
1315
1434
|
tempWire = Topology.SelfMerge(Cluster.ByTopologies(medialAxisEdges), tolerance=tolerance)
|
1316
|
-
if
|
1435
|
+
if Topology.IsInstance(tempWire, "Wire") and angTolerance > 0:
|
1317
1436
|
tempWire = Wire.RemoveCollinearEdges(tempWire, angTolerance=angTolerance)
|
1318
1437
|
medialAxisEdges = Wire.Edges(tempWire)
|
1319
1438
|
for v in theVertices:
|
1320
1439
|
nv = Vertex.NearestVertex(v, tempWire, useKDTree=False)
|
1321
1440
|
|
1322
|
-
if
|
1441
|
+
if Topology.IsInstance(nv, "Vertex"):
|
1323
1442
|
if toLeavesOnly:
|
1324
1443
|
adjVertices = Topology.AdjacentTopologies(nv, tempWire)
|
1325
1444
|
if len(adjVertices) < 2:
|
@@ -1327,19 +1446,19 @@ class Face(Topology):
|
|
1327
1446
|
else:
|
1328
1447
|
medialAxisEdges.append(Edge.ByVertices([nv, v], tolerance=tolerance))
|
1329
1448
|
medialAxis = Topology.SelfMerge(Cluster.ByTopologies(medialAxisEdges), tolerance=tolerance)
|
1330
|
-
if
|
1449
|
+
if Topology.IsInstance(medialAxis, "Wire") and angTolerance > 0:
|
1331
1450
|
medialAxis = Topology.RemoveCollinearEdges(medialAxis, angTolerance=angTolerance)
|
1332
1451
|
medialAxis = Topology.Unflatten(medialAxis, origin=origin,direction=normal)
|
1333
1452
|
return medialAxis
|
1334
1453
|
|
1335
1454
|
@staticmethod
|
1336
|
-
def Normal(face
|
1455
|
+
def Normal(face, outputType: str = "xyz", mantissa: int = 6) -> list:
|
1337
1456
|
"""
|
1338
1457
|
Returns the normal vector to the input face. A normal vector of a face is a vector perpendicular to it.
|
1339
1458
|
|
1340
1459
|
Parameters
|
1341
1460
|
----------
|
1342
|
-
face :
|
1461
|
+
face : topologic_core.Face
|
1343
1462
|
The input face.
|
1344
1463
|
outputType : string , optional
|
1345
1464
|
The string defining the desired output. This can be any subset or permutation of "xyz". It is case insensitive. The default is "xyz".
|
@@ -1355,13 +1474,13 @@ class Face(Topology):
|
|
1355
1474
|
return Face.NormalAtParameters(face, u=0.5, v=0.5, outputType=outputType, mantissa=mantissa)
|
1356
1475
|
|
1357
1476
|
@staticmethod
|
1358
|
-
def NormalAtParameters(face
|
1477
|
+
def NormalAtParameters(face, u: float = 0.5, v: float = 0.5, outputType: str = "xyz", mantissa: int = 6) -> list:
|
1359
1478
|
"""
|
1360
1479
|
Returns the normal vector to the input face. A normal vector of a face is a vector perpendicular to it.
|
1361
1480
|
|
1362
1481
|
Parameters
|
1363
1482
|
----------
|
1364
|
-
face :
|
1483
|
+
face : topologic_core.Face
|
1365
1484
|
The input face.
|
1366
1485
|
u : float , optional
|
1367
1486
|
The *u* parameter at which to compute the normal to the input face. The default is 0.5.
|
@@ -1380,7 +1499,7 @@ class Face(Topology):
|
|
1380
1499
|
"""
|
1381
1500
|
returnResult = []
|
1382
1501
|
try:
|
1383
|
-
coords = topologic.FaceUtility.NormalAtParameters(face, u, v)
|
1502
|
+
coords = topologic.FaceUtility.NormalAtParameters(face, u, v) # Hook to Core
|
1384
1503
|
x = round(coords[0], mantissa)
|
1385
1504
|
y = round(coords[1], mantissa)
|
1386
1505
|
z = round(coords[2], mantissa)
|
@@ -1397,13 +1516,13 @@ class Face(Topology):
|
|
1397
1516
|
return returnResult
|
1398
1517
|
|
1399
1518
|
@staticmethod
|
1400
|
-
def NormalEdge(face
|
1519
|
+
def NormalEdge(face, length: float = 1.0, tolerance: float = 0.0001, silent: bool = False):
|
1401
1520
|
"""
|
1402
1521
|
Returns the normal vector to the input face as an edge with the desired input length. A normal vector of a face is a vector perpendicular to it.
|
1403
1522
|
|
1404
1523
|
Parameters
|
1405
1524
|
----------
|
1406
|
-
face :
|
1525
|
+
face : topologic_core.Face
|
1407
1526
|
The input face.
|
1408
1527
|
length : float , optional
|
1409
1528
|
The desired length of the normal edge. The default is 1.
|
@@ -1412,13 +1531,14 @@ class Face(Topology):
|
|
1412
1531
|
|
1413
1532
|
Returns
|
1414
1533
|
-------
|
1415
|
-
|
1534
|
+
topologic_core.Edge
|
1416
1535
|
The created normal edge to the input face. This is computed at the approximate center of the face.
|
1417
1536
|
|
1418
1537
|
"""
|
1419
1538
|
from topologicpy.Edge import Edge
|
1539
|
+
from topologicpy.Topology import Topology
|
1420
1540
|
|
1421
|
-
if not
|
1541
|
+
if not Topology.IsInstance(face, "Face"):
|
1422
1542
|
if not silent:
|
1423
1543
|
print("Face.NormalEdge - Error: The input face parameter is not a valid face. Retuning None.")
|
1424
1544
|
return None
|
@@ -1433,13 +1553,13 @@ class Face(Topology):
|
|
1433
1553
|
return Edge.ByVertices([iv, ev], tolerance=tolerance, silent=silent)
|
1434
1554
|
|
1435
1555
|
@staticmethod
|
1436
|
-
def NormalEdgeAtParameters(face
|
1556
|
+
def NormalEdgeAtParameters(face, u: float = 0.5, v: float = 0.5, length: float = 1.0, tolerance: float = 0.0001):
|
1437
1557
|
"""
|
1438
1558
|
Returns the normal vector to the input face as an edge with the desired input length. A normal vector of a face is a vector perpendicular to it.
|
1439
1559
|
|
1440
1560
|
Parameters
|
1441
1561
|
----------
|
1442
|
-
face :
|
1562
|
+
face : topologic_core.Face
|
1443
1563
|
The input face.
|
1444
1564
|
u : float , optional
|
1445
1565
|
The *u* parameter at which to compute the normal to the input face. The default is 0.5.
|
@@ -1452,13 +1572,13 @@ class Face(Topology):
|
|
1452
1572
|
|
1453
1573
|
Returns
|
1454
1574
|
-------
|
1455
|
-
|
1575
|
+
topologic_core.Edge
|
1456
1576
|
The created normal edge to the input face. This is computed at the approximate center of the face.
|
1457
1577
|
|
1458
1578
|
"""
|
1459
1579
|
from topologicpy.Edge import Edge
|
1460
1580
|
from topologicpy.Topology import Topology
|
1461
|
-
if not
|
1581
|
+
if not Topology.IsInstance(face, "Face"):
|
1462
1582
|
return None
|
1463
1583
|
sv = Face.VertexByParameters(face=face, u=u, v=v)
|
1464
1584
|
vec = Face.NormalAtParameters(face, u=u, v=v)
|
@@ -1466,13 +1586,13 @@ class Face(Topology):
|
|
1466
1586
|
return Edge.ByVertices([sv, ev], tolerance=tolerance, silent=True)
|
1467
1587
|
|
1468
1588
|
@staticmethod
|
1469
|
-
def PlaneEquation(face
|
1589
|
+
def PlaneEquation(face, mantissa: int = 6) -> dict:
|
1470
1590
|
"""
|
1471
1591
|
Returns the a, b, c, d coefficients of the plane equation of the input face. The input face is assumed to be planar.
|
1472
1592
|
|
1473
1593
|
Parameters
|
1474
1594
|
----------
|
1475
|
-
face :
|
1595
|
+
face : topologic_core.Face
|
1476
1596
|
The input face.
|
1477
1597
|
|
1478
1598
|
Returns
|
@@ -1486,7 +1606,7 @@ class Face(Topology):
|
|
1486
1606
|
import random
|
1487
1607
|
import time
|
1488
1608
|
|
1489
|
-
if not
|
1609
|
+
if not Topology.IsInstance(face, "Face"):
|
1490
1610
|
print("Face.PlaneEquation - Error: The input face is not a valid topologic face. Returning None.")
|
1491
1611
|
return None
|
1492
1612
|
vertices = Topology.Vertices(face)
|
@@ -1496,23 +1616,23 @@ class Face(Topology):
|
|
1496
1616
|
return Vertex.PlaneEquation(vertices, mantissa=mantissa)
|
1497
1617
|
|
1498
1618
|
@staticmethod
|
1499
|
-
def Planarize(face
|
1500
|
-
tolerance: float = 0.0001)
|
1619
|
+
def Planarize(face, origin= None,
|
1620
|
+
tolerance: float = 0.0001):
|
1501
1621
|
"""
|
1502
1622
|
Planarizes the input face such that its center of mass is located at the input origin and its normal is pointed in the input direction.
|
1503
1623
|
|
1504
1624
|
Parameters
|
1505
1625
|
----------
|
1506
|
-
face :
|
1626
|
+
face : topologic_core.Face
|
1507
1627
|
The input face.
|
1508
|
-
origin :
|
1628
|
+
origin : topologic_core.Vertex , optional
|
1509
1629
|
The desired vertex to use as the origin of the plane to project the face unto. If set to None, the centroidof the input face is used. The default is None.
|
1510
1630
|
tolerance : float , optional
|
1511
1631
|
The desired tolerance. The default is 0.0001.
|
1512
1632
|
|
1513
1633
|
Returns
|
1514
1634
|
-------
|
1515
|
-
|
1635
|
+
topologic_core.Face
|
1516
1636
|
The planarized face.
|
1517
1637
|
|
1518
1638
|
"""
|
@@ -1520,9 +1640,9 @@ class Face(Topology):
|
|
1520
1640
|
from topologicpy.Wire import Wire
|
1521
1641
|
from topologicpy.Topology import Topology
|
1522
1642
|
|
1523
|
-
if not
|
1643
|
+
if not Topology.IsInstance(face, "Face"):
|
1524
1644
|
return None
|
1525
|
-
if not
|
1645
|
+
if not Topology.IsInstance(origin, "Vertex"):
|
1526
1646
|
origin = Topology.Centroid(face)
|
1527
1647
|
eb = Face.ExternalBoundary(face)
|
1528
1648
|
plan_eb = Wire.Planarize(eb, origin=origin)
|
@@ -1534,16 +1654,16 @@ class Face(Topology):
|
|
1534
1654
|
return plan_face
|
1535
1655
|
|
1536
1656
|
@staticmethod
|
1537
|
-
def Project(faceA
|
1538
|
-
mantissa: int = 6, tolerance: float = 0.0001)
|
1657
|
+
def Project(faceA, faceB, direction : list = None,
|
1658
|
+
mantissa: int = 6, tolerance: float = 0.0001):
|
1539
1659
|
"""
|
1540
1660
|
Creates a projection of the first input face unto the second input face.
|
1541
1661
|
|
1542
1662
|
Parameters
|
1543
1663
|
----------
|
1544
|
-
faceA :
|
1664
|
+
faceA : topologic_core.Face
|
1545
1665
|
The face to be projected.
|
1546
|
-
faceB :
|
1666
|
+
faceB : topologic_core.Face
|
1547
1667
|
The face unto which the first input face will be projected.
|
1548
1668
|
direction : list, optional
|
1549
1669
|
The vector direction of the projection. If None, the reverse vector of the receiving face normal will be used. The default is None.
|
@@ -1554,20 +1674,20 @@ class Face(Topology):
|
|
1554
1674
|
|
1555
1675
|
Returns
|
1556
1676
|
-------
|
1557
|
-
|
1677
|
+
topologic_core.Face
|
1558
1678
|
The projected Face.
|
1559
1679
|
|
1560
1680
|
"""
|
1561
|
-
|
1562
1681
|
from topologicpy.Wire import Wire
|
1682
|
+
from topologicpy.Topology import Topology
|
1563
1683
|
|
1564
1684
|
if not faceA:
|
1565
1685
|
return None
|
1566
|
-
if not
|
1686
|
+
if not Topology.IsInstance(faceA, "Face"):
|
1567
1687
|
return None
|
1568
1688
|
if not faceB:
|
1569
1689
|
return None
|
1570
|
-
if not
|
1690
|
+
if not Topology.IsInstance(faceB, "Face"):
|
1571
1691
|
return None
|
1572
1692
|
|
1573
1693
|
eb = faceA.ExternalBoundary()
|
@@ -1582,7 +1702,7 @@ class Face(Topology):
|
|
1582
1702
|
return Face.ByWires(p_eb, p_ib_list, tolerance=tolerance)
|
1583
1703
|
|
1584
1704
|
@staticmethod
|
1585
|
-
def RectangleByPlaneEquation(origin
|
1705
|
+
def RectangleByPlaneEquation(origin= None, width: float = 1.0, length: float = 1.0, placement: str = "center", equation: dict = None, tolerance: float = 0.0001):
|
1586
1706
|
from topologicpy.Vertex import Vertex
|
1587
1707
|
# Extract coefficients of the plane equation
|
1588
1708
|
a = equation['a']
|
@@ -1598,13 +1718,13 @@ class Face(Topology):
|
|
1598
1718
|
return Face.Rectangle(origin=origin, width=width, length=length, direction = direction, placement=placement, tolerance=tolerance)
|
1599
1719
|
|
1600
1720
|
@staticmethod
|
1601
|
-
def Rectangle(origin
|
1721
|
+
def Rectangle(origin= None, width: float = 1.0, length: float = 1.0, direction: list = [0, 0, 1], placement: str = "center", tolerance: float = 0.0001):
|
1602
1722
|
"""
|
1603
1723
|
Creates a rectangle.
|
1604
1724
|
|
1605
1725
|
Parameters
|
1606
1726
|
----------
|
1607
|
-
origin :
|
1727
|
+
origin : topologic_core.Vertex, optional
|
1608
1728
|
The location of the origin of the rectangle. The default is None which results in the rectangle being placed at (0, 0, 0).
|
1609
1729
|
width : float , optional
|
1610
1730
|
The width of the rectangle. The default is 1.0.
|
@@ -1619,26 +1739,27 @@ class Face(Topology):
|
|
1619
1739
|
|
1620
1740
|
Returns
|
1621
1741
|
-------
|
1622
|
-
|
1742
|
+
topologic_core.Face
|
1623
1743
|
The created face.
|
1624
1744
|
|
1625
1745
|
"""
|
1626
1746
|
from topologicpy.Wire import Wire
|
1747
|
+
from topologicpy.Topology import Topology
|
1627
1748
|
|
1628
1749
|
wire = Wire.Rectangle(origin=origin, width=width, length=length, direction=direction, placement=placement, tolerance=tolerance)
|
1629
|
-
if not
|
1750
|
+
if not Topology.IsInstance(wire, "Wire"):
|
1630
1751
|
print("Face.Rectangle - Error: Could not create the base wire for the rectangle. Returning None.")
|
1631
1752
|
return None
|
1632
1753
|
return Face.ByWire(wire, tolerance=tolerance)
|
1633
1754
|
|
1634
1755
|
@staticmethod
|
1635
|
-
def RemoveCollinearEdges(face
|
1756
|
+
def RemoveCollinearEdges(face, angTolerance: float = 0.1, tolerance: float = 0.0001):
|
1636
1757
|
"""
|
1637
1758
|
Removes any collinear edges in the input face.
|
1638
1759
|
|
1639
1760
|
Parameters
|
1640
1761
|
----------
|
1641
|
-
face :
|
1762
|
+
face : topologic_core.Face
|
1642
1763
|
The input face.
|
1643
1764
|
angTolerance : float , optional
|
1644
1765
|
The desired angular tolerance. The default is 0.1.
|
@@ -1647,19 +1768,51 @@ class Face(Topology):
|
|
1647
1768
|
|
1648
1769
|
Returns
|
1649
1770
|
-------
|
1650
|
-
|
1771
|
+
topologic_core.Face
|
1651
1772
|
The created face without any collinear edges.
|
1652
1773
|
|
1653
1774
|
"""
|
1654
1775
|
from topologicpy.Wire import Wire
|
1776
|
+
from topologicpy.Topology import Topology
|
1655
1777
|
|
1656
|
-
if not
|
1778
|
+
if not Topology.IsInstance(face, "Face"):
|
1657
1779
|
print("Face.RemoveCollinearEdges - Error: The input face parameter is not a valid face. Returning None.")
|
1658
1780
|
return None
|
1659
1781
|
eb = Wire.RemoveCollinearEdges(Face.Wire(face), angTolerance=angTolerance, tolerance=tolerance)
|
1660
1782
|
ib = [Wire.RemoveCollinearEdges(w, angTolerance=angTolerance, tolerance=tolerance) for w in Face.InternalBoundaries(face)]
|
1661
1783
|
return Face.ByWires(eb, ib)
|
1662
1784
|
|
1785
|
+
@staticmethod
|
1786
|
+
def Simplify(face, tolerance=0.0001):
|
1787
|
+
"""
|
1788
|
+
Simplifies the input face edges based on the Douglas Peucker algorthim. See https://en.wikipedia.org/wiki/Ramer%E2%80%93Douglas%E2%80%93Peucker_algorithm
|
1789
|
+
Part of this code was contributed by gaoxipeng. See https://github.com/wassimj/topologicpy/issues/35
|
1790
|
+
|
1791
|
+
Parameters
|
1792
|
+
----------
|
1793
|
+
face : topologic_core.Face
|
1794
|
+
The input face.
|
1795
|
+
tolerance : float , optional
|
1796
|
+
The desired tolerance. The default is 0.0001. Edges shorter than this length will be removed.
|
1797
|
+
|
1798
|
+
Returns
|
1799
|
+
-------
|
1800
|
+
topologic_core.Face
|
1801
|
+
The simplified face.
|
1802
|
+
"""
|
1803
|
+
from topologicpy.Wire import Wire
|
1804
|
+
from topologicpy.Topology import Topology
|
1805
|
+
|
1806
|
+
if not Topology.IsInstance(face, "Face"):
|
1807
|
+
print("Face.Simplify - Error: The input face parameter is not a valid face. Returning None.")
|
1808
|
+
return None
|
1809
|
+
|
1810
|
+
eb = Face.ExternalBoundary(face)
|
1811
|
+
eb = Wire.Simplify(eb, tolerance=tolerance)
|
1812
|
+
ibList = Face.InternalBoundaries(face)
|
1813
|
+
ibList = [Wire.Simplify(ib) for ib in ibList]
|
1814
|
+
return Face.ByWires(eb, ibList)
|
1815
|
+
|
1663
1816
|
@staticmethod
|
1664
1817
|
def Skeleton(face, tolerance=0.001):
|
1665
1818
|
"""
|
@@ -1668,31 +1821,33 @@ class Face(Topology):
|
|
1668
1821
|
|
1669
1822
|
Parameters
|
1670
1823
|
----------
|
1671
|
-
face :
|
1824
|
+
face : topologic_core.Face
|
1672
1825
|
The input face.
|
1673
1826
|
tolerance : float , optional
|
1674
1827
|
The desired tolerance. The default is 0.001. (This is set to a larger number than the usual 0.0001 as it was found to work better)
|
1675
1828
|
|
1676
1829
|
Returns
|
1677
1830
|
-------
|
1678
|
-
|
1831
|
+
topologic_core.Wire
|
1679
1832
|
The created straight skeleton.
|
1680
1833
|
|
1681
1834
|
"""
|
1682
1835
|
from topologicpy.Wire import Wire
|
1683
|
-
|
1836
|
+
from topologicpy.Topology import Topology
|
1837
|
+
|
1838
|
+
if not Topology.IsInstance(face, "Face"):
|
1684
1839
|
print("Face.Skeleton - Error: The input face is not a valid topologic face. Retruning None.")
|
1685
1840
|
return None
|
1686
1841
|
return Wire.Skeleton(face, tolerance=tolerance)
|
1687
1842
|
|
1688
1843
|
@staticmethod
|
1689
|
-
def Square(origin
|
1844
|
+
def Square(origin= None, size: float = 1.0, direction: list = [0, 0, 1], placement: str = "center", tolerance: float = 0.0001):
|
1690
1845
|
"""
|
1691
1846
|
Creates a square.
|
1692
1847
|
|
1693
1848
|
Parameters
|
1694
1849
|
----------
|
1695
|
-
origin :
|
1850
|
+
origin : topologic_core.Vertex , optional
|
1696
1851
|
The location of the origin of the square. The default is None which results in the square being placed at (0, 0, 0).
|
1697
1852
|
size : float , optional
|
1698
1853
|
The size of the square. The default is 1.0.
|
@@ -1705,20 +1860,62 @@ class Face(Topology):
|
|
1705
1860
|
|
1706
1861
|
Returns
|
1707
1862
|
-------
|
1708
|
-
|
1863
|
+
topologic_core.Face
|
1709
1864
|
The created square.
|
1710
1865
|
|
1711
1866
|
"""
|
1712
1867
|
return Face.Rectangle(origin=origin, width=size, length=size, direction=direction, placement=placement, tolerance=tolerance)
|
1713
1868
|
|
1869
|
+
|
1870
|
+
@staticmethod
|
1871
|
+
def Squircle(origin = None, radius: float = 0.5, sides: int = 121, a: float = 2.0, b: float = 2.0, direction: list = [0, 0, 1], placement: str = "center", angTolerance: float = 0.1, tolerance: float = 0.0001):
|
1872
|
+
"""
|
1873
|
+
Creates a Squircle which is a hybrid between a circle and a square. See https://en.wikipedia.org/wiki/Squircle
|
1874
|
+
|
1875
|
+
Parameters
|
1876
|
+
----------
|
1877
|
+
origin : topologic_core.Vertex , optional
|
1878
|
+
The location of the origin of the squircle. The default is None which results in the squircle being placed at (0, 0, 0).
|
1879
|
+
radius : float , optional
|
1880
|
+
The radius of the squircle. The default is 0.5.
|
1881
|
+
sides : int , optional
|
1882
|
+
The number of sides of the squircle. The default is 121.
|
1883
|
+
a : float , optional
|
1884
|
+
The "a" factor affects the x position of the points to interpolate between a circle and a square.
|
1885
|
+
A value of 1 will create a circle. Higher values will create a more square-like shape. The default is 2.0.
|
1886
|
+
b : float , optional
|
1887
|
+
The "b" factor affects the y position of the points to interpolate between a circle and a square.
|
1888
|
+
A value of 1 will create a circle. Higher values will create a more square-like shape. The default is 2.0.
|
1889
|
+
radius : float , optional
|
1890
|
+
The desired radius of the squircle. The default is 0.5.
|
1891
|
+
sides : int , optional
|
1892
|
+
The desired number of sides for the squircle. The default is 100.
|
1893
|
+
direction : list , optional
|
1894
|
+
The vector representing the up direction of the circle. The default is [0, 0, 1].
|
1895
|
+
placement : str , optional
|
1896
|
+
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".
|
1897
|
+
angTolerance : float , optional
|
1898
|
+
The desired angular tolerance. The default is 0.1.
|
1899
|
+
tolerance : float , optional
|
1900
|
+
The desired tolerance. The default is 0.0001.
|
1901
|
+
|
1902
|
+
Returns
|
1903
|
+
-------
|
1904
|
+
topologic_core.Face
|
1905
|
+
The created squircle.
|
1906
|
+
"""
|
1907
|
+
from topologicpy.Wire import Wire
|
1908
|
+
wire = Wire.Squircle(origin = origin, radius= radius, sides = sides, a = a, b = b, direction = direction, placement = placement, angTolerance = angTolerance, tolerance = tolerance)
|
1909
|
+
return Face.ByWire(wire)
|
1910
|
+
|
1714
1911
|
@staticmethod
|
1715
|
-
def Star(origin
|
1912
|
+
def Star(origin= None, radiusA: float = 1.0, radiusB: float = 0.4, rays: int = 5, direction: list = [0, 0, 1], placement: str = "center", tolerance: float = 0.0001):
|
1716
1913
|
"""
|
1717
1914
|
Creates a star.
|
1718
1915
|
|
1719
1916
|
Parameters
|
1720
1917
|
----------
|
1721
|
-
origin :
|
1918
|
+
origin : topologic_core.Vertex, optional
|
1722
1919
|
The location of the origin of the star. The default is None which results in the star being placed at (0, 0, 0).
|
1723
1920
|
radiusA : float , optional
|
1724
1921
|
The outer radius of the star. The default is 1.0.
|
@@ -1735,25 +1932,27 @@ class Face(Topology):
|
|
1735
1932
|
|
1736
1933
|
Returns
|
1737
1934
|
-------
|
1738
|
-
|
1935
|
+
topologic_core.Face
|
1739
1936
|
The created face.
|
1740
1937
|
|
1741
1938
|
"""
|
1742
1939
|
from topologicpy.Wire import Wire
|
1940
|
+
from topologicpy.Topology import Topology
|
1941
|
+
|
1743
1942
|
wire = Wire.Star(origin=origin, radiusA=radiusA, radiusB=radiusB, rays=rays, direction=direction, placement=placement, tolerance=tolerance)
|
1744
|
-
if not
|
1943
|
+
if not Topology.IsInstance(wire, "Wire"):
|
1745
1944
|
print("Face.Rectangle - Error: Could not create the base wire for the star. Returning None.")
|
1746
1945
|
return None
|
1747
1946
|
return Face.ByWire(wire, tolerance=tolerance)
|
1748
1947
|
|
1749
1948
|
@staticmethod
|
1750
|
-
def Trapezoid(origin
|
1949
|
+
def Trapezoid(origin= 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):
|
1751
1950
|
"""
|
1752
1951
|
Creates a trapezoid.
|
1753
1952
|
|
1754
1953
|
Parameters
|
1755
1954
|
----------
|
1756
|
-
origin :
|
1955
|
+
origin : topologic_core.Vertex, optional
|
1757
1956
|
The location of the origin of the trapezoid. The default is None which results in the trapezoid being placed at (0, 0, 0).
|
1758
1957
|
widthA : float , optional
|
1759
1958
|
The width of the bottom edge of the trapezoid. The default is 1.0.
|
@@ -1774,25 +1973,27 @@ class Face(Topology):
|
|
1774
1973
|
|
1775
1974
|
Returns
|
1776
1975
|
-------
|
1777
|
-
|
1976
|
+
topologic_core.Face
|
1778
1977
|
The created trapezoid.
|
1779
1978
|
|
1780
1979
|
"""
|
1781
1980
|
from topologicpy.Wire import Wire
|
1981
|
+
from topologicpy.Topology import Topology
|
1982
|
+
|
1782
1983
|
wire = Wire.Trapezoid(origin=origin, widthA=widthA, widthB=widthB, offsetA=offsetA, offsetB=offsetB, length=length, direction=direction, placement=placement, tolerance=tolerance)
|
1783
|
-
if not
|
1984
|
+
if not Topology.IsInstance(wire, "Wire"):
|
1784
1985
|
print("Face.Rectangle - Error: Could not create the base wire for the trapezoid. Returning None.")
|
1785
1986
|
return None
|
1786
1987
|
return Face.ByWire(wire, tolerance=tolerance)
|
1787
1988
|
|
1788
1989
|
@staticmethod
|
1789
|
-
def Triangulate(face
|
1990
|
+
def Triangulate(face, mode: int = 0, meshSize: float = None, tolerance: float = 0.0001) -> list:
|
1790
1991
|
"""
|
1791
1992
|
Triangulates the input face and returns a list of faces.
|
1792
1993
|
|
1793
1994
|
Parameters
|
1794
1995
|
----------
|
1795
|
-
face :
|
1996
|
+
face : topologic_core.Face
|
1796
1997
|
The input face.
|
1797
1998
|
tolerance : float , optional
|
1798
1999
|
The desired tolerance. The default is 0.0001.
|
@@ -1828,7 +2029,7 @@ class Face(Topology):
|
|
1828
2029
|
|
1829
2030
|
Parameters
|
1830
2031
|
----------
|
1831
|
-
face :
|
2032
|
+
face : topologic_core.Face
|
1832
2033
|
The input face.
|
1833
2034
|
meshSize : float , optional
|
1834
2035
|
The desired mesh size.
|
@@ -1837,7 +2038,7 @@ class Face(Topology):
|
|
1837
2038
|
|
1838
2039
|
Returns
|
1839
2040
|
----------
|
1840
|
-
|
2041
|
+
topologic_core.Shell
|
1841
2042
|
The shell of triangular meshes.
|
1842
2043
|
|
1843
2044
|
"""
|
@@ -1877,7 +2078,7 @@ class Face(Topology):
|
|
1877
2078
|
from topologicpy.Wire import Wire
|
1878
2079
|
from topologicpy.Face import Face
|
1879
2080
|
|
1880
|
-
if not
|
2081
|
+
if not Topology.IsInstance(face, "Face"):
|
1881
2082
|
print("Shell.ByMeshFace - Error: The input face parameter is not a valid face. Returning None.")
|
1882
2083
|
return None
|
1883
2084
|
if not meshSize:
|
@@ -1952,7 +2153,7 @@ class Face(Topology):
|
|
1952
2153
|
faces.append(Face.ByVertices(face_vertices))
|
1953
2154
|
return faces
|
1954
2155
|
|
1955
|
-
if not
|
2156
|
+
if not Topology.IsInstance(face, "Face"):
|
1956
2157
|
print("Face.Triangulate - Error: The input face parameter is not a valid face. Returning None.")
|
1957
2158
|
return None
|
1958
2159
|
vertices = Topology.Vertices(face)
|
@@ -1966,7 +2167,7 @@ class Face(Topology):
|
|
1966
2167
|
shell_faces = []
|
1967
2168
|
for i in range(0,5,1):
|
1968
2169
|
try:
|
1969
|
-
_ = topologic.FaceUtility.Triangulate(flatFace, float(i)*0.1, shell_faces)
|
2170
|
+
_ = topologic.FaceUtility.Triangulate(flatFace, float(i)*0.1, shell_faces) # Hook to Core
|
1970
2171
|
break
|
1971
2172
|
except:
|
1972
2173
|
continue
|
@@ -1981,49 +2182,51 @@ class Face(Topology):
|
|
1981
2182
|
if Face.Angle(face, f) > 90:
|
1982
2183
|
wire = Face.ExternalBoundary(f)
|
1983
2184
|
wire = Wire.Invert(wire)
|
1984
|
-
f =
|
2185
|
+
f = Face.ByWire(wire)
|
1985
2186
|
finalFaces.append(f)
|
1986
2187
|
else:
|
1987
2188
|
finalFaces.append(f)
|
1988
2189
|
return finalFaces
|
1989
2190
|
|
1990
2191
|
@staticmethod
|
1991
|
-
def TrimByWire(face
|
2192
|
+
def TrimByWire(face, wire, reverse: bool = False):
|
1992
2193
|
"""
|
1993
2194
|
Trims the input face by the input wire.
|
1994
2195
|
|
1995
2196
|
Parameters
|
1996
2197
|
----------
|
1997
|
-
face :
|
2198
|
+
face : topologic_core.Face
|
1998
2199
|
The input face.
|
1999
|
-
wire :
|
2200
|
+
wire : topologic_core.Wire
|
2000
2201
|
The input wire.
|
2001
2202
|
reverse : bool , optional
|
2002
2203
|
If set to True, the effect of the trim will be reversed. The default is False.
|
2003
2204
|
|
2004
2205
|
Returns
|
2005
2206
|
-------
|
2006
|
-
|
2207
|
+
topologic_core.Face
|
2007
2208
|
The resulting trimmed face.
|
2008
2209
|
|
2009
2210
|
"""
|
2010
|
-
|
2211
|
+
from topologicpy.Topology import Topology
|
2212
|
+
|
2213
|
+
if not Topology.IsInstance(face, "Face"):
|
2011
2214
|
return None
|
2012
|
-
if not
|
2215
|
+
if not Topology.IsInstance(wire, "Wire"):
|
2013
2216
|
return face
|
2014
|
-
trimmed_face = topologic.FaceUtility.TrimByWire(face, wire, False)
|
2217
|
+
trimmed_face = topologic.FaceUtility.TrimByWire(face, wire, False) # Hook to Core
|
2015
2218
|
if reverse:
|
2016
2219
|
trimmed_face = face.Difference(trimmed_face)
|
2017
2220
|
return trimmed_face
|
2018
2221
|
|
2019
2222
|
@staticmethod
|
2020
|
-
def VertexByParameters(face
|
2223
|
+
def VertexByParameters(face, u: float = 0.5, v: float = 0.5):
|
2021
2224
|
"""
|
2022
2225
|
Creates a vertex at the *u* and *v* parameters of the input face.
|
2023
2226
|
|
2024
2227
|
Parameters
|
2025
2228
|
----------
|
2026
|
-
face :
|
2229
|
+
face : topologic_core.Face
|
2027
2230
|
The input face.
|
2028
2231
|
u : float , optional
|
2029
2232
|
The *u* parameter of the input face. The default is 0.5.
|
@@ -2036,20 +2239,22 @@ class Face(Topology):
|
|
2036
2239
|
The created vertex.
|
2037
2240
|
|
2038
2241
|
"""
|
2039
|
-
|
2242
|
+
from topologicpy.Topology import Topology
|
2243
|
+
|
2244
|
+
if not Topology.IsInstance(face, "Face"):
|
2040
2245
|
return None
|
2041
|
-
return topologic.FaceUtility.VertexAtParameters(face, u, v)
|
2246
|
+
return topologic.FaceUtility.VertexAtParameters(face, u, v) # Hook to Core
|
2042
2247
|
|
2043
2248
|
@staticmethod
|
2044
|
-
def VertexParameters(face
|
2249
|
+
def VertexParameters(face, vertex, outputType: str = "uv", mantissa: int = 6) -> list:
|
2045
2250
|
"""
|
2046
2251
|
Returns the *u* and *v* parameters of the input face at the location of the input vertex.
|
2047
2252
|
|
2048
2253
|
Parameters
|
2049
2254
|
----------
|
2050
|
-
face :
|
2255
|
+
face : topologic_core.Face
|
2051
2256
|
The input face.
|
2052
|
-
vertex :
|
2257
|
+
vertex : topologic_core.Vertex
|
2053
2258
|
The input vertex.
|
2054
2259
|
outputType : string , optional
|
2055
2260
|
The string defining the desired output. This can be any subset or permutation of "uv". It is case insensitive. The default is "uv".
|
@@ -2062,11 +2267,13 @@ class Face(Topology):
|
|
2062
2267
|
The list of *u* and/or *v* as specified by the outputType input.
|
2063
2268
|
|
2064
2269
|
"""
|
2065
|
-
|
2270
|
+
from topologicpy.Topology import Topology
|
2271
|
+
|
2272
|
+
if not Topology.IsInstance(face, "Face"):
|
2066
2273
|
return None
|
2067
|
-
if not
|
2274
|
+
if not Topology.IsInstance(vertex, "Vertex"):
|
2068
2275
|
return None
|
2069
|
-
params = topologic.FaceUtility.ParametersAtVertex(face, vertex)
|
2276
|
+
params = topologic.FaceUtility.ParametersAtVertex(face, vertex) # Hook to Core
|
2070
2277
|
u = round(params[0], mantissa)
|
2071
2278
|
v = round(params[1], mantissa)
|
2072
2279
|
outputType = list(outputType.lower())
|
@@ -2079,13 +2286,13 @@ class Face(Topology):
|
|
2079
2286
|
return returnResult
|
2080
2287
|
|
2081
2288
|
@staticmethod
|
2082
|
-
def Vertices(face
|
2289
|
+
def Vertices(face) -> list:
|
2083
2290
|
"""
|
2084
2291
|
Returns the vertices of the input face.
|
2085
2292
|
|
2086
2293
|
Parameters
|
2087
2294
|
----------
|
2088
|
-
face :
|
2295
|
+
face : topologic_core.Face
|
2089
2296
|
The input face.
|
2090
2297
|
|
2091
2298
|
Returns
|
@@ -2094,38 +2301,40 @@ class Face(Topology):
|
|
2094
2301
|
The list of vertices.
|
2095
2302
|
|
2096
2303
|
"""
|
2097
|
-
|
2304
|
+
from topologicpy.Topology import Topology
|
2305
|
+
|
2306
|
+
if not Topology.IsInstance(face, "Face"):
|
2098
2307
|
return None
|
2099
2308
|
vertices = []
|
2100
2309
|
_ = face.Vertices(None, vertices)
|
2101
2310
|
return vertices
|
2102
2311
|
|
2103
2312
|
@staticmethod
|
2104
|
-
def Wire(face
|
2313
|
+
def Wire(face):
|
2105
2314
|
"""
|
2106
2315
|
Returns the external boundary (closed wire) of the input face.
|
2107
2316
|
|
2108
2317
|
Parameters
|
2109
2318
|
----------
|
2110
|
-
face :
|
2319
|
+
face : topologic_core.Face
|
2111
2320
|
The input face.
|
2112
2321
|
|
2113
2322
|
Returns
|
2114
2323
|
-------
|
2115
|
-
|
2324
|
+
topologic_core.Wire
|
2116
2325
|
The external boundary of the input face.
|
2117
2326
|
|
2118
2327
|
"""
|
2119
|
-
return
|
2328
|
+
return Face.ExternalBoundary(face)
|
2120
2329
|
|
2121
2330
|
@staticmethod
|
2122
|
-
def Wires(face
|
2331
|
+
def Wires(face) -> list:
|
2123
2332
|
"""
|
2124
2333
|
Returns the wires of the input face.
|
2125
2334
|
|
2126
2335
|
Parameters
|
2127
2336
|
----------
|
2128
|
-
face :
|
2337
|
+
face : topologic_core.Face
|
2129
2338
|
The input face.
|
2130
2339
|
|
2131
2340
|
Returns
|
@@ -2134,7 +2343,9 @@ class Face(Topology):
|
|
2134
2343
|
The list of wires.
|
2135
2344
|
|
2136
2345
|
"""
|
2137
|
-
|
2346
|
+
from topologicpy.Topology import Topology
|
2347
|
+
|
2348
|
+
if not Topology.IsInstance(face, "Face"):
|
2138
2349
|
return None
|
2139
2350
|
wires = []
|
2140
2351
|
_ = face.Wires(None, wires)
|