topologicpy 0.8.29__py3-none-any.whl → 0.8.31__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/Face.py CHANGED
@@ -571,6 +571,9 @@ class Face():
571
571
  The desired angular tolerance. The default is 0.1.
572
572
  tolerance : float , optional
573
573
  The desired tolerance. The default is 0.0001.
574
+ silent : bool , optional
575
+ If set to True, no error and warning messages are printed. Otherwise, they are. The default is False.
576
+
574
577
 
575
578
  Returns
576
579
  -------
@@ -604,8 +607,7 @@ class Face():
604
607
 
605
608
  # Try the simple method first
606
609
  face = None
607
- ext_boundary = Wire.RemoveCollinearEdges(Shell.ExternalBoundary(shell))
608
- #ext_boundary = Shell.ExternalBoundary(shell)
610
+ ext_boundary = Wire.RemoveCollinearEdges(Shell.ExternalBoundary(shell), tolerance=tolerance, silent=silent)
609
611
  if Topology.IsInstance(ext_boundary, "Wire"):
610
612
  face = Face.ByWire(ext_boundary, silent=silent)
611
613
  elif Topology.IsInstance(ext_boundary, "Cluster"):
@@ -629,7 +631,7 @@ class Face():
629
631
  new_vertices.append(new_v)
630
632
  planar_shell = Topology.SelfMerge(Topology.ReplaceVertices(planar_shell, verticesA=vertices, verticesB=new_vertices), tolerance=tolerance)
631
633
  ext_boundary = Shell.ExternalBoundary(planar_shell, tolerance=tolerance)
632
- ext_boundary = Topology.RemoveCollinearEdges(ext_boundary, angTolerance)
634
+ ext_boundary = Topology.RemoveCollinearEdges(ext_boundary, angTolerance=angTolerance, tolerance=tolerance, silent=silent)
633
635
  if not Topology.IsInstance(ext_boundary, "Topology"):
634
636
  print("Face.ByShell - Error: Could not derive the external boundary of the input shell parameter. Returning None.")
635
637
  return None
@@ -637,9 +639,9 @@ class Face():
637
639
  if Topology.IsInstance(ext_boundary, "Wire"):
638
640
  if not Topology.IsPlanar(ext_boundary, tolerance=tolerance):
639
641
  ext_boundary = Wire.Planarize(ext_boundary, origin=origin, tolerance=tolerance)
640
- ext_boundary = Topology.RemoveCollinearEdges(ext_boundary, angTolerance)
642
+ ext_boundary = Topology.RemoveCollinearEdges(ext_boundary, angTolerance=angTolerance, tolerance=tolerance, silent=silent)
641
643
  try:
642
- face = Face.ByWire(ext_boundary)
644
+ face = Face.ByWire(ext_boundary, tolerance=tolerance, silent=silent)
643
645
  face = Topology.Unflatten(face, origin=origin, direction=normal)
644
646
  return face
645
647
  except:
@@ -663,11 +665,11 @@ class Face():
663
665
  int_wires = []
664
666
  for int_boundary in int_boundaries:
665
667
  temp_wires = Topology.Wires(int_boundary)
666
- int_wires.append(Topology.RemoveCollinearEdges(temp_wires[0], angTolerance))
668
+ int_wires.append(Topology.RemoveCollinearEdges(temp_wires[0], angTolerance=angTolerance, tolerance=tolerance, silent=silent))
667
669
  #int_wires.append(temp_wires[0])
668
670
 
669
671
  temp_wires = Topology.Wires(ext_boundary)
670
- ext_wire = Topology.RemoveCollinearEdges(temp_wires[0], angTolerance)
672
+ ext_wire = Topology.RemoveCollinearEdges(temp_wires[0], angTolerance=angTolerance, tolerance=tolerance, silent=silent)
671
673
  #ext_wire = temp_wires[0]
672
674
  face = Face.ByWires(ext_wire, int_wires)
673
675
  face = Topology.Unflatten(face, origin=origin, direction=normal)
@@ -676,7 +678,7 @@ class Face():
676
678
  return None
677
679
 
678
680
  @staticmethod
