topologicpy 0.8.40__py3-none-any.whl → 0.8.42__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 CHANGED
@@ -2762,7 +2762,7 @@ class Cell():
2762
2762
  return prism
2763
2763
 
2764
2764
  @staticmethod
2765
- def RemoveCollinearEdges(cell, angTolerance: float = 0.1, tolerance: float = 0.0001):
2765
+ def RemoveCollinearEdges(cell, angTolerance: float = 0.1, tolerance: float = 0.0001, silent: bool = False):
2766
2766
  """
2767
2767
  Removes any collinear edges in the input cell.
2768
2768
 
@@ -2774,6 +2774,8 @@ class Cell():
2774
2774
  The desired angular tolerance. The default is 0.1.
2775
2775
  tolerance : float , optional
2776
2776
  The desired tolerance. The default is 0.0001.
2777
+ silent : bool , optional
2778
+ If set to True, error and warning messages are suppressed. The default is False.
2777
2779
 
2778
2780
  Returns
2779
2781
  -------
@@ -2786,15 +2788,16 @@ class Cell():
2786
2788
  import inspect
2787
2789
 
2788
2790
  if not Topology.IsInstance(cell, "Cell"):
2789
- print("Cell.RemoveCollinearEdges - Error: The input cell parameter is not a valid cell. Returning None.")
2790
- curframe = inspect.currentframe()
2791
- calframe = inspect.getouterframes(curframe, 2)
2792
- print('caller name:', calframe[1][3])
2791
+ if not silent:
2792
+ print("Cell.RemoveCollinearEdges - Error: The input cell parameter is not a valid cell. Returning None.")
2793
+ curframe = inspect.currentframe()
2794
+ calframe = inspect.getouterframes(curframe, 2)
2795
+ print('caller name:', calframe[1][3])
2793
2796
  return None
2794
2797
  faces = Cell.Faces(cell)
2795
2798
  clean_faces = []
2796
2799
  for face in faces:
2797
- clean_faces.append(Face.RemoveCollinearEdges(face, angTolerance=angTolerance, tolerance=tolerance))
2800
+ clean_faces.append(Face.RemoveCollinearEdges(face, angTolerance=angTolerance, tolerance=tolerance, silent=silent))
2798
2801
  return Cell.ByFaces(clean_faces, tolerance=tolerance)
2799
2802
 
2800
2803
  @staticmethod
@@ -104,7 +104,7 @@ class CellComplex():
104
104
  tolerance : float , optional
105
105
  The desired tolerance. The default is 0.0001.
106
106
  silent : bool , optional
107
- If set to True, error and warning messages are suppressed. The default is False.
107
+ If set to True, error and warning messages are suppressed. The default is False.
108
108
 
109
109
  Returns
110
110
  -------
@@ -990,7 +990,7 @@ class CellComplex():
990
990
  return None
991
991
 
992
992
  @staticmethod
993
- def RemoveCollinearEdges(cellComplex, angTolerance: float = 0.1, tolerance: float = 0.0001):
993
+ def RemoveCollinearEdges(cellComplex, angTolerance: float = 0.1, tolerance: float = 0.0001, silent: bool = True):
994
994
  """
995
995
  Removes any collinear edges in the input cellComplex.
996
996
 
@@ -1002,6 +1002,8 @@ class CellComplex():
1002
1002
  The desired angular tolerance. The default is 0.1.
1003
1003
  tolerance : float , optional
1004
1004
  The desired tolerance. The default is 0.0001.
1005
+ silent : bool , optional
1006
+ If set to True, error and warning messages are suppressed. The default is False.
1005
1007
 
1006
1008
  Returns
1007
1009
  -------
@@ -1023,7 +1025,7 @@ class CellComplex():
1023
1025
  cells = CellComplex.Cells(cellComplex)
1024
1026
  clean_cells = []
1025
1027
  for cell in cells:
1026
- clean_cells.append(Cell.RemoveCollinearEdges(cell, angTolerance=angTolerance, tolerance=tolerance))
1028
+ clean_cells.append(Cell.RemoveCollinearEdges(cell, angTolerance=angTolerance, tolerance=tolerance, silent=silent))
1027
1029
  return CellComplex.ByCells(clean_cells, tolerance=tolerance)
1028
1030
 
1029
1031
  @staticmethod
@@ -1098,6 +1100,8 @@ class CellComplex():
1098
1100
  The desired length of the mantissa. The default is 6.
1099
1101
  tolerance : float , optional
1100
1102
  The desired tolerance. The default is 0.0001.
1103
+ silent : bool , optional
1104
+ If set to True, error and warning messages are suppressed. The default is False.
1101
1105
 
1102
1106
  Returns
1103
1107
  -------
topologicpy/Edge.py CHANGED
@@ -256,31 +256,63 @@ class Edge():
256
256
  @staticmethod
257
257
  def ByOffset2D(edge, offset: float = 1.0, tolerance: float = 0.0001):
258
258
  """
259
- Creates and edge offset from the input edge. This method is intended for edges that are in the XY plane.
260
-
261
- Parameters
262
- ----------
263
- edge : topologic_core.Edge
264
- The input edge.
265
- offset : float , optional
266
- The desired offset. The default is 1.
267
- tolerance : float , optional
268
- The desired tolerance. The default is 0.0001.
269
-
270
- Returns
271
- -------
272
- topologic_core.Edge
273
- An edge offset from the input edge.
274
-
259
+ Creates an edge offset from the input edge in the XY plane.
275
260
  """
276
261
  from topologicpy.Topology import Topology
277
- from topologicpy.Vector import Vector
262
+ from topologicpy.Vertex import Vertex
263
+ from topologicpy.Edge import Edge
278
264
 
279
- n = Edge.Normal(edge)
280
- n = Vector.Normalize(n)
281
- n = Vector.Multiply(n, offset, tolerance=tolerance)
282
- edge = Topology.Translate(edge, n[0], n[1], n[2])
283
- return edge
265
+ sv = Edge.StartVertex(edge)
266
+ ev = Edge.EndVertex(edge)
267
+
268
+ x1, y1, _ = Vertex.Coordinates(sv)
269
+ x2, y2, _ = Vertex.Coordinates(ev)
270
+
271
+ dx = x2 - x1
272
+ dy = y2 - y1
273
+ length = (dx**2 + dy**2)**0.5
274
+ if length < tolerance:
275
+ return None
276
+
277
+ # Perpendicular vector to the left
278
+ nx = -dy / length
279
+ ny = dx / length
280
+
281
+ ox = nx * offset
282
+ oy = ny * offset
283
+
284
+ new_sv = Vertex.ByCoordinates(x1 + ox, y1 + oy, 0)
285
+ new_ev = Vertex.ByCoordinates(x2 + ox, y2 + oy, 0)
286
+
287
+ return Edge.ByVertices(new_sv, new_ev)
288
+ # @staticmethod
289
+ # def ByOffset2D(edge, offset: float = 1.0, tolerance: float = 0.0001):
290
+ # """
291
+ # Creates and edge offset from the input edge. This method is intended for edges that are in the XY plane.
292
+
293
+ # Parameters
294
+ # ----------
295
+ # edge : topologic_core.Edge
296
+ # The input edge.
297
+ # offset : float , optional
298
+ # The desired offset. The default is 1.
299
+ # tolerance : float , optional
300
+ # The desired tolerance. The default is 0.0001.
301
+
302
+ # Returns
303
+ # -------
304
+ # topologic_core.Edge
305
+ # An edge offset from the input edge.
306
+
307
+ # """
308
+ # from topologicpy.Topology import Topology
309
+ # from topologicpy.Vector import Vector
310
+
311
+ # n = Edge.Normal(edge)
312
+ # n = Vector.Normalize(n)
313
+ # n = Vector.Multiply(n, offset, tolerance=tolerance)
314
+ # edge = Topology.Translate(edge, n[0], n[1], n[2])
315
+ # return edge
284
316
 
