topologicpy 0.7.83__py3-none-any.whl → 0.7.85__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 +10 -6
- topologicpy/CellComplex.py +10 -5
- topologicpy/Cluster.py +8 -8
- topologicpy/Dictionary.py +34 -1
- topologicpy/Edge.py +3 -3
- topologicpy/Face.py +11 -3
- topologicpy/Graph.py +91 -49
- topologicpy/Grid.py +4 -4
- topologicpy/Helper.py +42 -1
- topologicpy/Plotly.py +21 -22
- topologicpy/Shell.py +10 -6
- topologicpy/Topology.py +160 -54
- topologicpy/Vertex.py +8 -3
- topologicpy/Wire.py +111 -18
- topologicpy/version.py +1 -1
- {topologicpy-0.7.83.dist-info → topologicpy-0.7.85.dist-info}/METADATA +1 -1
- topologicpy-0.7.85.dist-info/RECORD +36 -0
- topologicpy-0.7.83.dist-info/RECORD +0 -36
- {topologicpy-0.7.83.dist-info → topologicpy-0.7.85.dist-info}/LICENSE +0 -0
- {topologicpy-0.7.83.dist-info → topologicpy-0.7.85.dist-info}/WHEEL +0 -0
- {topologicpy-0.7.83.dist-info → topologicpy-0.7.85.dist-info}/top_level.txt +0 -0
topologicpy/Topology.py
CHANGED
@@ -286,7 +286,7 @@ class Topology():
|
|
286
286
|
usedTopologies.append(0)
|
287
287
|
ap = 1
|
288
288
|
for aperture in apertures:
|
289
|
-
apCenter = Topology.InternalVertex(aperture, tolerance)
|
289
|
+
apCenter = Topology.InternalVertex(aperture, tolerance=tolerance)
|
290
290
|
for i in range(len(subTopologies)):
|
291
291
|
subTopology = subTopologies[i]
|
292
292
|
if exclusive == True and usedTopologies[i] == 1:
|
@@ -319,7 +319,7 @@ class Topology():
|
|
319
319
|
subTopologies = [topology]
|
320
320
|
else:
|
321
321
|
subTopologies = Topology.SubTopologies(topology, subTopologyType)
|
322
|
-
processApertures(subTopologies, apertures, exclusive, tolerance)
|
322
|
+
processApertures(subTopologies, apertures, exclusive, tolerance=tolerance)
|
323
323
|
return topology
|
324
324
|
|
325
325
|
@staticmethod
|
@@ -1524,7 +1524,7 @@ class Topology():
|
|
1524
1524
|
from topologicpy.CellComplex import CellComplex
|
1525
1525
|
from topologicpy.Cluster import Cluster
|
1526
1526
|
|
1527
|
-
def topologyByFaces(faces, topologyType, tolerance):
|
1527
|
+
def topologyByFaces(faces, topologyType, tolerance=0.0001):
|
1528
1528
|
if len(faces) == 1:
|
1529
1529
|
return faces[0]
|
1530
1530
|
|
@@ -1663,7 +1663,7 @@ class Topology():
|
|
1663
1663
|
The created topology. The topology will have a dictionary embedded in it that records the input attributes (color, id, lengthUnit, name, type)
|
1664
1664
|
|
1665
1665
|
"""
|
1666
|
-
def topologyByFaces(faces, outputMode, tolerance):
|
1666
|
+
def topologyByFaces(faces, outputMode, tolerance=0.0001):
|
1667
1667
|
output = None
|
1668
1668
|
if len(faces) == 1:
|
1669
1669
|
return faces[0]
|
@@ -2386,6 +2386,10 @@ class Topology():
|
|
2386
2386
|
|
2387
2387
|
import ifcopenshell, ifcopenshell.geom
|
2388
2388
|
from topologicpy.Dictionary import Dictionary
|
2389
|
+
from topologicpy.Vertex import Vertex
|
2390
|
+
from topologicpy.Edge import Edge
|
2391
|
+
from topologicpy.Face import Face
|
2392
|
+
import numpy as np
|
2389
2393
|
|
2390
2394
|
def get_psets(entity):
|
2391
2395
|
# Initialize the PSET dictionary for this entity
|
@@ -2506,47 +2510,55 @@ class Topology():
|
|
2506
2510
|
color = (random.random(), random.random(), random.random())
|
2507
2511
|
|
2508
2512
|
return color, default_transparency, material_list
|
2509
|
-
|
2513
|
+
# Create a 4x4 unity matrix
|
2514
|
+
matrix = [[1.0 if i == j else 0.0 for j in range(4)] for i in range(4)]
|
2510
2515
|
def convert_to_topology(entity, settings, transferDictionaries=False):
|
2511
2516
|
if hasattr(entity, "Representation") and entity.Representation:
|
2512
2517
|
for rep in entity.Representation.Representations:
|
2513
2518
|
if rep.is_a("IfcShapeRepresentation"):
|
2514
2519
|
# Generate the geometry for this entity
|
2515
2520
|
shape = ifcopenshell.geom.create_shape(settings, entity)
|
2516
|
-
|
2517
|
-
|
2518
|
-
|
2519
|
-
|
2520
|
-
|
2521
|
-
|
2522
|
-
|
2523
|
-
|
2521
|
+
try:
|
2522
|
+
trans = shape.transformation
|
2523
|
+
# Convert into a 4x4 matrix
|
2524
|
+
matrix = [trans.matrix[i:i+4] for i in range(0, len(trans.matrix), 4)]
|
2525
|
+
except:
|
2526
|
+
pass
|
2527
|
+
# Get grouped vertices and grouped faces
|
2528
|
+
grouped_verts = shape.geometry.verts
|
2529
|
+
verts = [ [grouped_verts[i], grouped_verts[i + 1], grouped_verts[i + 2]] for i in range(0, len(grouped_verts), 3)]
|
2530
|
+
grouped_edges = shape.geometry.edges
|
2531
|
+
edges = [[grouped_edges[i], grouped_edges[i + 1]] for i in range(0, len(grouped_edges), 2)]
|
2532
|
+
grouped_faces = shape.geometry.faces
|
2533
|
+
faces = [ [grouped_faces[i], grouped_faces[i + 1], grouped_faces[i + 2]] for i in range(0, len(grouped_faces), 3)]
|
2524
2534
|
#shape_topology = ifc_to_topologic_geometry(verts, edges, faces)
|
2525
2535
|
#shape_topology = Topology.SelfMerge(Topology.ByGeometry(verts, edges, faces))
|
2526
2536
|
shape_topology = Topology.ByGeometry(verts, edges, faces, silent=True)
|
2527
|
-
if
|
2528
|
-
|
2529
|
-
|
2530
|
-
|
2531
|
-
|
2532
|
-
|
2533
|
-
|
2534
|
-
|
2535
|
-
|
2536
|
-
|
2537
|
-
|
2538
|
-
|
2539
|
-
|
2540
|
-
|
2541
|
-
|
2542
|
-
|
2543
|
-
|
2544
|
-
|
2545
|
-
|
2546
|
-
|
2547
|
-
|
2548
|
-
|
2549
|
-
|
2537
|
+
if not shape_topology == None:
|
2538
|
+
if removeCoplanarFaces == True:
|
2539
|
+
shape_topology = Topology.RemoveCoplanarFaces(shape_topology, epsilon=0.0001)
|
2540
|
+
shape_topology = Topology.Transform(shape_topology, matrix)
|
2541
|
+
|
2542
|
+
# Store relevant information
|
2543
|
+
if transferDictionaries == True:
|
2544
|
+
color, transparency, material_list = get_color_transparency_material(entity)
|
2545
|
+
entity_dict = {
|
2546
|
+
"TOPOLOGIC_id": str(Topology.UUID(shape_topology)),
|
2547
|
+
"TOPOLOGIC_name": getattr(entity, 'Name', "Untitled"),
|
2548
|
+
"TOPOLOGIC_type": Topology.TypeAsString(shape_topology),
|
2549
|
+
"TOPOLOGIC_color": color,
|
2550
|
+
"TOPOLOGIC_opacity": 1.0 - transparency,
|
2551
|
+
"IFC_global_id": getattr(entity, 'GlobalId', 0),
|
2552
|
+
"IFC_name": getattr(entity, 'Name', "Untitled"),
|
2553
|
+
"IFC_type": entity.is_a(),
|
2554
|
+
"IFC_material_list": material_list,
|
2555
|
+
}
|
2556
|
+
topology_dict = Dictionary.ByPythonDictionary(entity_dict)
|
2557
|
+
# Get PSETs dictionary
|
2558
|
+
pset_python_dict = get_psets(entity)
|
2559
|
+
pset_dict = Dictionary.ByPythonDictionary(pset_python_dict)
|
2560
|
+
topology_dict = Dictionary.ByMergedDictionaries([topology_dict, pset_dict])
|
2561
|
+
shape_topology = Topology.SetDictionary(shape_topology, topology_dict)
|
2550
2562
|
return shape_topology
|
2551
2563
|
return None
|
2552
2564
|
|
@@ -4184,7 +4196,6 @@ class Topology():
|
|
4184
4196
|
from topologicpy.Dictionary import Dictionary
|
4185
4197
|
from topologicpy.Helper import Helper
|
4186
4198
|
import inspect
|
4187
|
-
print("input topologies:", topologies)
|
4188
4199
|
|
4189
4200
|
topologies_list = []
|
4190
4201
|
if Topology.IsInstance(topologies, "Topology"):
|
@@ -6229,7 +6240,7 @@ class Topology():
|
|
6229
6240
|
return Topology.Type(topology)
|
6230
6241
|
|
6231
6242
|
@staticmethod
|
6232
|
-
def
|
6243
|
+
def _InternalVertex(topology, tolerance: float = 0.0001):
|
6233
6244
|
"""
|
6234
6245
|
Returns a vertex guaranteed to be inside the input topology.
|
6235
6246
|
|
@@ -6284,11 +6295,54 @@ class Topology():
|
|
6284
6295
|
elif Topology.IsInstance(top, "Vertex"): #Vertex
|
6285
6296
|
vst = top
|
6286
6297
|
elif Topology.IsInstance(topology, "Aperture"): #Aperture
|
6287
|
-
vst = Face.InternalVertex(Aperture.Topology(top), tolerance)
|
6298
|
+
vst = Face.InternalVertex(Aperture.Topology(top), tolerance=tolerance)
|
6288
6299
|
else:
|
6289
6300
|
vst = Topology.Centroid(top)
|
6290
6301
|
return vst
|
6291
6302
|
|
6303
|
+
|
6304
|
+
|
6305
|
+
@staticmethod
|
6306
|
+
def InternalVertex(topology, timeout: int = 10, tolerance: float = 0.0001):
|
6307
|
+
"""
|
6308
|
+
Returns a vertex guaranteed to be inside the input topology.
|
6309
|
+
|
6310
|
+
Parameters
|
6311
|
+
----------
|
6312
|
+
topology : topologic_core.Topology
|
6313
|
+
The input topology.
|
6314
|
+
timeout : int , optional
|
6315
|
+
The amount of seconds to wait before timing out. The default is 10 seconds.
|
6316
|
+
tolerance : float , ptional
|
6317
|
+
The desired tolerance. The default is 0.0001.
|
6318
|
+
|
6319
|
+
Returns
|
6320
|
+
-------
|
6321
|
+
topologic_core.Vertex
|
6322
|
+
A vertex guaranteed to be inside the input topology.
|
6323
|
+
|
6324
|
+
"""
|
6325
|
+
import concurrent.futures
|
6326
|
+
import time
|
6327
|
+
# Wrapper function with timeout
|
6328
|
+
def run_with_timeout(func, topology, tolerance=0.0001, timeout=10):
|
6329
|
+
with concurrent.futures.ThreadPoolExecutor() as executor:
|
6330
|
+
future = executor.submit(func, topology, tolerance=tolerance)
|
6331
|
+
try:
|
6332
|
+
result = future.result(timeout=timeout) # Wait for the result with a timeout
|
6333
|
+
return result
|
6334
|
+
except concurrent.futures.TimeoutError:
|
6335
|
+
print("Function took too long, retrying with a different solution.")
|
6336
|
+
return None # or try another approach here
|
6337
|
+
|
6338
|
+
result = run_with_timeout(Topology._InternalVertex, topology=topology, tolerance=tolerance, timeout=timeout) # Set a 10 second timeout
|
6339
|
+
if result is None:
|
6340
|
+
# Handle failure case (e.g., try a different solution)
|
6341
|
+
print("Using a different approach.")
|
6342
|
+
result = Topology.Centroid(topology)
|
6343
|
+
print("Result is:", result)
|
6344
|
+
return result
|
6345
|
+
|
6292
6346
|
@staticmethod
|
6293
6347
|
def IsInstance(topology, type: str):
|
6294
6348
|
"""
|
@@ -6372,7 +6426,7 @@ class Topology():
|
|
6372
6426
|
"""
|
6373
6427
|
from topologicpy.Vertex import Vertex
|
6374
6428
|
|
6375
|
-
def isOnPlane(v, plane, tolerance):
|
6429
|
+
def isOnPlane(v, plane, tolerance=0.0001):
|
6376
6430
|
x, y, z = v
|
6377
6431
|
a, b, c, d = plane
|
6378
6432
|
if math.fabs(a*x + b*y + c*z + d) <= tolerance:
|
@@ -6403,7 +6457,7 @@ class Topology():
|
|
6403
6457
|
else:
|
6404
6458
|
p = plane(vertices[0], vertices[1], vertices[2])
|
6405
6459
|
for i in range(len(vertices)):
|
6406
|
-
if isOnPlane([Vertex.X(vertices[i], mantissa=mantissa), Vertex.Y(vertices[i], mantissa=mantissa), Vertex.Z(vertices[i], mantissa=mantissa)], p, tolerance) == False:
|
6460
|
+
if isOnPlane([Vertex.X(vertices[i], mantissa=mantissa), Vertex.Y(vertices[i], mantissa=mantissa), Vertex.Z(vertices[i], mantissa=mantissa)], p, tolerance=tolerance) == False:
|
6407
6461
|
result = False
|
6408
6462
|
break
|
6409
6463
|
return result
|
@@ -6749,8 +6803,13 @@ class Topology():
|
|
6749
6803
|
from topologicpy.Cell import Cell
|
6750
6804
|
from topologicpy.CellComplex import CellComplex
|
6751
6805
|
from topologicpy.Cluster import Cluster
|
6752
|
-
|
6806
|
+
import inspect
|
6753
6807
|
if not Topology.IsInstance(topology, "Topology"):
|
6808
|
+
if not silent:
|
6809
|
+
print("Topology.RemoveCollinearEdges - Error: The input topology parameter is not a valid topology. Returning None.")
|
6810
|
+
curframe = inspect.currentframe()
|
6811
|
+
calframe = inspect.getouterframes(curframe, 2)
|
6812
|
+
print('caller name:', calframe[1][3])
|
6754
6813
|
return None
|
6755
6814
|
return_topology = topology
|
6756
6815
|
if Topology.IsInstance(topology, "Vertex") or Topology.IsInstance(topology, "Edge"): #Vertex or Edge or Cluster, return the original topology
|
@@ -6776,7 +6835,7 @@ class Topology():
|
|
6776
6835
|
topologies += Cluster.FreeEdges(topology)
|
6777
6836
|
faces = Topology.Faces(topology)
|
6778
6837
|
for face in faces:
|
6779
|
-
topologies.append(Face.RemoveCollinearEdges(
|
6838
|
+
topologies.append(Face.RemoveCollinearEdges(face, angTolerance=angTolerance, tolerance=tolerance))
|
6780
6839
|
return_topology = Topology.SelfMerge(Cluster.ByTopologies(topologies), tolerance=tolerance)
|
6781
6840
|
return return_topology
|
6782
6841
|
|
@@ -7865,14 +7924,14 @@ class Topology():
|
|
7865
7924
|
@staticmethod
|
7866
7925
|
def Show(*topologies,
|
7867
7926
|
opacityKey = "opacity",
|
7868
|
-
showVertices=True, vertexSize=
|
7927
|
+
showVertices=True, vertexSize=None, vertexSizeKey = None, vertexColor="black", vertexColorKey = None,
|
7869
7928
|
vertexLabelKey=None, showVertexLabel= False,
|
7870
7929
|
vertexGroupKey=None, vertexGroups=[],
|
7871
7930
|
vertexMinGroup=None, vertexMaxGroup=None,
|
7872
7931
|
showVertexLegend=False, vertexLegendLabel="Topology Vertices", vertexLegendRank=1,
|
7873
7932
|
vertexLegendGroup=1,
|
7874
7933
|
|
7875
|
-
showEdges=True, edgeWidth=
|
7934
|
+
showEdges=True, edgeWidth=None, edgeWidthKey = None, edgeColor="black", edgeColorKey = None,
|
7876
7935
|
edgeLabelKey=None, showEdgeLabel = False,
|
7877
7936
|
edgeGroupKey=None, edgeGroups=[],
|
7878
7937
|
edgeMinGroup=None, edgeMaxGroup=None,
|
@@ -7932,7 +7991,7 @@ class Topology():
|
|
7932
7991
|
The list of vertex groups against which to index the color of the vertex. The default is [].
|
7933
7992
|
vertexMinGroup : int or float , optional
|
7934
7993
|
For numeric vertexGroups, vertexMinGroup is the desired minimum value for the scaling of colors. This should match the type of value associated with the vertexGroupKey. If set to None, it is set to the minimum value in vertexGroups. The default is None.
|
7935
|
-
|
7994
|
+
vertexMaxGroup : int or float , optional
|
7936
7995
|
For numeric vertexGroups, vertexMaxGroup is the desired maximum value for the scaling of colors. This should match the type of value associated with the vertexGroupKey. If set to None, it is set to the maximum value in vertexGroups. The default is None.
|
7937
7996
|
showVertexLegend : bool, optional
|
7938
7997
|
If set to True, the legend for the vertices of this topology is shown. Otherwise, it isn't. The default is False.
|
@@ -8101,23 +8160,70 @@ class Topology():
|
|
8101
8160
|
if not silent:
|
8102
8161
|
print("Topology.Show - Error: the input topologies parameter does not contain any valid topology. Returning None.")
|
8103
8162
|
return None
|
8163
|
+
|
8104
8164
|
if camera[0] == 0 and camera[1] == 0 and up == [0,0,1]:
|
8105
8165
|
up = [0,1,0] #default to positive Y axis being up if looking down or up at the XY plane
|
8106
8166
|
data = []
|
8107
8167
|
for topology in new_topologies:
|
8108
8168
|
if Topology.IsInstance(topology, "Graph"):
|
8109
|
-
|
8169
|
+
if vertexSize == None:
|
8170
|
+
vSize = 6
|
8171
|
+
else:
|
8172
|
+
vSize = vertexSize
|
8173
|
+
if edgeWidth == None:
|
8174
|
+
eWidth = 1
|
8175
|
+
else:
|
8176
|
+
eWidth = edgeWidth
|
8177
|
+
data += Plotly.DataByGraph(topology,
|
8178
|
+
sagitta=sagitta,
|
8179
|
+
absolute=absolute,
|
8180
|
+
sides=sides,
|
8181
|
+
angle=angle,
|
8182
|
+
vertexColor=vertexColor,
|
8183
|
+
vertexColorKey=vertexColorKey,
|
8184
|
+
vertexSize=vSize,
|
8185
|
+
vertexSizeKey=vertexSizeKey,
|
8186
|
+
vertexLabelKey=vertexLabelKey,
|
8187
|
+
vertexGroupKey=vertexGroupKey,
|
8188
|
+
vertexGroups=vertexGroups,
|
8189
|
+
vertexMinGroup=vertexMinGroup,
|
8190
|
+
vertexMaxGroup=vertexMaxGroup,
|
8191
|
+
showVertices=showVertices,
|
8192
|
+
showVertexLabel=showVertexLabel,
|
8193
|
+
showVertexLegend=showVertexLegend,
|
8194
|
+
edgeColor=edgeColor,
|
8195
|
+
edgeColorKey=edgeColorKey,
|
8196
|
+
edgeWidth=eWidth,
|
8197
|
+
edgeWidthKey=edgeWidthKey,
|
8198
|
+
edgeLabelKey=edgeLabelKey,
|
8199
|
+
edgeGroupKey=edgeGroupKey,
|
8200
|
+
edgeGroups=edgeGroups,
|
8201
|
+
edgeMinGroup=edgeMinGroup,
|
8202
|
+
edgeMaxGroup=edgeMaxGroup,
|
8203
|
+
showEdges=showEdges,
|
8204
|
+
showEdgeLabel=showEdgeLabel,
|
8205
|
+
showEdgeLegend=showEdgeLegend,
|
8206
|
+
colorScale=colorScale,
|
8207
|
+
silent=silent)
|
8110
8208
|
else:
|
8209
|
+
if vertexSize == None:
|
8210
|
+
vSize = 1.1
|
8211
|
+
else:
|
8212
|
+
vSize = vertexSize
|
8213
|
+
if edgeWidth == None:
|
8214
|
+
eWidth = 1
|
8215
|
+
else:
|
8216
|
+
eWidth = edgeWidth
|
8111
8217
|
d = Topology.Dictionary(topology)
|
8112
8218
|
if not d == None:
|
8113
8219
|
faceOpacity = Dictionary.ValueAtKey(d, opacityKey) or faceOpacity
|
8114
8220
|
data += Plotly.DataByTopology(topology=topology,
|
8115
|
-
showVertices=showVertices, vertexSize=
|
8221
|
+
showVertices=showVertices, vertexSize=vSize, vertexSizeKey=vertexSizeKey, vertexColor=vertexColor, vertexColorKey=vertexColorKey,
|
8116
8222
|
vertexLabelKey=vertexLabelKey, showVertexLabel=showVertexLabel, vertexGroupKey=vertexGroupKey, vertexGroups=vertexGroups,
|
8117
8223
|
vertexMinGroup=vertexMinGroup, vertexMaxGroup=vertexMaxGroup,
|
8118
8224
|
showVertexLegend=showVertexLegend, vertexLegendLabel=vertexLegendLabel, vertexLegendRank=vertexLegendRank,
|
8119
8225
|
vertexLegendGroup=vertexLegendGroup,
|
8120
|
-
showEdges=showEdges, edgeWidth=
|
8226
|
+
showEdges=showEdges, edgeWidth=eWidth, edgeWidthKey=edgeWidthKey, edgeColor=edgeColor, edgeColorKey=edgeColorKey,
|
8121
8227
|
edgeLabelKey=edgeLabelKey, showEdgeLabel=showEdgeLabel, edgeGroupKey=edgeGroupKey, edgeGroups=edgeGroups,
|
8122
8228
|
edgeMinGroup=edgeMinGroup, edgeMaxGroup=edgeMaxGroup,
|
8123
8229
|
showEdgeLegend=showEdgeLegend, edgeLegendLabel=edgeLegendLabel, edgeLegendRank=edgeLegendRank,
|
@@ -8172,7 +8278,7 @@ class Topology():
|
|
8172
8278
|
found = False
|
8173
8279
|
for j in range(len(topologies)):
|
8174
8280
|
if usedTopologies[j] == 0:
|
8175
|
-
if Vertex.IsInternal( selectors[i], topologies[j], tolerance):
|
8281
|
+
if Vertex.IsInternal( selectors[i], topologies[j], tolerance=tolerance):
|
8176
8282
|
sortedTopologies.append(topologies[j])
|
8177
8283
|
if exclusive == True:
|
8178
8284
|
usedTopologies[j] = 1
|
@@ -8309,7 +8415,7 @@ class Topology():
|
|
8309
8415
|
returnTopology = Cell.ByShell(returnTopology)
|
8310
8416
|
except:
|
8311
8417
|
try:
|
8312
|
-
returnTopology = CellComplex.ByWires(topologies, tolerance)
|
8418
|
+
returnTopology = CellComplex.ByWires(topologies, tolerance=tolerance)
|
8313
8419
|
try:
|
8314
8420
|
returnTopology = CellComplex.ExternalBoundary(returnTopology)
|
8315
8421
|
except:
|
@@ -8336,7 +8442,7 @@ class Topology():
|
|
8336
8442
|
for t in topologies:
|
8337
8443
|
external_wires.append(topologic.Face.ExternalBoundary(t))
|
8338
8444
|
try:
|
8339
|
-
returnTopology = CellComplex.ByWires(external_wires, tolerance)
|
8445
|
+
returnTopology = CellComplex.ByWires(external_wires, tolerance=tolerance)
|
8340
8446
|
except:
|
8341
8447
|
try:
|
8342
8448
|
returnTopology = Shell.ByWires(external_wires, triangulate=triangulate, tolerance=tolerance, silent=True)
|
@@ -8846,7 +8952,7 @@ class Topology():
|
|
8846
8952
|
mergingProcess = MergingProcess(queue, sources_str, sink_items, so_dicts)
|
8847
8953
|
mergingProcess.start()
|
8848
8954
|
|
8849
|
-
workerProcessPool = WorkerProcessPool(numWorkers, queue, sources_str, sink_items, so_dicts, tolerance)
|
8955
|
+
workerProcessPool = WorkerProcessPool(numWorkers, queue, sources_str, sink_items, so_dicts, tolerance=tolerance)
|
8850
8956
|
workerProcessPool.startProcesses()
|
8851
8957
|
workerProcessPool.join()
|
8852
8958
|
|
@@ -9045,7 +9151,7 @@ class Topology():
|
|
9045
9151
|
r_shells = Topology.Shells(return_topology)
|
9046
9152
|
r_cells = Topology.Cells(return_topology)
|
9047
9153
|
r_cellComplexes = Topology.CellComplexes(return_topology)
|
9048
|
-
|
9154
|
+
|
9049
9155
|
for i, t in enumerate(r_vertices):
|
9050
9156
|
t = Topology.SetDictionary(t, Topology.Dictionary(vertices[i]), silent=True)
|
9051
9157
|
for i, t in enumerate(r_edges):
|
topologicpy/Vertex.py
CHANGED
@@ -771,7 +771,7 @@ class Vertex():
|
|
771
771
|
from topologicpy.Topology import Topology
|
772
772
|
import numpy as np
|
773
773
|
|
774
|
-
def fuse_vertices(vertices, tolerance):
|
774
|
+
def fuse_vertices(vertices, tolerance=0.0001):
|
775
775
|
fused_vertices = []
|
776
776
|
merged_indices = {}
|
777
777
|
|
@@ -818,7 +818,7 @@ class Vertex():
|
|
818
818
|
return None
|
819
819
|
|
820
820
|
vertices = [(Vertex.X(v, mantissa=mantissa), Vertex.Y(v, mantissa=mantissa), Vertex.Z(v, mantissa=mantissa)) for v in vertices]
|
821
|
-
fused_vertices = fuse_vertices(vertices, tolerance)
|
821
|
+
fused_vertices = fuse_vertices(vertices, tolerance=tolerance)
|
822
822
|
return_vertices = [Vertex.ByCoordinates(list(coord)) for coord in fused_vertices]
|
823
823
|
return return_vertices
|
824
824
|
|
@@ -1110,13 +1110,18 @@ class Vertex():
|
|
1110
1110
|
import inspect
|
1111
1111
|
|
1112
1112
|
if not Topology.IsInstance(vertex, "Vertex"):
|
1113
|
-
print("Called from:", inspect.stack()[1][3])
|
1114
1113
|
if not silent:
|
1115
1114
|
print("Vertex.IsInternal - Error: The input vertex parameter is not a valid vertex. Returning None.", vertex, topology)
|
1115
|
+
curframe = inspect.currentframe()
|
1116
|
+
calframe = inspect.getouterframes(curframe, 2)
|
1117
|
+
print('caller name:', calframe[1][3])
|
1116
1118
|
return None
|
1117
1119
|
if not Topology.IsInstance(topology, "Topology"):
|
1118
1120
|
if not silent:
|
1119
1121
|
print("Vertex.IsInternal - Error: The input topology parameter is not a valid topology. Returning None.")
|
1122
|
+
curframe = inspect.currentframe()
|
1123
|
+
calframe = inspect.getouterframes(curframe, 2)
|
1124
|
+
print('caller name:', calframe[1][3])
|
1120
1125
|
return None
|
1121
1126
|
|
1122
1127
|
if Topology.IsInstance(topology, "Vertex"):
|
topologicpy/Wire.py
CHANGED
@@ -1445,7 +1445,7 @@ class Wire():
|
|
1445
1445
|
from topologicpy.Edge import Edge
|
1446
1446
|
from topologicpy.Topology import Topology
|
1447
1447
|
|
1448
|
-
def vIndex(v, vList, tolerance):
|
1448
|
+
def vIndex(v, vList, tolerance=0.0001):
|
1449
1449
|
for i in range(len(vList)):
|
1450
1450
|
if Vertex.Distance(v, vList[i]) < tolerance:
|
1451
1451
|
return i+1
|
@@ -1512,7 +1512,7 @@ class Wire():
|
|
1512
1512
|
|
1513
1513
|
graph = []
|
1514
1514
|
for anEdge in tEdges:
|
1515
|
-
graph.append([vIndex(anEdge.StartVertex(), tVertices, tolerance), vIndex(anEdge.EndVertex(), tVertices, tolerance)])
|
1515
|
+
graph.append([vIndex(anEdge.StartVertex(), tVertices, tolerance), vIndex(anEdge.EndVertex(), tVertices, tolerance)]) # Hook to Core
|
1516
1516
|
|
1517
1517
|
cycles = []
|
1518
1518
|
resultingCycles = main(graph, cycles, maxVertices)
|
@@ -2331,7 +2331,7 @@ class Wire():
|
|
2331
2331
|
j += k
|
2332
2332
|
return False
|
2333
2333
|
|
2334
|
-
def angleBetweenEdges(e1, e2, tolerance):
|
2334
|
+
def angleBetweenEdges(e1, e2, tolerance=0.0001):
|
2335
2335
|
a = e1.EndVertex().X() - e1.StartVertex().X()
|
2336
2336
|
b = e1.EndVertex().Y() - e1.StartVertex().Y()
|
2337
2337
|
c = e1.EndVertex().Z() - e1.StartVertex().Z()
|
@@ -2350,16 +2350,16 @@ class Wire():
|
|
2350
2350
|
angleInDegrees = math.degrees(math.acos(angle))
|
2351
2351
|
return angleInDegrees
|
2352
2352
|
|
2353
|
-
def getInteriorAngles(edges, tolerance):
|
2353
|
+
def getInteriorAngles(edges, tolerance=0.0001):
|
2354
2354
|
angles = []
|
2355
2355
|
for i in range(len(edges)-1):
|
2356
2356
|
e1 = edges[i]
|
2357
2357
|
e2 = edges[i+1]
|
2358
|
-
angles.append(angleBetweenEdges(e1, e2, tolerance))
|
2358
|
+
angles.append(angleBetweenEdges(e1, e2, tolerance=tolerance))
|
2359
2359
|
return angles
|
2360
2360
|
|
2361
|
-
def getRep(edges, tolerance):
|
2362
|
-
angles = getInteriorAngles(edges, tolerance)
|
2361
|
+
def getRep(edges, tolerance=0.0001):
|
2362
|
+
angles = getInteriorAngles(edges, tolerance=tolerance)
|
2363
2363
|
lengths = []
|
2364
2364
|
for anEdge in edges:
|
2365
2365
|
lengths.append(Edge.Length(anEdge))
|
@@ -2379,8 +2379,8 @@ class Wire():
|
|
2379
2379
|
_ = wireB.Edges(None, edgesB)
|
2380
2380
|
if len(edgesA) != len(edgesB):
|
2381
2381
|
return False
|
2382
|
-
repA = getRep(list(edgesA), tolerance)
|
2383
|
-
repB = getRep(list(edgesB), tolerance)
|
2382
|
+
repA = getRep(list(edgesA), tolerance=tolerance)
|
2383
|
+
repB = getRep(list(edgesB), tolerance=tolerance)
|
2384
2384
|
if isCyclicallyEquivalent(repA, repB, tolerance, angTolerance):
|
2385
2385
|
return True
|
2386
2386
|
if isCyclicallyEquivalent(repA, repB[::-1], tolerance, angTolerance):
|
@@ -2966,12 +2966,107 @@ class Wire():
|
|
2966
2966
|
if direction != [0, 0, 1]:
|
2967
2967
|
baseWire = Topology.Orient(baseWire, origin=origin, dirA=[0, 0, 1], dirB=direction)
|
2968
2968
|
return baseWire
|
2969
|
-
|
2969
|
+
|
2970
|
+
|
2970
2971
|
@staticmethod
|
2971
2972
|
def RemoveCollinearEdges(wire, angTolerance: float = 0.1, tolerance: float = 0.0001, silent: bool = False):
|
2972
2973
|
"""
|
2973
2974
|
Removes any collinear edges in the input wire.
|
2974
2975
|
|
2976
|
+
Parameters
|
2977
|
+
----------
|
2978
|
+
wire : topologic_core.Wire
|
2979
|
+
The input wire.
|
2980
|
+
angTolerance : float, optional
|
2981
|
+
The desired angular tolerance. The default is 0.1.
|
2982
|
+
tolerance : float, optional
|
2983
|
+
The desired tolerance. The default is 0.0001.
|
2984
|
+
silent : bool, optional
|
2985
|
+
If set to True, no error and warning messages are printed. Otherwise, they are. The default is False.
|
2986
|
+
|
2987
|
+
Returns
|
2988
|
+
-------
|
2989
|
+
topologic_core.Wire
|
2990
|
+
The wire without collinear edges, or the original wire if no modifications were necessary.
|
2991
|
+
"""
|
2992
|
+
from topologicpy.Vertex import Vertex
|
2993
|
+
from topologicpy.Edge import Edge
|
2994
|
+
from topologicpy.Wire import Wire
|
2995
|
+
from topologicpy.Cluster import Cluster
|
2996
|
+
from topologicpy.Topology import Topology
|
2997
|
+
|
2998
|
+
def cleanup(wire):
|
2999
|
+
"""Fuses vertices and removes edges below the tolerance distance."""
|
3000
|
+
vertices = Vertex.Fuse(Topology.Vertices(wire), tolerance=tolerance)
|
3001
|
+
edges = Topology.Edges(wire)
|
3002
|
+
new_edges = []
|
3003
|
+
|
3004
|
+
for edge in edges:
|
3005
|
+
sv = vertices[Vertex.Index(Edge.StartVertex(edge), vertices, tolerance=tolerance)]
|
3006
|
+
ev = vertices[Vertex.Index(Edge.EndVertex(edge), vertices, tolerance=tolerance)]
|
3007
|
+
if Vertex.Distance(sv, ev) > tolerance:
|
3008
|
+
new_edges.append(Edge.ByVertices([sv, ev]))
|
3009
|
+
|
3010
|
+
return Topology.SelfMerge(Cluster.ByTopologies(new_edges, silent=silent), tolerance=tolerance) if new_edges else wire
|
3011
|
+
|
3012
|
+
def remove_collinear_vertices(wire):
|
3013
|
+
"""Removes collinear vertices from a wire."""
|
3014
|
+
if not Topology.IsInstance(wire, "Wire"):
|
3015
|
+
return wire
|
3016
|
+
|
3017
|
+
vertices = Topology.Vertices(wire)
|
3018
|
+
filtered_vertices = []
|
3019
|
+
|
3020
|
+
for i, vertex in enumerate(vertices):
|
3021
|
+
edges = Topology.SuperTopologies(topology=vertex, hostTopology=wire, topologyType="edge")
|
3022
|
+
|
3023
|
+
if len(edges) != 2:
|
3024
|
+
filtered_vertices.append(vertex)
|
3025
|
+
elif not Edge.IsCollinear(edges[0], edges[1], tolerance=tolerance):
|
3026
|
+
filtered_vertices.append(vertex)
|
3027
|
+
|
3028
|
+
if len(filtered_vertices) > 2:
|
3029
|
+
return Wire.ByVertices(filtered_vertices, close=wire.IsClosed())
|
3030
|
+
elif len(filtered_vertices) == 2:
|
3031
|
+
return Edge.ByStartVertexEndVertex(filtered_vertices[0], filtered_vertices[1], tolerance=tolerance, silent=True)
|
3032
|
+
else:
|
3033
|
+
return wire
|
3034
|
+
|
3035
|
+
# Main function logic
|
3036
|
+
if Topology.IsInstance(wire, "Cluster"):
|
3037
|
+
wires = Topology.Wires(wire)
|
3038
|
+
processed_wires = [Wire.RemoveCollinearEdges(w, angTolerance, tolerance, silent) for w in wires]
|
3039
|
+
if len(processed_wires) == 0:
|
3040
|
+
if not silent:
|
3041
|
+
print("Wire.RemoveCollinearEdges - Error: No wires were produced. Returning None.")
|
3042
|
+
return None
|
3043
|
+
elif len(processed_wires) == 1:
|
3044
|
+
return Topology.SelfMerge(processed_wires[0])
|
3045
|
+
else:
|
3046
|
+
return Topology.SelfMerge(Cluster.ByTopologies(processed_wires, silent=silent))
|
3047
|
+
|
3048
|
+
if not Topology.IsInstance(wire, "Wire"):
|
3049
|
+
if not silent:
|
3050
|
+
print(f"Wire.RemoveCollinearEdges - Error: Input is not a valid wire. Returning None.")
|
3051
|
+
return None
|
3052
|
+
|
3053
|
+
new_wire = cleanup(wire)
|
3054
|
+
wires = Wire.Split(new_wire) if not Wire.IsManifold(new_wire) else [new_wire]
|
3055
|
+
|
3056
|
+
processed_wires = [remove_collinear_vertices(w) for w in wires]
|
3057
|
+
|
3058
|
+
if len(processed_wires) == 0:
|
3059
|
+
return wire
|
3060
|
+
elif len(processed_wires) == 1:
|
3061
|
+
return Topology.SelfMerge(processed_wires[0])
|
3062
|
+
else:
|
3063
|
+
return Topology.SelfMerge(Cluster.ByTopologies(processed_wires, silent=silent))
|
3064
|
+
|
3065
|
+
@staticmethod
|
3066
|
+
def RemoveCollinearEdges_old(wire, angTolerance: float = 0.1, tolerance: float = 0.0001, silent: bool = False):
|
3067
|
+
"""
|
3068
|
+
Removes any collinear edges in the input wire.
|
3069
|
+
|
2975
3070
|
Parameters
|
2976
3071
|
----------
|
2977
3072
|
wire : topologic_core.Wire
|
@@ -2996,7 +3091,7 @@ class Wire():
|
|
2996
3091
|
from topologicpy.Topology import Topology
|
2997
3092
|
import inspect
|
2998
3093
|
|
2999
|
-
def cleanup(wire, tolerance):
|
3094
|
+
def cleanup(wire, tolerance=0.0001):
|
3000
3095
|
vertices = Topology.Vertices(wire)
|
3001
3096
|
vertices = Vertex.Fuse(vertices, tolerance=tolerance)
|
3002
3097
|
edges = Topology.Edges(wire)
|
@@ -3051,8 +3146,6 @@ class Wire():
|
|
3051
3146
|
return result
|
3052
3147
|
if not Topology.IsInstance(wire, "Wire"):
|
3053
3148
|
if not silent:
|
3054
|
-
print("The wire is:", wire)
|
3055
|
-
Topology.Show(wire)
|
3056
3149
|
print("Wire.RemoveCollinearEdges - Error: The input wire parameter is not a valid wire. Returning None.")
|
3057
3150
|
curframe = inspect.currentframe()
|
3058
3151
|
calframe = inspect.getouterframes(curframe, 2)
|
@@ -3300,7 +3393,7 @@ class Wire():
|
|
3300
3393
|
|
3301
3394
|
return numerator / denominator
|
3302
3395
|
|
3303
|
-
def douglas_peucker(wire, tolerance):
|
3396
|
+
def douglas_peucker(wire, tolerance=0.0001):
|
3304
3397
|
if isinstance(wire, list):
|
3305
3398
|
points = wire
|
3306
3399
|
else:
|
@@ -3323,12 +3416,12 @@ class Wire():
|
|
3323
3416
|
if max_distance <= tolerance:
|
3324
3417
|
return [start_point, end_point]
|
3325
3418
|
|
3326
|
-
first_segment = douglas_peucker(points[:max_index + 1], tolerance)
|
3327
|
-
second_segment = douglas_peucker(points[max_index:], tolerance)
|
3419
|
+
first_segment = douglas_peucker(points[:max_index + 1], tolerance=tolerance)
|
3420
|
+
second_segment = douglas_peucker(points[max_index:], tolerance=tolerance)
|
3328
3421
|
|
3329
3422
|
return first_segment[:-1] + second_segment
|
3330
3423
|
|
3331
|
-
def visvalingam_whyatt(wire, tolerance):
|
3424
|
+
def visvalingam_whyatt(wire, tolerance=0.0001):
|
3332
3425
|
if isinstance(wire, list):
|
3333
3426
|
points = wire
|
3334
3427
|
else:
|
@@ -3360,7 +3453,7 @@ class Wire():
|
|
3360
3453
|
|
3361
3454
|
return simplified_points
|
3362
3455
|
|
3363
|
-
def reumann_witkam(wire, tolerance):
|
3456
|
+
def reumann_witkam(wire, tolerance=0.0001):
|
3364
3457
|
if isinstance(wire, list):
|
3365
3458
|
points = wire
|
3366
3459
|
else:
|
topologicpy/version.py
CHANGED
@@ -1 +1 @@
|
|
1
|
-
__version__ = '0.7.
|
1
|
+
__version__ = '0.7.85'
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: topologicpy
|
3
|
-
Version: 0.7.
|
3
|
+
Version: 0.7.85
|
4
4
|
Summary: An AI-Powered Spatial Modelling and Analysis Software Library for Architecture, Engineering, and Construction.
|
5
5
|
Author-email: Wassim Jabi <wassim.jabi@gmail.com>
|
6
6
|
License: AGPL v3 License
|