679
- def ByThickenedWire(wire, offsetA: float = 1.0, offsetB: float = 0.0, tolerance: float = 0.0001):
681
+ def ByThickenedWire(wire, offsetA: float = 1.0, offsetB: float = 0.0, tolerance: float = 0.0001, silent: bool = False):
680
682
  """
681
683
  Creates a face by thickening the input wire. This method assumes the wire is manifold and planar.
682
684
 
@@ -690,6 +692,8 @@ class Face():
690
692
  The desired offset to the interior of the wire. The default is 0.0.
691
693
  tolerance : float , optional
692
694
  The desired tolerance. The default is 0.0001.
695
+ silent : bool , optional
696
+ If set to True, no error and warning messages are printed. Otherwise, they are. The default is False.
693
697
 
694
698
  Returns
695
699
  -------
@@ -710,7 +714,7 @@ class Face():
710
714
  print("Face.ByThickenedWire - Error: The input wire parameter is not a manifold wire. Returning None.")
711
715
  return None
712
716
  three_vertices = Topology.Vertices(wire)[0:3]
713
- temp_w = Wire.ByVertices(three_vertices, close=True)
717
+ temp_w = Wire.ByVertices(three_vertices, close=True, tolerance=tolerance, silent=silent)
714
718
  flat_face = Face.ByWire(temp_w, tolerance=tolerance)
715
719
  origin = Vertex.Origin()
716
720
  normal = Face.Normal(flat_face)
@@ -733,7 +737,7 @@ class Face():
733
737
  out_vertices = Topology.Vertices(outside_wire)[1:-1]
734
738
  in_vertices = Topology.Vertices(inside_wire)[1:-1]
735
739
  vertices = [sv2] + out_vertices + [ev2,ev1] + in_vertices + [sv1]
736
- return_face = Face.ByWire(Wire.ByVertices(vertices))
740
+ return_face = Face.ByWire(Wire.ByVertices(vertices, close=True, tolerance=tolerance, silent=silent))
737
741
  else:
738
742
  return_face = Face.ByWires(outside_wire, [inside_wire])
739
743
  return_face = Topology.Unflatten(return_face, origin=origin, direction=normal)
@@ -773,7 +777,7 @@ class Face():
773
777
  print("Face.ByVertices - Error: The input vertices parameter does not contain at least three valid vertices. Returning None.")
774
778
  return None
775
779
 
776
- w = Wire.ByVertices(vertexList, tolerance=tolerance)
780
+ w = Wire.ByVertices(vertexList, close=True, tolerance=tolerance, silent=silent)
777
781
  if not Topology.IsInstance(w, "Wire"):
778
782
  if not silent:
779
783
  print("Face.ByVertices - Error: Could not create the base wire. Returning None.")
@@ -782,8 +786,8 @@ class Face():
782
786
  if not silent:
783
787
  print("Face.ByVertices - Error: Could not create a closed base wire. Returning None.")
784
788
  return None
785
- f = Face.ByWire(w, tolerance=tolerance)
786
- if not Topology.IsInstance(w, "Wire"):
789
+ f = Face.ByWire(w, tolerance=tolerance, silent=silent)
790
+ if not Topology.IsInstance(f, "Face"):
787
791
  if not silent:
788
792
  print("Face.ByVertices - Error: Could not create the face. Returning None.")
789
793
  return None
@@ -851,7 +855,7 @@ class Face():
851
855
  import inspect
852
856
 
853
857
  def triangulateWire(wire):
854
- wire = Topology.RemoveCollinearEdges(wire)
858
+ wire = Topology.RemoveCollinearEdges(wire, angTolerance=0.1, tolerance=tolerance, silent=silent)
855
859
  vertices = Topology.Vertices(wire)
856
860
  shell = Shell.Delaunay(vertices)
857
861
  if Topology.IsInstance(shell, "Topology"):
@@ -1707,7 +1711,7 @@ class Face():
1707
1711
  return None
1708
1712
  ib_wires = []
1709
1713
  for ib in ib_list:
1710
- ib = Wire.ByVertices(Topology.Vertices(ib))
1714
+ ib = Wire.ByVertices(Topology.Vertices(ib), close=True, tolerance=tolerance, silent=silent)
1711
1715
  ib = Wire.Reverse(ib)
1712
1716
  if isinstance(radiusKey, str):
1713
1717
  ib = Topology.TransferDictionariesBySelectors(ib, selectors=f_vertices, tranVertices=True)
@@ -1721,7 +1725,7 @@ class Face():
1721
1725
  return Face.ByWires(eb, ib_wires)
1722
1726
 
1723
1727
  @staticmethod
1724
- def Harmonize(face, tolerance: float = 0.0001):
1728
+ def Harmonize(face, tolerance: float = 0.0001, silent: bool = False):
1725
1729
  """
1726
1730
  Returns a harmonized version of the input face such that the *u* and *v* origins are always in the upperleft corner.
1727
1731
 
@@ -1731,6 +1735,8 @@ class Face():
1731
1735
  The input face.
1732
1736
  tolerance : float , optional
1733
1737
  The desired tolerance. The default is 0.0001.
1738
+ silent : bool , optional
1739
+ If set to True, no error and warning messages are printed. Otherwise, they are. The default is False.
1734
1740
 
1735
1741
  Returns
1736
1742
  -------
@@ -1744,19 +1750,20 @@ class Face():
1744
1750
  from topologicpy.Dictionary import Dictionary
1745
1751
 
1746
1752
  if not Topology.IsInstance(face, "Face"):
1747
- print("Face.Harmonize - Error: The input face parameter is not a valid face. Returning None.")
1753
+ if not silent:
1754
+ print("Face.Harmonize - Error: The input face parameter is not a valid face. Returning None.")
1748
1755
  return None