285
317
  @staticmethod
286
318
  def ByStartVertexEndVertex(vertexA, vertexB, tolerance: float = 0.0001, silent=False):
topologicpy/Face.py CHANGED
@@ -827,7 +827,7 @@ class Face():
827
827
  return Face.ByVertices(vertices, tolerance=tolerance)
828
828
 
829
829
  @staticmethod
830
- def ByWire(wire, tolerance: float = 0.0001, silent=False):
830
+ def ByWire(wire, tolerance: float = 0.0001, silent: bool = False):
831
831
  """
832
832
  Creates a face from the input closed wire.
833
833
 
@@ -942,14 +942,21 @@ class Face():
942
942
  """
943
943
  from topologicpy.Wire import Wire
944
944
  from topologicpy.Topology import Topology
945
+ import inspect
945
946
 
946
947
  if not Topology.IsInstance(externalBoundary, "Wire"):
947
948
  if not silent:
948
949
  print("Face.ByWires - Error: The input externalBoundary parameter is not a valid topologic wire. Returning None.")
950
+ curframe = inspect.currentframe()
951
+ calframe = inspect.getouterframes(curframe, 2)
952
+ print('caller name:', calframe[1][3])
949
953
  return None
950
954
  if not Wire.IsClosed(externalBoundary):
951
955
  if not silent:
952
956
  print("Face.ByWires - Error: The input externalBoundary parameter is not a closed topologic wire. Returning None.")
957
+ curframe = inspect.currentframe()
958
+ calframe = inspect.getouterframes(curframe, 2)
959
+ print('caller name:', calframe[1][3])
953
960
  return None
954
961
  ibList = [x for x in internalBoundaries if Topology.IsInstance(x, "Wire") and Wire.IsClosed(x)]
955
962
  face = None
@@ -958,6 +965,9 @@ class Face():
958
965
  except:
959
966
  if not silent:
960
967
  print("Face.ByWires - Error: The operation failed. Returning None.")
968
+ curframe = inspect.currentframe()
969
+ calframe = inspect.getouterframes(curframe, 2)
970
+ print('caller name:', calframe[1][3])
961
971
  face = None
962
972
  return face
963
973
 
@@ -3404,7 +3414,7 @@ class Face():
3404
3414
  return None
3405
3415
  eb = Wire.RemoveCollinearEdges(Face.Wire(face), angTolerance=angTolerance, tolerance=tolerance, silent=silent)
3406
3416
  ib = [Wire.RemoveCollinearEdges(w, angTolerance=angTolerance, tolerance=tolerance, silent=silent) for w in Face.InternalBoundaries(face)]
3407
- return Face.ByWires(eb, ib)
3417
+ return Face.ByWires(eb, ib, silent=silent)
3408
3418
 
3409
3419
  @staticmethod
3410
3420
  def RHS(origin= None, width: float = 1.0, length: float = 1.0, thickness: float = 0.25, outerFillet: float = 0.0, innerFillet: float = 0.0, sides: int = 16, direction: list = [0, 0, 1], placement: str = "center", tolerance: float = 0.0001, silent: bool = False):
@@ -3602,35 +3612,51 @@ class Face():
3602
3612
  return Face.RHS(origin = origin, width = size, length = size, thickness = thickness, outerFillet = outerFillet, innerFillet = innerFillet, sides = sides, direction = direction, placement = placement, tolerance = tolerance, silent = silent)
3603
3613
 
3604
3614
  @staticmethod
3605
- def Simplify(face, tolerance=0.0001):
3615
+ def Simplify(face, method='douglas-peucker', tolerance=0.0001, silent=False):
3606
3616
  """
3607
- Simplifies the input face edges based on the Douglas Peucker algorthim. See https://en.wikipedia.org/wiki/Ramer%E2%80%93Douglas%E2%80%93Peucker_algorithm
3608
- Part of this code was contributed by gaoxipeng. See https://github.com/wassimj/topologicpy/issues/35
3617
+ Simplifies the input wire edges based on the selected algorithm: Douglas-Peucker or Visvalingam–Whyatt.
3609
3618
 
3610
3619
  Parameters
3611
3620
  ----------
3612
3621
  face : topologic_core.Face
3613
3622
  The input face.
3623
+ method : str, optional
3624
+ The simplification method to use: 'douglas-peucker' or 'visvalingam-whyatt' or 'reumann-witkam'.
3625
+ The default is 'douglas-peucker'.
3614
3626
  tolerance : float , optional
3615
- The desired tolerance. The default is 0.0001. Edges shorter than this length will be removed.
3616
-
3627
+ The desired tolerance.
3628
+ If using the douglas-peucker method, edge lengths shorter than this amount will be removed.
3629
+ If using the visvalingam-whyatt method, triangulare areas less than is amount will be removed.
3630
+ If using the Reumann-Witkam method, the tolerance specifies the maximum perpendicular distance allowed
3631
+ between any point and the current line segment; points falling within this distance are discarded.
3632
+ The default is 0.0001.
3633
+ silent : bool , optional
3634
+ If set to True, error and warning messages are suppressed. The default is False.
3635
+
3617
3636
  Returns
3618
3637
  -------
3619
3638
  topologic_core.Face
3620
3639
  The simplified face.
3640
+
3621
3641
  """
3622
3642
  from topologicpy.Wire import Wire
3623
3643
  from topologicpy.Topology import Topology
3624
3644
 
3625
3645
  if not Topology.IsInstance(face, "Face"):
3626
- print("Face.Simplify - Error: The input face parameter is not a valid face. Returning None.")
3646
+ if not silent:
3647
+ print("Face.Simplify - Error: The input face parameter is not a valid face. Returning None.")
3627
3648
  return None
3628
3649
 
3629
3650
  eb = Face.ExternalBoundary(face)
3630
- eb = Wire.Simplify(eb, tolerance=tolerance)
3651
+ eb = Wire.Simplify(eb, method=method, tolerance=tolerance, silent=silent)
3631
3652
  ibList = Face.InternalBoundaries(face)
3632
- ibList = [Wire.Simplify(ib) for ib in ibList]
3633
- return Face.ByWires(eb, ibList)
3653
+ ibList = [Wire.Simplify(ib, method=method, tolerance=tolerance, silent=silent) for ib in ibList]
3654
+ return_face = Face.ByWires(eb, ibList, tolerance=tolerance, silent=silent)
3655
+ if not Topology.IsInstance(return_face, "Face"):
3656
+ if not silent:
3657
+ print("Face.Simplify - Error: Could not simplify the face. Returning the original input face.")
3658
+ return face
3659
+ return return_face
3634
3660
 
3635
3661
  @staticmethod
3636
3662
  def Skeleton(face, boundary: bool = True, tolerance: float = 0.001):
topologicpy/Graph.py CHANGED
@@ -7751,6 +7751,34 @@ class Graph:
7751
7751
  edge = Topology.SetDictionary(edge, d)
7752
7752
  return graph
7753
7753
 
