topologicpy 0.4.55__py3-none-any.whl → 0.4.57__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 +95 -22
- topologicpy/CellComplex.py +36 -5
- topologicpy/DGL.py +4 -1
- topologicpy/Edge.py +1 -1
- topologicpy/Face.py +86 -64
- topologicpy/Graph.py +37 -34
- topologicpy/Helper.py +83 -44
- topologicpy/Plotly.py +15 -14
- topologicpy/Shell.py +70 -28
- topologicpy/Topology.py +155 -174
- topologicpy/Wire.py +64 -146
- topologicpy/__init__.py +22 -22
- topologicpy/bin/linux/topologic/__init__.py +2 -2
- topologicpy/bin/linux/topologic/topologic.cpython-310-x86_64-linux-gnu.so +0 -0
- topologicpy/bin/linux/topologic/topologic.cpython-311-x86_64-linux-gnu.so +0 -0
- topologicpy/bin/linux/topologic/topologic.cpython-38-x86_64-linux-gnu.so +0 -0
- topologicpy/bin/linux/topologic/topologic.cpython-39-x86_64-linux-gnu.so +0 -0
- topologicpy/bin/linux/topologic.libs/libTKBO-6bdf205d.so.7.7.0 +0 -0
- topologicpy/bin/linux/topologic.libs/libTKBRep-2960a069.so.7.7.0 +0 -0
- topologicpy/bin/linux/topologic.libs/libTKBool-c44b74bd.so.7.7.0 +0 -0
- topologicpy/bin/linux/topologic.libs/libTKFillet-9a670ba0.so.7.7.0 +0 -0
- topologicpy/bin/linux/topologic.libs/libTKG2d-8f31849e.so.7.7.0 +0 -0
- topologicpy/bin/linux/topologic.libs/libTKG3d-4c6bce57.so.7.7.0 +0 -0
- topologicpy/bin/linux/topologic.libs/libTKGeomAlgo-26066fd9.so.7.7.0 +0 -0
- topologicpy/bin/linux/topologic.libs/libTKGeomBase-2116cabe.so.7.7.0 +0 -0
- topologicpy/bin/linux/topologic.libs/libTKMath-72572fa8.so.7.7.0 +0 -0
- topologicpy/bin/linux/topologic.libs/libTKMesh-2a060427.so.7.7.0 +0 -0
- topologicpy/bin/linux/topologic.libs/libTKOffset-6cab68ff.so.7.7.0 +0 -0
- topologicpy/bin/linux/topologic.libs/libTKPrim-eb1262b3.so.7.7.0 +0 -0
- topologicpy/bin/linux/topologic.libs/libTKShHealing-e67e5cc7.so.7.7.0 +0 -0
- topologicpy/bin/linux/topologic.libs/libTKTopAlgo-e4c96c33.so.7.7.0 +0 -0
- topologicpy/bin/linux/topologic.libs/libTKernel-fb7fe3b7.so.7.7.0 +0 -0
- topologicpy/bin/linux/topologic.libs/libgcc_s-32c1665e.so.1 +0 -0
- topologicpy/bin/linux/topologic.libs/libstdc++-672d7b41.so.6.0.30 +0 -0
- topologicpy/bin/macos/topologic/__init__.py +2 -2
- topologicpy/bin/windows/topologic/topologic.cp310-win_amd64.pyd +0 -0
- topologicpy/bin/windows/topologic/topologic.cp311-win_amd64.pyd +0 -0
- topologicpy/bin/windows/topologic/topologic.cp38-win_amd64.pyd +0 -0
- topologicpy/bin/windows/topologic/topologic.cp39-win_amd64.pyd +0 -0
- {topologicpy-0.4.55.dist-info → topologicpy-0.4.57.dist-info}/METADATA +1 -1
- {topologicpy-0.4.55.dist-info → topologicpy-0.4.57.dist-info}/RECORD +44 -48
- topologicpy/bin/linux/topologic.libs/libgcc_s-b928ac34.so.1 +0 -0
- topologicpy/bin/linux/topologic.libs/libstdc++-e9ef912c.so.6.0.32 +0 -0
- topologicpy/bin/macos/topologic/topologic.cpython-310-darwin.so +0 -0
- topologicpy/bin/macos/topologic/topologic.cpython-311-darwin.so +0 -0
- topologicpy/bin/macos/topologic/topologic.cpython-38-darwin.so +0 -0
- topologicpy/bin/macos/topologic/topologic.cpython-39-darwin.so +0 -0
- {topologicpy-0.4.55.dist-info → topologicpy-0.4.57.dist-info}/LICENSE +0 -0
- {topologicpy-0.4.55.dist-info → topologicpy-0.4.57.dist-info}/WHEEL +0 -0
- {topologicpy-0.4.55.dist-info → topologicpy-0.4.57.dist-info}/top_level.txt +0 -0
topologicpy/Graph.py
CHANGED
|
@@ -4183,6 +4183,12 @@ class Graph:
|
|
|
4183
4183
|
for edge in Topology.Edges(temp_path):
|
|
4184
4184
|
new_edges.append(g_edges[Edge.Index(edge, g_edges)])
|
|
4185
4185
|
longest_path = Topology.SelfMerge(Cluster.ByTopologies(new_edges), tolerance=tolerance)
|
|
4186
|
+
sv = Topology.Vertices(longest_path)[0]
|
|
4187
|
+
if Vertex.Distance(sv, vertexB) < tolerance: # Wire is reversed. Re-reverse it
|
|
4188
|
+
if isinstance(longest_path, topologic.Edges):
|
|
4189
|
+
longest_path = Edge.Reverse(longest_path)
|
|
4190
|
+
if isinstance(longest_path, topologic.Wire):
|
|
4191
|
+
longest_path = Wire.Reverse(longest_path)
|
|
4186
4192
|
if not costKey == None:
|
|
4187
4193
|
lengths.sort()
|
|
4188
4194
|
d = Dictionary.ByKeysValues([costKey], [cost])
|
|
@@ -4874,7 +4880,7 @@ class Graph:
|
|
|
4874
4880
|
return graph
|
|
4875
4881
|
|
|
4876
4882
|
@staticmethod
|
|
4877
|
-
def ShortestPath(graph, vertexA, vertexB, vertexKey="", edgeKey="Length"):
|
|
4883
|
+
def ShortestPath(graph, vertexA, vertexB, vertexKey="", edgeKey="Length", tolerance=0.0001):
|
|
4878
4884
|
"""
|
|
4879
4885
|
Returns the shortest path that connects the input vertices.
|
|
4880
4886
|
|
|
@@ -4890,13 +4896,19 @@ class Graph:
|
|
|
4890
4896
|
The vertex key to minimise. If set the vertices dictionaries will be searched for this key and the associated value will be used to compute the shortest path that minimized the total value. The value must be numeric. The default is None.
|
|
4891
4897
|
edgeKey : string , optional
|
|
4892
4898
|
The edge key to minimise. If set the edges dictionaries will be searched for this key and the associated value will be used to compute the shortest path that minimized the total value. The value of the key must be numeric. If set to "length" (case insensitive), the shortest path by length is computed. The default is "length".
|
|
4893
|
-
|
|
4899
|
+
tolerance : float , optional
|
|
4900
|
+
The desired tolerance. The default is 0.0001.
|
|
4901
|
+
|
|
4894
4902
|
Returns
|
|
4895
4903
|
-------
|
|
4896
4904
|
topologic.Wire
|
|
4897
4905
|
The shortest path between the input vertices.
|
|
4898
4906
|
|
|
4899
4907
|
"""
|
|
4908
|
+
from topologicpy.Edge import Edge
|
|
4909
|
+
from topologicpy.Wire import Wire
|
|
4910
|
+
from topologicpy.Topology import Topology
|
|
4911
|
+
|
|
4900
4912
|
if not isinstance(graph, topologic.Graph):
|
|
4901
4913
|
print("Graph.ShortestPath - Error: The input graph is not a valid graph. Returning None.")
|
|
4902
4914
|
return None
|
|
@@ -4910,7 +4922,16 @@ class Graph:
|
|
|
4910
4922
|
if edgeKey.lower() == "length":
|
|
4911
4923
|
edgeKey = "Length"
|
|
4912
4924
|
try:
|
|
4913
|
-
|
|
4925
|
+
gsv = Graph.NearestVertex(graph, vertexA, tolerance)
|
|
4926
|
+
gev = Graph.NearestVertex(graph, vertexB, tolerance)
|
|
4927
|
+
shortest_path = graph.ShortestPath(gsv, gev, vertexKey, edgeKey)
|
|
4928
|
+
sv = Topology.Vertices(shortest_path)[0]
|
|
4929
|
+
if Vertex.Distance(sv, gev) < tolerance: # Path is reversed. Correct it.
|
|
4930
|
+
if isinstance(shortest_path, topologic.Edges):
|
|
4931
|
+
shortest_path = Edge.Reverse(shortest_path)
|
|
4932
|
+
if isinstance(shortest_path, topologic.Wire):
|
|
4933
|
+
shortest_path = Wire.Reverse(shortest_path)
|
|
4934
|
+
return shortest_path
|
|
4914
4935
|
except:
|
|
4915
4936
|
return None
|
|
4916
4937
|
|
|
@@ -4936,62 +4957,49 @@ class Graph:
|
|
|
4936
4957
|
The search time limit in seconds. The default is 10 seconds
|
|
4937
4958
|
pathLimit: int , optional
|
|
4938
4959
|
The number of found paths limit. The default is 10 paths.
|
|
4960
|
+
tolerance : float , optional
|
|
4961
|
+
The desired tolerance. The default is 0.0001.
|
|
4939
4962
|
|
|
4940
4963
|
Returns
|
|
4941
4964
|
-------
|
|
4942
|
-
|
|
4965
|
+
list
|
|
4943
4966
|
The list of shortest paths between the input vertices.
|
|
4944
4967
|
|
|
4945
4968
|
"""
|
|
4946
4969
|
from topologicpy.Vertex import Vertex
|
|
4947
4970
|
from topologicpy.Wire import Wire
|
|
4948
|
-
def nearestVertex(g, v, tolerance):
|
|
4949
|
-
vertices = Graph.Vertices(g)
|
|
4950
|
-
for aVertex in vertices:
|
|
4951
|
-
d = Vertex.Distance(v, aVertex)
|
|
4952
|
-
if d < tolerance:
|
|
4953
|
-
return aVertex
|
|
4954
|
-
return None
|
|
4955
4971
|
|
|
4956
|
-
def isUnique(paths,
|
|
4972
|
+
def isUnique(paths, path):
|
|
4973
|
+
if path == None:
|
|
4974
|
+
return False
|
|
4957
4975
|
if len(paths) < 1:
|
|
4958
4976
|
return True
|
|
4959
4977
|
for aPath in paths:
|
|
4960
4978
|
copyPath = topologic.Topology.DeepCopy(aPath)
|
|
4961
|
-
dif = copyPath.Difference(
|
|
4979
|
+
dif = copyPath.Difference(path, False)
|
|
4962
4980
|
if dif == None:
|
|
4963
4981
|
return False
|
|
4964
4982
|
return True
|
|
4965
4983
|
|
|
4966
4984
|
if not isinstance(graph, topologic.Graph):
|
|
4967
|
-
print("Graph.ShortestPaths - Error: The input graph is not a valid graph. Returning None.")
|
|
4985
|
+
print("Graph.ShortestPaths - Error: The input graph parameter is not a valid graph. Returning None.")
|
|
4968
4986
|
return None
|
|
4969
4987
|
if not isinstance(vertexA, topologic.Vertex):
|
|
4970
|
-
print("Graph.ShortestPaths - Error: The input vertexA is not a valid vertex. Returning None.")
|
|
4988
|
+
print("Graph.ShortestPaths - Error: The input vertexA parameter is not a valid vertex. Returning None.")
|
|
4971
4989
|
return None
|
|
4972
4990
|
if not isinstance(vertexB, topologic.Vertex):
|
|
4973
|
-
print("Graph.ShortestPaths - Error: The input vertexB is not a valid vertex. Returning None.")
|
|
4991
|
+
print("Graph.ShortestPaths - Error: The input vertexB parameter is not a valid vertex. Returning None.")
|
|
4974
4992
|
return None
|
|
4975
4993
|
shortestPaths = []
|
|
4976
4994
|
end = time.time() + timeLimit
|
|
4977
4995
|
while time.time() < end and len(shortestPaths) < pathLimit:
|
|
4978
|
-
gsv = nearestVertex(graph, vertexA, tolerance)
|
|
4979
|
-
gev = nearestVertex(graph, vertexB, tolerance)
|
|
4980
4996
|
if (graph != None):
|
|
4981
4997
|
if edgeKey:
|
|
4982
4998
|
if edgeKey.lower() == "length":
|
|
4983
4999
|
edgeKey = "Length"
|
|
4984
|
-
|
|
4985
|
-
|
|
4986
|
-
|
|
4987
|
-
try:
|
|
4988
|
-
wireVertices = Wire.Vertices(wire)
|
|
4989
|
-
flag = True
|
|
4990
|
-
except:
|
|
4991
|
-
flag = False
|
|
4992
|
-
if (flag):
|
|
4993
|
-
if isUnique(shortestPaths, wire):
|
|
4994
|
-
shortestPaths.append(wire)
|
|
5000
|
+
shortest_path = Graph.ShortestPath(graph, vertexA, vertexB, vertexKey=vertexKey, edgeKey=edgeKey, tolerance=tolerance) # Find the first shortest path
|
|
5001
|
+
if isUnique(shortestPaths, shortest_path):
|
|
5002
|
+
shortestPaths.append(shortest_path)
|
|
4995
5003
|
vertices = Graph.Vertices(graph)
|
|
4996
5004
|
random.shuffle(vertices)
|
|
4997
5005
|
edges = Graph.Edges(graph)
|
|
@@ -5399,11 +5407,6 @@ class Graph:
|
|
|
5399
5407
|
e = Topology.Boolean(e, boundaryFace, operation="intersect", tolerance=tolerance)
|
|
5400
5408
|
if isinstance(e, topologic.Edge):
|
|
5401
5409
|
edges = addEdge(e, edges, viewpointsA, viewpointsB, 0.0001)
|
|
5402
|
-
elif isinstance(e, topologic.Cluster):
|
|
5403
|
-
tempEdges = Cluster.Edges(e)
|
|
5404
|
-
if tempEdges:
|
|
5405
|
-
for tempEdge in tempEdges:
|
|
5406
|
-
edges = addEdge(tempEdge, edges, viewpointsA, viewpointsB, 0.0001)
|
|
5407
5410
|
|
|
5408
5411
|
except:
|
|
5409
5412
|
for i in range(len(viewpointsA)):
|
topologicpy/Helper.py
CHANGED
|
@@ -5,7 +5,7 @@ import math
|
|
|
5
5
|
|
|
6
6
|
class Helper:
|
|
7
7
|
@staticmethod
|
|
8
|
-
def Flatten(
|
|
8
|
+
def Flatten(listA):
|
|
9
9
|
"""
|
|
10
10
|
Flattens the input nested list.
|
|
11
11
|
|
|
@@ -21,22 +21,22 @@ class Helper:
|
|
|
21
21
|
|
|
22
22
|
"""
|
|
23
23
|
|
|
24
|
-
if not isinstance(
|
|
25
|
-
return [
|
|
24
|
+
if not isinstance(listA, list):
|
|
25
|
+
return [listA]
|
|
26
26
|
flat_list = []
|
|
27
|
-
for item in
|
|
27
|
+
for item in listA:
|
|
28
28
|
flat_list = flat_list + Helper.Flatten(item)
|
|
29
29
|
return flat_list
|
|
30
30
|
|
|
31
31
|
@staticmethod
|
|
32
|
-
def Iterate(
|
|
32
|
+
def Iterate(listA):
|
|
33
33
|
"""
|
|
34
34
|
Iterates the input nested list so that each sublist has the same number of members. To fill extra members, the shorter lists are iterated from their first member.
|
|
35
35
|
For example Iterate([[1,2,3],['m','n','o','p'],['a','b','c','d','e']]) yields [[1, 2, 3, 1, 2], ['m', 'n', 'o', 'p', 'm'], ['a', 'b', 'c', 'd', 'e']]
|
|
36
36
|
|
|
37
37
|
Parameters
|
|
38
38
|
----------
|
|
39
|
-
|
|
39
|
+
listA : list
|
|
40
40
|
The input nested list.
|
|
41
41
|
|
|
42
42
|
Returns
|
|
@@ -56,13 +56,13 @@ class Helper:
|
|
|
56
56
|
base = base[1:]+[base[0]] # rotate
|
|
57
57
|
return base
|
|
58
58
|
|
|
59
|
-
maxLength = len(
|
|
59
|
+
maxLength = len(listA[0])
|
|
60
60
|
iterated_list = []
|
|
61
|
-
for aSubList in
|
|
61
|
+
for aSubList in listA:
|
|
62
62
|
newLength = len(aSubList)
|
|
63
63
|
if newLength > maxLength:
|
|
64
64
|
maxLength = newLength
|
|
65
|
-
for anItem in
|
|
65
|
+
for anItem in listA:
|
|
66
66
|
for i in range(len(anItem), maxLength):
|
|
67
67
|
anItem.append(None)
|
|
68
68
|
y=[]
|
|
@@ -107,13 +107,13 @@ class Helper:
|
|
|
107
107
|
return {'clusters': clusters, 'centroids': centroids}
|
|
108
108
|
|
|
109
109
|
@staticmethod
|
|
110
|
-
def MergeByThreshold(
|
|
110
|
+
def MergeByThreshold(listA, threshold=0.0001):
|
|
111
111
|
"""
|
|
112
112
|
Merges the numbers in the input list so that numbers within the input threshold are averaged into one number.
|
|
113
113
|
|
|
114
114
|
Parameters
|
|
115
115
|
----------
|
|
116
|
-
|
|
116
|
+
listA : list
|
|
117
117
|
The input nested list.
|
|
118
118
|
threshold : float , optional
|
|
119
119
|
The desired merge threshold value. The default is 0.0001.
|
|
@@ -125,31 +125,31 @@ class Helper:
|
|
|
125
125
|
|
|
126
126
|
"""
|
|
127
127
|
# Sort the list in ascending order
|
|
128
|
-
|
|
128
|
+
listA.sort()
|
|
129
129
|
merged_list = []
|
|
130
130
|
|
|
131
131
|
# Initialize the first element in the merged list
|
|
132
|
-
merged_list.append(
|
|
132
|
+
merged_list.append(listA[0])
|
|
133
133
|
|
|
134
134
|
# Merge numbers within the threshold
|
|
135
|
-
for i in range(1, len(
|
|
136
|
-
if
|
|
135
|
+
for i in range(1, len(listA)):
|
|
136
|
+
if listA[i] - merged_list[-1] <= threshold:
|
|
137
137
|
# Merge the current number with the last element in the merged list
|
|
138
|
-
merged_list[-1] = (merged_list[-1] +
|
|
138
|
+
merged_list[-1] = (merged_list[-1] + listA[i]) / 2
|
|
139
139
|
else:
|
|
140
140
|
# If the current number is beyond the threshold, add it as a new element
|
|
141
|
-
merged_list.append(
|
|
141
|
+
merged_list.append(listA[i])
|
|
142
142
|
|
|
143
143
|
return merged_list
|
|
144
144
|
|
|
145
145
|
@staticmethod
|
|
146
|
-
def Normalize(
|
|
146
|
+
def Normalize(listA, mantissa: int = 6):
|
|
147
147
|
"""
|
|
148
148
|
Normalizes the input list so that it is in the range 0 to 1
|
|
149
149
|
|
|
150
150
|
Parameters
|
|
151
151
|
----------
|
|
152
|
-
|
|
152
|
+
listA : list
|
|
153
153
|
The input nested list.
|
|
154
154
|
mantissa : int , optional
|
|
155
155
|
The desired mantissa value. The default is 4.
|
|
@@ -160,12 +160,12 @@ class Helper:
|
|
|
160
160
|
The normalized list.
|
|
161
161
|
|
|
162
162
|
"""
|
|
163
|
-
if
|
|
163
|
+
if not isinstance(listA, list):
|
|
164
164
|
print("Helper.Normalize - Error: The input list is not valid. Returning None.")
|
|
165
165
|
return None
|
|
166
166
|
|
|
167
167
|
# Make sure the list is numeric
|
|
168
|
-
l = [x for x in
|
|
168
|
+
l = [x for x in listA if type(x) == int or type(x) == float]
|
|
169
169
|
if len(l) < 1:
|
|
170
170
|
print("Helper.Normalize - Error: The input list does not contain numeric values. Returning None.")
|
|
171
171
|
return None
|
|
@@ -178,14 +178,14 @@ class Helper:
|
|
|
178
178
|
return normalized_list
|
|
179
179
|
|
|
180
180
|
@staticmethod
|
|
181
|
-
def Repeat(
|
|
181
|
+
def Repeat(listA):
|
|
182
182
|
"""
|
|
183
183
|
Repeats the input nested list so that each sublist has the same number of members. To fill extra members, the last item in the shorter lists are repeated and appended.
|
|
184
184
|
For example Iterate([[1,2,3],['m','n','o','p'],['a','b','c','d','e']]) yields [[1, 2, 3, 3, 3], ['m', 'n', 'o', 'p', 'p'], ['a', 'b', 'c', 'd', 'e']]
|
|
185
185
|
|
|
186
186
|
Parameters
|
|
187
187
|
----------
|
|
188
|
-
|
|
188
|
+
listA : list
|
|
189
189
|
The input nested list.
|
|
190
190
|
|
|
191
191
|
Returns
|
|
@@ -194,9 +194,9 @@ class Helper:
|
|
|
194
194
|
The repeated list.
|
|
195
195
|
|
|
196
196
|
"""
|
|
197
|
-
if not isinstance(
|
|
197
|
+
if not isinstance(listA, list):
|
|
198
198
|
return None
|
|
199
|
-
repeated_list = [x for x in
|
|
199
|
+
repeated_list = [x for x in listA if isinstance(x, list)]
|
|
200
200
|
if len(repeated_list) < 1:
|
|
201
201
|
return None
|
|
202
202
|
maxLength = len(repeated_list[0])
|
|
@@ -214,16 +214,27 @@ class Helper:
|
|
|
214
214
|
return repeated_list
|
|
215
215
|
|
|
216
216
|
@staticmethod
|
|
217
|
-
def Sort(
|
|
217
|
+
def Sort(listA, *otherLists, reverseFlags=None):
|
|
218
218
|
"""
|
|
219
|
-
Sorts the first input list according to the values in the
|
|
219
|
+
Sorts the first input list according to the values in the subsequent input lists in order. For example,
|
|
220
|
+
your first list can be a list of topologies and the next set of lists can be their volume, surface area, and z level.
|
|
221
|
+
The list of topologies will then be sorted first by volume, then by surface, and lastly by z level. You can choose
|
|
222
|
+
to reverse the order of sorting by including a list of TRUE/FALSE values in the reverseFlags input parameter.
|
|
223
|
+
For example, if you wish to sort the volume in reverse order (from large to small), but sort the other parameters
|
|
224
|
+
normally, you would include the following list for reverseFlag: [True, False, False].
|
|
220
225
|
|
|
221
226
|
Parameters
|
|
222
227
|
----------
|
|
223
|
-
|
|
228
|
+
listA : list
|
|
224
229
|
The first input list to be sorts
|
|
225
|
-
|
|
226
|
-
|
|
230
|
+
*otherLists : any number of lists to use for sorting listA, optional.
|
|
231
|
+
Any number of lists that are used to sort the listA input parameter. The order of these input
|
|
232
|
+
parameters determines the order of sorting (from left to right). If no lists are included, the input list will be sorted as is.
|
|
233
|
+
reverseFlags : list, optional.
|
|
234
|
+
The list of booleans (TRUE/FALSE) to indicated if sorting based on a particular list should be conducted in reverse order.
|
|
235
|
+
The length of the reverseFlags list should match the number of the lists in the input otherLists parameter. If set to None,
|
|
236
|
+
a default list of FALSE values is created to match the number of the lists in the input otherLists parameter. The default
|
|
237
|
+
is None.
|
|
227
238
|
|
|
228
239
|
Returns
|
|
229
240
|
-------
|
|
@@ -231,17 +242,45 @@ class Helper:
|
|
|
231
242
|
The sorted list.
|
|
232
243
|
|
|
233
244
|
"""
|
|
234
|
-
|
|
235
|
-
|
|
245
|
+
|
|
246
|
+
# If reverseFlags is not provided, assume all lists should be sorted in ascending order
|
|
247
|
+
if reverseFlags is None:
|
|
248
|
+
reverseFlags = [False] * len(otherLists)
|
|
249
|
+
if not isinstance(otherLists, tuple):
|
|
250
|
+
print("Helper.Sort - Error: No other lists to use for sorting have been provided. Returning None.")
|
|
251
|
+
return None
|
|
252
|
+
if len(otherLists) < 1:
|
|
253
|
+
print("Helper.Sort - Error: The otherLists input parameter does not contain any valid lists. Returning None.")
|
|
254
|
+
return None
|
|
255
|
+
if not len(reverseFlags) == len(otherLists):
|
|
256
|
+
print("Helper.Sort - Error: The length of the reverseFlags input parameter is not equal to the number of input lists. Returning None.")
|
|
257
|
+
return None
|
|
258
|
+
# Convert other_lists to numeric and reverse if needed.
|
|
259
|
+
sorting_lists = []
|
|
260
|
+
for i, a_list in enumerate(otherLists):
|
|
261
|
+
temp_list = []
|
|
262
|
+
temp_set = list(set(a_list))
|
|
263
|
+
temp_set = sorted(temp_set)
|
|
264
|
+
if reverseFlags[i] == True:
|
|
265
|
+
temp_set.reverse()
|
|
266
|
+
for item in a_list:
|
|
267
|
+
temp_list.append(temp_set.index(item))
|
|
268
|
+
sorting_lists.append(temp_list)
|
|
269
|
+
|
|
270
|
+
combined_lists = list(zip(listA, *sorting_lists))
|
|
271
|
+
# Sort the combined list based on all the elements and reverse the lists as needed
|
|
272
|
+
combined_lists.sort(key=lambda x: tuple((-val) if reverse else val for val, reverse in zip(x[1:], reverseFlags)))
|
|
273
|
+
sorted_listA = [item[0] for item in combined_lists]
|
|
274
|
+
return sorted_listA
|
|
236
275
|
|
|
237
276
|
@staticmethod
|
|
238
|
-
def Transpose(
|
|
277
|
+
def Transpose(listA):
|
|
239
278
|
"""
|
|
240
|
-
Transposes (swaps rows and columns)
|
|
279
|
+
Transposes the input list (swaps rows and columns).
|
|
241
280
|
|
|
242
281
|
Parameters
|
|
243
282
|
----------
|
|
244
|
-
|
|
283
|
+
listA : list
|
|
245
284
|
The input list.
|
|
246
285
|
|
|
247
286
|
Returns
|
|
@@ -250,26 +289,26 @@ class Helper:
|
|
|
250
289
|
The transposed list.
|
|
251
290
|
|
|
252
291
|
"""
|
|
253
|
-
if not isinstance(
|
|
292
|
+
if not isinstance(listA, list):
|
|
254
293
|
return None
|
|
255
|
-
length = len(
|
|
294
|
+
length = len(listA[0])
|
|
256
295
|
transposed_list = []
|
|
257
296
|
for i in range(length):
|
|
258
297
|
tempRow = []
|
|
259
|
-
for j in range(len(
|
|
260
|
-
tempRow.append(
|
|
298
|
+
for j in range(len(listA)):
|
|
299
|
+
tempRow.append(listA[j][i])
|
|
261
300
|
transposed_list.append(tempRow)
|
|
262
301
|
return transposed_list
|
|
263
302
|
|
|
264
303
|
@staticmethod
|
|
265
|
-
def Trim(
|
|
304
|
+
def Trim(listA):
|
|
266
305
|
"""
|
|
267
306
|
Trims the input nested list so that each sublist has the same number of members. All lists are trimmed to match the length of the shortest list.
|
|
268
307
|
For example Trim([[1,2,3],['m','n','o','p'],['a','b','c','d','e']]) yields [[1, 2, 3], ['m', 'n', 'o'], ['a', 'b', 'c']]
|
|
269
308
|
|
|
270
309
|
Parameters
|
|
271
310
|
----------
|
|
272
|
-
|
|
311
|
+
listA : list
|
|
273
312
|
The input nested list.
|
|
274
313
|
|
|
275
314
|
Returns
|
|
@@ -278,13 +317,13 @@ class Helper:
|
|
|
278
317
|
The repeated list.
|
|
279
318
|
|
|
280
319
|
"""
|
|
281
|
-
minLength = len(
|
|
320
|
+
minLength = len(listA[0])
|
|
282
321
|
returnList = []
|
|
283
|
-
for aSubList in
|
|
322
|
+
for aSubList in listA:
|
|
284
323
|
newLength = len(aSubList)
|
|
285
324
|
if newLength < minLength:
|
|
286
325
|
minLength = newLength
|
|
287
|
-
for anItem in
|
|
326
|
+
for anItem in listA:
|
|
288
327
|
anItem = anItem[:minLength]
|
|
289
328
|
returnList.append(anItem)
|
|
290
329
|
return returnList
|
topologicpy/Plotly.py
CHANGED
|
@@ -391,7 +391,7 @@ class Plotly:
|
|
|
391
391
|
edgeMinGroup=None, edgeMaxGroup=None,
|
|
392
392
|
showEdgeLegend=False, edgeLegendLabel="Topology Edges", edgeLegendRank=2,
|
|
393
393
|
edgeLegendGroup=2,
|
|
394
|
-
showFaces=True, faceOpacity=0.5, faceColor="
|
|
394
|
+
showFaces=True, faceOpacity=0.5, faceColor="#FAFAFA",
|
|
395
395
|
faceLabelKey=None, faceGroupKey=None, faceGroups=[],
|
|
396
396
|
faceMinGroup=None, faceMaxGroup=None,
|
|
397
397
|
showFaceLegend=False, faceLegendLabel="Topology Faces", faceLegendRank=3,
|
|
@@ -478,7 +478,7 @@ class Plotly:
|
|
|
478
478
|
- An hsl/hsla string (e.g. 'hsl(0,100%,50%)')
|
|
479
479
|
- An hsv/hsva string (e.g. 'hsv(0,100%,100%)')
|
|
480
480
|
- A named CSS color.
|
|
481
|
-
The default is "
|
|
481
|
+
The default is "#FAFAFA".
|
|
482
482
|
faceLabelKey : str , optional
|
|
483
483
|
The dictionary key to use to display the face label. The default is None.
|
|
484
484
|
faceGroupKey : str , optional
|
|
@@ -677,7 +677,7 @@ class Plotly:
|
|
|
677
677
|
return eData
|
|
678
678
|
|
|
679
679
|
|
|
680
|
-
def faceData(vertices, faces, dictionaries=None, color="
|
|
680
|
+
def faceData(vertices, faces, dictionaries=None, color="#FAFAFA",
|
|
681
681
|
opacity=0.5, labelKey=None, groupKey=None,
|
|
682
682
|
minGroup=None, maxGroup=None, groups=[], legendLabel="Topology Faces",
|
|
683
683
|
legendGroup=3, legendRank=3, showLegend=True, intensities=None, colorScale="Viridis"):
|
|
@@ -786,7 +786,7 @@ class Plotly:
|
|
|
786
786
|
data = []
|
|
787
787
|
|
|
788
788
|
if showVertices:
|
|
789
|
-
tp_vertices = Topology.
|
|
789
|
+
tp_vertices = Topology.Vertices(topology)
|
|
790
790
|
if not (tp_vertices == None or tp_vertices == []):
|
|
791
791
|
vertices = []
|
|
792
792
|
v_dictionaries = []
|
|
@@ -812,7 +812,7 @@ class Plotly:
|
|
|
812
812
|
intensities = None
|
|
813
813
|
|
|
814
814
|
if showEdges and topology.Type() > topologic.Vertex.Type():
|
|
815
|
-
tp_edges = Topology.
|
|
815
|
+
tp_edges = Topology.Edges(topology)
|
|
816
816
|
if not (tp_edges == None or tp_edges == []):
|
|
817
817
|
e_dictionaries = []
|
|
818
818
|
if edgeLabelKey or edgeGroupKey:
|
|
@@ -825,23 +825,24 @@ class Plotly:
|
|
|
825
825
|
data.append(edgeData(vertices, edges, dictionaries=e_dictionaries, color=edgeColor, width=edgeWidth, labelKey=edgeLabelKey, groupKey=edgeGroupKey, minGroup=edgeMinGroup, maxGroup=edgeMaxGroup, groups=edgeGroups, legendLabel=edgeLegendLabel, legendGroup=edgeLegendGroup, legendRank=edgeLegendRank, showLegend=showEdgeLegend, colorScale=colorScale))
|
|
826
826
|
|
|
827
827
|
if showFaces and topology.Type() >= topologic.Face.Type():
|
|
828
|
-
|
|
828
|
+
if isinstance(topology, topologic.Face):
|
|
829
|
+
tp_faces = [topology]
|
|
830
|
+
else:
|
|
831
|
+
tp_faces = Topology.Faces(topology)
|
|
829
832
|
if not(tp_faces == None or tp_faces == []):
|
|
830
833
|
f_dictionaries = []
|
|
831
834
|
all_triangles = []
|
|
832
835
|
for tp_face in tp_faces:
|
|
833
|
-
|
|
834
|
-
if isinstance(shell, topologic.Face):
|
|
835
|
-
triangles = [shell]
|
|
836
|
-
else:
|
|
837
|
-
triangles = Topology.SubTopologies(shell, subTopologyType="face")
|
|
836
|
+
triangles = Face.Triangulate(tp_face, tolerance=tolerance)
|
|
838
837
|
for tri in triangles:
|
|
839
838
|
if faceLabelKey or faceGroupKey:
|
|
840
839
|
d = Topology.Dictionary(tp_face)
|
|
841
840
|
f_dictionaries.append(d)
|
|
842
841
|
if d:
|
|
843
842
|
_ = Topology.SetDictionary(tri, d)
|
|
844
|
-
|
|
843
|
+
c = Topology.Centroid(tri)
|
|
844
|
+
if Face.IsInternal(tp_face, c):
|
|
845
|
+
all_triangles.append(tri)
|
|
845
846
|
if len(all_triangles) > 0:
|
|
846
847
|
f_cluster = Cluster.ByTopologies(all_triangles)
|
|
847
848
|
geo = Topology.Geometry(f_cluster, mantissa=mantissa)
|
|
@@ -1378,7 +1379,7 @@ class Plotly:
|
|
|
1378
1379
|
showEdgeLegend=False, edgeLegendLabel="Topology Edges", edgeLegendRank=2,
|
|
1379
1380
|
edgeLegendGroup=2,
|
|
1380
1381
|
|
|
1381
|
-
showFaces=True, faceOpacity=0.5, faceColor="
|
|
1382
|
+
showFaces=True, faceOpacity=0.5, faceColor="#FAFAFA",
|
|
1382
1383
|
faceLabelKey=None, faceGroupKey=None, faceGroups=[],
|
|
1383
1384
|
faceMinGroup=None, faceMaxGroup=None,
|
|
1384
1385
|
showFaceLegend=False, faceLegendLabel="Topology Faces", faceLegendRank=3,
|
|
@@ -1473,7 +1474,7 @@ class Plotly:
|
|
|
1473
1474
|
- An hsl/hsla string (e.g. 'hsl(0,100%,50%)')
|
|
1474
1475
|
- An hsv/hsva string (e.g. 'hsv(0,100%,100%)')
|
|
1475
1476
|
- A named CSS color.
|
|
1476
|
-
The default is "
|
|
1477
|
+
The default is "#FAFAFA".
|
|
1477
1478
|
faceLabelKey : str , optional
|
|
1478
1479
|
The dictionary key to use to display the face label. The default is None.
|
|
1479
1480
|
faceGroupKey : str , optional
|