1749
1756
  normal = Face.Normal(face)
1750
1757
  origin = Topology.Centroid(face)
1751
1758
  flatFace = Topology.Flatten(face, origin=origin, direction=normal)
1752
1759
  world_origin = Vertex.Origin()
1753
1760
  vertices = Topology.Vertices(Face.ExternalBoundary(flatFace))
1754
- harmonizedEB = Wire.ByVertices(vertices)
1761
+ harmonizedEB = Wire.ByVertices(vertices, close=True, tolerance=tolerance, silent=silent)
1755
1762
  internalBoundaries = Face.InternalBoundaries(flatFace)
1756
1763
  harmonizedIB = []
1757
1764
  for ib in internalBoundaries:
1758
1765
  ibVertices = Topology.Vertices(ib)
1759
- harmonizedIB.append(Wire.ByVertices(ibVertices))
1766
+ harmonizedIB.append(Wire.ByVertices(ibVertices, close=True, tolerance=tolerance, silent=silent))
1760
1767
  harmonizedFace = Face.ByWires(harmonizedEB, harmonizedIB, tolerance=tolerance)
1761
1768
  harmonizedFace = Topology.Unflatten(harmonizedFace, origin=origin, direction=normal)
1762
1769
  return harmonizedFace
@@ -1895,7 +1902,7 @@ class Face():
1895
1902
  return vert
1896
1903
 
1897
1904
  @staticmethod
1898
- def Invert(face, tolerance: float = 0.0001):
1905
+ def Invert(face, tolerance: float = 0.0001, silent: bool = False):
1899
1906
  """
1900
1907
  Creates a face that is an inverse (mirror) of the input face.
1901
1908
 
@@ -1905,6 +1912,8 @@ class Face():
1905
1912
  The input face.
1906
1913
  tolerance : float , optional
1907
1914
  The desired tolerance. The default is 0.0001.
1915
+ silent : bool , optional
1916
+ If set to True, no error and warning messages are printed. Otherwise, they are. The default is False.
1908
1917
 
1909
1918
  Returns
1910
1919
  -------
@@ -1920,12 +1929,12 @@ class Face():
1920
1929
  eb = Face.ExternalBoundary(face)
1921
1930
  vertices = Topology.Vertices(eb)
1922
1931
  vertices.reverse()
1923
- inverted_wire = Wire.ByVertices(vertices)
1932
+ inverted_wire = Wire.ByVertices(vertices, close=Wire.IsClosed(eb), tolerance=tolerance, silent=silent)
1924
1933
  internal_boundaries = Face.InternalBoundaries(face)
1925
1934
  if not internal_boundaries:
1926
- inverted_face = Face.ByWire(inverted_wire, tolerance=tolerance)
1935
+ inverted_face = Face.ByWire(inverted_wire, tolerance=tolerance, silent=silent)
1927
1936
  else:
1928
- inverted_face = Face.ByWires(inverted_wire, internal_boundaries, tolerance=tolerance)
1937
+ inverted_face = Face.ByWires(inverted_wire, internal_boundaries, tolerance=tolerance, silent=silent)
1929
1938
  return inverted_face
1930
1939
  @staticmethod
1931
1940
  def IsConvex(face, mantissa: int = 6, silent: bool = False) -> bool:
@@ -2140,7 +2149,7 @@ class Face():
2140
2149
  return Face.ByWire(i_shape_wire, tolerance=tolerance, silent=silent)
2141
2150
 
2142
2151
  @staticmethod
2143
- def Isovist(face, vertex, obstacles: list = [], direction: list = [0,1,0], fov: float = 360, transferDictionaries: bool = False, metrics: bool = False, triangles: bool = False, mantissa: int = 6, tolerance: float = 0.0001):
2152
+ def Isovist(face, vertex, obstacles: list = [], direction: list = [0,1,0], fov: float = 360, transferDictionaries: bool = False, metrics: bool = False, triangles: bool = False, mantissa: int = 6, tolerance: float = 0.0001, silent: bool = False):
2144
2153
  """
2145
2154
  Returns the face representing the isovist projection from the input viewpoint.
2146
2155
  This method assumes all input is in 2D. Z coordinates are ignored.
@@ -2199,6 +2208,8 @@ class Face():
2199
2208
  The desired length of the mantissa. The default is 6.
2200
2209
  tolerance : float , optional:
2201
2210
  The desired tolerance. The default is 0.0001.
2211
+ silent : bool , optional
2212
+ If set to True, no error and warning messages are printed. Otherwise, they are. The default is False.
2202
2213
 
2203
2214
  Returns
2204
2215
  -------
@@ -2481,7 +2492,7 @@ class Face():
2481
2492
  vertices = Topology.Vertices(eb)
2482
2493
  coords = [Vertex.Coordinates(v, outputType="xy") for v in vertices]
2483
2494
  new_vertices = [Vertex.ByCoordinates(coord) for coord in coords]