7754
+ @staticmethod
7755
+ def IsEmpty(graph, silent: bool = False):
7756
+ """
7757
+ Tests if the input graph is empty (Has no vertices).
7758
+
7759
+ Parameters
7760
+ ----------
7761
+ graph : topologic_core.Graph
7762
+ The input graph.
7763
+ silent : bool , optional
7764
+ If set to True, error and warning messages are suppressed. The default is False.
7765
+
7766
+ Returns
7767
+ -------
7768
+ bool
7769
+ True if the two input graphs are isomorphic. False otherwise
7770
+
7771
+ """
7772
+
7773
+ from topologicpy.Topology import Topology
7774
+
7775
+ if not Topology.IsInstance(graph, "Graph"):
7776
+ if not silent:
7777
+ print("Graph.IsEmpty - Error: The input graph parameter is not a valid graph. Returning None.")
7778
+ return None
7779
+
7780
+ return (len(Graph.Vertices(graph)) == 0)
7781
+
7754
7782
  @staticmethod
7755
7783
  def IsIsomorphic(graphA, graphB, maxIterations=10, silent=False):
7756
7784
  """
@@ -9192,6 +9220,142 @@ class Graph:
9192
9220
  return None
9193
9221
  return graph.GetGUID()
9194
9222
 
9223
+ @staticmethod
9224
+ def HasseDiagram(topology, types=["vertex", "edge", "wire", "face", "shell", "cell", "cellComplex"], topDown: bool = False, minDistance: float=0.1, vertexLabelKey: str="label", vertexTypeKey: str="type", vertexColorKey: str="color", colorScale: str="viridis", storeBREP: bool = False, tolerance: float=0.0001, silent: bool=False):
9225
+ """
9226
+ Constructs a Hasse diagram from the input topology as a directed graph. See: https://en.wikipedia.org/wiki/Hasse_diagram
9227
+ Vertices represent topologies (vertices, edges, wires, faces, shells, cells, cellComplexes).
9228
+ Edges represent inclusion (e.g. vertex ⊂ edge, edge ⊂ wire).
9229
+
9230
+ Parameters
9231
+ ----------
9232
+ topology : topologic_core.Topology
9233
+ The input topology
9234
+ types : optional, list
9235
+ The list of topology types that you wish to encode in the Hasse diagram.
9236
+ This list must be ordered according to topologic_core's class hierarchy.
9237
+ If you are not interested in representing some topology types. These can be omitted.
9238
+ The default is:
9239
+ ["vertex", "edge", "wire", "face", "shell", "cell", "cellComplex"].
9240
+ topDown : bool , optional
9241
+ If set to True, the graph edges are directed from topologies to their subtopologies.
9242
+ Otherwise, they are directed from topologies to their supertopologies. The default is False.
9243
+ minDistance : float , optional
9244
+ The desired minimum distance between the vertices of the graph. The default is 0.1.
9245
+ vertexLabelKey: str , optional
9246
+ The desired vertex dictionary key under which to store a unique label (of the form Type_Index). The default is "label".
9247
+ vertexTypeKey: str , optional
9248
+ The desired vertex dictionary key under which to store the topology type (e.g. "vertex", "edge", "wire"). The default is "type".
9249
+ vertexColorKey: str , optional
9250
+ The desired vertex dictionary key under which to store the topology color. The default is "color".
9251
+ colorScale : str , optional
9252
+ The desired type of plotly color scales to use (e.g. "viridis", "plasma"). The default is "viridis". For a full list of names, see https://plotly.com/python/builtin-colorscales/.
9253
+ In addition to these, three color-blind friendly scales are included. These are "protanopia", "deuteranopia", and "tritanopia" for red, green, and blue colorblindness respectively.
9254
+ storeBREP : bool , optional
9255
+ If set to True, store the BRep of the topology in its representative vertex. The default is False.
9256
+ tolerance : float
9257
+ The desired tolerance. The default is 0.0001.
9258
+ silent : bool , optional
9259
+ If set to True, error and warning messages are suppressed. The default is False.
9260
+
9261
+ Returns
9262
+ -------
9263
+ topologic_core.Graph
9264
+ The created Hesse diagram graph.
9265
+
9266
+ """
9267
+ from topologicpy.Vertex import Vertex
9268
+ from topologicpy.Edge import Edge
9269
+ from topologicpy.Dictionary import Dictionary
9270
+ from topologicpy.Color import Color
9271
+ from topologicpy.Topology import Topology
9272
+
9273
+ def label(topo, index):
9274
+ cls = Topology.TypeAsString(topo)
9275
+ return f"{cls}_{index}"
9276
+
9277
+ def collect_topologies(topology, topo_types):
9278
+ """
9279
+ Returns a dict of all sub-topologies by dimension.
9280
+ """
9281
+ topo_by_type = {}
9282
+ for sub_type in topo_types:
9283
+ topo_by_type[sub_type] = Topology.SubTopologies(topology, subTopologyType=sub_type)
9284
+ return topo_by_type
9285
+
9286
+ if not Topology.IsInstance(topology, "topology"):
9287
+ if not silent:
9288
+ print("Graph.HasseDiagram - Error: The input topology parameter is not a valid topology. Returning None.")
9289
+ return None
9290
+ if minDistance <= tolerance:
9291
+ if not silent:
9292
+ print("Graph.HasseDiagram - Error: The input minDistance parameter cannot be less than the input tolerance parameter. Returning None.")
9293
+ return None
9294
+ types = [t.lower() for t in types]
9295
+ for type in types:
9296
+ if type not in ["vertex", "edge", "wire", "face", "shell", "cell", "cellcomplex"]:
9297
+ if not silent:
9298
+ print("Graph.HasseDiagram - Error: Unknown type found in the types input parameter. Returning None.")
9299
+ return None
9300
+
9301
+ topology_type = Topology.TypeAsString(topology).lower()
9302
+ try:
9303
+ sub_types = types[:types.index(topology_type)]
9304
+ except:
9305
+ sub_types = types
9306
+ topo_by_type = collect_topologies(topology, sub_types)
9307
+ all_topos = []
9308
+ topo_ids = {}
9309
+ index = 0
9310
+
9311
+ # Flatten and assign unique labels
9312
+ for sub_type in sub_types:
9313
+ color = Color.AnyToHex(Color.ByValueInRange(float(types.index(sub_type)), minValue=0, maxValue=6, colorScale=colorScale))
9314
+ lbl_index = 1
9315
+ for t in topo_by_type[sub_type]:
9316
+ lbl = label(t, lbl_index)
9317
+ d = Topology.Dictionary(t)
9318
+ d = Dictionary.SetValuesAtKeys(d, [vertexLabelKey, vertexTypeKey, vertexColorKey], [lbl, sub_type, color])
9319
+ t = Topology.SetDictionary(t, d)
9320
+ all_topos.append(t)
9321
+ topo_ids[lbl] = index
9322
+ index += 1
9323
+ lbl_index += 1
9324
+
9325
+ # Create graph vertices
9326
+ graph_vertices = [Topology.Centroid(_) for _ in all_topos]
9327
+
9328
+ # Add dictionaries to each vertex
9329
+ for i, t in enumerate(all_topos):
9330
+ d = Topology.Dictionary(t)
9331
+ if storeBREP == True:
9332
+ d = Dictionary.SetValueAtKey(d,"brep", Topology.BREPString(t))
9333
+ graph_vertices[i] = Topology.SetDictionary(graph_vertices[i], d)
9334
+
9335
+ graph_vertices = Vertex.Separate(graph_vertices, minDistance= minDistance, tolerance=tolerance)
9336
+ # Build edges of Hasse diagram
9337
+ graph_edges = []
9338
+ for parent_type in sub_types[1:]:
9339
+ for parent in topo_by_type[parent_type]:
9340
+ parent_label = Dictionary.ValueAtKey(Topology.Dictionary(parent), vertexLabelKey)
9341
+ children = Topology.SubTopologies(parent, subTopologyType=types[types.index(parent_type) - 1])
9342
+ for child in children:
9343
+ child_label = Dictionary.ValueAtKey(Topology.Dictionary(child), vertexLabelKey)
9344
+ child_id = topo_ids.get(child_label)
9345
+ parent_id = topo_ids.get(parent_label)
9346
+ if child_id is not None and parent_id is not None:
9347
+ if topDown:
9348
+ sv = graph_vertices[parent_id]
9349
+ ev = graph_vertices[child_id]
9350
+ else:
9351
+ sv = graph_vertices[child_id]
9352
+ ev = graph_vertices[parent_id]
9353
+ graph_edges.append(Edge.ByVertices(sv, ev, tolerance=tolerance, silent=silent))
9354
+
9355
+ return_graph = Graph.ByVerticesEdges(graph_vertices, graph_edges)
9356
+ return_graph = Graph.SetDictionary(return_graph, Topology.Dictionary(topology))
9357
+ return return_graph
9358
+
9195
9359
  @staticmethod
9196
9360
  def IncomingEdges(graph, vertex, directed: bool = False, tolerance: float = 0.0001) -> list:
9197
9361
  """
