topologicpy 0.6.3__py3-none-any.whl → 0.7.0__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 +185 -148
- topologicpy/EnergyModel.py +23 -24
- topologicpy/Face.py +512 -313
- 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 +533 -765
- topologicpy/Vector.py +4 -3
- topologicpy/Vertex.py +145 -126
- topologicpy/Wire.py +542 -325
- topologicpy/version.py +1 -1
- {topologicpy-0.6.3.dist-info → topologicpy-0.7.0.dist-info}/METADATA +1 -1
- topologicpy-0.7.0.dist-info/RECORD +33 -0
- topologicpy-0.6.3.dist-info/RECORD +0 -33
- {topologicpy-0.6.3.dist-info → topologicpy-0.7.0.dist-info}/LICENSE +0 -0
- {topologicpy-0.6.3.dist-info → topologicpy-0.7.0.dist-info}/WHEEL +0 -0
- {topologicpy-0.6.3.dist-info → topologicpy-0.7.0.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,31 @@ 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
|
return face.ExternalBoundary()
|
977
931
|
|
978
932
|
@staticmethod
|
979
|
-
def FacingToward(face
|
933
|
+
def FacingToward(face, direction: list = [0,0,-1], asVertex: bool = False, tolerance: float = 0.0001) -> bool:
|
980
934
|
"""
|
981
935
|
Returns True if the input face is facing toward the input direction.
|
982
936
|
|
983
937
|
Parameters
|
984
938
|
----------
|
985
|
-
face :
|
939
|
+
face : topologic_core.Face
|
986
940
|
The input face.
|
987
941
|
direction : list , optional
|
988
942
|
The input direction. The default is [0,0,-1].
|
@@ -997,8 +951,10 @@ class Face(Topology):
|
|
997
951
|
True if the face is facing toward the direction. False otherwise.
|
998
952
|
|
999
953
|
"""
|
1000
|
-
|
1001
|
-
|
954
|
+
from topologicpy.Vector import Vector
|
955
|
+
|
956
|
+
faceNormal = Face.Normal(face)
|
957
|
+
faceCenter = Face.VertexByParameters(face,0.5,0.5)
|
1002
958
|
cList = [faceCenter.X(), faceCenter.Y(), faceCenter.Z()]
|
1003
959
|
try:
|
1004
960
|
vList = [direction.X(), direction.Y(), direction.Z()]
|
@@ -1017,21 +973,80 @@ class Face(Topology):
|
|
1017
973
|
return False
|
1018
974
|
return True
|
1019
975
|
|
976
|
+
|
1020
977
|
@staticmethod
|
1021
|
-
def
|
978
|
+
def Fillet(face, radius: float = 0, radiusKey: str = None, tolerance: float = 0.0001, silent: bool = False):
|
979
|
+
"""
|
980
|
+
Fillets (rounds) the interior and exterior corners of the input face given the input radius. See https://en.wikipedia.org/wiki/Fillet_(mechanics)
|
981
|
+
|
982
|
+
Parameters
|
983
|
+
----------
|
984
|
+
face : topologic_core.Face
|
985
|
+
The input face.
|
986
|
+
radius : float
|
987
|
+
The desired radius of the fillet.
|
988
|
+
radiusKey : str , optional
|
989
|
+
If specified, the dictionary of the vertices will be queried for this key to specify the desired fillet radius. The default is None.
|
990
|
+
tolerance : float , optional
|
991
|
+
The desired tolerance. The default is 0.0001.
|
992
|
+
silent : bool , optional
|
993
|
+
If set to False, error and warning messages are printed. Otherwise, they are not. The default is False.
|
994
|
+
|
995
|
+
Returns
|
996
|
+
-------
|
997
|
+
topologic_core.Face
|
998
|
+
The filleted face.
|
999
|
+
|
1000
|
+
"""
|
1001
|
+
from topologicpy.Wire import Wire
|
1002
|
+
from topologicpy.Topology import Topology
|
1003
|
+
|
1004
|
+
if not Topology.IsInstance(face, "Face"):
|
1005
|
+
if not silent:
|
1006
|
+
print("Face.Fillet - Error: The input face parameter is not a valid face. Returning None.")
|
1007
|
+
return None
|
1008
|
+
|
1009
|
+
eb = Topology.Copy(Face.ExternalBoundary(face))
|
1010
|
+
ib_list = Face.InternalBoundaries(face)
|
1011
|
+
ib_list = [Topology.Copy(ib) for ib in ib_list]
|
1012
|
+
f_vertices = Face.Vertices(face)
|
1013
|
+
if isinstance(radiusKey, str):
|
1014
|
+
eb = Topology.TransferDictionariesBySelectors(eb, selectors=f_vertices, tranVertices=True)
|
1015
|
+
eb = Wire.Fillet(eb, radius=radius, radiusKey=radiusKey, tolerance=tolerance)
|
1016
|
+
if not Topology.IsInstance(eb, "Wire"):
|
1017
|
+
if not silent:
|
1018
|
+
print("Face.Fillet - Error: The operation failed. Returning None.")
|
1019
|
+
return None
|
1020
|
+
ib_wires = []
|
1021
|
+
for ib in ib_list:
|
1022
|
+
ib = Wire.ByVertices(Topology.Vertices(ib))
|
1023
|
+
ib = Wire.Reverse(ib)
|
1024
|
+
if isinstance(radiusKey, str):
|
1025
|
+
ib = Topology.TransferDictionariesBySelectors(ib, selectors=f_vertices, tranVertices=True)
|
1026
|
+
|
1027
|
+
ib_wire = Wire.Fillet(ib, radius=radius, radiusKey=radiusKey, tolerance=tolerance, silent=silent)
|
1028
|
+
if Topology.IsInstance(ib, "Wire"):
|
1029
|
+
ib_wires.append(ib_wire)
|
1030
|
+
else:
|
1031
|
+
if not silent:
|
1032
|
+
print("Face.Fillet - Error: The operation for one of the interior boundaries failed. Skipping.")
|
1033
|
+
return Face.ByWires(eb, ib_wires)
|
1034
|
+
|
1035
|
+
@staticmethod
|
1036
|
+
def Harmonize(face, tolerance: float = 0.0001):
|
1022
1037
|
"""
|
1023
1038
|
Returns a harmonized version of the input face such that the *u* and *v* origins are always in the upperleft corner.
|
1024
1039
|
|
1025
1040
|
Parameters
|
1026
1041
|
----------
|
1027
|
-
face :
|
1042
|
+
face : topologic_core.Face
|
1028
1043
|
The input face.
|
1029
1044
|
tolerance : float , optional
|
1030
1045
|
The desired tolerance. The default is 0.0001.
|
1031
1046
|
|
1032
1047
|
Returns
|
1033
1048
|
-------
|
1034
|
-
|
1049
|
+
topologic_core.Face
|
1035
1050
|
The harmonized face.
|
1036
1051
|
|
1037
1052
|
"""
|
@@ -1040,7 +1055,7 @@ class Face(Topology):
|
|
1040
1055
|
from topologicpy.Topology import Topology
|
1041
1056
|
from topologicpy.Dictionary import Dictionary
|
1042
1057
|
|
1043
|
-
if not
|
1058
|
+
if not Topology.IsInstance(face, "Face"):
|
1044
1059
|
print("Face.Harmonize - Error: The input face parameter is not a valid face. Returning None.")
|
1045
1060
|
return None
|
1046
1061
|
normal = Face.Normal(face)
|
@@ -1059,13 +1074,13 @@ class Face(Topology):
|
|
1059
1074
|
return harmonizedFace
|
1060
1075
|
|
1061
1076
|
@staticmethod
|
1062
|
-
def InteriorAngles(face
|
1077
|
+
def InteriorAngles(face, includeInternalBoundaries: bool = False, mantissa: int = 6) -> list:
|
1063
1078
|
"""
|
1064
1079
|
Returns the interior angles of the input face in degrees. The face must be planar.
|
1065
1080
|
|
1066
1081
|
Parameters
|
1067
1082
|
----------
|
1068
|
-
face :
|
1083
|
+
face : topologic_core.Face
|
1069
1084
|
The input face.
|
1070
1085
|
includeInternalBoundaries : bool , optional
|
1071
1086
|
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 +1095,10 @@ class Face(Topology):
|
|
1080
1095
|
list
|
1081
1096
|
The list of interior angles.
|
1082
1097
|
"""
|
1083
|
-
|
1084
1098
|
from topologicpy.Wire import Wire
|
1099
|
+
from topologicpy.Topology import Topology
|
1085
1100
|
|
1086
|
-
if not
|
1101
|
+
if not Topology.IsInstance(face, "Face"):
|
1087
1102
|
print("Face.InteriorAngles - Error: The input face parameter is not a valid face. Returning None.")
|
1088
1103
|
return None
|
1089
1104
|
eb = Face.ExternalBoundary(face)
|
@@ -1100,13 +1115,13 @@ class Face(Topology):
|
|
1100
1115
|
return return_list
|
1101
1116
|
|
1102
1117
|
@staticmethod
|
1103
|
-
def InternalBoundaries(face
|
1118
|
+
def InternalBoundaries(face) -> list:
|
1104
1119
|
"""
|
1105
1120
|
Returns the internal boundaries (closed wires) of the input face.
|
1106
1121
|
|
1107
1122
|
Parameters
|
1108
1123
|
----------
|
1109
|
-
face :
|
1124
|
+
face : topologic_core.Face
|
1110
1125
|
The input face.
|
1111
1126
|
|
1112
1127
|
Returns
|
@@ -1115,33 +1130,36 @@ class Face(Topology):
|
|
1115
1130
|
The list of internal boundaries (closed wires).
|
1116
1131
|
|
1117
1132
|
"""
|
1118
|
-
|
1133
|
+
from topologicpy.Topology import Topology
|
1134
|
+
|
1135
|
+
if not Topology.IsInstance(face, "Face"):
|
1119
1136
|
return None
|
1120
1137
|
wires = []
|
1121
1138
|
_ = face.InternalBoundaries(wires)
|
1122
1139
|
return list(wires)
|
1123
1140
|
|
1124
1141
|
@staticmethod
|
1125
|
-
def InternalVertex(face
|
1142
|
+
def InternalVertex(face, tolerance: float = 0.0001):
|
1126
1143
|
"""
|
1127
1144
|
Creates a vertex guaranteed to be inside the input face.
|
1128
1145
|
|
1129
1146
|
Parameters
|
1130
1147
|
----------
|
1131
|
-
face :
|
1148
|
+
face : topologic_core.Face
|
1132
1149
|
The input face.
|
1133
1150
|
tolerance : float , optional
|
1134
1151
|
The desired tolerance. The default is 0.0001.
|
1135
1152
|
|
1136
1153
|
Returns
|
1137
1154
|
-------
|
1138
|
-
|
1155
|
+
topologic_core.Vertex
|
1139
1156
|
The created vertex.
|
1140
1157
|
|
1141
1158
|
"""
|
1142
1159
|
from topologicpy.Vertex import Vertex
|
1143
1160
|
from topologicpy.Topology import Topology
|
1144
|
-
|
1161
|
+
|
1162
|
+
if not Topology.IsInstance(face, "Face"):
|
1145
1163
|
return None
|
1146
1164
|
v = Topology.Centroid(face)
|
1147
1165
|
if Vertex.IsInternal(v, face, tolerance=tolerance):
|
@@ -1152,30 +1170,31 @@ class Face(Topology):
|
|
1152
1170
|
v = Face.VertexByParameters(face, u, v)
|
1153
1171
|
if Vertex.IsInternal(v, face, tolerance=tolerance):
|
1154
1172
|
return v
|
1155
|
-
v = topologic.FaceUtility.InternalVertex(face, tolerance)
|
1173
|
+
v = topologic.FaceUtility.InternalVertex(face, tolerance) # Hook to Core
|
1156
1174
|
return v
|
1157
1175
|
|
1158
1176
|
@staticmethod
|
1159
|
-
def Invert(face
|
1177
|
+
def Invert(face, tolerance: float = 0.0001):
|
1160
1178
|
"""
|
1161
1179
|
Creates a face that is an inverse (mirror) of the input face.
|
1162
1180
|
|
1163
1181
|
Parameters
|
1164
1182
|
----------
|
1165
|
-
face :
|
1183
|
+
face : topologic_core.Face
|
1166
1184
|
The input face.
|
1167
1185
|
tolerance : float , optional
|
1168
1186
|
The desired tolerance. The default is 0.0001.
|
1169
1187
|
|
1170
1188
|
Returns
|
1171
1189
|
-------
|
1172
|
-
|
1190
|
+
topologic_core.Face
|
1173
1191
|
The inverted face.
|
1174
1192
|
|
1175
1193
|
"""
|
1176
1194
|
from topologicpy.Wire import Wire
|
1195
|
+
from topologicpy.Topology import Topology
|
1177
1196
|
|
1178
|
-
if not
|
1197
|
+
if not Topology.IsInstance(face, "Face"):
|
1179
1198
|
return None
|
1180
1199
|
eb = Face.ExternalBoundary(face)
|
1181
1200
|
vertices = Wire.Vertices(eb)
|
@@ -1189,15 +1208,15 @@ class Face(Topology):
|
|
1189
1208
|
return inverted_face
|
1190
1209
|
|
1191
1210
|
@staticmethod
|
1192
|
-
def IsCoplanar(faceA
|
1211
|
+
def IsCoplanar(faceA, faceB, tolerance: float = 0.0001) -> bool:
|
1193
1212
|
"""
|
1194
1213
|
Returns True if the two input faces are coplanar. Returns False otherwise.
|
1195
1214
|
|
1196
1215
|
Parameters
|
1197
1216
|
----------
|
1198
|
-
faceA :
|
1217
|
+
faceA : topologic_core.Face
|
1199
1218
|
The first input face.
|
1200
|
-
faceB :
|
1219
|
+
faceB : topologic_core.Face
|
1201
1220
|
The second input face
|
1202
1221
|
tolerance : float , optional
|
1203
1222
|
The desired tolerance. The deafault is 0.0001.
|
@@ -1213,24 +1232,112 @@ class Face(Topology):
|
|
1213
1232
|
True if the two input faces are coplanar. False otherwise.
|
1214
1233
|
|
1215
1234
|
"""
|
1216
|
-
|
1235
|
+
from topologicpy.Vector import Vector
|
1236
|
+
from topologicpy.Topology import Topology
|
1237
|
+
|
1238
|
+
if not Topology.IsInstance(faceA, "Face"):
|
1217
1239
|
print("Face.IsInide - Error: The input faceA parameter is not a valid topologic face. Returning None.")
|
1218
1240
|
return None
|
1219
|
-
if not
|
1241
|
+
if not Topology.IsInstance(faceB, "Face"):
|
1220
1242
|
print("Face.IsInide - Error: The input faceB parameter is not a valid topologic face. Returning None.")
|
1221
1243
|
return None
|
1222
1244
|
dirA = Face.NormalAtParameters(faceA, 0.5, 0.5, "xyz", 3)
|
1223
1245
|
dirB = Face.NormalAtParameters(faceB, 0.5, 0.5, "xyz", 3)
|
1224
1246
|
return Vector.IsCollinear(dirA, dirB)
|
1225
|
-
|
1247
|
+
|
1248
|
+
@staticmethod
|
1249
|
+
def Isovist(face, vertex, obstacles = None, fromAngle=0, toAngle=360, tolerance: float = 0.0001):
|
1250
|
+
"""
|
1251
|
+
Returns the face representing the isovist projection from the input viewpoint.
|
1252
|
+
This method assumes all input is in 2D. Z coordinates are ignored.
|
1253
|
+
|
1254
|
+
Parameters
|
1255
|
+
----------
|
1256
|
+
face : topologic_core.Face
|
1257
|
+
The face representing the boundary of the isovist.
|
1258
|
+
vertex : topologic_core.Vertex
|
1259
|
+
The vertex representing the location of the viewpoint of the isovist.
|
1260
|
+
obstacles : list , optional
|
1261
|
+
A list of wires representing the obstacles within the face. All obstacles are assumed to be within the
|
1262
|
+
boundary of the face.
|
1263
|
+
fromAngle : float , optional
|
1264
|
+
The angle in degrees from which to start creating the arc of the circle. The default is 0.
|
1265
|
+
0 is considered to be in the positive X-axis direction. 90 is considered to be in the
|
1266
|
+
positive Y-axis direction.
|
1267
|
+
toAngle : float , optional
|
1268
|
+
The angle in degrees at which to end creating the arc of the circle. The default is 360.
|
1269
|
+
Angles are measured in an anti-clockwise fashion.
|
1270
|
+
tolerance : float , optional:
|
1271
|
+
The desired tolerance. The default is 0.0001.
|
1272
|
+
|
1273
|
+
Returns
|
1274
|
+
-------
|
1275
|
+
topologic_core.Face
|
1276
|
+
The face representing the isovist projection from the input viewpoint.
|
1277
|
+
|
1278
|
+
"""
|
1279
|
+
from topologicpy.Vertex import Vertex
|
1280
|
+
from topologicpy.Edge import Edge
|
1281
|
+
from topologicpy.Wire import Wire
|
1282
|
+
from topologicpy.Face import Face
|
1283
|
+
from topologicpy.Shell import Shell
|
1284
|
+
from topologicpy.Cluster import Cluster
|
1285
|
+
from topologicpy.Topology import Topology
|
1286
|
+
|
1287
|
+
def vertexPartofFace(vertex, face, tolerance):
|
1288
|
+
vertices = []
|
1289
|
+
_ = face.Vertices(None, vertices)
|
1290
|
+
for v in vertices:
|
1291
|
+
if Vertex.Distance(vertex, v) < tolerance:
|
1292
|
+
return True
|
1293
|
+
return False
|
1294
|
+
|
1295
|
+
if not Topology.IsInstance(face, "Face"):
|
1296
|
+
print("Face.Isovist - Error: The input boundary parameter is not a valid Face. Returning None")
|
1297
|
+
return None
|
1298
|
+
if not Topology.IsInstance(vertex, "Vertex"):
|
1299
|
+
print("Face.Isovist - Error: The input viewPoint parameter is not a valid Vertex. Returning None")
|
1300
|
+
return None
|
1301
|
+
if isinstance(obstacles, list):
|
1302
|
+
obstacles = [obs for obs in obstacles if Topology.IsInstance(obs, "Wire")]
|
1303
|
+
for obs in obstacles:
|
1304
|
+
face = Topology.Difference(face, Face.ByWire(obs))
|
1305
|
+
targets = Topology.Vertices(face)
|
1306
|
+
distances = []
|
1307
|
+
for target in targets:
|
1308
|
+
distances.append(Vertex.Distance(vertex, target))
|
1309
|
+
distances.sort()
|
1310
|
+
max_d = distances[-1]*1.05
|
1311
|
+
edges = []
|
1312
|
+
for target in targets:
|
1313
|
+
e = Edge.ByVertices(vertex, target)
|
1314
|
+
e = Edge.SetLength(e, length=max_d, bothSides=False)
|
1315
|
+
edges.append(e)
|
1316
|
+
shell = Topology.Slice(face, Cluster.ByTopologies(edges))
|
1317
|
+
faces = Topology.Faces(shell)
|
1318
|
+
final_faces = []
|
1319
|
+
for face in faces:
|
1320
|
+
if vertexPartofFace(vertex, face, tolerance=0.001):
|
1321
|
+
final_faces.append(face)
|
1322
|
+
shell = Shell.ByFaces(final_faces)
|
1323
|
+
return_face = Topology.RemoveCoplanarFaces(shell)
|
1324
|
+
if abs(360 - toAngle - fromAngle) > tolerance:
|
1325
|
+
c = Wire.Circle(origin= vertex, radius=max_d, sides=180, fromAngle=fromAngle, toAngle=toAngle, close = False)
|
1326
|
+
e1 = Edge.ByVertices(Wire.StartVertex(c), vertex)
|
1327
|
+
e2 = Edge.ByVertices(Wire.EndVertex(c), vertex)
|
1328
|
+
edges = Topology.Edges(c) + [e1,e2]
|
1329
|
+
pie = Face.ByWire(Topology.SelfMerge(Cluster.ByTopologies(edges)))
|
1330
|
+
return_face = Topology.Intersect(pie, return_face)
|
1331
|
+
return return_face
|
1332
|
+
|
1226
1333
|
@staticmethod
|
1227
|
-
def MedialAxis(face
|
1334
|
+
def MedialAxis(face, resolution: int = 0, externalVertices: bool = False, internalVertices: bool = False, toLeavesOnly: bool = False, angTolerance: float = 0.1, tolerance: float = 0.0001):
|
1228
1335
|
"""
|
1229
1336
|
Returns a wire representing an approximation of the medial axis of the input topology. See https://en.wikipedia.org/wiki/Medial_axis.
|
1230
1337
|
|
1231
1338
|
Parameters
|
1232
1339
|
----------
|
1233
|
-
face :
|
1340
|
+
face : topologic_core.Face
|
1234
1341
|
The input face.
|
1235
1342
|
resolution : int , optional
|
1236
1343
|
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 +1354,7 @@ class Face(Topology):
|
|
1247
1354
|
|
1248
1355
|
Returns
|
1249
1356
|
-------
|
1250
|
-
|
1357
|
+
topologic_core.Wire
|
1251
1358
|
The medial axis of the input face.
|
1252
1359
|
|
1253
1360
|
"""
|
@@ -1260,7 +1367,7 @@ class Face(Topology):
|
|
1260
1367
|
from topologicpy.Dictionary import Dictionary
|
1261
1368
|
|
1262
1369
|
def touchesEdge(vertex,edges, tolerance=0.0001):
|
1263
|
-
if not
|
1370
|
+
if not Topology.IsInstance(vertex, "Vertex"):
|
1264
1371
|
return False
|
1265
1372
|
for edge in edges:
|
1266
1373
|
u = Edge.ParameterAtVertex(edge, vertex, mantissa=6)
|
@@ -1313,13 +1420,13 @@ class Face(Topology):
|
|
1313
1420
|
theVertices = theVertices+extVertices
|
1314
1421
|
|
1315
1422
|
tempWire = Topology.SelfMerge(Cluster.ByTopologies(medialAxisEdges), tolerance=tolerance)
|
1316
|
-
if
|
1423
|
+
if Topology.IsInstance(tempWire, "Wire") and angTolerance > 0:
|
1317
1424
|
tempWire = Wire.RemoveCollinearEdges(tempWire, angTolerance=angTolerance)
|
1318
1425
|
medialAxisEdges = Wire.Edges(tempWire)
|
1319
1426
|
for v in theVertices:
|
1320
1427
|
nv = Vertex.NearestVertex(v, tempWire, useKDTree=False)
|
1321
1428
|
|
1322
|
-
if
|
1429
|
+
if Topology.IsInstance(nv, "Vertex"):
|
1323
1430
|
if toLeavesOnly:
|
1324
1431
|
adjVertices = Topology.AdjacentTopologies(nv, tempWire)
|
1325
1432
|
if len(adjVertices) < 2:
|
@@ -1327,19 +1434,19 @@ class Face(Topology):
|
|
1327
1434
|
else:
|
1328
1435
|
medialAxisEdges.append(Edge.ByVertices([nv, v], tolerance=tolerance))
|
1329
1436
|
medialAxis = Topology.SelfMerge(Cluster.ByTopologies(medialAxisEdges), tolerance=tolerance)
|
1330
|
-
if
|
1437
|
+
if Topology.IsInstance(medialAxis, "Wire") and angTolerance > 0:
|
1331
1438
|
medialAxis = Topology.RemoveCollinearEdges(medialAxis, angTolerance=angTolerance)
|
1332
1439
|
medialAxis = Topology.Unflatten(medialAxis, origin=origin,direction=normal)
|
1333
1440
|
return medialAxis
|
1334
1441
|
|
1335
1442
|
@staticmethod
|
1336
|
-
def Normal(face
|
1443
|
+
def Normal(face, outputType: str = "xyz", mantissa: int = 6) -> list:
|
1337
1444
|
"""
|
1338
1445
|
Returns the normal vector to the input face. A normal vector of a face is a vector perpendicular to it.
|
1339
1446
|
|
1340
1447
|
Parameters
|
1341
1448
|
----------
|
1342
|
-
face :
|
1449
|
+
face : topologic_core.Face
|
1343
1450
|
The input face.
|
1344
1451
|
outputType : string , optional
|
1345
1452
|
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 +1462,13 @@ class Face(Topology):
|
|
1355
1462
|
return Face.NormalAtParameters(face, u=0.5, v=0.5, outputType=outputType, mantissa=mantissa)
|
1356
1463
|
|
1357
1464
|
@staticmethod
|
1358
|
-
def NormalAtParameters(face
|
1465
|
+
def NormalAtParameters(face, u: float = 0.5, v: float = 0.5, outputType: str = "xyz", mantissa: int = 6) -> list:
|
1359
1466
|
"""
|
1360
1467
|
Returns the normal vector to the input face. A normal vector of a face is a vector perpendicular to it.
|
1361
1468
|
|
1362
1469
|
Parameters
|
1363
1470
|
----------
|
1364
|
-
face :
|
1471
|
+
face : topologic_core.Face
|
1365
1472
|
The input face.
|
1366
1473
|
u : float , optional
|
1367
1474
|
The *u* parameter at which to compute the normal to the input face. The default is 0.5.
|
@@ -1380,7 +1487,7 @@ class Face(Topology):
|
|
1380
1487
|
"""
|
1381
1488
|
returnResult = []
|
1382
1489
|
try:
|
1383
|
-
coords = topologic.FaceUtility.NormalAtParameters(face, u, v)
|
1490
|
+
coords = topologic.FaceUtility.NormalAtParameters(face, u, v) # Hook to Core
|
1384
1491
|
x = round(coords[0], mantissa)
|
1385
1492
|
y = round(coords[1], mantissa)
|
1386
1493
|
z = round(coords[2], mantissa)
|
@@ -1397,13 +1504,13 @@ class Face(Topology):
|
|
1397
1504
|
return returnResult
|
1398
1505
|
|
1399
1506
|
@staticmethod
|
1400
|
-
def NormalEdge(face
|
1507
|
+
def NormalEdge(face, length: float = 1.0, tolerance: float = 0.0001, silent: bool = False):
|
1401
1508
|
"""
|
1402
1509
|
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
1510
|
|
1404
1511
|
Parameters
|
1405
1512
|
----------
|
1406
|
-
face :
|
1513
|
+
face : topologic_core.Face
|
1407
1514
|
The input face.
|
1408
1515
|
length : float , optional
|
1409
1516
|
The desired length of the normal edge. The default is 1.
|
@@ -1412,13 +1519,14 @@ class Face(Topology):
|
|
1412
1519
|
|
1413
1520
|
Returns
|
1414
1521
|
-------
|
1415
|
-
|
1522
|
+
topologic_core.Edge
|
1416
1523
|
The created normal edge to the input face. This is computed at the approximate center of the face.
|
1417
1524
|
|
1418
1525
|
"""
|
1419
1526
|
from topologicpy.Edge import Edge
|
1527
|
+
from topologicpy.Topology import Topology
|
1420
1528
|
|
1421
|
-
if not
|
1529
|
+
if not Topology.IsInstance(face, "Face"):
|
1422
1530
|
if not silent:
|
1423
1531
|
print("Face.NormalEdge - Error: The input face parameter is not a valid face. Retuning None.")
|
1424
1532
|
return None
|
@@ -1433,13 +1541,13 @@ class Face(Topology):
|
|
1433
1541
|
return Edge.ByVertices([iv, ev], tolerance=tolerance, silent=silent)
|
1434
1542
|
|
1435
1543
|
@staticmethod
|
1436
|
-
def NormalEdgeAtParameters(face
|
1544
|
+
def NormalEdgeAtParameters(face, u: float = 0.5, v: float = 0.5, length: float = 1.0, tolerance: float = 0.0001):
|
1437
1545
|
"""
|
1438
1546
|
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
1547
|
|
1440
1548
|
Parameters
|
1441
1549
|
----------
|
1442
|
-
face :
|
1550
|
+
face : topologic_core.Face
|
1443
1551
|
The input face.
|
1444
1552
|
u : float , optional
|
1445
1553
|
The *u* parameter at which to compute the normal to the input face. The default is 0.5.
|
@@ -1452,13 +1560,13 @@ class Face(Topology):
|
|
1452
1560
|
|
1453
1561
|
Returns
|
1454
1562
|
-------
|
1455
|
-
|
1563
|
+
topologic_core.Edge
|
1456
1564
|
The created normal edge to the input face. This is computed at the approximate center of the face.
|
1457
1565
|
|
1458
1566
|
"""
|
1459
1567
|
from topologicpy.Edge import Edge
|
1460
1568
|
from topologicpy.Topology import Topology
|
1461
|
-
if not
|
1569
|
+
if not Topology.IsInstance(face, "Face"):
|
1462
1570
|
return None
|
1463
1571
|
sv = Face.VertexByParameters(face=face, u=u, v=v)
|
1464
1572
|
vec = Face.NormalAtParameters(face, u=u, v=v)
|
@@ -1466,13 +1574,13 @@ class Face(Topology):
|
|
1466
1574
|
return Edge.ByVertices([sv, ev], tolerance=tolerance, silent=True)
|
1467
1575
|
|
1468
1576
|
@staticmethod
|
1469
|
-
def PlaneEquation(face
|
1577
|
+
def PlaneEquation(face, mantissa: int = 6) -> dict:
|
1470
1578
|
"""
|
1471
1579
|
Returns the a, b, c, d coefficients of the plane equation of the input face. The input face is assumed to be planar.
|
1472
1580
|
|
1473
1581
|
Parameters
|
1474
1582
|
----------
|
1475
|
-
face :
|
1583
|
+
face : topologic_core.Face
|
1476
1584
|
The input face.
|
1477
1585
|
|
1478
1586
|
Returns
|
@@ -1486,7 +1594,7 @@ class Face(Topology):
|
|
1486
1594
|
import random
|
1487
1595
|
import time
|
1488
1596
|
|
1489
|
-
if not
|
1597
|
+
if not Topology.IsInstance(face, "Face"):
|
1490
1598
|
print("Face.PlaneEquation - Error: The input face is not a valid topologic face. Returning None.")
|
1491
1599
|
return None
|
1492
1600
|
vertices = Topology.Vertices(face)
|
@@ -1496,23 +1604,23 @@ class Face(Topology):
|
|
1496
1604
|
return Vertex.PlaneEquation(vertices, mantissa=mantissa)
|
1497
1605
|
|
1498
1606
|
@staticmethod
|
1499
|
-
def Planarize(face
|
1500
|
-
tolerance: float = 0.0001)
|
1607
|
+
def Planarize(face, origin= None,
|
1608
|
+
tolerance: float = 0.0001):
|
1501
1609
|
"""
|
1502
1610
|
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
1611
|
|
1504
1612
|
Parameters
|
1505
1613
|
----------
|
1506
|
-
face :
|
1614
|
+
face : topologic_core.Face
|
1507
1615
|
The input face.
|
1508
|
-
origin :
|
1616
|
+
origin : topologic_core.Vertex , optional
|
1509
1617
|
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
1618
|
tolerance : float , optional
|
1511
1619
|
The desired tolerance. The default is 0.0001.
|
1512
1620
|
|
1513
1621
|
Returns
|
1514
1622
|
-------
|
1515
|
-
|
1623
|
+
topologic_core.Face
|
1516
1624
|
The planarized face.
|
1517
1625
|
|
1518
1626
|
"""
|
@@ -1520,9 +1628,9 @@ class Face(Topology):
|
|
1520
1628
|
from topologicpy.Wire import Wire
|
1521
1629
|
from topologicpy.Topology import Topology
|
1522
1630
|
|
1523
|
-
if not
|
1631
|
+
if not Topology.IsInstance(face, "Face"):
|
1524
1632
|
return None
|
1525
|
-
if not
|
1633
|
+
if not Topology.IsInstance(origin, "Vertex"):
|
1526
1634
|
origin = Topology.Centroid(face)
|
1527
1635
|
eb = Face.ExternalBoundary(face)
|
1528
1636
|
plan_eb = Wire.Planarize(eb, origin=origin)
|
@@ -1534,16 +1642,16 @@ class Face(Topology):
|
|
1534
1642
|
return plan_face
|
1535
1643
|
|
1536
1644
|
@staticmethod
|
1537
|
-
def Project(faceA
|
1538
|
-
mantissa: int = 6, tolerance: float = 0.0001)
|
1645
|
+
def Project(faceA, faceB, direction : list = None,
|
1646
|
+
mantissa: int = 6, tolerance: float = 0.0001):
|
1539
1647
|
"""
|
1540
1648
|
Creates a projection of the first input face unto the second input face.
|
1541
1649
|
|
1542
1650
|
Parameters
|
1543
1651
|
----------
|
1544
|
-
faceA :
|
1652
|
+
faceA : topologic_core.Face
|
1545
1653
|
The face to be projected.
|
1546
|
-
faceB :
|
1654
|
+
faceB : topologic_core.Face
|
1547
1655
|
The face unto which the first input face will be projected.
|
1548
1656
|
direction : list, optional
|
1549
1657
|
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 +1662,20 @@ class Face(Topology):
|
|
1554
1662
|
|
1555
1663
|
Returns
|
1556
1664
|
-------
|
1557
|
-
|
1665
|
+
topologic_core.Face
|
1558
1666
|
The projected Face.
|
1559
1667
|
|
1560
1668
|
"""
|
1561
|
-
|
1562
1669
|
from topologicpy.Wire import Wire
|
1670
|
+
from topologicpy.Topology import Topology
|
1563
1671
|
|
1564
1672
|
if not faceA:
|
1565
1673
|
return None
|
1566
|
-
if not
|
1674
|
+
if not Topology.IsInstance(faceA, "Face"):
|
1567
1675
|
return None
|
1568
1676
|
if not faceB:
|
1569
1677
|
return None
|
1570
|
-
if not
|
1678
|
+
if not Topology.IsInstance(faceB, "Face"):
|
1571
1679
|
return None
|
1572
1680
|
|
1573
1681
|
eb = faceA.ExternalBoundary()
|
@@ -1582,7 +1690,7 @@ class Face(Topology):
|
|
1582
1690
|
return Face.ByWires(p_eb, p_ib_list, tolerance=tolerance)
|
1583
1691
|
|
1584
1692
|
@staticmethod
|
1585
|
-
def RectangleByPlaneEquation(origin
|
1693
|
+
def RectangleByPlaneEquation(origin= None, width: float = 1.0, length: float = 1.0, placement: str = "center", equation: dict = None, tolerance: float = 0.0001):
|
1586
1694
|
from topologicpy.Vertex import Vertex
|
1587
1695
|
# Extract coefficients of the plane equation
|
1588
1696
|
a = equation['a']
|
@@ -1598,13 +1706,13 @@ class Face(Topology):
|
|
1598
1706
|
return Face.Rectangle(origin=origin, width=width, length=length, direction = direction, placement=placement, tolerance=tolerance)
|
1599
1707
|
|
1600
1708
|
@staticmethod
|
1601
|
-
def Rectangle(origin
|
1709
|
+
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
1710
|
"""
|
1603
1711
|
Creates a rectangle.
|
1604
1712
|
|
1605
1713
|
Parameters
|
1606
1714
|
----------
|
1607
|
-
origin :
|
1715
|
+
origin : topologic_core.Vertex, optional
|
1608
1716
|
The location of the origin of the rectangle. The default is None which results in the rectangle being placed at (0, 0, 0).
|
1609
1717
|
width : float , optional
|
1610
1718
|
The width of the rectangle. The default is 1.0.
|
@@ -1619,26 +1727,27 @@ class Face(Topology):
|
|
1619
1727
|
|
1620
1728
|
Returns
|
1621
1729
|
-------
|
1622
|
-
|
1730
|
+
topologic_core.Face
|
1623
1731
|
The created face.
|
1624
1732
|
|
1625
1733
|
"""
|
1626
1734
|
from topologicpy.Wire import Wire
|
1735
|
+
from topologicpy.Topology import Topology
|
1627
1736
|
|
1628
1737
|
wire = Wire.Rectangle(origin=origin, width=width, length=length, direction=direction, placement=placement, tolerance=tolerance)
|
1629
|
-
if not
|
1738
|
+
if not Topology.IsInstance(wire, "Wire"):
|
1630
1739
|
print("Face.Rectangle - Error: Could not create the base wire for the rectangle. Returning None.")
|
1631
1740
|
return None
|
1632
1741
|
return Face.ByWire(wire, tolerance=tolerance)
|
1633
1742
|
|
1634
1743
|
@staticmethod
|
1635
|
-
def RemoveCollinearEdges(face
|
1744
|
+
def RemoveCollinearEdges(face, angTolerance: float = 0.1, tolerance: float = 0.0001):
|
1636
1745
|
"""
|
1637
1746
|
Removes any collinear edges in the input face.
|
1638
1747
|
|
1639
1748
|
Parameters
|
1640
1749
|
----------
|
1641
|
-
face :
|
1750
|
+
face : topologic_core.Face
|
1642
1751
|
The input face.
|
1643
1752
|
angTolerance : float , optional
|
1644
1753
|
The desired angular tolerance. The default is 0.1.
|
@@ -1647,19 +1756,51 @@ class Face(Topology):
|
|
1647
1756
|
|
1648
1757
|
Returns
|
1649
1758
|
-------
|
1650
|
-
|
1759
|
+
topologic_core.Face
|
1651
1760
|
The created face without any collinear edges.
|
1652
1761
|
|
1653
1762
|
"""
|
1654
1763
|
from topologicpy.Wire import Wire
|
1764
|
+
from topologicpy.Topology import Topology
|
1655
1765
|
|
1656
|
-
if not
|
1766
|
+
if not Topology.IsInstance(face, "Face"):
|
1657
1767
|
print("Face.RemoveCollinearEdges - Error: The input face parameter is not a valid face. Returning None.")
|
1658
1768
|
return None
|
1659
1769
|
eb = Wire.RemoveCollinearEdges(Face.Wire(face), angTolerance=angTolerance, tolerance=tolerance)
|
1660
1770
|
ib = [Wire.RemoveCollinearEdges(w, angTolerance=angTolerance, tolerance=tolerance) for w in Face.InternalBoundaries(face)]
|
1661
1771
|
return Face.ByWires(eb, ib)
|
1662
1772
|
|
1773
|
+
@staticmethod
|
1774
|
+
def Simplify(face, tolerance=0.0001):
|
1775
|
+
"""
|
1776
|
+
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
|
1777
|
+
Part of this code was contributed by gaoxipeng. See https://github.com/wassimj/topologicpy/issues/35
|
1778
|
+
|
1779
|
+
Parameters
|
1780
|
+
----------
|
1781
|
+
face : topologic_core.Face
|
1782
|
+
The input face.
|
1783
|
+
tolerance : float , optional
|
1784
|
+
The desired tolerance. The default is 0.0001. Edges shorter than this length will be removed.
|
1785
|
+
|
1786
|
+
Returns
|
1787
|
+
-------
|
1788
|
+
topologic_core.Face
|
1789
|
+
The simplified face.
|
1790
|
+
"""
|
1791
|
+
from topologicpy.Wire import Wire
|
1792
|
+
from topologicpy.Topology import Topology
|
1793
|
+
|
1794
|
+
if not Topology.IsInstance(face, "Face"):
|
1795
|
+
print("Face.Simplify - Error: The input face parameter is not a valid face. Returning None.")
|
1796
|
+
return None
|
1797
|
+
|
1798
|
+
eb = Face.ExternalBoundary(face)
|
1799
|
+
eb = Wire.Simplify(eb, tolerance=tolerance)
|
1800
|
+
ibList = Face.InternalBoundaries(face)
|
1801
|
+
ibList = [Wire.Simplify(ib) for ib in ibList]
|
1802
|
+
return Face.ByWires(eb, ibList)
|
1803
|
+
|
1663
1804
|
@staticmethod
|
1664
1805
|
def Skeleton(face, tolerance=0.001):
|
1665
1806
|
"""
|
@@ -1668,31 +1809,33 @@ class Face(Topology):
|
|
1668
1809
|
|
1669
1810
|
Parameters
|
1670
1811
|
----------
|
1671
|
-
face :
|
1812
|
+
face : topologic_core.Face
|
1672
1813
|
The input face.
|
1673
1814
|
tolerance : float , optional
|
1674
1815
|
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
1816
|
|
1676
1817
|
Returns
|
1677
1818
|
-------
|
1678
|
-
|
1819
|
+
topologic_core.Wire
|
1679
1820
|
The created straight skeleton.
|
1680
1821
|
|
1681
1822
|
"""
|
1682
1823
|
from topologicpy.Wire import Wire
|
1683
|
-
|
1824
|
+
from topologicpy.Topology import Topology
|
1825
|
+
|
1826
|
+
if not Topology.IsInstance(face, "Face"):
|
1684
1827
|
print("Face.Skeleton - Error: The input face is not a valid topologic face. Retruning None.")
|
1685
1828
|
return None
|
1686
1829
|
return Wire.Skeleton(face, tolerance=tolerance)
|
1687
1830
|
|
1688
1831
|
@staticmethod
|
1689
|
-
def Square(origin
|
1832
|
+
def Square(origin= None, size: float = 1.0, direction: list = [0, 0, 1], placement: str = "center", tolerance: float = 0.0001):
|
1690
1833
|
"""
|
1691
1834
|
Creates a square.
|
1692
1835
|
|
1693
1836
|
Parameters
|
1694
1837
|
----------
|
1695
|
-
origin :
|
1838
|
+
origin : topologic_core.Vertex , optional
|
1696
1839
|
The location of the origin of the square. The default is None which results in the square being placed at (0, 0, 0).
|
1697
1840
|
size : float , optional
|
1698
1841
|
The size of the square. The default is 1.0.
|
@@ -1705,20 +1848,62 @@ class Face(Topology):
|
|
1705
1848
|
|
1706
1849
|
Returns
|
1707
1850
|
-------
|
1708
|
-
|
1851
|
+
topologic_core.Face
|
1709
1852
|
The created square.
|
1710
1853
|
|
1711
1854
|
"""
|
1712
1855
|
return Face.Rectangle(origin=origin, width=size, length=size, direction=direction, placement=placement, tolerance=tolerance)
|
1713
1856
|
|
1857
|
+
|
1714
1858
|
@staticmethod
|
1715
|
-
def
|
1859
|
+
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):
|
1860
|
+
"""
|
1861
|
+
Creates a Squircle which is a hybrid between a circle and a square. See https://en.wikipedia.org/wiki/Squircle
|
1862
|
+
|
1863
|
+
Parameters
|
1864
|
+
----------
|
1865
|
+
origin : topologic_core.Vertex , optional
|
1866
|
+
The location of the origin of the squircle. The default is None which results in the squircle being placed at (0, 0, 0).
|
1867
|
+
radius : float , optional
|
1868
|
+
The radius of the squircle. The default is 0.5.
|
1869
|
+
sides : int , optional
|
1870
|
+
The number of sides of the squircle. The default is 121.
|
1871
|
+
a : float , optional
|
1872
|
+
The "a" factor affects the x position of the points to interpolate between a circle and a square.
|
1873
|
+
A value of 1 will create a circle. Higher values will create a more square-like shape. The default is 2.0.
|
1874
|
+
b : float , optional
|
1875
|
+
The "b" factor affects the y position of the points to interpolate between a circle and a square.
|
1876
|
+
A value of 1 will create a circle. Higher values will create a more square-like shape. The default is 2.0.
|
1877
|
+
radius : float , optional
|
1878
|
+
The desired radius of the squircle. The default is 0.5.
|
1879
|
+
sides : int , optional
|
1880
|
+
The desired number of sides for the squircle. The default is 100.
|
1881
|
+
direction : list , optional
|
1882
|
+
The vector representing the up direction of the circle. The default is [0, 0, 1].
|
1883
|
+
placement : str , optional
|
1884
|
+
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".
|
1885
|
+
angTolerance : float , optional
|
1886
|
+
The desired angular tolerance. The default is 0.1.
|
1887
|
+
tolerance : float , optional
|
1888
|
+
The desired tolerance. The default is 0.0001.
|
1889
|
+
|
1890
|
+
Returns
|
1891
|
+
-------
|
1892
|
+
topologic_core.Face
|
1893
|
+
The created squircle.
|
1894
|
+
"""
|
1895
|
+
from topologicpy.Wire import Wire
|
1896
|
+
wire = Wire.Squircle(origin = origin, radius= radius, sides = sides, a = a, b = b, direction = direction, placement = placement, angTolerance = angTolerance, tolerance = tolerance)
|
1897
|
+
return Face.ByWire(wire)
|
1898
|
+
|
1899
|
+
@staticmethod
|
1900
|
+
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
1901
|
"""
|
1717
1902
|
Creates a star.
|
1718
1903
|
|
1719
1904
|
Parameters
|
1720
1905
|
----------
|
1721
|
-
origin :
|
1906
|
+
origin : topologic_core.Vertex, optional
|
1722
1907
|
The location of the origin of the star. The default is None which results in the star being placed at (0, 0, 0).
|
1723
1908
|
radiusA : float , optional
|
1724
1909
|
The outer radius of the star. The default is 1.0.
|
@@ -1735,25 +1920,27 @@ class Face(Topology):
|
|
1735
1920
|
|
1736
1921
|
Returns
|
1737
1922
|
-------
|
1738
|
-
|
1923
|
+
topologic_core.Face
|
1739
1924
|
The created face.
|
1740
1925
|
|
1741
1926
|
"""
|
1742
1927
|
from topologicpy.Wire import Wire
|
1928
|
+
from topologicpy.Topology import Topology
|
1929
|
+
|
1743
1930
|
wire = Wire.Star(origin=origin, radiusA=radiusA, radiusB=radiusB, rays=rays, direction=direction, placement=placement, tolerance=tolerance)
|
1744
|
-
if not
|
1931
|
+
if not Topology.IsInstance(wire, "Wire"):
|
1745
1932
|
print("Face.Rectangle - Error: Could not create the base wire for the star. Returning None.")
|
1746
1933
|
return None
|
1747
1934
|
return Face.ByWire(wire, tolerance=tolerance)
|
1748
1935
|
|
1749
1936
|
@staticmethod
|
1750
|
-
def Trapezoid(origin
|
1937
|
+
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
1938
|
"""
|
1752
1939
|
Creates a trapezoid.
|
1753
1940
|
|
1754
1941
|
Parameters
|
1755
1942
|
----------
|
1756
|
-
origin :
|
1943
|
+
origin : topologic_core.Vertex, optional
|
1757
1944
|
The location of the origin of the trapezoid. The default is None which results in the trapezoid being placed at (0, 0, 0).
|
1758
1945
|
widthA : float , optional
|
1759
1946
|
The width of the bottom edge of the trapezoid. The default is 1.0.
|
@@ -1774,25 +1961,27 @@ class Face(Topology):
|
|
1774
1961
|
|
1775
1962
|
Returns
|
1776
1963
|
-------
|
1777
|
-
|
1964
|
+
topologic_core.Face
|
1778
1965
|
The created trapezoid.
|
1779
1966
|
|
1780
1967
|
"""
|
1781
1968
|
from topologicpy.Wire import Wire
|
1969
|
+
from topologicpy.Topology import Topology
|
1970
|
+
|
1782
1971
|
wire = Wire.Trapezoid(origin=origin, widthA=widthA, widthB=widthB, offsetA=offsetA, offsetB=offsetB, length=length, direction=direction, placement=placement, tolerance=tolerance)
|
1783
|
-
if not
|
1972
|
+
if not Topology.IsInstance(wire, "Wire"):
|
1784
1973
|
print("Face.Rectangle - Error: Could not create the base wire for the trapezoid. Returning None.")
|
1785
1974
|
return None
|
1786
1975
|
return Face.ByWire(wire, tolerance=tolerance)
|
1787
1976
|
|
1788
1977
|
@staticmethod
|
1789
|
-
def Triangulate(face
|
1978
|
+
def Triangulate(face, mode: int = 0, meshSize: float = None, tolerance: float = 0.0001) -> list:
|
1790
1979
|
"""
|
1791
1980
|
Triangulates the input face and returns a list of faces.
|
1792
1981
|
|
1793
1982
|
Parameters
|
1794
1983
|
----------
|
1795
|
-
face :
|
1984
|
+
face : topologic_core.Face
|
1796
1985
|
The input face.
|
1797
1986
|
tolerance : float , optional
|
1798
1987
|
The desired tolerance. The default is 0.0001.
|
@@ -1828,7 +2017,7 @@ class Face(Topology):
|
|
1828
2017
|
|
1829
2018
|
Parameters
|
1830
2019
|
----------
|
1831
|
-
face :
|
2020
|
+
face : topologic_core.Face
|
1832
2021
|
The input face.
|
1833
2022
|
meshSize : float , optional
|
1834
2023
|
The desired mesh size.
|
@@ -1837,7 +2026,7 @@ class Face(Topology):
|
|
1837
2026
|
|
1838
2027
|
Returns
|
1839
2028
|
----------
|
1840
|
-
|
2029
|
+
topologic_core.Shell
|
1841
2030
|
The shell of triangular meshes.
|
1842
2031
|
|
1843
2032
|
"""
|
@@ -1877,7 +2066,7 @@ class Face(Topology):
|
|
1877
2066
|
from topologicpy.Wire import Wire
|
1878
2067
|
from topologicpy.Face import Face
|
1879
2068
|
|
1880
|
-
if not
|
2069
|
+
if not Topology.IsInstance(face, "Face"):
|
1881
2070
|
print("Shell.ByMeshFace - Error: The input face parameter is not a valid face. Returning None.")
|
1882
2071
|
return None
|
1883
2072
|
if not meshSize:
|
@@ -1952,7 +2141,7 @@ class Face(Topology):
|
|
1952
2141
|
faces.append(Face.ByVertices(face_vertices))
|
1953
2142
|
return faces
|
1954
2143
|
|
1955
|
-
if not
|
2144
|
+
if not Topology.IsInstance(face, "Face"):
|
1956
2145
|
print("Face.Triangulate - Error: The input face parameter is not a valid face. Returning None.")
|
1957
2146
|
return None
|
1958
2147
|
vertices = Topology.Vertices(face)
|
@@ -1966,7 +2155,7 @@ class Face(Topology):
|
|
1966
2155
|
shell_faces = []
|
1967
2156
|
for i in range(0,5,1):
|
1968
2157
|
try:
|
1969
|
-
_ = topologic.FaceUtility.Triangulate(flatFace, float(i)*0.1, shell_faces)
|
2158
|
+
_ = topologic.FaceUtility.Triangulate(flatFace, float(i)*0.1, shell_faces) # Hook to Core
|
1970
2159
|
break
|
1971
2160
|
except:
|
1972
2161
|
continue
|
@@ -1981,49 +2170,51 @@ class Face(Topology):
|
|
1981
2170
|
if Face.Angle(face, f) > 90:
|
1982
2171
|
wire = Face.ExternalBoundary(f)
|
1983
2172
|
wire = Wire.Invert(wire)
|
1984
|
-
f =
|
2173
|
+
f = Face.ByWire(wire)
|
1985
2174
|
finalFaces.append(f)
|
1986
2175
|
else:
|
1987
2176
|
finalFaces.append(f)
|
1988
2177
|
return finalFaces
|
1989
2178
|
|
1990
2179
|
@staticmethod
|
1991
|
-
def TrimByWire(face
|
2180
|
+
def TrimByWire(face, wire, reverse: bool = False):
|
1992
2181
|
"""
|
1993
2182
|
Trims the input face by the input wire.
|
1994
2183
|
|
1995
2184
|
Parameters
|
1996
2185
|
----------
|
1997
|
-
face :
|
2186
|
+
face : topologic_core.Face
|
1998
2187
|
The input face.
|
1999
|
-
wire :
|
2188
|
+
wire : topologic_core.Wire
|
2000
2189
|
The input wire.
|
2001
2190
|
reverse : bool , optional
|
2002
2191
|
If set to True, the effect of the trim will be reversed. The default is False.
|
2003
2192
|
|
2004
2193
|
Returns
|
2005
2194
|
-------
|
2006
|
-
|
2195
|
+
topologic_core.Face
|
2007
2196
|
The resulting trimmed face.
|
2008
2197
|
|
2009
2198
|
"""
|
2010
|
-
|
2199
|
+
from topologicpy.Topology import Topology
|
2200
|
+
|
2201
|
+
if not Topology.IsInstance(face, "Face"):
|
2011
2202
|
return None
|
2012
|
-
if not
|
2203
|
+
if not Topology.IsInstance(wire, "Wire"):
|
2013
2204
|
return face
|
2014
|
-
trimmed_face = topologic.FaceUtility.TrimByWire(face, wire, False)
|
2205
|
+
trimmed_face = topologic.FaceUtility.TrimByWire(face, wire, False) # Hook to Core
|
2015
2206
|
if reverse:
|
2016
2207
|
trimmed_face = face.Difference(trimmed_face)
|
2017
2208
|
return trimmed_face
|
2018
2209
|
|
2019
2210
|
@staticmethod
|
2020
|
-
def VertexByParameters(face
|
2211
|
+
def VertexByParameters(face, u: float = 0.5, v: float = 0.5):
|
2021
2212
|
"""
|
2022
2213
|
Creates a vertex at the *u* and *v* parameters of the input face.
|
2023
2214
|
|
2024
2215
|
Parameters
|
2025
2216
|
----------
|
2026
|
-
face :
|
2217
|
+
face : topologic_core.Face
|
2027
2218
|
The input face.
|
2028
2219
|
u : float , optional
|
2029
2220
|
The *u* parameter of the input face. The default is 0.5.
|
@@ -2036,20 +2227,22 @@ class Face(Topology):
|
|
2036
2227
|
The created vertex.
|
2037
2228
|
|
2038
2229
|
"""
|
2039
|
-
|
2230
|
+
from topologicpy.Topology import Topology
|
2231
|
+
|
2232
|
+
if not Topology.IsInstance(face, "Face"):
|
2040
2233
|
return None
|
2041
|
-
return topologic.FaceUtility.VertexAtParameters(face, u, v)
|
2234
|
+
return topologic.FaceUtility.VertexAtParameters(face, u, v) # Hook to Core
|
2042
2235
|
|
2043
2236
|
@staticmethod
|
2044
|
-
def VertexParameters(face
|
2237
|
+
def VertexParameters(face, vertex, outputType: str = "uv", mantissa: int = 6) -> list:
|
2045
2238
|
"""
|
2046
2239
|
Returns the *u* and *v* parameters of the input face at the location of the input vertex.
|
2047
2240
|
|
2048
2241
|
Parameters
|
2049
2242
|
----------
|
2050
|
-
face :
|
2243
|
+
face : topologic_core.Face
|
2051
2244
|
The input face.
|
2052
|
-
vertex :
|
2245
|
+
vertex : topologic_core.Vertex
|
2053
2246
|
The input vertex.
|
2054
2247
|
outputType : string , optional
|
2055
2248
|
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 +2255,13 @@ class Face(Topology):
|
|
2062
2255
|
The list of *u* and/or *v* as specified by the outputType input.
|
2063
2256
|
|
2064
2257
|
"""
|
2065
|
-
|
2258
|
+
from topologicpy.Topology import Topology
|
2259
|
+
|
2260
|
+
if not Topology.IsInstance(face, "Face"):
|
2066
2261
|
return None
|
2067
|
-
if not
|
2262
|
+
if not Topology.IsInstance(vertex, "Vertex"):
|
2068
2263
|
return None
|
2069
|
-
params = topologic.FaceUtility.ParametersAtVertex(face, vertex)
|
2264
|
+
params = topologic.FaceUtility.ParametersAtVertex(face, vertex) # Hook to Core
|
2070
2265
|
u = round(params[0], mantissa)
|
2071
2266
|
v = round(params[1], mantissa)
|
2072
2267
|
outputType = list(outputType.lower())
|
@@ -2079,13 +2274,13 @@ class Face(Topology):
|
|
2079
2274
|
return returnResult
|
2080
2275
|
|
2081
2276
|
@staticmethod
|
2082
|
-
def Vertices(face
|
2277
|
+
def Vertices(face) -> list:
|
2083
2278
|
"""
|
2084
2279
|
Returns the vertices of the input face.
|
2085
2280
|
|
2086
2281
|
Parameters
|
2087
2282
|
----------
|
2088
|
-
face :
|
2283
|
+
face : topologic_core.Face
|
2089
2284
|
The input face.
|
2090
2285
|
|
2091
2286
|
Returns
|
@@ -2094,38 +2289,40 @@ class Face(Topology):
|
|
2094
2289
|
The list of vertices.
|
2095
2290
|
|
2096
2291
|
"""
|
2097
|
-
|
2292
|
+
from topologicpy.Topology import Topology
|
2293
|
+
|
2294
|
+
if not Topology.IsInstance(face, "Face"):
|
2098
2295
|
return None
|
2099
2296
|
vertices = []
|
2100
2297
|
_ = face.Vertices(None, vertices)
|
2101
2298
|
return vertices
|
2102
2299
|
|
2103
2300
|
@staticmethod
|
2104
|
-
def Wire(face
|
2301
|
+
def Wire(face):
|
2105
2302
|
"""
|
2106
2303
|
Returns the external boundary (closed wire) of the input face.
|
2107
2304
|
|
2108
2305
|
Parameters
|
2109
2306
|
----------
|
2110
|
-
face :
|
2307
|
+
face : topologic_core.Face
|
2111
2308
|
The input face.
|
2112
2309
|
|
2113
2310
|
Returns
|
2114
2311
|
-------
|
2115
|
-
|
2312
|
+
topologic_core.Wire
|
2116
2313
|
The external boundary of the input face.
|
2117
2314
|
|
2118
2315
|
"""
|
2119
2316
|
return face.ExternalBoundary()
|
2120
2317
|
|
2121
2318
|
@staticmethod
|
2122
|
-
def Wires(face
|
2319
|
+
def Wires(face) -> list:
|
2123
2320
|
"""
|
2124
2321
|
Returns the wires of the input face.
|
2125
2322
|
|
2126
2323
|
Parameters
|
2127
2324
|
----------
|
2128
|
-
face :
|
2325
|
+
face : topologic_core.Face
|
2129
2326
|
The input face.
|
2130
2327
|
|
2131
2328
|
Returns
|
@@ -2134,7 +2331,9 @@ class Face(Topology):
|
|
2134
2331
|
The list of wires.
|
2135
2332
|
|
2136
2333
|
"""
|
2137
|
-
|
2334
|
+
from topologicpy.Topology import Topology
|
2335
|
+
|
2336
|
+
if not Topology.IsInstance(face, "Face"):
|
2138
2337
|
return None
|
2139
2338
|
wires = []
|
2140
2339
|
_ = face.Wires(None, wires)
|