topologicpy 0.7.15__py3-none-any.whl → 0.7.18__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 +19 -12
- topologicpy/CellComplex.py +3 -3
- topologicpy/DGL.py +1 -1
- topologicpy/Edge.py +46 -20
- topologicpy/Face.py +215 -110
- topologicpy/Graph.py +230 -106
- topologicpy/Neo4j.py +2 -2
- topologicpy/Shell.py +57 -11
- topologicpy/Topology.py +17 -37
- topologicpy/Vector.py +1 -3
- topologicpy/Vertex.py +2 -4
- topologicpy/Wire.py +288 -191
- topologicpy/version.py +1 -1
- {topologicpy-0.7.15.dist-info → topologicpy-0.7.18.dist-info}/METADATA +37 -1
- topologicpy-0.7.18.dist-info/RECORD +33 -0
- topologicpy-0.7.15.dist-info/RECORD +0 -33
- {topologicpy-0.7.15.dist-info → topologicpy-0.7.18.dist-info}/LICENSE +0 -0
- {topologicpy-0.7.15.dist-info → topologicpy-0.7.18.dist-info}/WHEEL +0 -0
- {topologicpy-0.7.15.dist-info → topologicpy-0.7.18.dist-info}/top_level.txt +0 -0
topologicpy/Face.py
CHANGED
@@ -131,8 +131,8 @@ class Face():
|
|
131
131
|
if not Topology.IsInstance(faceB, "Face"):
|
132
132
|
print("Face.Angle - Warning: The input faceB parameter is not a valid topologic face. Returning None.")
|
133
133
|
return None
|
134
|
-
dirA = Face.
|
135
|
-
dirB = Face.
|
134
|
+
dirA = Face.Normal(faceA, outputType="xyz", mantissa=3)
|
135
|
+
dirB = Face.Normal(faceB, outputType="xyz", mantissa=3)
|
136
136
|
return round((Vector.Angle(dirA, dirB)), mantissa)
|
137
137
|
|
138
138
|
@staticmethod
|
@@ -258,11 +258,9 @@ class Face():
|
|
258
258
|
return Face.ByEdges(edges, tolerance=tolerance)
|
259
259
|
|
260
260
|
@staticmethod
|
261
|
-
def ByOffset(face, offset: float = 1.0,
|
262
|
-
miterThreshold: float = None, offsetKey: str = None,
|
263
|
-
miterThresholdKey: str = None, step: bool = True, tolerance: float = 0.0001):
|
261
|
+
def ByOffset(face, offset: float = 1.0, tolerance: float = 0.0001):
|
264
262
|
"""
|
265
|
-
Creates an offset face from the input face.
|
263
|
+
Creates an offset face from the input face. A positive offset value results in a smaller face to the inside of the input face.
|
266
264
|
|
267
265
|
Parameters
|
268
266
|
----------
|
@@ -270,16 +268,6 @@ class Face():
|
|
270
268
|
The input face.
|
271
269
|
offset : float , optional
|
272
270
|
The desired offset distance. The default is 1.0.
|
273
|
-
miter : bool , optional
|
274
|
-
if set to True, the corners will be mitered. The default is False.
|
275
|
-
miterThreshold : float , optional
|
276
|
-
The distance beyond which a miter should be added. The default is None which means the miter threshold is set to the offset distance multiplied by the square root of 2.
|
277
|
-
offsetKey : str , optional
|
278
|
-
If specified, the dictionary of the edges will be queried for this key to sepcify the desired offset. The default is None.
|
279
|
-
miterThresholdKey : str , optional
|
280
|
-
If specified, the dictionary of the vertices will be queried for this key to sepcify the desired miter threshold distance. The default is None.
|
281
|
-
step : bool , optional
|
282
|
-
If set to True, The transition between collinear edges with different offsets will be a step. Otherwise, it will be a continous edge. The default is True.
|
283
271
|
tolerance : float , optional
|
284
272
|
The desired tolerance. The default is 0.0001.
|
285
273
|
|
@@ -293,18 +281,18 @@ class Face():
|
|
293
281
|
from topologicpy.Topology import Topology
|
294
282
|
|
295
283
|
if not Topology.IsInstance(face, "Face"):
|
296
|
-
print("Face.ByOffset - Warning: The input face parameter is not a valid
|
284
|
+
print("Face.ByOffset - Warning: The input face parameter is not a valid face. Returning None.")
|
297
285
|
return None
|
298
286
|
eb = Face.Wire(face)
|
299
287
|
internal_boundaries = Face.InternalBoundaries(face)
|
300
|
-
offset_external_boundary = Wire.ByOffset(wire=eb, offset=offset,
|
288
|
+
offset_external_boundary = Wire.ByOffset(wire=eb, offset=offset, bisectors=False, tolerance=tolerance)
|
301
289
|
offset_internal_boundaries = []
|
302
290
|
for internal_boundary in internal_boundaries:
|
303
|
-
offset_internal_boundaries.append(Wire.ByOffset(wire=internal_boundary, offset=offset,
|
291
|
+
offset_internal_boundaries.append(Wire.ByOffset(wire=internal_boundary, offset=offset, bisectors=False, tolerance=tolerance))
|
304
292
|
return Face.ByWires(offset_external_boundary, offset_internal_boundaries, tolerance=tolerance)
|
305
293
|
|
306
294
|
@staticmethod
|
307
|
-
def ByShell(shell, origin= None, angTolerance: float = 0.1, tolerance: float = 0.0001):
|
295
|
+
def ByShell(shell, origin= None, angTolerance: float = 0.1, tolerance: float = 0.0001, silent=False):
|
308
296
|
"""
|
309
297
|
Creates a face by merging the faces of the input shell.
|
310
298
|
|
@@ -351,13 +339,13 @@ class Face():
|
|
351
339
|
face = None
|
352
340
|
ext_boundary = Wire.RemoveCollinearEdges(Shell.ExternalBoundary(shell))
|
353
341
|
if Topology.IsInstance(ext_boundary, "Wire"):
|
354
|
-
face = Face.ByWire(ext_boundary)
|
342
|
+
face = Face.ByWire(ext_boundary, silent=silent)
|
355
343
|
elif Topology.IsInstance(ext_boundary, "Cluster"):
|
356
344
|
wires = Topology.Wires(ext_boundary)
|
357
|
-
faces = [Face.ByWire(w) for w in wires]
|
345
|
+
faces = [Face.ByWire(w, silent=silent) for w in wires]
|
358
346
|
areas = [Face.Area(f) for f in faces]
|
359
347
|
wires = Helper.Sort(wires, areas, reverseFlags=[True])
|
360
|
-
face = Face.ByWires(wires[0], wires[1:])
|
348
|
+
face = Face.ByWires(wires[0], wires[1:], silent=silent)
|
361
349
|
|
362
350
|
if Topology.IsInstance(face, "Face"):
|
363
351
|
return face
|
@@ -420,6 +408,70 @@ class Face():
|
|
420
408
|
else:
|
421
409
|
return None
|
422
410
|
|
411
|
+
@staticmethod
|
412
|
+
def ByThickenedWire(wire, offsetA: float = 1.0, offsetB: float = 0.0, tolerance: float = 0.0001):
|
413
|
+
"""
|
414
|
+
Creates a face by thickening the input wire. This method assumes the wire is manifold and planar.
|
415
|
+
|
416
|
+
Parameters
|
417
|
+
----------
|
418
|
+
wire : topologic_core.Wire
|
419
|
+
The input wire to be thickened.
|
420
|
+
offsetA : float , optional
|
421
|
+
The desired offset to the exterior of the wire. The default is 1.0.
|
422
|
+
offsetB : float , optional
|
423
|
+
The desired offset to the interior of the wire. The default is 0.0.
|
424
|
+
tolerance : float , optional
|
425
|
+
The desired tolerance. The default is 0.0001.
|
426
|
+
|
427
|
+
Returns
|
428
|
+
-------
|
429
|
+
topologic_core.Cell
|
430
|
+
The created cell.
|
431
|
+
|
432
|
+
"""
|
433
|
+
from topologicpy.Vertex import Vertex
|
434
|
+
from topologicpy.Edge import Edge
|
435
|
+
from topologicpy.Wire import Wire
|
436
|
+
from topologicpy.Vector import Vector
|
437
|
+
from topologicpy.Topology import Topology
|
438
|
+
|
439
|
+
if not Topology.IsInstance(wire, "Wire"):
|
440
|
+
print("Face.ByThickenedWire - Error: The input wire parameter is not a valid wire. Returning None.")
|
441
|
+
return None
|
442
|
+
if not Wire.IsManifold(wire):
|
443
|
+
print("Face.ByThickenedWire - Error: The input wire parameter is not a manifold wire. Returning None.")
|
444
|
+
return None
|
445
|
+
three_vertices = Wire.Vertices(wire)[0:3]
|
446
|
+
temp_w = Wire.ByVertices(three_vertices, close=True)
|
447
|
+
flat_face = Face.ByWire(temp_w, tolerance=tolerance)
|
448
|
+
origin = Vertex.Origin()
|
449
|
+
normal = Face.Normal(flat_face)
|
450
|
+
flat_wire = Topology.Flatten(wire, origin=origin, direction=normal)
|
451
|
+
outside_wire = Wire.ByOffset(flat_wire, offset=abs(offsetA)*-1, bisectors = False, tolerance=tolerance)
|
452
|
+
inside_wire = Wire.ByOffset(flat_wire, offset=abs(offsetB), bisectors = False, tolerance=tolerance)
|
453
|
+
inside_wire = Wire.Reverse(inside_wire)
|
454
|
+
if not Wire.IsClosed(flat_wire):
|
455
|
+
sv = Topology.Vertices(flat_wire)[0]
|
456
|
+
ev = Topology.Vertices(flat_wire)[-1]
|
457
|
+
edges = Topology.Edges(flat_wire)
|
458
|
+
first_edge = Topology.SuperTopologies(sv, flat_wire, topologyType="edge")[0]
|
459
|
+
first_normal = Edge.Normal(first_edge)
|
460
|
+
last_edge = Topology.SuperTopologies(ev, flat_wire, topologyType="edge")[0]
|
461
|
+
last_normal = Edge.Normal(last_edge)
|
462
|
+
sv1 = Topology.TranslateByDirectionDistance(sv, first_normal, abs(offsetB))
|
463
|
+
sv2 = Topology.TranslateByDirectionDistance(sv, Vector.Reverse(first_normal), abs(offsetA))
|
464
|
+
ev1 = Topology.TranslateByDirectionDistance(ev, last_normal, abs(offsetB))
|
465
|
+
ev2 = Topology.TranslateByDirectionDistance(ev, Vector.Reverse(last_normal), abs(offsetA))
|
466
|
+
out_vertices = Topology.Vertices(outside_wire)[1:-1]
|
467
|
+
in_vertices = Topology.Vertices(inside_wire)[1:-1]
|
468
|
+
vertices = [sv2] + out_vertices + [ev2,ev1] + in_vertices + [sv1]
|
469
|
+
return_face = Face.ByWire(Wire.ByVertices(vertices))
|
470
|
+
else:
|
471
|
+
return_face = Face.ByWires(outside_wire, [inside_wire])
|
472
|
+
return_face = Topology.Unflatten(return_face, origin=origin, direction=normal)
|
473
|
+
return return_face
|
474
|
+
|
423
475
|
@staticmethod
|
424
476
|
def ByVertices(vertices: list, tolerance: float = 0.0001):
|
425
477
|
|
@@ -808,7 +860,7 @@ class Face():
|
|
808
860
|
return None
|
809
861
|
if not north:
|
810
862
|
north = Vector.North()
|
811
|
-
dirA = Face.
|
863
|
+
dirA = Face.Normal(face, outputType="xyz", mantissa=mantissa)
|
812
864
|
return Vector.CompassAngle(vectorA=dirA, vectorB=north, mantissa=mantissa, tolerance=tolerance)
|
813
865
|
|
814
866
|
@staticmethod
|
@@ -839,7 +891,7 @@ class Face():
|
|
839
891
|
def Einstein(origin= None, radius: float = 0.5, direction: list = [0, 0, 1],
|
840
892
|
placement: str = "center", tolerance: float = 0.0001):
|
841
893
|
"""
|
842
|
-
Creates an aperiodic monotile, also called an 'einstein' tile (meaning one tile in German, not the name of the famous
|
894
|
+
Creates an aperiodic monotile, also called an 'einstein' tile (meaning one tile in German, not the name of the famous physicist). See https://arxiv.org/abs/2303.10798
|
843
895
|
|
844
896
|
Parameters
|
845
897
|
----------
|
@@ -869,6 +921,64 @@ class Face():
|
|
869
921
|
return None
|
870
922
|
return Face.ByWire(wire, tolerance=tolerance)
|
871
923
|
|
924
|
+
@staticmethod
|
925
|
+
def Ellipse(origin= None, inputMode: int = 1, width: float = 2.0, length: float = 1.0, focalLength: float = 0.866025, eccentricity: float = 0.866025, majorAxisLength: float = 1.0, minorAxisLength: float = 0.5, sides: float = 32, fromAngle: float = 0.0, toAngle: float = 360.0, close: bool = True, direction: list = [0, 0, 1], placement: str = "center", tolerance: float = 0.0001):
|
926
|
+
"""
|
927
|
+
Creates an ellipse and returns all its geometry and parameters.
|
928
|
+
|
929
|
+
Parameters
|
930
|
+
----------
|
931
|
+
origin : topologic_core.Vertex , optional
|
932
|
+
The location of the origin of the ellipse. The default is None which results in the ellipse being placed at (0, 0, 0).
|
933
|
+
inputMode : int , optional
|
934
|
+
The method by which the ellipse is defined. The default is 1.
|
935
|
+
Based on the inputMode value, only the following inputs will be considered. The options are:
|
936
|
+
1. Width and Length (considered inputs: width, length)
|
937
|
+
2. Focal Length and Eccentricity (considered inputs: focalLength, eccentricity)
|
938
|
+
3. Focal Length and Minor Axis Length (considered inputs: focalLength, minorAxisLength)
|
939
|
+
4. Major Axis Length and Minor Axis Length (considered input: majorAxisLength, minorAxisLength)
|
940
|
+
width : float , optional
|
941
|
+
The width of the ellipse. The default is 2.0. This is considered if the inputMode is 1.
|
942
|
+
length : float , optional
|
943
|
+
The length of the ellipse. The default is 1.0. This is considered if the inputMode is 1.
|
944
|
+
focalLength : float , optional
|
945
|
+
The focal length of the ellipse. The default is 0.866025. This is considered if the inputMode is 2 or 3.
|
946
|
+
eccentricity : float , optional
|
947
|
+
The eccentricity of the ellipse. The default is 0.866025. This is considered if the inputMode is 2.
|
948
|
+
majorAxisLength : float , optional
|
949
|
+
The length of the major axis of the ellipse. The default is 1.0. This is considered if the inputMode is 4.
|
950
|
+
minorAxisLength : float , optional
|
951
|
+
The length of the minor axis of the ellipse. The default is 0.5. This is considered if the inputMode is 3 or 4.
|
952
|
+
sides : int , optional
|
953
|
+
The number of sides of the ellipse. The default is 32.
|
954
|
+
fromAngle : float , optional
|
955
|
+
The angle in degrees from which to start creating the arc of the ellipse. The default is 0.
|
956
|
+
toAngle : float , optional
|
957
|
+
The angle in degrees at which to end creating the arc of the ellipse. The default is 360.
|
958
|
+
close : bool , optional
|
959
|
+
If set to True, arcs will be closed by connecting the last vertex to the first vertex. Otherwise, they will be left open.
|
960
|
+
direction : list , optional
|
961
|
+
The vector representing the up direction of the ellipse. The default is [0, 0, 1].
|
962
|
+
placement : str , optional
|
963
|
+
The description of the placement of the origin of the ellipse. This can be "center", or "lowerleft". It is case insensitive. The default is "center".
|
964
|
+
tolerance : float , optional
|
965
|
+
The desired tolerance. The default is 0.0001.
|
966
|
+
|
967
|
+
Returns
|
968
|
+
-------
|
969
|
+
topologic_core.Face
|
970
|
+
The created ellipse
|
971
|
+
|
972
|
+
"""
|
973
|
+
from topologicpy.Wire import Wire
|
974
|
+
w = Wire.Ellipse(origin=origin, inputMode=inputMode, width=width, length=length,
|
975
|
+
focalLength=focalLength, eccentricity=eccentricity,
|
976
|
+
majorAxisLength=majorAxisLength, minorAxisLength=minorAxisLength,
|
977
|
+
sides=sides, fromAngle=fromAngle, toAngle=toAngle,
|
978
|
+
close=close, direction=direction,
|
979
|
+
placement=placement, tolerance=tolerance)
|
980
|
+
return Face.ByWire(w)
|
981
|
+
|
872
982
|
@staticmethod
|
873
983
|
def ExteriorAngles(face, includeInternalBoundaries=False, mantissa: int = 6) -> list:
|
874
984
|
"""
|
@@ -933,12 +1043,9 @@ class Face():
|
|
933
1043
|
|
934
1044
|
eb = face.ExternalBoundary()
|
935
1045
|
f_dir = Face.Normal(face)
|
936
|
-
|
937
|
-
|
938
|
-
|
939
|
-
if Vector.IsAntiParallel(f_dir, temp_dir):
|
940
|
-
faceVertices.reverse()
|
941
|
-
eb = Wire.ByVertices(faceVertices)
|
1046
|
+
w_dir = Wire.Normal(eb)
|
1047
|
+
if Vector.IsAntiParallel(f_dir, w_dir):
|
1048
|
+
eb = Wire.Reverse(eb)
|
942
1049
|
return eb
|
943
1050
|
|
944
1051
|
@staticmethod
|
@@ -1256,10 +1363,10 @@ class Face():
|
|
1256
1363
|
return None
|
1257
1364
|
|
1258
1365
|
if not Topology.IsInstance(faceA, "Face"):
|
1259
|
-
print("Face.
|
1366
|
+
print("Face.IsInside - Error: The input faceA parameter is not a valid topologic face. Returning None.")
|
1260
1367
|
return None
|
1261
1368
|
if not Topology.IsInstance(faceB, "Face"):
|
1262
|
-
print("Face.
|
1369
|
+
print("Face.IsInside - Error: The input faceB parameter is not a valid topologic face. Returning None.")
|
1263
1370
|
return None
|
1264
1371
|
|
1265
1372
|
def normalize_plane_coefficients(plane):
|
@@ -1540,29 +1647,7 @@ class Face():
|
|
1540
1647
|
return medialAxis
|
1541
1648
|
|
1542
1649
|
@staticmethod
|
1543
|
-
def Normal(face, outputType
|
1544
|
-
"""
|
1545
|
-
Returns the normal vector to the input face. A normal vector of a face is a vector perpendicular to it.
|
1546
|
-
|
1547
|
-
Parameters
|
1548
|
-
----------
|
1549
|
-
face : topologic_core.Face
|
1550
|
-
The input face.
|
1551
|
-
outputType : string , optional
|
1552
|
-
The string defining the desired output. This can be any subset or permutation of "xyz". It is case insensitive. The default is "xyz".
|
1553
|
-
mantissa : int , optional
|
1554
|
-
The desired length of the mantissa. The default is 6.
|
1555
|
-
|
1556
|
-
Returns
|
1557
|
-
-------
|
1558
|
-
list
|
1559
|
-
The normal vector to the input face. This is computed at the approximate center of the face.
|
1560
|
-
|
1561
|
-
"""
|
1562
|
-
return Face.NormalAtParameters(face, u=0.5, v=0.5, outputType=outputType, mantissa=mantissa)
|
1563
|
-
|
1564
|
-
@staticmethod
|
1565
|
-
def NormalAtParameters(face, u: float = 0.5, v: float = 0.5, outputType: str = "xyz", mantissa: int = 6) -> list:
|
1650
|
+
def Normal(face, outputType="xyz", mantissa=6):
|
1566
1651
|
"""
|
1567
1652
|
Returns the normal vector to the input face. A normal vector of a face is a vector perpendicular to it.
|
1568
1653
|
|
@@ -1570,10 +1655,6 @@ class Face():
|
|
1570
1655
|
----------
|
1571
1656
|
face : topologic_core.Face
|
1572
1657
|
The input face.
|
1573
|
-
u : float , optional
|
1574
|
-
The *u* parameter at which to compute the normal to the input face. The default is 0.5.
|
1575
|
-
v : float , optional
|
1576
|
-
The *v* parameter at which to compute the normal to the input face. The default is 0.5.
|
1577
1658
|
outputType : string , optional
|
1578
1659
|
The string defining the desired output. This can be any subset or permutation of "xyz". It is case insensitive. The default is "xyz".
|
1579
1660
|
mantissa : int , optional
|
@@ -1585,23 +1666,80 @@ class Face():
|
|
1585
1666
|
The normal vector to the input face.
|
1586
1667
|
|
1587
1668
|
"""
|
1588
|
-
|
1669
|
+
from topologicpy.Topology import Topology
|
1670
|
+
from topologicpy.Vertex import Vertex
|
1671
|
+
import os
|
1672
|
+
import warnings
|
1589
1673
|
try:
|
1590
|
-
|
1591
|
-
x = round(coords[0], mantissa)
|
1592
|
-
y = round(coords[1], mantissa)
|
1593
|
-
z = round(coords[2], mantissa)
|
1594
|
-
outputType = list(outputType.lower())
|
1595
|
-
for axis in outputType:
|
1596
|
-
if axis == "x":
|
1597
|
-
returnResult.append(x)
|
1598
|
-
elif axis == "y":
|
1599
|
-
returnResult.append(y)
|
1600
|
-
elif axis == "z":
|
1601
|
-
returnResult.append(z)
|
1674
|
+
import numpy as np
|
1602
1675
|
except:
|
1603
|
-
|
1604
|
-
|
1676
|
+
print("Face.Normal - Warning: Installing required numpy library.")
|
1677
|
+
try:
|
1678
|
+
os.system("pip install numpy")
|
1679
|
+
except:
|
1680
|
+
os.system("pip install numpy --user")
|
1681
|
+
try:
|
1682
|
+
import numpy as np
|
1683
|
+
print("Face.Normal - Warning: numpy library installed correctly.")
|
1684
|
+
except:
|
1685
|
+
warnings.warn("Face.Normal - Error: Could not import numpy. Please try to install numpy manually. Returning None.")
|
1686
|
+
return None
|
1687
|
+
|
1688
|
+
if not Topology.IsInstance(face, "Face"):
|
1689
|
+
print("Face.Normal - Error: The input face parameter is not a valid face. Returning None.")
|
1690
|
+
return None
|
1691
|
+
|
1692
|
+
vertices = Topology.Vertices(face)
|
1693
|
+
vertices = [Vertex.Coordinates(v, mantissa=mantissa) for v in vertices]
|
1694
|
+
|
1695
|
+
if len(vertices) < 3:
|
1696
|
+
print("Face.Normal - Error: At least three vertices are required to define a plane. Returning None.")
|
1697
|
+
return None
|
1698
|
+
|
1699
|
+
# Convert vertices to numpy array for easier manipulation
|
1700
|
+
vertices = np.array(vertices)
|
1701
|
+
|
1702
|
+
# Try to find two non-collinear edge vectors
|
1703
|
+
vec1 = None
|
1704
|
+
vec2 = None
|
1705
|
+
for i in range(1, len(vertices)):
|
1706
|
+
for j in range(i + 1, len(vertices)):
|
1707
|
+
temp_vec1 = vertices[i] - vertices[0]
|
1708
|
+
temp_vec2 = vertices[j] - vertices[0]
|
1709
|
+
cross_product = np.cross(temp_vec1, temp_vec2)
|
1710
|
+
if np.linalg.norm(cross_product) > 1e-6: # Check if the cross product is not near zero
|
1711
|
+
vec1 = temp_vec1
|
1712
|
+
vec2 = temp_vec2
|
1713
|
+
break
|
1714
|
+
if vec1 is not None and vec2 is not None:
|
1715
|
+
break
|
1716
|
+
|
1717
|
+
if vec1 is None or vec2 is None:
|
1718
|
+
print("Face.Normal - Error: The given vertices do not form a valid plane (all vertices might be collinear). Returning None.")
|
1719
|
+
return None
|
1720
|
+
|
1721
|
+
# Calculate the cross product of the two edge vectors
|
1722
|
+
normal = np.cross(vec1, vec2)
|
1723
|
+
|
1724
|
+
# Normalize the normal vector
|
1725
|
+
normal_length = np.linalg.norm(normal)
|
1726
|
+
if normal_length == 0:
|
1727
|
+
print("Face.Normal - Error: The given vertices do not form a valid plane (cross product resulted in a zero vector). Returning None.")
|
1728
|
+
return None
|
1729
|
+
|
1730
|
+
normal = normal / normal_length
|
1731
|
+
normal = normal.tolist()
|
1732
|
+
normal = [round(x, mantissa) for x in normal]
|
1733
|
+
return_normal = []
|
1734
|
+
outputType = list(outputType.lower())
|
1735
|
+
for axis in outputType:
|
1736
|
+
if axis == "x":
|
1737
|
+
return_normal.append(normal[0])
|
1738
|
+
elif axis == "y":
|
1739
|
+
return_normal.append(normal[1])
|
1740
|
+
elif axis == "z":
|
1741
|
+
return_normal.append(normal[2])
|
1742
|
+
return return_normal
|
1605
1743
|
|
1606
1744
|
@staticmethod
|
1607
1745
|
def NormalEdge(face, length: float = 1.0, tolerance: float = 0.0001, silent: bool = False):
|
@@ -1636,43 +1774,10 @@ class Face():
|
|
1636
1774
|
return None
|
1637
1775
|
iv = Face.InternalVertex(face)
|
1638
1776
|
u, v = Face.VertexParameters(face, iv)
|
1639
|
-
vec = Face.
|
1777
|
+
vec = Face.Normal(face)
|
1640
1778
|
ev = Topology.TranslateByDirectionDistance(iv, vec, length)
|
1641
1779
|
return Edge.ByVertices([iv, ev], tolerance=tolerance, silent=silent)
|
1642
1780
|
|
1643
|
-
@staticmethod
|
1644
|
-
def NormalEdgeAtParameters(face, u: float = 0.5, v: float = 0.5, length: float = 1.0, tolerance: float = 0.0001):
|
1645
|
-
"""
|
1646
|
-
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.
|
1647
|
-
|
1648
|
-
Parameters
|
1649
|
-
----------
|
1650
|
-
face : topologic_core.Face
|
1651
|
-
The input face.
|
1652
|
-
u : float , optional
|
1653
|
-
The *u* parameter at which to compute the normal to the input face. The default is 0.5.
|
1654
|
-
v : float , optional
|
1655
|
-
The *v* parameter at which to compute the normal to the input face. The default is 0.5.
|
1656
|
-
length : float , optional
|
1657
|
-
The desired length of the normal edge. The default is 1.
|
1658
|
-
tolerance : float , optional
|
1659
|
-
The desired tolerance. The default is 0.0001.
|
1660
|
-
|
1661
|
-
Returns
|
1662
|
-
-------
|
1663
|
-
topologic_core.Edge
|
1664
|
-
The created normal edge to the input face. This is computed at the approximate center of the face.
|
1665
|
-
|
1666
|
-
"""
|
1667
|
-
from topologicpy.Edge import Edge
|
1668
|
-
from topologicpy.Topology import Topology
|
1669
|
-
if not Topology.IsInstance(face, "Face"):
|
1670
|
-
return None
|
1671
|
-
sv = Face.VertexByParameters(face=face, u=u, v=v)
|
1672
|
-
vec = Face.NormalAtParameters(face, u=u, v=v)
|
1673
|
-
ev = Topology.TranslateByDirectionDistance(sv, vec, length)
|
1674
|
-
return Edge.ByVertices([sv, ev], tolerance=tolerance, silent=True)
|
1675
|
-
|
1676
1781
|
@staticmethod
|
1677
1782
|
def PlaneEquation(face, mantissa: int = 6) -> dict:
|
1678
1783
|
"""
|
@@ -1924,7 +2029,7 @@ class Face():
|
|
1924
2029
|
from topologicpy.Topology import Topology
|
1925
2030
|
|
1926
2031
|
if not Topology.IsInstance(face, "Face"):
|
1927
|
-
print("Face.Skeleton - Error: The input face is not a valid topologic face.
|
2032
|
+
print("Face.Skeleton - Error: The input face is not a valid topologic face. Returning None.")
|
1928
2033
|
return None
|
1929
2034
|
return Wire.Skeleton(face, tolerance=tolerance)
|
1930
2035
|
|