topologicpy/Plotly.py CHANGED
@@ -277,6 +277,9 @@ class Plotly:
277
277
  absolute: bool = False,
278
278
  sides: int = 8,
279
279
  angle: float = 0,
280
+ directed: bool = False,
281
+ arrowSize: int = 0.1,
282
+ arrowSizeKey: str = None,
280
283
  vertexColor: str = "black",
281
284
  vertexColorKey: str = None,
282
285
  vertexSize: float = 10,
@@ -330,6 +333,12 @@ class Plotly:
330
333
  For example, if the length of the edge is 10, the sagitta is set to 0.5, and absolute is set to False, the sagitta length will be 5. The default is True.
331
334
  sides : int , optional
332
335
  The number of sides of the arc. The default is 8.
336
+ directed : bool , optional
337
+ If set to True, arrowheads are drawn to show direction. The default is False.
338
+ arrowSize : int, optional
339
+ The desired size of arrowheads for directed graphs. The default is 0.1.
340
+ arrowSizeKey: str , optional
341
+ The edge dictionary key under which to find the arrowhead size. The default is None.
333
342
  vertexColor : str , optional
334
343
  The desired color of the output vertices. This can be any plotly color string and may be specified as:
335
344
  - A hex string (e.g. '#ff0000')
@@ -479,7 +488,7 @@ class Plotly:
479
488
  geo = Topology.Geometry(e_cluster, mantissa=mantissa)
480
489
  vertices = geo['vertices']
481
490
  edges = geo['edges']
482
- data.extend(Plotly.edgeData(vertices, edges, dictionaries=e_dictionaries, color=edgeColor, colorKey=edgeColorKey, width=edgeWidth, widthKey=edgeWidthKey, dash=edgeDash, dashKey=edgeDashKey, labelKey=edgeLabelKey, showEdgeLabel=showEdgeLabel, groupKey=edgeGroupKey, minGroup=edgeMinGroup, maxGroup=edgeMaxGroup, groups=edgeGroups, legendLabel=edgeLegendLabel, legendGroup=edgeLegendGroup, legendRank=edgeLegendRank, showLegend=showEdgeLegend, colorScale=colorScale))
491
+ data.extend(Plotly.edgeData(vertices, edges, dictionaries=e_dictionaries, color=edgeColor, colorKey=edgeColorKey, width=edgeWidth, widthKey=edgeWidthKey, dash=edgeDash, dashKey=edgeDashKey, directed=directed, arrowSize=arrowSize, arrowSizeKey=arrowSizeKey, labelKey=edgeLabelKey, showEdgeLabel=showEdgeLabel, groupKey=edgeGroupKey, minGroup=edgeMinGroup, maxGroup=edgeMaxGroup, groups=edgeGroups, legendLabel=edgeLegendLabel, legendGroup=edgeLegendGroup, legendRank=edgeLegendRank, showLegend=showEdgeLegend, colorScale=colorScale))
483
492
  return data
484
493
 
485
494
  @staticmethod
@@ -638,11 +647,60 @@ class Plotly:
638
647
  return return_value
639
648
 
640
649
  @staticmethod
641
- def edgeData(vertices, edges, dictionaries=None, color="black", colorKey=None, width=1, widthKey=None, dash=False, dashKey=None, labelKey=None, showEdgeLabel = False, groupKey=None, minGroup=None, maxGroup=None, groups=[], legendLabel="Topology Edges", legendGroup=2, legendRank=2, showLegend=True, colorScale="Viridis"):
650
+ def edgeData(vertices, edges, dictionaries=None, color="black", colorKey=None, width=1, widthKey=None, dash=False, dashKey=None, directed=False, arrowSize=0.1, arrowSizeKey=None, labelKey=None, showEdgeLabel = False, groupKey=None, minGroup=None, maxGroup=None, groups=[], legendLabel="Topology Edges", legendGroup=2, legendRank=2, showLegend=True, colorScale="Viridis"):
642
651
 
643
652
  from topologicpy.Color import Color
644
653
  from topologicpy.Dictionary import Dictionary
645
654
  from topologicpy.Helper import Helper
655
+
656
+ def create_arrowheads(x, y, z, arrowSize=4):
657
+ import plotly.graph_objects as go
658
+ import numpy as np
659
+
660
+ arrow_traces = []
661
+
662
+ # Compute segment directions
663
+ cone_x, cone_y, cone_z = [], [], []
664
+ cone_u, cone_v, cone_w = [], [], []
665
+
666
+ for i in range(len(x) - 1):
667
+ if x[i] == None or x[i+1] == None:
668
+ continue
669
+ u = x[i+1] - x[i]
670
+ v = y[i+1] - y[i]
671
+ w = z[i+1] - z[i]
672
+
673
+ norm = np.linalg.norm([u, v, w])
674
+ if norm > 0:
675
+ u /= norm
676
+ v /= norm
677
+ w /= norm
678
+ cone_x.append(x[i+1])
679
+ cone_y.append(y[i+1])
680
+ cone_z.append(z[i+1])
681
+ cone_u.append(u)
682
+ cone_v.append(v)
683
+ cone_w.append(w)
684
+
685
+ cone_trace = go.Cone(
686
+ x=cone_x,
687
+ y=cone_y,
688
+ z=cone_z,
689
+ u=cone_u,
690
+ v=cone_v,
691
+ w=cone_w,
692
+ sizemode="raw",
693
+ sizeref=arrowSize,
694
+ showscale=False,
695
+ colorscale=[[0, color], [1, color]],
696
+ anchor="tip",
697
+ name="", # Hide legend
698
+ hoverinfo="skip",
699
+ showlegend=False
700
+ )
701
+ arrow_traces.append(cone_trace)
702
+
703
+ return arrow_traces
646
704
  traces = []
647
705
  x = []
648
706
  y = []
@@ -676,8 +734,8 @@ class Plotly:
676
734
  maxGroup = 1
677
735
 
678
736
 