2484
- eb = Wire.ByVertices(new_vertices, close=True)
2495
+ eb = Wire.ByVertices(new_vertices, close=True, tolerance=tolerance, silent=silent)
2485
2496
 
2486
2497
  ib_list = Face.InternalBoundaries(flat_face)
2487
2498
  new_ib_list = []
@@ -2489,7 +2500,7 @@ class Face():
2489
2500
  vertices = Topology.Vertices(ib)
2490
2501
  coords = [Vertex.Coordinates(v, outputType="xy") for v in vertices]
2491
2502
  new_vertices = [Vertex.ByCoordinates(coord) for coord in coords]
2492
- new_ib_list.append(Wire.ByVertices(new_vertices, close=True))
2503
+ new_ib_list.append(Wire.ByVertices(new_vertices, close=True, tolerance=tolerance, silent=silent))
2493
2504
 
2494
2505
  flat_face = Face.ByWires(eb, new_ib_list)
2495
2506
  for obs in flat_obstacles:
@@ -2508,7 +2519,7 @@ class Face():
2508
2519
  edges = []
2509
2520
  for target in targets:
2510
2521
  if Vertex.Distance(flat_vertex, target) > tolerance:
2511
- e = Edge.ByVertices(flat_vertex, target, silent=True)
2522
+ e = Edge.ByVertices([flat_vertex, target], tolerance=tolerance, silent=True)
2512
2523
  e = Edge.SetLength(e, length=max_d, bothSides=False, tolerance=tolerance)
2513
2524
  edges.append(e)
2514
2525
  shell = Topology.Slice(flat_face, Cluster.ByTopologies(edges))
@@ -2533,11 +2544,12 @@ class Face():
2533
2544
  sv = vertices[Vertex.Index(Edge.StartVertex(edge), vertices, tolerance=0.01)]
2534
2545
  ev = vertices[Vertex.Index(Edge.EndVertex(edge), vertices, tolerance=0.01)]
2535
2546
  if Vertex.Distance(sv, ev) > tolerance:
2536
- new_edges.append(Edge.ByVertices([sv,ev]))
2547
+ new_edges.append(Edge.ByVertices([sv,ev], tolerance=tolerance, silent=True))
2537
2548
  w = Wire.ByEdges(new_edges, tolerance=0.01)
2538
2549
  return_face = Face.ByWire(w)
2539
2550
  if not Topology.IsInstance(return_face, "Face"):
2540
- print("Face.Isovist - Error: Could not create isovist. Returning None.")
2551
+ if not silent:
2552
+ print("Face.Isovist - Error: Could not create isovist. Returning None.")
2541
2553
  return None
2542
2554
  compAngle = 0
2543
2555
  if fov == 360:
@@ -2555,9 +2567,10 @@ class Face():
2555
2567
  if not Topology.IsInstance(return_face, "face"):
2556
2568
  return_face = Topology.SelfMerge(return_face)
2557
2569
  if return_face == None:
2558
- print("Face.Isovist - Error: Could not create isovist. Returning None.")
2570
+ if not silent:
2571
+ print("Face.Isovist - Error: Could not create isovist. Returning None.")
2559
2572
  return None
2560
- simpler_face = Face.RemoveCollinearEdges(return_face)
2573
+ simpler_face = Face.RemoveCollinearEdges(return_face, angTolerance=0.1, tolerance=tolerance, silent=silent)
2561
2574
  if Topology.IsInstance(simpler_face, "face"):
2562
2575
  if transferDictionaries == True or metrics == True:
2563
2576
  j_edges = [Topology.Edges(t) for t in obstacles]
@@ -2729,10 +2742,10 @@ class Face():
2729
2742
  edges = Topology.Edges(return_face)
2730
2743
  for edge in edges:
2731
2744
  d = Topology.Dictionary(edge)
2732
- if Vertex.Distance(Edge.StartVertex(edge), v) > 0.0001:
2733
- e1 = Edge.ByVertices(Edge.StartVertex(edge), v)
2734
- if Vertex.Distance(Edge.EndVertex(edge), v) > 0.0001:
2735
- e2 = Edge.ByVertices(Edge.EndVertex(edge), v)
2745
+ if Vertex.Distance(Edge.StartVertex(edge), v) > tolerance:
2746
+ e1 = Edge.ByVertices([Edge.StartVertex(edge), v], tolerance=tolerance, silent=True)
2747
+ if Vertex.Distance(Edge.EndVertex(edge), v) > tolerance:
2748
+ e2 = Edge.ByVertices([Edge.EndVertex(edge), v], tolerance=tolerance, silent=True)
2736
2749
  triangle = Topology.SelfMerge(Cluster.ByTopologies(edge, e1, e2))
2737
2750
  if Topology.IsInstance(triangle, "wire"):
2738
2751
  if Wire.IsClosed(triangle):
@@ -2863,7 +2876,7 @@ class Face():
2863
2876
  return Face.ByWire(l_shape_wire, tolerance=tolerance, silent=silent)
