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/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
- shape_geometry = shape.geometry
2517
- verts = shape_geometry.verts
2518
- verts = [ [verts[i], verts[i + 1], verts[i + 2]] for i in range(0, len(verts), 3)]
2519
- edges = shape_geometry.edges
2520
- edges = [[edges[i], edges[i + 1]] for i in range(0, len(edges), 2)]
2521
- faces = shape_geometry.faces
2522
- faces = [ [faces[i], faces[i + 1], faces[i + 2]] for i in range(0, len(faces), 3)]
2523
- # Convert geometry to Topologic format
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 removeCoplanarFaces == True:
2528
- shape_topology = Topology.RemoveCoplanarFaces(shape_topology, epsilon=0.0001)
2529
-
2530
- # Store relevant information
2531
- if transferDictionaries == True:
2532
- color, transparency, material_list = get_color_transparency_material(entity)
2533
- entity_dict = {
2534
- "TOPOLOGIC_id": str(Topology.UUID(shape_topology)),
2535
- "TOPOLOGIC_name": getattr(entity, 'Name', "Untitled"),
2536
- "TOPOLOGIC_type": Topology.TypeAsString(shape_topology),
2537
- "TOPOLOGIC_color": color,
2538
- "TOPOLOGIC_opacity": 1.0 - transparency,
2539
- "IFC_global_id": getattr(entity, 'GlobalId', 0),
2540
- "IFC_name": getattr(entity, 'Name', "Untitled"),
2541
- "IFC_type": entity.is_a(),
2542
- "IFC_material_list": material_list,
2543
- }
2544
- topology_dict = Dictionary.ByPythonDictionary(entity_dict)
2545
- # Get PSETs dictionary
2546
- pset_python_dict = get_psets(entity)
2547
- pset_dict = Dictionary.ByPythonDictionary(pset_python_dict)
2548
- topology_dict = Dictionary.ByMergedDictionaries([topology_dict, pset_dict])
2549
- shape_topology = Topology.SetDictionary(shape_topology, topology_dict)
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 InternalVertex(topology, tolerance: float = 0.0001):
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(topology, angTolerance=angTolerance, tolerance=tolerance))
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=1.1, vertexSizeKey = None, vertexColor="black", vertexColorKey = None,
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=1, edgeWidthKey = None, edgeColor="black", edgeColorKey = None,
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
- edgeMaxGroup : int or float , optional
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
- data += Plotly.DataByGraph(topology, sagitta=sagitta, absolute=absolute, sides=sides, angle=angle, vertexColor=vertexColor, vertexColorKey=vertexColorKey, vertexSize=vertexSize, vertexSizeKey=vertexSizeKey, vertexLabelKey=vertexLabelKey, vertexGroupKey=vertexGroupKey, vertexGroups=vertexGroups, showVertices=showVertices, showVertexLabel=showVertexLabel, showVertexLegend=showVertexLegend, edgeColor=edgeColor, edgeColorKey=edgeColorKey, edgeWidth=edgeWidth, edgeWidthKey=edgeWidthKey, edgeLabelKey=edgeLabelKey, edgeGroupKey=edgeGroupKey, edgeGroups=edgeGroups, showEdges=showEdges, showEdgeLabel=showEdgeLabel, showEdgeLegend=showEdgeLegend, colorScale=colorScale, silent=silent)
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=vertexSize, vertexSizeKey=vertexSizeKey, vertexColor=vertexColor, vertexColorKey=vertexColorKey,
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=edgeWidth, edgeWidthKey=edgeWidthKey, edgeColor=edgeColor, edgeColorKey=edgeColorKey,
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.83'
1
+ __version__ = '0.7.85'
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: topologicpy
3
- Version: 0.7.83
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