679
- if colorKey or widthKey or labelKey or groupKey or dashKey:
680
- keys = [x for x in [colorKey, widthKey, labelKey, groupKey, dashKey] if not x == None]
737
+ if colorKey or widthKey or labelKey or groupKey or dashKey or arrowSizeKey:
738
+ keys = [x for x in [colorKey, widthKey, labelKey, groupKey, dashKey, arrowSizeKey] if not x == None]
681
739
  temp_dict = Helper.ClusterByKeys(edges, dictionaries, keys, silent=False)
682
740
  dict_clusters = temp_dict["dictionaries"]
683
741
  elements_clusters = temp_dict['elements']
@@ -685,13 +743,16 @@ class Plotly:
685
743
  labels = []
686
744
  for j, elements_cluster in enumerate(elements_clusters):
687
745
  d_color = color
746
+ d_arrowSize = arrowSize
747
+ d_dash = dash
688
748
  d = dict_clusters[j][0] # All dicitonaries have same values in dictionaries, so take first one.
689
749
  if d:
690
750
  if not colorKey == None:
691
- d_color = Dictionary.ValueAtKey(d, key=colorKey) or color
692
- d_color = Color.AnyToHex(d_color)
751
+ d_color = Color.AnyToHex(Dictionary.ValueAtKey(d, key=colorKey, default=color))
693
752
  if not dashKey == None:
694
- d_dash = Dictionary.ValueAtKey(d, key=dashKey) or dash
753
+ d_dash = Dictionary.ValueAtKey(d, key=dashKey, default=dash)
754
+ if not arrowSizeKey == None:
755
+ d_arrowSize = Dictionary.ValueAtKey(d, key=arrowSizeKey, default=arrowSize)
695
756
  if not labelKey == None:
696
757
  labels.append(str(Dictionary.ValueAtKey(d, labelKey, "")))
697
758
  if not widthKey == None:
@@ -727,7 +788,7 @@ class Plotly:
727
788
  marker_width = width[0]*0.25
728
789
  else:
729
790
  marker_width = width*0.25
730
- if dash:
791
+ if d_dash:
731
792
  dot = "dot"
732
793
  else:
733
794
  dot = "solid"
@@ -744,6 +805,9 @@ class Plotly:
744
805
  text=labels,
745
806
  hoverinfo='text',
746
807
  hovertext=labels)
808
+ if directed:
809
+ arrow_traces = create_arrowheads(x, y, z, arrowSize=d_arrowSize)
810
+ traces += arrow_traces
747
811
  traces.append(trace)
748
812
  else:
749
813
  x = []
@@ -775,6 +839,9 @@ class Plotly:
775
839
  legendrank=legendRank,
776
840
  text=label,
777
841
  hoverinfo='text')
842
+ if directed:
843
+ arrow_traces = create_arrowheads(x, y, z, arrowSize=arrowSize)
844
+ traces += arrow_traces
778
845
  traces.append(trace)
779
846
  return traces
780
847
 
@@ -799,6 +866,9 @@ class Plotly:
799
866
  vertexLegendLabel="Topology Vertices",
800
867
  vertexLegendRank=1,
801
868
  vertexLegendGroup=1,
869
+ directed=False,
870
+ arrowSize=0.1,
871
+ arrowSizeKey=None,
802
872
  showEdges=True,
803
873
  edgeWidth=1,
804
874
  edgeWidthKey=None,
@@ -884,7 +954,12 @@ class Plotly:
884
954
  The legend rank order of the vertices of this topology. The default is 1.
885
955
  vertexLegendGroup : int , optional
886
956
  The number of the vertex legend group to which the vertices of this topology belong. The default is 1.
887
-
957
+ directed : bool , optional
958
+ If set to True, arrowheads are drawn to show direction. The default is False.
959
+ arrowSize : int, optional
960
+ The desired size of arrowheads for directed graphs. The default is 0.1.
961
+ arrowSizeKey: str , optional
962
+ The edge dictionary key under which to find the arrowhead size. The default is None.
888
963
  showEdges : bool , optional
889
964
  If set to True the edges will be drawn. Otherwise, they will not be drawn. The default is True.
890
965
  edgeWidth : float , optional
@@ -1194,7 +1269,7 @@ class Plotly:
1194
1269
  vertices = geo['vertices']
1195
1270
  edges = geo['edges']
1196
1271
  if len(edges) > 0:
1197
- data.extend(Plotly.edgeData(vertices, edges, dictionaries=e_dictionaries, color=edgeColor, colorKey=edgeColorKey, width=edgeWidth, widthKey=edgeWidthKey, labelKey=edgeLabelKey, showEdgeLabel=showEdgeLabel, groupKey=edgeGroupKey, minGroup=edgeMinGroup, maxGroup=edgeMaxGroup, groups=edgeGroups, legendLabel=edgeLegendLabel, legendGroup=edgeLegendGroup, legendRank=edgeLegendRank, showLegend=showEdgeLegend, colorScale=colorScale))
1272
+ data.extend(Plotly.edgeData(vertices, edges, dictionaries=e_dictionaries, color=edgeColor, colorKey=edgeColorKey, width=edgeWidth, widthKey=edgeWidthKey, directed=directed, arrowSize=arrowSize, arrowSizeKey=arrowSizeKey, labelKey=edgeLabelKey, showEdgeLabel=showEdgeLabel, groupKey=edgeGroupKey, minGroup=edgeMinGroup, maxGroup=edgeMaxGroup, groups=edgeGroups, legendLabel=edgeLegendLabel, legendGroup=edgeLegendGroup, legendRank=edgeLegendRank, showLegend=showEdgeLegend, colorScale=colorScale))
1198
1273
 
1199
1274
  if showFaces and Topology.Type(topology) >= Topology.TypeID("Face"):
1200
1275
  if not faceColorKey == None:
topologicpy/Topology.py CHANGED
@@ -6992,16 +6992,16 @@ class Topology():
6992
6992
  return_topology = Wire.RemoveCollinearEdges(topology, angTolerance=angTolerance, tolerance=tolerance, silent=silent)
6993
6993
  return return_topology
6994
6994
  elif Topology.IsInstance(topology, "Face"):
6995
- return_topology = Face.RemoveCollinearEdges(topology, angTolerance=angTolerance, tolerance=tolerance)
6995
+ return_topology = Face.RemoveCollinearEdges(topology, angTolerance=angTolerance, tolerance=tolerance, silent=silent)
6996
6996
  return return_topology
6997
6997
  elif Topology.IsInstance(topology, "Shell"):
6998
- return_topology = Shell.RemoveCollinearEdges(topology, angTolerance=angTolerance, tolerance=tolerance)
6998
+ return_topology = Shell.RemoveCollinearEdges(topology, angTolerance=angTolerance, tolerance=tolerance, silent=silent)
6999
6999
  return return_topology
7000
7000
  elif Topology.IsInstance(topology, "Cell"):
7001
- return_topology = Cell.RemoveCollinearEdges(topology, angTolerance=angTolerance, tolerance=tolerance)
7001
+ return_topology = Cell.RemoveCollinearEdges(topology, angTolerance=angTolerance, tolerance=tolerance, silent=silent)
7002
7002
  return return_topology
7003
7003
  elif Topology.IsInstance(topology, "CellComplex"):
7004
- return_topology = CellComplex.RemoveCollinearEdges(topology, angTolerance=angTolerance, tolerance=tolerance)
7004
+ return_topology = CellComplex.RemoveCollinearEdges(topology, angTolerance=angTolerance, tolerance=tolerance, silent=silent)
7005
7005
  return return_topology
7006
7006
  elif Topology.IsInstance(topology, "Cluster"):
7007
7007
  topologies = []
@@ -7009,7 +7009,7 @@ class Topology():
7009
7009
  topologies += Cluster.FreeEdges(topology)