2864
2877
 
2865
2878
  @staticmethod
2866
- def MedialAxis(face, resolution: int = 0, externalVertices: bool = False, internalVertices: bool = False, toLeavesOnly: bool = False, angTolerance: float = 0.1, tolerance: float = 0.0001):
2879
+ def MedialAxis(face, resolution: int = 0, externalVertices: bool = False, internalVertices: bool = False, toLeavesOnly: bool = False, angTolerance: float = 0.1, tolerance: float = 0.0001, silent: bool = False):
2867
2880
  """
2868
2881
  Returns a wire representing an approximation of the medial axis of the input topology. See https://en.wikipedia.org/wiki/Medial_axis.
2869
2882
 
@@ -2883,6 +2896,8 @@ class Face():
2883
2896
  The desired angular tolerance in degrees for removing collinear edges. The default is 0.1.
2884
2897
  tolerance : float , optional
2885
2898
  The desired tolerance. The default is 0.0001.
2899
+ silent : bool , optional
2900
+ If set to True, no error and warning messages are printed. Otherwise, they are. The default is False.
2886
2901
 
2887
2902
  Returns
2888
2903
  -------
@@ -2953,7 +2968,7 @@ class Face():
2953
2968
 
2954
2969
  tempWire = Topology.SelfMerge(Cluster.ByTopologies(medialAxisEdges), tolerance=tolerance)
2955
2970
  if Topology.IsInstance(tempWire, "Wire") and angTolerance > 0:
2956
- tempWire = Wire.RemoveCollinearEdges(tempWire, angTolerance=angTolerance)
2971
+ tempWire = Wire.RemoveCollinearEdges(tempWire, angTolerance=angTolerance, tolerance=tolerance, silent=silent)
2957
2972
  medialAxisEdges = Wire.Edges(tempWire)
2958
2973
  for v in theVertices:
2959
2974
  nv = Vertex.NearestVertex(v, tempWire, useKDTree=False)
@@ -2962,12 +2977,12 @@ class Face():
2962
2977
  if toLeavesOnly:
2963
2978
  adjVertices = Topology.AdjacentTopologies(nv, tempWire)
2964
2979
  if len(adjVertices) < 2:
2965
- medialAxisEdges.append(Edge.ByVertices([nv, v], tolerance=tolerance))
2980
+ medialAxisEdges.append(Edge.ByVertices([nv, v], tolerance=tolerance, silent=silent))
2966
2981
  else:
2967
- medialAxisEdges.append(Edge.ByVertices([nv, v], tolerance=tolerance))
2982
+ medialAxisEdges.append(Edge.ByVertices([nv, v], tolerance=tolerance, silent=silent))
2968
2983
  medialAxis = Topology.SelfMerge(Cluster.ByTopologies(medialAxisEdges), tolerance=tolerance)
2969
2984
  if Topology.IsInstance(medialAxis, "Wire") and angTolerance > 0:
2970
- medialAxis = Topology.RemoveCollinearEdges(medialAxis, angTolerance=angTolerance)
2985
+ medialAxis = Topology.RemoveCollinearEdges(medialAxis, angTolerance=angTolerance, tolerance=tolerance, silent=silent)
2971
2986
  medialAxis = Topology.Unflatten(medialAxis, origin=origin,direction=normal)
2972
2987
  return medialAxis
2973
2988
 
@@ -3281,7 +3296,7 @@ class Face():
3281
3296
  return Face.ByWire(wire, tolerance=tolerance)
3282
3297
 
3283
3298
  @staticmethod
3284
- def RemoveCollinearEdges(face, angTolerance: float = 0.1, tolerance: float = 0.0001):
3299
+ def RemoveCollinearEdges(face, angTolerance: float = 0.1, tolerance: float = 0.0001, silent: bool = False):
3285
3300
  """
3286
3301
  Removes any collinear edges in the input face.
3287
3302
 
@@ -3293,6 +3308,8 @@ class Face():
3293
3308
  The desired angular tolerance. The default is 0.1.
3294
3309
  tolerance : float , optional
3295
3310
  The desired tolerance. The default is 0.0001.
3311
+ silent : bool , optional
3312
+ If set to True, no error and warning messages are printed. Otherwise, they are. The default is False.
3296
3313
 
3297
3314
  Returns
3298
3315
  -------
@@ -3305,13 +3322,14 @@ class Face():
3305
3322
  import inspect
3306
3323
 
3307
3324
  if not Topology.IsInstance(face, "Face"):
3308
- print("Face.RemoveCollinearEdges - Error: The input face parameter is not a valid face. Returning None.")
3309
- curframe = inspect.currentframe()
3310
- calframe = inspect.getouterframes(curframe, 2)
3311
- print('caller name:', calframe[1][3])
3325
+ if not silent:
3326
+ print("Face.RemoveCollinearEdges - Error: The input face parameter is not a valid face. Returning None.")
3327
+ curframe = inspect.currentframe()
3328
+ calframe = inspect.getouterframes(curframe, 2)
3329
+ print('caller name:', calframe[1][3])
3312
3330
  return None
