topologicpy 0.8.30__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/BVH.py +5 -3
- topologicpy/CSG.py +1 -1
- topologicpy/Cell.py +12 -7
- topologicpy/Cluster.py +4 -2
- topologicpy/Edge.py +45 -28
- topologicpy/Face.py +65 -47
- topologicpy/Graph.py +149 -2
- topologicpy/Plotly.py +0 -1
- topologicpy/ShapeGrammar.py +65 -6
- topologicpy/Topology.py +49 -409
- topologicpy/Wire.py +33 -18
- topologicpy/version.py +1 -1
- {topologicpy-0.8.30.dist-info → topologicpy-0.8.31.dist-info}/METADATA +1 -1
- {topologicpy-0.8.30.dist-info → topologicpy-0.8.31.dist-info}/RECORD +17 -17
- {topologicpy-0.8.30.dist-info → topologicpy-0.8.31.dist-info}/WHEEL +1 -1
- {topologicpy-0.8.30.dist-info → topologicpy-0.8.31.dist-info}/licenses/LICENSE +0 -0
- {topologicpy-0.8.30.dist-info → topologicpy-0.8.31.dist-info}/top_level.txt +0 -0
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(
|
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
|
-
|
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
|
-
|
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
|
-
|
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) >
|
2733
|
-
e1 = Edge.ByVertices(Edge.StartVertex(edge), v)
|
2734
|
-
if Vertex.Distance(Edge.EndVertex(edge), v) >
|
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
|
-
|
3309
|
-
|
3310
|
-
|
3311
|
-
|
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
topologicpy/ShapeGrammar.py
CHANGED
@@ -384,7 +384,7 @@ class ShapeGrammar:
|
|
384
384
|
|
385
385
|
return result_output
|
386
386
|
|
387
|
-
def
|
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.
|
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.
|
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
|
-
|
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)
|