7010
7010
  faces = Topology.Faces(topology)
7011
7011
  for face in faces:
7012
- topologies.append(Face.RemoveCollinearEdges(face, angTolerance=angTolerance, tolerance=tolerance))
7012
+ topologies.append(Face.RemoveCollinearEdges(face, angTolerance=angTolerance, tolerance=tolerance, silent=silent))
7013
7013
  return_topology = Topology.SelfMerge(Cluster.ByTopologies(topologies), tolerance=tolerance)
7014
7014
  return return_topology
7015
7015
 
@@ -8162,7 +8162,10 @@ class Topology():
8162
8162
  vertexMaxGroup=None,
8163
8163
  showVertexLegend=False,
8164
8164
  vertexLegendLabel="Vertices",
8165
-
8165
+
8166
+ directed=False,
8167
+ arrowSize=0.1,
8168
+ arrowSizeKey=None,
8166
8169
  showEdges=True,
8167
8170
  edgeWidth=None,
8168
8171
  edgeWidthKey=None,
@@ -8281,7 +8284,12 @@ class Topology():
8281
8284
  If set to True, the legend for the vertices of this topology is shown. Otherwise, it isn't. The default is False.
8282
8285
  vertexLegendLabel : str , optional
8283
8286
  The legend label string used to identify vertices. The default is "Topology Vertices".
8284
-
8287
+ directed : bool , optional
8288
+ If set to True, arrowheads are drawn to show direction. The default is False.
8289
+ arrowSize : int, optional
8290
+ The desired size of arrowheads for directed graphs. The default is 0.1.
8291
+ arrowSizeKey: str , optional
8292
+ The edge dictionary key under which to find the arrowhead size. The default is None.
8285
8293
  showEdges : bool , optional
8286
8294
  If set to True the edges will be drawn. Otherwise, they will not be drawn. The default is True.
8287
8295
  edgeWidth : float , optional
@@ -8470,6 +8478,9 @@ class Topology():
8470
8478
  absolute=absolute,
8471
8479
  sides=sides,
8472
8480
  angle=angle,
8481
+ directed=directed,
8482
+ arrowSize=arrowSize,
8483
+ arrowSizeKey=arrowSizeKey,
8473
8484
  vertexColor=vertexColor,
8474
8485
  vertexColorKey=vertexColorKey,
8475
8486
  vertexSize=vSize,
@@ -8543,6 +8554,9 @@ class Topology():
8543
8554
  vertexLegendLabel=str(i+1)+": "+name+" ("+vertexLegendLabel+")",
8544
8555
  vertexLegendRank=topology_counter+1,
8545
8556
  vertexLegendGroup=topology_counter+1,
8557
+ directed=directed,
8558
+ arrowSize=arrowSize,
8559
+ arrowSizeKey=arrowSizeKey,
8546
8560
  showEdges=showEdges,
8547
8561
  edgeWidth=eWidth,
8548
8562
  edgeWidthKey=edgeWidthKey,
topologicpy/Vertex.py CHANGED
@@ -1819,7 +1819,7 @@ class Vertex():
1819
1819
  return Vertex.ByCoordinates(pt[0], pt[1], pt[2])
1820
1820
 
1821
1821
  @staticmethod
1822
- def Separate(*vertices, minDistance: float = 0.0001, silent: bool = False):
1822
+ def Separate(*vertices, minDistance: float = 0.0001, iterations: int = 100, strength: float = 0.1, tolerance: float = 0.0001, silent: bool = False):
1823
1823
  """
1824
1824
  Separates the input vertices such that no two vertices are within the input minimum distance.
1825
1825
 
@@ -1829,6 +1829,12 @@ class Vertex():
1829
1829
  One or more instances of a topologic vertex to be processed.
1830
1830
  minDistance : float , optional
1831
1831
  The desired minimum distance. The default is 0.0001.
1832
+ iterations : int
1833
+ The number of iterations to run the repulsion simulation. The default is 100.
1834
+ strength : float
1835
+ The force multiplier controlling how strongly vertices repel each other. The default is 0.1.
1836
+ tolerance : float
1837
+ The desired tolerance. The default is 0.0001.
1832
1838
  silent : bool , optional
1833
1839
  If set to True, error and warning messages are suppressed. The default is False.
1834
1840
 
@@ -1840,10 +1846,7 @@ class Vertex():
1840
1846
  """
1841
1847
  from topologicpy.Topology import Topology
1842
1848
  from topologicpy.Helper import Helper
1843
- from topologicpy.Dictionary import Dictionary
1844
- from math import sqrt
1845
- from scipy.spatial import KDTree
1846
- import numpy as np
1849
+ import math
1847
1850
 
1848
1851
  if len(vertices) == 0:
1849
1852
  if not silent:
@@ -1873,33 +1876,37 @@ class Vertex():
1873
1876
  if not silent:
1874
1877
  print("Vertex.Separate - Error: The input parameters do not contain any valid vertices. Returning None.")
1875
1878
  return None
1876
-
1877
- coords = np.array([[v.X(), v.Y(), v.Z()] for v in vertexList]) # Extract coordinates
1878
- tree = KDTree(coords) # Build k-d tree for efficient neighbor search
1879
+
1880
+ minDistance = minDistance + tolerance # Add a bit of a safety factor
1881
+
1882
+ # Convert to mutable coordinates
1883
+ coords = [[v.X(), v.Y(), v.Z()] for v in vertices]
1884
+
1885
+ for _ in range(iterations):
1886
+ for i in range(len(coords)):
1887
+ for j in range(i + 1, len(coords)):
1888
+ dx = coords[j][0] - coords[i][0]
1889
+ dy = coords[j][1] - coords[i][1]
1890
+ dz = coords[j][2] - coords[i][2]
1891
+ dist = math.sqrt(dx*dx + dy*dy + dz*dz)
1892
+
1893
+ if dist < minDistance and dist > 1e-9:
1894
+ # Calculate repulsion vector
1895
+ repel = (minDistance - dist) / dist * strength
1896
+ shift = [dx * repel * 0.5, dy * repel * 0.5, dz * repel * 0.5]
1897
+ coords[i][0] -= shift[0]
1898
+ coords[i][1] -= shift[1]
1899
+ coords[i][2] -= shift[2]
1900
+ coords[j][0] += shift[0]
1901
+ coords[j][1] += shift[1]
1902
+ coords[j][2] += shift[2]
1879
1903
 
1880
- for i, vertex in enumerate(coords):
1881
- neighbors = tree.query_ball_point(vertex, minDistance)
1882
- for neighbor_index in neighbors:
1883
- if neighbor_index != i: # Avoid self-comparison
1884
- direction = coords[neighbor_index] - vertex
1885
- distance = np.linalg.norm(direction)
1886
- if distance < minDistance:
1887
- # Move current vertex away from its neighbor
1888
- adjustment = (minDistance - distance) / 2
1889
- unit_vector = direction / distance if distance != 0 else np.random.rand(3)
1890
- coords[i] -= unit_vector * adjustment
1891
- coords[neighbor_index] += unit_vector * adjustment
1892
-
1893
- # Rebuild the k-d tree after adjustment
1894
- tree = KDTree(coords)
1895
-
1896
- # Convert adjusted coordinates back to Vertex objects
1897
- separated_vertices = [Vertex.ByCoordinates(x, y, z) for x, y, z in coords]
1898
- for i, vertex in enumerate(vertexList):
1899
- d = Topology.Dictionary(vertex)
1900
- if len(Dictionary.Keys(d)) > 0:
1901
- separated_vertices[i] = Topology.SetDictionary(separated_vertices[i], d)
1902
- return separated_vertices
1904
+ # Reconstruct TopologicPy Vertex objects
1905
+ new_vertices = [Vertex.ByCoordinates(x, y, z) for x, y, z in coords]
1906
+ # Transfer the dictionaries
1907
+ for i, v in enumerate(new_vertices):
1908
+ v = Topology.SetDictionary(v, Topology.Dictionary(vertices[i]))
1909
+ return new_vertices
1903
1910
 