3313
- eb = Wire.RemoveCollinearEdges(Face.Wire(face), angTolerance=angTolerance, tolerance=tolerance)
3314
- ib = [Wire.RemoveCollinearEdges(w, angTolerance=angTolerance, tolerance=tolerance) for w in Face.InternalBoundaries(face)]
3331
+ eb = Wire.RemoveCollinearEdges(Face.Wire(face), angTolerance=angTolerance, tolerance=tolerance, silent=silent)
3332
+ ib = [Wire.RemoveCollinearEdges(w, angTolerance=angTolerance, tolerance=tolerance, silent=silent) for w in Face.InternalBoundaries(face)]
3315
3333
  return Face.ByWires(eb, ib)
3316
3334
 
3317
3335
  @staticmethod
topologicpy/Graph.py CHANGED
@@ -171,7 +171,7 @@ class WorkerProcess(Process):
171
171
  if self.used[i + self.start_index][j] == 1 or self.used[j][i + self.start_index]:
172
172
  continue
173
173
  if Vertex.Distance(source, destination) > self.tolerance:
174
- edge = Edge.ByVertices([source, destination])
174
+ edge = Edge.ByVertices([source, destination], tolerance=self.tolerance, silent=True)
175
175
  e = Topology.Intersect(edge, face)
176
176
  if Topology.IsInstance(e, "Edge"):
177
177
  edges.append(edge)
@@ -437,7 +437,7 @@ class Graph:
437
437
  for vertex in vertices:
438
438
  graph_vertices, nv = addIfUnique(graph_vertices, vertex, tolerance=tolerance)
439
439
  new_vertices.append(nv)
440
- new_edge = Edge.ByVertices([new_vertices[0], new_vertices[1]], tolerance=tolerance)
440
+ new_edge = Edge.ByVertices([new_vertices[0], new_vertices[1]], tolerance=tolerance, silent=silent)
441
441
  if transferEdgeDictionaries == True:
442
442
  d = Topology.Dictionary(edge)
443
443
  keys = Dictionary.Keys(d)
@@ -10133,6 +10133,153 @@ class Graph:
10133
10133
  edge = Topology.SetDictionary(edge, d)
10134
10134
  return max_flow
10135
10135
 
