topologicpy 0.8.0__py3-none-any.whl → 0.8.2__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- topologicpy/Cluster.py +67 -0
- topologicpy/Edge.py +57 -0
- topologicpy/Face.py +160 -4
- topologicpy/Helper.py +158 -44
- topologicpy/Matrix.py +46 -74
- topologicpy/Topology.py +84 -3
- topologicpy/Wire.py +239 -43
- topologicpy/version.py +1 -1
- {topologicpy-0.8.0.dist-info → topologicpy-0.8.2.dist-info}/METADATA +1 -1
- {topologicpy-0.8.0.dist-info → topologicpy-0.8.2.dist-info}/RECORD +13 -13
- {topologicpy-0.8.0.dist-info → topologicpy-0.8.2.dist-info}/WHEEL +1 -1
- {topologicpy-0.8.0.dist-info → topologicpy-0.8.2.dist-info}/LICENSE +0 -0
- {topologicpy-0.8.0.dist-info → topologicpy-0.8.2.dist-info}/top_level.txt +0 -0
topologicpy/Matrix.py
CHANGED
@@ -49,70 +49,47 @@ class Matrix:
|
|
49
49
|
|
50
50
|
@staticmethod
|
51
51
|
def ByRotation(angleX=0, angleY=0, angleZ=0, order="xyz"):
|
52
|
-
"""
|
53
|
-
Creates a 4x4 rotation matrix.
|
54
|
-
|
55
|
-
Parameters
|
56
|
-
----------
|
57
|
-
angleX : float , optional
|
58
|
-
The desired rotation angle in degrees around the X axis. The default is 0.
|
59
|
-
angleY : float , optional
|
60
|
-
The desired rotation angle in degrees around the Y axis. The default is 0.
|
61
|
-
angleZ : float , optional
|
62
|
-
The desired rotation angle in degrees around the Z axis. The default is 0.
|
63
|
-
order : string , optional
|
64
|
-
The order by which the roatations will be applied. The possible values are any permutation of "xyz". This input is case insensitive. The default is "xyz".
|
65
|
-
|
66
|
-
Returns
|
67
|
-
-------
|
68
|
-
list
|
69
|
-
The created 4X4 rotation matrix.
|
70
|
-
|
71
|
-
"""
|
72
52
|
def rotateXMatrix(radians):
|
73
|
-
""" Return matrix for rotating about the x-axis by 'radians' radians """
|
74
53
|
c = math.cos(radians)
|
75
54
|
s = math.sin(radians)
|
76
55
|
return [[1, 0, 0, 0],
|
77
|
-
[0, c
|
56
|
+
[0, c, -s, 0],
|
78
57
|
[0, s, c, 0],
|
79
58
|
[0, 0, 0, 1]]
|
80
59
|
|
81
60
|
def rotateYMatrix(radians):
|
82
|
-
""" Return matrix for rotating about the y-axis by 'radians' radians """
|
83
|
-
|
84
61
|
c = math.cos(radians)
|
85
62
|
s = math.sin(radians)
|
86
|
-
return [[
|
87
|
-
[
|
63
|
+
return [[c, 0, s, 0],
|
64
|
+
[0, 1, 0, 0],
|
88
65
|
[-s, 0, c, 0],
|
89
|
-
[
|
66
|
+
[0, 0, 0, 1]]
|
90
67
|
|
91
68
|
def rotateZMatrix(radians):
|
92
|
-
""" Return matrix for rotating about the z-axis by 'radians' radians """
|
93
|
-
|
94
69
|
c = math.cos(radians)
|
95
70
|
s = math.sin(radians)
|
96
|
-
return [[c
|
71
|
+
return [[c, -s, 0, 0],
|
97
72
|
[s, c, 0, 0],
|
98
73
|
[0, 0, 1, 0],
|
99
74
|
[0, 0, 0, 1]]
|
100
|
-
|
75
|
+
|
101
76
|
xMat = rotateXMatrix(math.radians(angleX))
|
102
77
|
yMat = rotateYMatrix(math.radians(angleY))
|
103
78
|
zMat = rotateZMatrix(math.radians(angleZ))
|
79
|
+
|
104
80
|
if order.lower() == "xyz":
|
105
|
-
return Matrix.Multiply(Matrix.Multiply(zMat,yMat),xMat)
|
81
|
+
return Matrix.Multiply(Matrix.Multiply(zMat, yMat), xMat)
|
106
82
|
if order.lower() == "xzy":
|
107
|
-
return Matrix.Multiply(Matrix.Multiply(yMat,zMat),xMat)
|
83
|
+
return Matrix.Multiply(Matrix.Multiply(yMat, zMat), xMat)
|
108
84
|
if order.lower() == "yxz":
|
109
|
-
return Matrix.Multiply(Matrix.Multiply(zMat,xMat),yMat)
|
110
|
-
if order.lower == "yzx":
|
111
|
-
return Matrix.Multiply(Matrix.Multiply(xMat,zMat),yMat)
|
85
|
+
return Matrix.Multiply(Matrix.Multiply(zMat, xMat), yMat)
|
86
|
+
if order.lower() == "yzx":
|
87
|
+
return Matrix.Multiply(Matrix.Multiply(xMat, zMat), yMat)
|
112
88
|
if order.lower() == "zxy":
|
113
|
-
return Matrix.Multiply(Matrix.Multiply(yMat,xMat),zMat)
|
89
|
+
return Matrix.Multiply(Matrix.Multiply(yMat, xMat), zMat)
|
114
90
|
if order.lower() == "zyx":
|
115
|
-
return Matrix.Multiply(Matrix.Multiply(xMat,yMat),zMat)
|
91
|
+
return Matrix.Multiply(Matrix.Multiply(xMat, yMat), zMat)
|
92
|
+
|
116
93
|
|
117
94
|
@staticmethod
|
118
95
|
def ByScaling(scaleX=1.0, scaleY=1.0, scaleZ=1.0):
|
@@ -159,10 +136,10 @@ class Matrix:
|
|
159
136
|
The created 4X4 translation matrix.
|
160
137
|
|
161
138
|
"""
|
162
|
-
return [[1,0,0,
|
163
|
-
[0,1,0,
|
164
|
-
[0,0,1,
|
165
|
-
[
|
139
|
+
return [[1,0,0,translateX],
|
140
|
+
[0,1,0,translateY],
|
141
|
+
[0,0,1,translateZ],
|
142
|
+
[0,0,0,1]]
|
166
143
|
|
167
144
|
@staticmethod
|
168
145
|
def EigenvaluesAndVectors(matrix, mantissa: int = 6, silent: bool = False):
|
@@ -230,47 +207,42 @@ class Matrix:
|
|
230
207
|
@staticmethod
|
231
208
|
def Multiply(matA, matB):
|
232
209
|
"""
|
233
|
-
Multiplies
|
234
|
-
|
235
|
-
|
210
|
+
Multiplies two matrices (matA and matB). The first matrix (matA) is applied first in the transformation,
|
211
|
+
followed by the second matrix (matB).
|
212
|
+
|
236
213
|
Parameters
|
237
214
|
----------
|
238
|
-
matA : list
|
215
|
+
matA : list of list of float
|
239
216
|
The first input matrix.
|
240
|
-
matB : list
|
217
|
+
matB : list of list of float
|
241
218
|
The second input matrix.
|
242
219
|
|
243
220
|
Returns
|
244
221
|
-------
|
245
|
-
list
|
246
|
-
The
|
222
|
+
list of list of float
|
223
|
+
The resulting matrix after multiplication.
|
247
224
|
|
248
225
|
"""
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
for j in range(len(matB[0])):
|
270
|
-
# iterate through rows of Y
|
271
|
-
for k in range(len(matB)):
|
272
|
-
matC[i][j] += matA[i][k] * matB[k][j]
|
273
|
-
return matC
|
226
|
+
# Input validation
|
227
|
+
if not (isinstance(matA, list) and all(isinstance(row, list) for row in matA) and
|
228
|
+
isinstance(matB, list) and all(isinstance(row, list) for row in matB)):
|
229
|
+
raise ValueError("Both inputs must be 2D lists representing matrices.")
|
230
|
+
|
231
|
+
# Check matrix dimension compatibility
|
232
|
+
if len(matA[0]) != len(matB):
|
233
|
+
raise ValueError("Number of columns in matA must equal the number of rows in matB.")
|
234
|
+
|
235
|
+
# Dimensions of the resulting matrix
|
236
|
+
rows_A, cols_A = len(matA), len(matA[0])
|
237
|
+
rows_B, cols_B = len(matB), len(matB[0])
|
238
|
+
result = [[0.0] * cols_B for _ in range(rows_A)]
|
239
|
+
|
240
|
+
# Matrix multiplication
|
241
|
+
for i in range(rows_A):
|
242
|
+
for j in range(cols_B):
|
243
|
+
result[i][j] = sum(matA[i][k] * matB[k][j] for k in range(cols_A))
|
244
|
+
|
245
|
+
return result
|
274
246
|
|
275
247
|
@staticmethod
|
276
248
|
def Subtract(matA, matB):
|
topologicpy/Topology.py
CHANGED
@@ -6492,6 +6492,87 @@ class Topology():
|
|
6492
6492
|
return None
|
6493
6493
|
return topologic.Topology.IsSame(topologyA, topologyB)
|
6494
6494
|
|
6495
|
+
def IsVertexMatched(topologyA, topologyB, mantissa: int = 6, tolerance=0.0001, silent : bool = False):
|
6496
|
+
"""
|
6497
|
+
Returns True if the input topologies are vertex matched (have same number of vertices and all vertices are coincedent within a tolerance). Returns False otherwise.
|
6498
|
+
|
6499
|
+
Parameters
|
6500
|
+
----------
|
6501
|
+
topologyA : topologic_core.Topology
|
6502
|
+
The first input topology.
|
6503
|
+
topologyB : topologic_core.Topology
|
6504
|
+
The second input topology.
|
6505
|
+
mantissa : int , optional
|
6506
|
+
The desired length of the mantissa. The default is 6
|
6507
|
+
tolerance : float , optional
|
6508
|
+
The desired tolerance. The default is 0.0001.
|
6509
|
+
silent : bool , optional
|
6510
|
+
If set to True, no error and warning messages are printed. Otherwise, they are. The default is False.
|
6511
|
+
|
6512
|
+
Returns
|
6513
|
+
-------
|
6514
|
+
bool
|
6515
|
+
True of the input topologies are vertex matched. False otherwise.
|
6516
|
+
|
6517
|
+
"""
|
6518
|
+
from topologicpy.Vertex import Vertex
|
6519
|
+
|
6520
|
+
def coordinates_match(list1, list2, tolerance):
|
6521
|
+
"""
|
6522
|
+
Checks if all coordinates in list1 have a corresponding coordinate in list2
|
6523
|
+
within a specified tolerance, with each match being unique.
|
6524
|
+
|
6525
|
+
Parameters
|
6526
|
+
----------
|
6527
|
+
list1 : list of list of float
|
6528
|
+
The first list of coordinates, where each coordinate is [x, y, z].
|
6529
|
+
list2 : list of list of float
|
6530
|
+
The second list of coordinates, where each coordinate is [x, y, z].
|
6531
|
+
tolerance : float
|
6532
|
+
The maximum distance within which two coordinates are considered matching.
|
6533
|
+
|
6534
|
+
Returns
|
6535
|
+
-------
|
6536
|
+
bool
|
6537
|
+
True if all coordinates in list1 have a corresponding coordinate in list2
|
6538
|
+
within the tolerance. False otherwise.
|
6539
|
+
"""
|
6540
|
+
def distance(coord1, coord2):
|
6541
|
+
"""Calculate the Euclidean distance between two coordinates."""
|
6542
|
+
return np.linalg.norm(np.array(coord1) - np.array(coord2))
|
6543
|
+
|
6544
|
+
# Copy list2 to keep track of unvisited coordinates
|
6545
|
+
unmatched = list2.copy()
|
6546
|
+
|
6547
|
+
for coord1 in list1:
|
6548
|
+
match_found = False
|
6549
|
+
for i, coord2 in enumerate(unmatched):
|
6550
|
+
if distance(coord1, coord2) <= tolerance:
|
6551
|
+
# Mark the coordinate as visited by removing it
|
6552
|
+
unmatched.pop(i)
|
6553
|
+
match_found = True
|
6554
|
+
break
|
6555
|
+
if not match_found:
|
6556
|
+
return False
|
6557
|
+
return True
|
6558
|
+
|
6559
|
+
if not Topology.IsInstance(topologyA, "topology"):
|
6560
|
+
if not silent:
|
6561
|
+
print("Topology.IsVertexMatched - Error: The input topologyA parameter is not a valid topology. Returning None.")
|
6562
|
+
return None
|
6563
|
+
if not Topology.IsInstance(topologyB, "topology"):
|
6564
|
+
if not silent:
|
6565
|
+
print("Topology.IsVertexMatched - Error: The input topologyB parameter is not a valid topology. Returning None.")
|
6566
|
+
return None
|
6567
|
+
|
6568
|
+
vertices_a = Topology.Vertices(topologyA)
|
6569
|
+
vertices_b = Topology.Vertices(topologyB)
|
6570
|
+
if not len(vertices_a) == len(vertices_b):
|
6571
|
+
return False
|
6572
|
+
coords_a = [Vertex.Coordinates(v, mantissa=mantissa) for v in vertices_a]
|
6573
|
+
coords_b = [Vertex.Coordinates(v, mantissa=mantissa) for v in vertices_b]
|
6574
|
+
return coordinates_match(coords_a, coords_b, tolerance=tolerance)
|
6575
|
+
|
6495
6576
|
@staticmethod
|
6496
6577
|
def MergeAll(topologies, tolerance=0.0001):
|
6497
6578
|
"""
|
@@ -9229,9 +9310,9 @@ class Topology():
|
|
9229
9310
|
kRotation31 = matrix[2][0]
|
9230
9311
|
kRotation32 = matrix[2][1]
|
9231
9312
|
kRotation33 = matrix[2][2]
|
9232
|
-
kTranslationX = matrix[
|
9233
|
-
kTranslationY = matrix[
|
9234
|
-
kTranslationZ = matrix[
|
9313
|
+
kTranslationX = matrix[0][3]
|
9314
|
+
kTranslationY = matrix[1][3]
|
9315
|
+
kTranslationZ = matrix[2][3]
|
9235
9316
|
|
9236
9317
|
return_topology = topologic.TopologyUtility.Transform(topology, kTranslationX, kTranslationY, kTranslationZ, kRotation11, kRotation12, kRotation13, kRotation21, kRotation22, kRotation23, kRotation31, kRotation32, kRotation33)
|
9237
9318
|
|