1904
1911
  @staticmethod
1905
1912
  def Transform(vertex, matrix, mantissa: int = 6, silent: bool = False):
topologicpy/Wire.py CHANGED
@@ -465,15 +465,13 @@ class Wire():
465
465
  from topologicpy.Cluster import Cluster
466
466
  from topologicpy.Topology import Topology
467
467
  from topologicpy.Vector import Vector
468
- from topologicpy.Helper import Helper
468
+ from topologicpy.Helper import Helper
469
469
 
470
470
  if not Topology.IsInstance(wire, "Wire"):
471
471
  if not silent:
472
472
  print("Wire.ByOffset - Error: The input wire parameter is not a valid wire. Returning None.")
473
473
  return None
474
474
 
475
- #temp_face = Face.ByWire(wire)
476
- #original_area = Face.Area(temp_face)
477
475
  if reverse == True:
478
476
  fac = -1
479
477
  else:
@@ -481,13 +479,10 @@ class Wire():
481
479
  origin = Topology.Centroid(wire)
482
480
  temp_vertices = [Topology.Vertices(wire)[0], Topology.Vertices(wire)[1], Topology.Centroid(wire)]
483
481
  temp_face = Face.ByWire(Wire.ByVertices(temp_vertices, close=True, tolerance=tolerance), silent=silent)
484
- temp_normal = Face.Normal(temp_face)
485
- flat_wire = Topology.Flatten(wire, direction=temp_normal, origin=origin)
486
482
  normal = Face.Normal(temp_face)
487
483
  flat_wire = Topology.Flatten(wire, direction=normal, origin=origin)
488
484
  original_edges = Topology.Edges(wire)
489
485
  edges = Topology.Edges(flat_wire)
490
- original_edges = Topology.Edges(wire)
491
486
  offsets = []
492
487
  offset_edges = []
493
488
  final_vertices = []
@@ -495,9 +490,7 @@ class Wire():
495
490
  edge_dictionaries = []
496
491
  for i, edge in enumerate(edges):
497
492
  d = Topology.Dictionary(original_edges[i])
498
- d_offset = Dictionary.ValueAtKey(d, offsetKey)
499
- if d_offset == None:
500
- d_offset = offset
493
+ d_offset = Dictionary.ValueAtKey(d, key=offsetKey, defaultValue=offset)
501
494
  d_offset = d_offset*fac
502
495
  offsets.append(d_offset)
503
496
  offset_edge = Edge.ByOffset2D(edge, d_offset)
@@ -595,23 +588,7 @@ class Wire():
595
588
  v1 = Topology.SetDictionary(v1, Topology.Dictionary(v_a), silent=True)
596
589
  if bisectors == True:
597
590
  bisectors_list.append(Edge.ByVertices(v_a, v1))
598
-
599
-
600
- # wire_edges = []
601
- # for i in range(len(final_vertices)-1):
602
- # v1 = final_vertices[i]
603
- # v2 = final_vertices[i+1]
604
- # w_e = Edge.ByVertices(v1,v2)
605
- # #w_e = Edge.SetLength(w_e, Edge.Length(w_e)+(2*epsilon), bothSides = True)
606
- # wire_edges.append(w_e)
607
- # if Wire.IsClosed(wire):
608
- # v1 = final_vertices[-1]
609
- # v2 = final_vertices[0]
610
- # #w_e = Edge.SetLength(w_e, Edge.Length(w_e)+(2*epsilon), bothSides = True)
611
- # wire_edges.append(w_e)
612
-
613
591
  return_wire = Wire.ByVertices(final_vertices, close=Wire.IsClosed(wire), tolerance=tolerance, silent=silent)
614
- #wire_edges = Topology.Edges(wire_edges)
615
592
  wire_edges = [Edge.SetLength(w_e, Edge.Length(w_e)+(2*epsilon), bothSides=True) for w_e in Topology.Edges(return_wire)]
616
593
  return_wire_edges = Topology.Edges(return_wire)
617
594
  if transferDictionaries == True:
@@ -651,7 +628,6 @@ class Wire():
651
628
  print("Wire.ByOffset - Warning: The resulting wire is non-manifold, please check your offsets.")
652
629
  print("Wire.ByOffset - Warning: Pursuing a workaround, but it might take longer to complete.")
653
630
 
654
- #cycles = Wire.Cycles(return_wire, maxVertices = len(final_vertices))
655
631
  temp_wire = Topology.SelfMerge(Cluster.ByTopologies(wire_edges))
656
632
  cycles = Wire.Cycles(temp_wire, maxVertices = len(final_vertices))
657
633
  if len(cycles) > 0:
@@ -679,7 +655,6 @@ class Wire():
679
655
  return_cycle = Topology.TransferDictionariesBySelectors(return_cycle, Topology.Vertices(return_wire), tranVertices=True, tolerance=tolerance, numWorkers=numWorkers)
680
656
  return_cycle = Topology.TransferDictionariesBySelectors(return_cycle, sel_edges, tranEdges=True, tolerance=tolerance, numWorkers=numWorkers)
681
657
  return_wire = return_cycle
682
-
683
658
  return_wire = Topology.Unflatten(return_wire, direction=normal, origin=origin)
684
659
  if transferDictionaries == True:
685
660
  return_wire = Topology.SetDictionary(return_wire, Topology.Dictionary(wire), silent=True)
@@ -3728,7 +3703,7 @@ class Wire():
3728
3703
  return None
3729
3704
 
3730
3705
  new_wire = cleanup(wire)
3731
- wires = Wire.Split(new_wire) if not Wire.IsManifold(new_wire) else [new_wire]
3706
+ wires = Wire.Split(new_wire) if not Wire.IsManifold(new_wire, silent=silent) else [new_wire]
3732
3707
 
3733
3708
  processed_wires = [remove_collinear_vertices(w) for w in wires]
3734
3709
 
topologicpy/version.py CHANGED
@@ -1 +1 @@
1
- __version__ = '0.8.40'
1
+ __version__ = '0.8.42'
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: topologicpy
3
- Version: 0.8.40
3
+ Version: 0.8.42
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
@@ -2,37 +2,37 @@ topologicpy/ANN.py,sha256=DrNAhNHp-jSvsPc1fb7KVPU46cYmejAvghhknOM430Y,47932
2
2
  topologicpy/Aperture.py,sha256=wNn5miB_IrGCBYuQ18HXQYRva20dUC3id4AJCulL7to,2723
3
3
  topologicpy/BVH.py,sha256=Iwp_8VDG8ETE4330k7ifWxdI4jmWmv9h8e8IIIZZFGY,13043
4
4
  topologicpy/CSG.py,sha256=uDkOSmc8m1V_k7T3UCerODhOSyYNO4FRDzoOqt0kEt8,15590