10136
+ @staticmethod
10137
+ def MergeVertices(graph, *vertices, targetVertex=None, transferDictionaries: bool = True, tolerance: float = 0.0001, silent: bool = False):
10138
+ """
10139
+ Merges the input vertices into one vertex and reconnects all edges to the new vertex.
10140
+ If two of the input vertices are the end points of the same edge, that edge is deleted.
10141
+
10142
+ Parameters
10143
+ ----------
10144
+ graph : topologic_core.Graph
10145
+ The input graph.
10146
+ *vertices : topologic_core.Vertex
10147
+ Two or more instances of `topologic_core.Topology` to be processed.
10148
+ targetVertex : topologic_core.Vertex, optional
10149
+ The target vertex to merge into. If None, a centroid is computed. Default is None.
10150
+ transferDictionaries : bool, optional
10151
+ If True, the dictionaries of all input vertices (including the target vertex if given) are merged. Default is True.
10152
+ tolerance : float , optional
10153
+ The desired tolerance. The default is 0.0001.
10154
+ silent : bool , optional
10155
+ If set to True, no error and warning messages are printed. Otherwise, they are. The default is False.
10156
+
10157
+ Returns
10158
+ -------
10159
+ topologic_core.Graph
10160
+ A new graph with the vertices merged and edges updated.
10161
+ """
10162
+ from topologicpy.Cluster import Cluster
10163
+ from topologicpy.Topology import Topology
10164
+ from topologicpy.Edge import Edge
10165
+ from topologicpy.Dictionary import Dictionary
10166
+ from topologicpy.Helper import Helper
10167
+ import inspect
10168
+
10169
+ if not Topology.IsInstance(graph, "Graph"):
10170
+ print("Graph:", graph)
10171
+ if not silent:
10172
+ print("Graph.MergeVertices - Error: The input graph is not valid. Returning None.")
10173
+ return None
10174
+
10175
+ if len(vertices) == 0:
10176
+ if not silent:
10177
+ print("Graph.MergeVertices - Error: The input vertices parameter is an empty list. Returning None.")
10178
+ curframe = inspect.currentframe()
10179
+ calframe = inspect.getouterframes(curframe, 2)
10180
+ print('caller name:', calframe[1][3])
10181
+ return None
10182
+ if len(vertices) == 1:
10183
+ vertices = vertices[0]
10184
+ if isinstance(vertices, list):
10185
+ if len(vertices) == 0:
10186
+ if not silent:
10187
+ print("Graph.MergeVertices - Error: The input topologies parameter is an empty list. Returning None.")
10188
+ curframe = inspect.currentframe()
10189
+ calframe = inspect.getouterframes(curframe, 2)
10190
+ print('caller name:', calframe[1][3])
10191
+ return None
10192
+ else:
10193
+ vertexList = [x for x in vertices if Topology.IsInstance(x, "Topology")]
10194
+ if len(vertexList) == 0:
10195
+ if not silent:
10196
+ print("Graph.MergeVertices - Error: The input topologies parameter does not contain any valid vertices. Returning None.")
10197
+ curframe = inspect.currentframe()
10198
+ calframe = inspect.getouterframes(curframe, 2)
10199
+ print('caller name:', calframe[1][3])
10200
+ return None
10201
+ else:
10202
+ if not silent:
10203
+ print("Graph.MergeVertices - Error: The input vertices parameter contains only one vertex. Returning None.")
10204
+ curframe = inspect.currentframe()
10205
+ calframe = inspect.getouterframes(curframe, 2)
10206
+ print('caller name:', calframe[1][3])
10207
+ return None
10208
+ else:
10209
+ vertexList = Helper.Flatten(list(vertices))
10210
+ vertexList = [x for x in vertexList if Topology.IsInstance(x, "Vertex")]
10211
+ if len(vertexList) == 0:
10212
+ if not silent:
10213
+ print("Graph.MergeVertices - Error: The input parameters do not contain any valid vertices. Returning None.")
10214
+ curframe = inspect.currentframe()
10215
+ calframe = inspect.getouterframes(curframe, 2)
10216
+ print('caller name:', calframe[1][3])
10217
+ return None
10218
+
10219
+ # Step 1: gather all vertices and edges
10220
+ all_vertices = Graph.Vertices(graph)
10221
+ all_edges = Graph.Edges(graph)
10222
+
10223
+ # Step 2: determine merged vertex
10224
+ dictionaries = []
10225
+ if targetVertex and Topology.IsInstance(targetVertex, "Vertex"):
10226
+ merged_vertex = targetVertex
10227
+ if targetVertex not in all_vertices:
10228
+ all_vertices.append(targetVertex)
10229
+ dictionaries.append(Topology.Dictionary(targetVertex))
10230
+ else:
10231
+ # Compute centroid
10232
+ merged_vertex = Topology.Centroid(Cluster.ByTopologies(vertexList))
10233
+
10234
+ # Step 3: collect dictionaries
10235
+ if transferDictionaries:
10236
+ for v in vertexList:
10237
+ d = Topology.Dictionary(v)
10238
+ dictionaries.append(d)
10239
+ merged_dict = Dictionary.ByMergedDictionaries(*dictionaries)
10240
+ merged_vertex = Topology.SetDictionary(merged_vertex, merged_dict, silent=True)
10241
+
10242
+ # Step 4: remove merged vertices from all_vertices
10243
+ for v in vertexList:
10244
+ for gv in all_vertices:
10245
+ if Topology.IsSame(v, gv):
10246
+ all_vertices.remove(gv)
10247
+ break
10248
+
10249
+ # Step 5: rebuild edge list
10250
+ new_edges = []
10251
+ seen = set()
10252
+ for edge in all_edges:
10253
+ sv = Edge.StartVertex(edge)
10254
+ ev = Edge.EndVertex(edge)
10255
+
10256
+ sv_merged = any(Topology.IsSame(sv, v) for v in vertexList)
10257
+ ev_merged = any(Topology.IsSame(ev, v) for v in vertexList)
10258
+
10259
+ if sv_merged and ev_merged:
10260
+ continue # Remove edges between merged vertices
10261
+
10262
+ new_sv = merged_vertex if sv_merged else sv
10263
+ new_ev = merged_vertex if ev_merged else ev
10264
+
10265
+ if Topology.IsSame(new_sv, new_ev):
10266
+ continue # Avoid self-loop
10267
+
10268
+ key = tuple(sorted([Topology.UUID(new_sv), Topology.UUID(new_ev)]))
10269
+ if key in seen:
10270
+ continue
10271
+ seen.add(key)
10272
+
10273
+ new_edge = Edge.ByVertices([new_sv, new_ev])
10274
+ if Topology.IsInstance(new_edge, "edge"):
10275
+ d = Topology.Dictionary(edge)
10276
+ if d:
10277
+ new_edge = Topology.SetDictionary(new_edge, d, silent=True)
10278
+ new_edges.append(new_edge)
10279
+
10280
+ all_vertices.append(merged_vertex)
10281
+ return Graph.ByVerticesEdges(all_vertices, new_edges)
10282
+
10136
10283
  @staticmethod
10137
10284
  def MeshData(graph, mantissa: int = 6, tolerance: float = 0.0001):
