topologicpy 0.8.93__py3-none-any.whl → 0.8.95__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- topologicpy/Cell.py +173 -58
- topologicpy/Edge.py +84 -5
- topologicpy/Face.py +37 -1
- topologicpy/Graph.py +605 -3
- topologicpy/Plotly.py +10 -12
- topologicpy/Topology.py +422 -8
- topologicpy/Vector.py +182 -21
- topologicpy/Vertex.py +155 -3
- topologicpy/version.py +1 -1
- {topologicpy-0.8.93.dist-info → topologicpy-0.8.95.dist-info}/METADATA +1 -1
- {topologicpy-0.8.93.dist-info → topologicpy-0.8.95.dist-info}/RECORD +14 -14
- {topologicpy-0.8.93.dist-info → topologicpy-0.8.95.dist-info}/WHEEL +0 -0
- {topologicpy-0.8.93.dist-info → topologicpy-0.8.95.dist-info}/licenses/LICENSE +0 -0
- {topologicpy-0.8.93.dist-info → topologicpy-0.8.95.dist-info}/top_level.txt +0 -0
topologicpy/Cell.py
CHANGED
|
@@ -331,12 +331,19 @@ class Cell():
|
|
|
331
331
|
return None
|
|
332
332
|
return cell
|
|
333
333
|
|
|
334
|
+
|
|
334
335
|
@staticmethod
|
|
335
|
-
def ByThickenedFace(face, thickness: float = 1.0, bothSides: bool = True,
|
|
336
|
-
|
|
336
|
+
def ByThickenedFace(face, thickness: float = 1.0, bothSides: bool = True, wSides: int = 1,
|
|
337
|
+
reverse: bool = False, tolerance: float = 0.0001, silent: bool = False):
|
|
337
338
|
"""
|
|
338
339
|
Creates a cell by thickening the input face.
|
|
339
340
|
|
|
341
|
+
Behaviour:
|
|
342
|
+
- Only the bottom and top faces are used as horizontal faces.
|
|
343
|
+
- wSides controls the number of vertical segments along the thickness.
|
|
344
|
+
Intermediate offset layers are used only to build side faces and are
|
|
345
|
+
not included as horizontal faces in Cell.ByFaces.
|
|
346
|
+
|
|
340
347
|
Parameters
|
|
341
348
|
----------
|
|
342
349
|
face : topologic_core.Face
|
|
@@ -344,11 +351,17 @@ class Cell():
|
|
|
344
351
|
thickness : float , optional
|
|
345
352
|
The desired thickness. Default is 1.0.
|
|
346
353
|
bothSides : bool
|
|
347
|
-
If True, the
|
|
354
|
+
If True, the thickening is symmetric about the original face
|
|
355
|
+
(i.e. from -thickness/2 to +thickness/2).
|
|
356
|
+
If False, the thickening is from 0 to +thickness along the face normal.
|
|
357
|
+
Default is True.
|
|
348
358
|
reverse : bool
|
|
349
|
-
If True, the
|
|
350
|
-
|
|
351
|
-
|
|
359
|
+
If True, the extrusion direction is flipped (normal is negated).
|
|
360
|
+
Default is False.
|
|
361
|
+
wSides: int, optional
|
|
362
|
+
The number of segments along the thickness direction.
|
|
363
|
+
This is the same definition regardless of bothSides.
|
|
364
|
+
Default is 1.
|
|
352
365
|
tolerance : float , optional
|
|
353
366
|
The desired tolerance. Default is 0.0001.
|
|
354
367
|
silent : bool , optional
|
|
@@ -357,60 +370,161 @@ class Cell():
|
|
|
357
370
|
Returns
|
|
358
371
|
-------
|
|
359
372
|
topologic_core.Cell
|
|
360
|
-
The created cell.
|
|
361
|
-
|
|
373
|
+
The created cell, or None on failure.
|
|
362
374
|
"""
|
|
375
|
+
import math
|
|
376
|
+
from topologicpy.Topology import Topology
|
|
377
|
+
from topologicpy.Face import Face
|
|
363
378
|
from topologicpy.Edge import Edge
|
|
364
379
|
from topologicpy.Wire import Wire
|
|
365
|
-
from topologicpy.
|
|
366
|
-
from topologicpy.Cluster import Cluster
|
|
367
|
-
from topologicpy.Topology import Topology
|
|
380
|
+
from topologicpy.Cell import Cell
|
|
368
381
|
|
|
382
|
+
# -----------------------------
|
|
383
|
+
# Validation
|
|
384
|
+
# -----------------------------
|
|
369
385
|
if not Topology.IsInstance(face, "Face"):
|
|
370
|
-
|
|
386
|
+
if not silent:
|
|
387
|
+
print("Cell.ByThickenedFace - Error: Input is not a valid Face. Returning None.")
|
|
371
388
|
return None
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
389
|
+
|
|
390
|
+
if thickness <= tolerance:
|
|
391
|
+
if not silent:
|
|
392
|
+
print("Cell.ByThickenedFace - Error: Thickness is less than or equal to the tolerance. Returning None.")
|
|
393
|
+
return None
|
|
394
|
+
|
|
395
|
+
if wSides < 1:
|
|
396
|
+
if not silent:
|
|
397
|
+
print("Cell.ByThickenedFace - Error: wSides is less than 1. Returning None.")
|
|
398
|
+
return None
|
|
399
|
+
|
|
400
|
+
if thickness/float(wSides) <= tolerance:
|
|
401
|
+
if not silent:
|
|
402
|
+
print("Cell.ByThickenedFace - Error: The distance between layers is less than or equal to the tolerance. Returning None.")
|
|
403
|
+
return None
|
|
404
|
+
|
|
405
|
+
# -----------------------------
|
|
406
|
+
# Face normal (normalized)
|
|
407
|
+
# -----------------------------
|
|
408
|
+
normal = Face.Normal(face)
|
|
409
|
+
if not isinstance(normal, (list, tuple)) or len(normal) != 3:
|
|
410
|
+
if not silent:
|
|
411
|
+
print("Cell.ByThickenedFace - Error: Could not compute face normal.")
|
|
412
|
+
return None
|
|
413
|
+
|
|
414
|
+
nx, ny, nz = normal
|
|
415
|
+
L = math.sqrt(nx*nx + ny*ny + nz*nz)
|
|
416
|
+
if L <= tolerance:
|
|
417
|
+
if not silent:
|
|
418
|
+
print("Cell.ByThickenedFace - Error: Degenerate face normal.")
|
|
419
|
+
return None
|
|
420
|
+
|
|
421
|
+
nx, ny, nz = nx/L, ny/L, nz/L
|
|
422
|
+
|
|
423
|
+
if reverse:
|
|
424
|
+
nx, ny, nz = -nx, -ny, -nz
|
|
425
|
+
|
|
426
|
+
# -----------------------------
|
|
427
|
+
# Build offset layers
|
|
428
|
+
# NOTE: We will only keep the min/max offset faces as bottom/top.
|
|
429
|
+
# Intermediate layers are used only for building side faces.
|
|
430
|
+
# -----------------------------
|
|
431
|
+
step = thickness / float(wSides)
|
|
432
|
+
layers = []
|
|
433
|
+
|
|
375
434
|
if bothSides:
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
topFace = Topology.Translate(face,
|
|
383
|
-
x=faceNormal[0]*0.5*thickness,
|
|
384
|
-
y=faceNormal[1]*0.5*thickness,
|
|
385
|
-
z=faceNormal[2]*0.5*thickness,
|
|
386
|
-
transferDictionaries=False,
|
|
387
|
-
silent=True)
|
|
435
|
+
# Symmetric: [-thickness/2, ..., +thickness/2]
|
|
436
|
+
start = -0.5 * thickness
|
|
437
|
+
for i in range(wSides + 1):
|
|
438
|
+
offset = start + step * i
|
|
439
|
+
f = Topology.Translate(face, nx*offset, ny*offset, nz*offset)
|
|
440
|
+
layers.append((offset, f))
|
|
388
441
|
else:
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
transferDictionaries=False,
|
|
395
|
-
silent=True)
|
|
442
|
+
# One-sided: [0, ..., thickness]
|
|
443
|
+
for i in range(wSides + 1):
|
|
444
|
+
offset = step * i
|
|
445
|
+
f = Topology.Translate(face, nx*offset, ny*offset, nz*offset)
|
|
446
|
+
layers.append((offset, f))
|
|
396
447
|
|
|
397
|
-
|
|
398
|
-
|
|
448
|
+
if len(layers) < 2:
|
|
449
|
+
if not silent:
|
|
450
|
+
print("Cell.ByThickenedFace - Error: Not enough layers to form a volume.")
|
|
451
|
+
return None
|
|
399
452
|
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
453
|
+
layers.sort(key=lambda x: x[0])
|
|
454
|
+
|
|
455
|
+
# Bottom and top faces only
|
|
456
|
+
bottom_face = layers[0][1]
|
|
457
|
+
top_face = layers[-1][1]
|
|
458
|
+
|
|
459
|
+
faces_all = [bottom_face, top_face]
|
|
460
|
+
|
|
461
|
+
# -----------------------------
|
|
462
|
+
# Build side faces between each consecutive pair of layers
|
|
463
|
+
# These are the vertical segmentation faces controlled by wSides.
|
|
464
|
+
# -----------------------------
|
|
465
|
+
for i in range(len(layers) - 1):
|
|
466
|
+
_, faceA = layers[i]
|
|
467
|
+
_, faceB = layers[i + 1]
|
|
468
|
+
|
|
469
|
+
edgesA = Topology.Edges(faceA)
|
|
470
|
+
edgesB = Topology.Edges(faceB)
|
|
471
|
+
|
|
472
|
+
if not edgesA or not edgesB or len(edgesA) != len(edgesB):
|
|
473
|
+
if not silent:
|
|
474
|
+
print("Cell.ByThickenedFace - Warning: Edge mismatch between layers. "
|
|
475
|
+
"Side faces may be incomplete.")
|
|
476
|
+
# We try to continue with min length
|
|
477
|
+
count = min(len(edgesA), len(edgesB))
|
|
478
|
+
|
|
479
|
+
for j in range(count):
|
|
480
|
+
eA = edgesA[j]
|
|
481
|
+
eB = edgesB[j]
|
|
482
|
+
|
|
483
|
+
vA = Topology.Vertices(eA)
|
|
484
|
+
vB = Topology.Vertices(eB)
|
|
485
|
+
|
|
486
|
+
if not vA or not vB or len(vA) != 2 or len(vB) != 2:
|
|
487
|
+
continue
|
|
488
|
+
|
|
489
|
+
vA1, vA2 = vA
|
|
490
|
+
vB1, vB2 = vB
|
|
491
|
+
|
|
492
|
+
try:
|
|
493
|
+
e1 = Edge.ByStartVertexEndVertex(vA1, vA2)
|
|
494
|
+
e2 = Edge.ByStartVertexEndVertex(vA2, vB2)
|
|
495
|
+
e3 = Edge.ByStartVertexEndVertex(vB2, vB1)
|
|
496
|
+
e4 = Edge.ByStartVertexEndVertex(vB1, vA1)
|
|
497
|
+
|
|
498
|
+
if not (e1 and e2 and e3 and e4):
|
|
499
|
+
continue
|
|
500
|
+
|
|
501
|
+
side_wire = Wire.ByEdges([e1, e2, e3, e4])
|
|
502
|
+
if not side_wire:
|
|
503
|
+
continue
|
|
504
|
+
|
|
505
|
+
side_face = Face.ByWire(side_wire)
|
|
506
|
+
if side_face:
|
|
507
|
+
faces_all.append(side_face)
|
|
508
|
+
except Exception:
|
|
509
|
+
# Skip problematic quads but continue
|
|
510
|
+
continue
|
|
511
|
+
|
|
512
|
+
# -----------------------------
|
|
513
|
+
# Build final cell
|
|
514
|
+
# -----------------------------
|
|
515
|
+
try:
|
|
516
|
+
cell = Cell.ByFaces(faces_all, tolerance=tolerance)
|
|
517
|
+
except Exception:
|
|
518
|
+
if not silent:
|
|
519
|
+
print("Cell.ByThickenedFace - Error: Cell.ByFaces failed.")
|
|
520
|
+
return None
|
|
521
|
+
|
|
522
|
+
if not Topology.IsInstance(cell, "Cell"):
|
|
523
|
+
if not silent:
|
|
524
|
+
print("Cell.ByThickenedFace - Error: Cell.ByFaces did not return a valid Cell.")
|
|
525
|
+
return None
|
|
526
|
+
|
|
527
|
+
return cell
|
|
414
528
|
|
|
415
529
|
@staticmethod
|
|
416
530
|
def ByThickenedShell(shell, direction: list = [0, 0, 1], thickness: float = 1.0, bothSides: bool = True, reverse: bool = False,
|
|
@@ -1158,7 +1272,7 @@ class Cell():
|
|
|
1158
1272
|
tolerance=tolerance,
|
|
1159
1273
|
silent=silent)
|
|
1160
1274
|
return_cell = Cell.ByThickenedFace(cross_shape_face, thickness=height, bothSides=True, reverse=False,
|
|
1161
|
-
|
|
1275
|
+
tolerance=tolerance, silent=silent)
|
|
1162
1276
|
xOffset = 0
|
|
1163
1277
|
yOffset = 0
|
|
1164
1278
|
zOffset = 0
|
|
@@ -1456,7 +1570,7 @@ class Cell():
|
|
|
1456
1570
|
|
|
1457
1571
|
baseWire = Wire.Circle(origin=circle_origin, radius=radius, sides=uSides, fromAngle=0, toAngle=360, close=True, direction=[0, 0, 1], placement="center", tolerance=tolerance)
|
|
1458
1572
|
baseFace = Face.ByWire(baseWire, tolerance=tolerance)
|
|
1459
|
-
cylinder = Cell.ByThickenedFace(face=baseFace, thickness=height, bothSides=False, tolerance=tolerance)
|
|
1573
|
+
cylinder = Cell.ByThickenedFace(face=baseFace, thickness=height, bothSides=False, reverse=False, tolerance=tolerance)
|
|
1460
1574
|
if vSides > 1:
|
|
1461
1575
|
cutting_planes = []
|
|
1462
1576
|
baseX = Vertex.X(origin, mantissa=mantissa) + xOffset
|
|
@@ -2972,15 +3086,16 @@ class Cell():
|
|
|
2972
3086
|
elif placement.lower() == "lowerleft":
|
|
2973
3087
|
xOffset = width*0.5
|
|
2974
3088
|
yOffset = length*0.5
|
|
2975
|
-
|
|
2976
|
-
|
|
2977
|
-
|
|
2978
|
-
|
|
3089
|
+
|
|
3090
|
+
vb1 = Vertex.ByCoordinates(Vertex.X(origin, mantissa=mantissa)-width*0.5+xOffset,Vertex.Y(origin, mantissa=mantissa)+length*0.5+yOffset,Vertex.Z(origin, mantissa=mantissa)+zOffset)
|
|
3091
|
+
vb2 = Vertex.ByCoordinates(Vertex.X(origin, mantissa=mantissa)+width*0.5+xOffset,Vertex.Y(origin, mantissa=mantissa)+length*0.5+yOffset,Vertex.Z(origin, mantissa=mantissa)+zOffset)
|
|
3092
|
+
vb3 = Vertex.ByCoordinates(Vertex.X(origin, mantissa=mantissa)+width*0.5+xOffset,Vertex.Y(origin, mantissa=mantissa)-length*0.5+yOffset,Vertex.Z(origin, mantissa=mantissa)+zOffset)
|
|
3093
|
+
vb4 = Vertex.ByCoordinates(Vertex.X(origin, mantissa=mantissa)-width*0.5+xOffset,Vertex.Y(origin, mantissa=mantissa)-length*0.5+yOffset,Vertex.Z(origin, mantissa=mantissa)+zOffset)
|
|
2979
3094
|
|
|
2980
3095
|
baseWire = Wire.ByVertices([vb1, vb2, vb3, vb4], close=True)
|
|
2981
3096
|
baseFace = Face.ByWire(baseWire, tolerance=tolerance)
|
|
2982
3097
|
|
|
2983
|
-
prism = Cell.ByThickenedFace(baseFace, thickness=height, bothSides = False)
|
|
3098
|
+
prism = Cell.ByThickenedFace(baseFace, thickness=height, bothSides = False, reverse=True)
|
|
2984
3099
|
|
|
2985
3100
|
if uSides > 1 or vSides > 1 or wSides > 1:
|
|
2986
3101
|
prism = sliceCell(prism, width, length, height, uSides, vSides, wSides)
|
|
@@ -3092,7 +3207,7 @@ class Cell():
|
|
|
3092
3207
|
origin = Vertex.Origin()
|
|
3093
3208
|
bottom_face = Face.RHS(origin = Vertex.Origin(), width=width, length=length, thickness=thickness, outerFillet=outerFillet, innerFillet=innerFillet, sides=sides, direction=[0,0,1], placement="center", tolerance=tolerance, silent=silent)
|
|
3094
3209
|
return_cell = Cell.ByThickenedFace(bottom_face, thickness=height, bothSides=True, reverse=False,
|
|
3095
|
-
|
|
3210
|
+
tolerance=tolerance, silent=silent)
|
|
3096
3211
|
xOffset = 0
|
|
3097
3212
|
yOffset = 0
|
|
3098
3213
|
zOffset = 0
|
topologicpy/Edge.py
CHANGED
|
@@ -412,12 +412,12 @@ class Edge():
|
|
|
412
412
|
|
|
413
413
|
if not Topology.IsInstance(origin, "vertex"):
|
|
414
414
|
if not silent:
|
|
415
|
-
print("Edge.
|
|
415
|
+
print("Edge.ByOriginDirectionLength - Error: The input vertex parameter is not a valid vertex. Returning None.")
|
|
416
416
|
return None
|
|
417
417
|
|
|
418
418
|
if length <= tolerance:
|
|
419
419
|
if not silent:
|
|
420
|
-
print("Edge.
|
|
420
|
+
print("Edge.ByOriginDirectionLength - Error: The input edge parameter must not be less than the input tolerance parameter. Returning None.")
|
|
421
421
|
return None
|
|
422
422
|
|
|
423
423
|
endVertex = Topology.TranslateByDirectionDistance(origin, direction=direction[:3], distance=length)
|
|
@@ -942,7 +942,7 @@ class Edge():
|
|
|
942
942
|
return Vertex.ByCoordinates(x,y,0)
|
|
943
943
|
|
|
944
944
|
@staticmethod
|
|
945
|
-
def IsCollinear(edgeA, edgeB, mantissa: int = 6, tolerance: float = 0.0001)
|
|
945
|
+
def IsCollinear(edgeA, edgeB, mantissa: int = 6, tolerance: float = 0.0001):
|
|
946
946
|
"""
|
|
947
947
|
Return True if the two input edges are collinear. Returns False otherwise.
|
|
948
948
|
This code is based on a contribution by https://github.com/gaoxipeng
|
|
@@ -1082,7 +1082,7 @@ class Edge():
|
|
|
1082
1082
|
return np.isclose(scalar_triple_product, 0, atol=tolerance)
|
|
1083
1083
|
|
|
1084
1084
|
@staticmethod
|
|
1085
|
-
def IsParallel(edgeA, edgeB, mantissa: int = 6, tolerance: float = 0.0001)
|
|
1085
|
+
def IsParallel(edgeA, edgeB, mantissa: int = 6, tolerance: float = 0.0001):
|
|
1086
1086
|
"""
|
|
1087
1087
|
Return True if the two input edges are parallel. Returns False otherwise.
|
|
1088
1088
|
|
|
@@ -1456,6 +1456,37 @@ class Edge():
|
|
|
1456
1456
|
return None #Return silently because topologic C++ returns a runtime error if point is not on curve.
|
|
1457
1457
|
return round(parameter, mantissa)
|
|
1458
1458
|
|
|
1459
|
+
|
|
1460
|
+
@staticmethod
|
|
1461
|
+
def Quadrance(edge, mantissa: int = 6) -> float:
|
|
1462
|
+
"""
|
|
1463
|
+
Returns the quadrance of the input edge. See: https://en.wikipedia.org/wiki/Euclidean_distance#Squared_Euclidean_distance
|
|
1464
|
+
|
|
1465
|
+
Parameters
|
|
1466
|
+
----------
|
|
1467
|
+
edge : topologic_core.Edge
|
|
1468
|
+
The input edge.
|
|
1469
|
+
mantissa : int , optional
|
|
1470
|
+
The number of decimal places to round the result to. Default is 6.
|
|
1471
|
+
|
|
1472
|
+
Returns
|
|
1473
|
+
-------
|
|
1474
|
+
float
|
|
1475
|
+
The quadrance of the input edge.
|
|
1476
|
+
|
|
1477
|
+
"""
|
|
1478
|
+
from topologicpy.Vertex import Vertex
|
|
1479
|
+
from topologicpy.Topology import Topology
|
|
1480
|
+
|
|
1481
|
+
if not Topology.IsInstance(edge, "Edge"):
|
|
1482
|
+
print("Edge.Quadrance - Error: The input edge parameter is not a valid topologic edge. Returning None.")
|
|
1483
|
+
return None
|
|
1484
|
+
sv = Edge.StartVertex(edge)
|
|
1485
|
+
ev = Edge.EndVertex(edge)
|
|
1486
|
+
|
|
1487
|
+
return Vertex.Quadrance(sv, ev, mantissa = mantissa)
|
|
1488
|
+
|
|
1489
|
+
|
|
1459
1490
|
@staticmethod
|
|
1460
1491
|
def Reverse(edge, tolerance: float = 0.0001, silent: bool = False):
|
|
1461
1492
|
"""
|
|
@@ -1518,6 +1549,54 @@ class Edge():
|
|
|
1518
1549
|
return Edge.Extend(edge=edge, distance=distance, bothSides=bothSides, reverse=reverse, tolerance=tolerance)
|
|
1519
1550
|
return Edge.Trim(edge=edge, distance=distance, bothSides=bothSides, reverse=reverse, tolerance=tolerance)
|
|
1520
1551
|
|
|
1552
|
+
@staticmethod
|
|
1553
|
+
def Spread(edgeA, edgeB, mantissa: int = 6, bracket: bool = False) -> float:
|
|
1554
|
+
"""
|
|
1555
|
+
Returns the spread between the two input edges.
|
|
1556
|
+
|
|
1557
|
+
Spread is the rational trigonometry equivalent of angle and is defined as:
|
|
1558
|
+
spread = sin^2(theta)
|
|
1559
|
+
|
|
1560
|
+
Properties
|
|
1561
|
+
----------
|
|
1562
|
+
- spread = 0 : edges are parallel
|
|
1563
|
+
- spread = 1 : edges are perpendicular
|
|
1564
|
+
- 0 <= spread <= 1
|
|
1565
|
+
- No trigonometric functions are used
|
|
1566
|
+
|
|
1567
|
+
Parameters
|
|
1568
|
+
----------
|
|
1569
|
+
edgeA : topologic_core.Edge
|
|
1570
|
+
The first input edge.
|
|
1571
|
+
edgeB : topologic_core.Edge
|
|
1572
|
+
The second input edge.
|
|
1573
|
+
mantissa : int , optional
|
|
1574
|
+
The number of decimal places to round the result to. Default is 6.
|
|
1575
|
+
bracket : bool
|
|
1576
|
+
If set to True, the spread is bracketed to represent the acute case
|
|
1577
|
+
(i.e. invariant under edge reversal). Default is False.
|
|
1578
|
+
|
|
1579
|
+
Returns
|
|
1580
|
+
-------
|
|
1581
|
+
float
|
|
1582
|
+
The spread between the two input edges.
|
|
1583
|
+
"""
|
|
1584
|
+
from topologicpy.Topology import Topology
|
|
1585
|
+
from topologicpy.Vector import Vector
|
|
1586
|
+
|
|
1587
|
+
if not Topology.IsInstance(edgeA, "Edge"):
|
|
1588
|
+
print("Edge.Spread - Error: The input edgeA parameter is not a valid topologic edge. Returning None.")
|
|
1589
|
+
return None
|
|
1590
|
+
if not Topology.IsInstance(edgeB, "Edge"):
|
|
1591
|
+
print("Edge.Spread - Error: The input edgeB parameter is not a valid topologic edge. Returning None.")
|
|
1592
|
+
return None
|
|
1593
|
+
|
|
1594
|
+
# Direction vectors
|
|
1595
|
+
u = Edge.Direction(edgeA, mantissa=15)
|
|
1596
|
+
v = Edge.Direction(edgeB, mantissa=15)
|
|
1597
|
+
|
|
1598
|
+
return Vector.Spread(u, v, mantissa = mantissa, bracket = bracket)
|
|
1599
|
+
|
|
1521
1600
|
@staticmethod
|
|
1522
1601
|
def StartVertex(edge, silent: bool = False):
|
|
1523
1602
|
"""
|
|
@@ -1672,7 +1751,7 @@ class Edge():
|
|
|
1672
1751
|
intVertex = Topology.Intersect(edgeA, edgeB)
|
|
1673
1752
|
if intVertex and (Vertex.IsInternal(intVertex, edgeA)):
|
|
1674
1753
|
if reverse:
|
|
1675
|
-
return Edge.ByVertices([eva, intVertex], tolerance=tolerance, silent=
|
|
1754
|
+
return Edge.ByVertices([eva, intVertex], tolerance=tolerance, silent=silent)
|
|
1676
1755
|
else:
|
|
1677
1756
|
return Edge.ByVertices([sva, intVertex], tolerance=tolerance, silent=silent)
|
|
1678
1757
|
return edgeA
|
topologicpy/Face.py
CHANGED
|
@@ -960,7 +960,43 @@ class Face():
|
|
|
960
960
|
calframe = inspect.getouterframes(curframe, 2)
|
|
961
961
|
print('caller name:', calframe[1][3])
|
|
962
962
|
return None
|
|
963
|
-
|
|
963
|
+
if not isinstance(internalBoundaries, list):
|
|
964
|
+
if not silent:
|
|
965
|
+
print("Face.ByWires - Error: The input internalBoundaries parameter is not a list. Returning None.")
|
|
966
|
+
curframe = inspect.currentframe()
|
|
967
|
+
calframe = inspect.getouterframes(curframe, 2)
|
|
968
|
+
print('caller name:', calframe[1][3])
|
|
969
|
+
return None
|
|
970
|
+
eb_face= Face.ByWire(externalBoundary)
|
|
971
|
+
eb_area = Face.Area(eb_face)
|
|
972
|
+
# Make sure all internal wires are actually inside the external wire.
|
|
973
|
+
ibList = []
|
|
974
|
+
for ib in internalBoundaries:
|
|
975
|
+
if not Topology.IsInstance(ib, "Wire") and Wire.IsClosed(ib):
|
|
976
|
+
if not silent:
|
|
977
|
+
print("Face.ByWires - Warning: One of the internal wires is not a valid closed wire. Ignoring.")
|
|
978
|
+
curframe = inspect.currentframe()
|
|
979
|
+
calframe = inspect.getouterframes(curframe, 2)
|
|
980
|
+
print('caller name:', calframe[1][3])
|
|
981
|
+
continue
|
|
982
|
+
ib_face = Face.ByWire(ib)
|
|
983
|
+
ib_area = Face.Area(ib_face)
|
|
984
|
+
if ib_area >= eb_area:
|
|
985
|
+
if not silent:
|
|
986
|
+
print("Face.ByWires - Warning: One of the iinternal wires has an area greater than that of the external wire. Ignoring.")
|
|
987
|
+
curframe = inspect.currentframe()
|
|
988
|
+
calframe = inspect.getouterframes(curframe, 2)
|
|
989
|
+
print('caller name:', calframe[1][3])
|
|
990
|
+
continue
|
|
991
|
+
sp = Topology.SpatialRelationship(ib_face, eb_face)
|
|
992
|
+
if not sp.lower() == "within":
|
|
993
|
+
if not silent:
|
|
994
|
+
print("Face.ByWires - Warning: One of the internal wires is not within the external wires. Ignoring.")
|
|
995
|
+
curframe = inspect.currentframe()
|
|
996
|
+
calframe = inspect.getouterframes(curframe, 2)
|
|
997
|
+
print('caller name:', calframe[1][3])
|
|
998
|
+
continue
|
|
999
|
+
ibList.append(ib)
|
|
964
1000
|
face = None
|
|
965
1001
|
try:
|
|
966
1002
|
face = topologic.Face.ByExternalInternalBoundaries(externalBoundary, ibList, tolerance) # Hook to Core
|