5
- topologicpy/Cell.py,sha256=3et98bv27m1-7OqFCeD4cLMBgC_BAsSGyxHi_4PgJ4Y,176072
6
- topologicpy/CellComplex.py,sha256=NP6yptbkGXYmlfBv9fRimOnNle0mkjV8Yo_ug5NKpKE,60877
5
+ topologicpy/Cell.py,sha256=M4Xv4gabSgtKYYA-Wh0lgYEbRNRVF9zr4DYejOXJc-4,176278
6
+ topologicpy/CellComplex.py,sha256=c2B3mF1c3iwOfT-V0JWt9qNcFdd6DPR0aBOE2UnZTn4,61165
7
7
  topologicpy/Cluster.py,sha256=wvfMAx6aPrSAt5nQ4--KnqD4EK9MGjch6Dg985WF7JQ,58748
8
8
  topologicpy/Color.py,sha256=FcR0-__giyGQqvgiOrG8GkA65arHbiS33Si-QbUADPI,23362
9
9
  topologicpy/Context.py,sha256=G3CwMvN8Jw2rnQRwB-n4MaQq_wLS0vPimbXKwsdMJ80,3055
10
10
  topologicpy/DGL.py,sha256=HQXy9iDnrvWGDxaBfe5pRbweQ2zLBvAf6UdjfhKkQYI,139041
11
11
  topologicpy/Dictionary.py,sha256=2Sxm8twR1W4ksZho0YXQB_EltK2qbZWK4UHskP3jvFQ,40846
12
- topologicpy/Edge.py,sha256=CPdQKaE7ft6zgh0vxekkfGRRUY_yEqkEJ14NvjSgJOA,73190
12
+ topologicpy/Edge.py,sha256=dLoAPuRKbjVg_dzloTgjRnQyv_05U9nfrtLO3tqyuys,74167
13
13
  topologicpy/EnergyModel.py,sha256=Pyb28gDDwhzlQIH0xqAygqS0P3SJxWyyV7OWS_AAfRs,53856
14
- topologicpy/Face.py,sha256=BT_5ymb7-s-Wb1tuaBtkopJpeNg-RbooTUk_-KInQ6c,201618
15
- topologicpy/Graph.py,sha256=z_9TeMkmwFXlCfVDW9Z56PX0sHxGj8iVKlCdJLreMo0,639785
14
+ topologicpy/Face.py,sha256=pN1fssyDLYWf1vU0NOBRx69DaUL958wRSxT-7VBCuCg,203184
15
+ topologicpy/Graph.py,sha256=GykBbB8KKcy2oPV2Dsnz_vkyWGgczxLi0puVx5NJUYU,648088
16
16
  topologicpy/Grid.py,sha256=EbI2NcYhQDpD5mItd7A1Lpr8Puuf87vZPWuoh7_gChQ,18483
17
17
  topologicpy/Helper.py,sha256=qEsE4yaboEGW94q9lFCff0I_JwwTTQnDAFXw006yHaQ,31203
18
18
  topologicpy/Honeybee.py,sha256=yctkwfdupKnp7bAOjP1Z4YaYpRrWoMEb4gz9Z5zaWwE,21751
19
19
  topologicpy/Matrix.py,sha256=LqVckk2qTwKwEo79eyNsOrHVSHdO82JCREcfy6WIk4I,22716
20
20
  topologicpy/Neo4j.py,sha256=ELKmON7R16j1kQD8xRHDGGCvzjIM2HGHNekdaXDUw6w,22371
21
- topologicpy/Plotly.py,sha256=Dmy9i9puSfvB42mrBUip3v0TCXIzHpAETWDUCDxfqNA,120556
21
+ topologicpy/Plotly.py,sha256=SqoQOFqchfDY52_mTGyBOqE_OPEfBI48YI3OyuJ7JQw,123758
22
22
  topologicpy/Polyskel.py,sha256=oVfM4lqSMPTjnkHfsRU9VI8Blt6Vf0LVPkD9ebz7Wmw,27082
23
23
  topologicpy/PyG.py,sha256=zvV6jtnol_aFiN6JRoMpYwBVfOU2aFs9gdWSdEo6mtU,109757
24
24
  topologicpy/ShapeGrammar.py,sha256=UVb8VPwVKd6V3zDTNzpBecQPgYo1EjSsS10XJ8k5YcI,23364
25
25
  topologicpy/Shell.py,sha256=fx0WTndC8blkvWe38nKsJsI_AmklOA0qsjU0gbZp4b4,90501
26
26
  topologicpy/Speckle.py,sha256=-eiTqJugd7pHiHpD3pDUcDO6CGhVyPV14HFRzaqEoaw,18187
27
27
  topologicpy/Sun.py,sha256=_VBBAUIDhvpkp72JBZlv7k9qx9jYubm3yM56UZ1Nc6c,36837
28
- topologicpy/Topology.py,sha256=G6KtKRKabV1gNUKCZ3rzZJkCogGkOJDnCl-_S7DuHKc,466648
28
+ topologicpy/Topology.py,sha256=FnDunqk4uq0iAqtOiQtjNArETXflx6cRBHMYv7NJqC8,467594
29
29
  topologicpy/Vector.py,sha256=X12eqskn28bdB7sLY1EZhq3noPYzPbNEgHPb4a959ss,42302
30
- topologicpy/Vertex.py,sha256=epBfbD7fm87T-TZ0WuwrioXdYqg9NgRlHn_qUFtVbkc,84562
31
- topologicpy/Wire.py,sha256=vE6IoObVucOZVTFMPiHuNN4DDezRHHyFbwhF5WRBm3s,231547
30
+ topologicpy/Vertex.py,sha256=RlGQnxQSb_kAus3tJgXd-v-Ptubtt09PQPA9IMwfXmI,84835
31
+ topologicpy/Wire.py,sha256=sJE8qwqYOomvN3snMWmj2P2-Sq25ul_OQ95YFz6DFUw,230553
32
32
  topologicpy/__init__.py,sha256=RMftibjgAnHB1vdL-muo71RwMS4972JCxHuRHOlU428,928
33
- topologicpy/version.py,sha256=9UtSkYQrOL8TXxQBwLoy5jvQKNWp84nSX32fmM7V0Ac,23
34
- topologicpy-0.8.40.dist-info/licenses/LICENSE,sha256=FK0vJ73LuE8PYJAn7LutsReWR47-Ooovw2dnRe5yV6Q,681
35
- topologicpy-0.8.40.dist-info/METADATA,sha256=8YuR3I1XDjArnIbbajaveZEDc7Q8eVk4aBOvtaLhULA,10535
36
- topologicpy-0.8.40.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
37
- topologicpy-0.8.40.dist-info/top_level.txt,sha256=J30bDzW92Ob7hw3zA8V34Jlp-vvsfIkGzkr8sqvb4Uw,12
38
- topologicpy-0.8.40.dist-info/RECORD,,
33
+ topologicpy/version.py,sha256=zx8I7AqRXGv-YmSUcQeFeKLCO2nWXVogDC-GQVEnTsI,23
34
+ topologicpy-0.8.42.dist-info/licenses/LICENSE,sha256=FK0vJ73LuE8PYJAn7LutsReWR47-Ooovw2dnRe5yV6Q,681
35
+ topologicpy-0.8.42.dist-info/METADATA,sha256=YEn71WRNeRaM0zD1L8Uh4HSmaxe_JJPkC5lBpaawXcc,10535
36
+ topologicpy-0.8.42.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
37
+ topologicpy-0.8.42.dist-info/top_level.txt,sha256=J30bDzW92Ob7hw3zA8V34Jlp-vvsfIkGzkr8sqvb4Uw,12
38
+ topologicpy-0.8.42.dist-info/RECORD,,