10138
10285
  """
topologicpy/Plotly.py CHANGED
@@ -730,7 +730,6 @@ class Plotly:
730
730
  legendgroup=legendGroup,
731
731
  legendrank=legendRank,
732
732
  text=labels,
733
- customdata=labels,
734
733
  hoverinfo='text',
735
734
  hovertext=labels)
736
735
  traces.append(trace)
@@ -384,7 +384,7 @@ class ShapeGrammar:
384
384
 
385
385
  return result_output
386
386
 
387
- def FigureByInputOutput(self, input, output, silent: bool = False):
387
+ def ClusterByInputOutput(self, input, output, silent: bool = False):
388
388
  """
389
389
  Returns the Plotly figure of the input and output topologies as a rule.
390
390
 
@@ -407,15 +407,14 @@ class ShapeGrammar:
407
407
  from topologicpy.Topology import Topology
408
408
  from topologicpy.Dictionary import Dictionary
409
409
  from topologicpy.Cluster import Cluster
410
- from topologicpy.Plotly import Plotly
411
410
 
412
411
  if not Topology.IsInstance(input, "Topology"):
413
412
  if not silent:
414
- print("ShapeGrammar.DrawInputOutput - Error: The input topology parameter is not a valid topology. Returning None.")
413
+ print("ShapeGrammar.ClusterByInputOutput - Error: The input topology parameter is not a valid topology. Returning None.")
415
414
  return None
416
415
  if not Topology.IsInstance(output, "Topology"):
417
416
  if not silent:
418
- print("ShapeGrammar.DrawInputOutput - Error: The output topology parameter is not a valid topology. Returning None.")
417
+ print("ShapeGrammar.ClusterByInputOutput - Error: The output topology parameter is not a valid topology. Returning None.")
419
418
  return None
420
419
 
421
420
  input_bb = Topology.BoundingBox(input)
@@ -463,6 +462,65 @@ class ShapeGrammar:
463
462
  cone = Topology.Translate(cone, 1.65, 0, 0)
464
463
  cluster = Cluster.ByTopologies([temp_input, temp_output, cyl, cone])
465
464
  cluster = Topology.Place(cluster, originA=Topology.Centroid(cluster), originB=Vertex.Origin())
465
+ return cluster
466
+
467
+ def ClusterByRule(self, rule, silent: bool = False):
468
+ """
469
+ Returns the Plotly figure of the input rule.
470
+
471
+ Parameters
472
+ ----------
473
+ rule : dict
474
+ The input rule
475
+ silent : bool, optional
476
+ If True, suppresses error/warning messages. Default is False.
477
+
478
+ Returns
479
+ -------
480
+ topologic_core.Cluster
481
+ The created rule cluster
482
+ """
483
+
484
+ if not isinstance(rule, dict):
485
+ if not silent:
486
+ print("ShapeGrammar.ClusterByRule - Error: The input rule parameter is not a valid rule. Returning None.")
487
+ return None
488
+ input = rule["input"]
489
+ output = self.ApplyRule(input, rule)
490
+ return self.ClusterByInputOutput(input, output, silent=silent)
491
+
492
+ def FigureByInputOutput(self, input, output, silent: bool = False):
493
+ """
494
+ Returns the Plotly figure of the input and output topologies as a rule.
495
+
496
+ Parameters
497
+ ----------
498
+ input : topologic_core.Topology
499
+ The input topology
500
+ output : topologic_core.Topology
501
+ The output topology
502
+ silent : bool, optional
503
+ If True, suppresses error/warning messages. Default is False.
504
+
505
+ Returns
506
+ -------
507
+ Plotly.Figure
508
+ The created plotly figure.
509
+ """
510
+
511
+ from topologicpy.Topology import Topology
512
+ from topologicpy.Plotly import Plotly
513
+
514
+ if not Topology.IsInstance(input, "Topology"):
515
+ if not silent:
516
+ print("ShapeGrammar.FigureByInputOutput - Error: The input topology parameter is not a valid topology. Returning None.")
517
+ return None
518
+ if not Topology.IsInstance(output, "Topology"):
519
+ if not silent:
520
+ print("ShapeGrammar.FigureByInputOutput - Error: The output topology parameter is not a valid topology. Returning None.")
521
+ return None
522
+
523
+ cluster = self.ClusterByInputOutput(input, output, silent=silent)
466
524
  data = Plotly.DataByTopology(cluster)
467
525
  fig = Plotly.FigureByData(data)
468
526
  return fig
@@ -480,7 +538,8 @@ class ShapeGrammar:
480
538
 
481
539
  Returns
482
540
  -------
483
- This function does not return a value
541
+ Plotly.Figure
542
+ The create plotly figure
484
543
  """
485
544
  from topologicpy.Topology import Topology
486
545
  if not isinstance(rule, dict):
@@ -489,4 +548,4 @@ class ShapeGrammar:
489
548
  return None
490
549
  input = rule["input"]
491
550
  output = self.ApplyRule(input, rule)
492
- return self.FigureByInputOutput(input, output)
551
+ return self.FigureByInputOutput(input, output, silent=silent)