topologicpy 0.8.33__py3-none-any.whl → 0.8.36__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 +4 -4
- topologicpy/CSG.py +5 -5
- topologicpy/Cell.py +17 -17
- topologicpy/CellComplex.py +3 -188
- topologicpy/Cluster.py +2 -2
- topologicpy/Dictionary.py +121 -2
- topologicpy/Edge.py +14 -14
- topologicpy/Face.py +31 -31
- topologicpy/Graph.py +105 -65
- topologicpy/Helper.py +56 -4
- topologicpy/Matrix.py +3 -3
- topologicpy/Neo4j.py +1 -1
- topologicpy/Plotly.py +29 -7
- topologicpy/ShapeGrammar.py +7 -7
- topologicpy/Shell.py +123 -96
- topologicpy/Topology.py +231 -46
- topologicpy/Vector.py +5 -5
- topologicpy/Vertex.py +6 -6
- topologicpy/Wire.py +21 -21
- topologicpy/version.py +1 -1
- {topologicpy-0.8.33.dist-info → topologicpy-0.8.36.dist-info}/METADATA +1 -1
- topologicpy-0.8.36.dist-info/RECORD +38 -0
- topologicpy-0.8.33.dist-info/RECORD +0 -38
- {topologicpy-0.8.33.dist-info → topologicpy-0.8.36.dist-info}/WHEEL +0 -0
- {topologicpy-0.8.33.dist-info → topologicpy-0.8.36.dist-info}/licenses/LICENSE +0 -0
- {topologicpy-0.8.33.dist-info → topologicpy-0.8.36.dist-info}/top_level.txt +0 -0
topologicpy/Plotly.py
CHANGED
@@ -300,6 +300,8 @@ class Plotly:
|
|
300
300
|
edgeColorKey: str = None,
|
301
301
|
edgeWidth: float = 1,
|
302
302
|
edgeWidthKey: str = None,
|
303
|
+
edgeDash: bool = False,
|
304
|
+
edgeDashKey: str = None,
|
303
305
|
edgeLabelKey: str = None,
|
304
306
|
edgeGroupKey: str = None,
|
305
307
|
edgeGroups: list = [],
|
@@ -378,6 +380,10 @@ class Plotly:
|
|
378
380
|
The dictionary key under which to find the edge width. The default is None.
|
379
381
|
edgeLabelKey : str , optional
|
380
382
|
The dictionary key to use to display the edge label. The default is None.
|
383
|
+
edgeDash : bool , optional
|
384
|
+
If set to True, the edges are drawn as dashed lines. The default is False.
|
385
|
+
edgeDashKey : str , optional
|
386
|
+
The key under which to find the boolean flag to draw edges as dashed lines. The default is None.
|
381
387
|
edgeGroupKey : str , optional
|
382
388
|
The dictionary key to use to display the edge group. The default is None.
|
383
389
|
edgeGroups : list , optional
|
@@ -391,7 +397,7 @@ class Plotly:
|
|
391
397
|
colorScale : str , optional
|
392
398
|
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/.
|
393
399
|
silent : bool , optional
|
394
|
-
If set to True,
|
400
|
+
If set to True, error and warning messages are suppressed. The default is False.
|
395
401
|
|
396
402
|
Returns
|
397
403
|
-------
|
@@ -473,7 +479,7 @@ class Plotly:
|
|
473
479
|
geo = Topology.Geometry(e_cluster, mantissa=mantissa)
|
474
480
|
vertices = geo['vertices']
|
475
481
|
edges = geo['edges']
|
476
|
-
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))
|
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))
|
477
483
|
return data
|
478
484
|
|
479
485
|
@staticmethod
|
@@ -632,7 +638,7 @@ class Plotly:
|
|
632
638
|
return return_value
|
633
639
|
|
634
640
|
@staticmethod
|
635
|
-
def edgeData(vertices, edges, dictionaries=None, color="black", colorKey=None, width=1, widthKey=None, labelKey=None, showEdgeLabel = False, groupKey=None, minGroup=None, maxGroup=None, groups=[], legendLabel="Topology Edges", legendGroup=2, legendRank=2, showLegend=True, colorScale="Viridis"):
|
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"):
|
636
642
|
|
637
643
|
from topologicpy.Color import Color
|
638
644
|
from topologicpy.Dictionary import Dictionary
|
@@ -670,8 +676,8 @@ class Plotly:
|
|
670
676
|
maxGroup = 1
|
671
677
|
|
672
678
|
|
673
|
-
if colorKey or widthKey or labelKey or groupKey:
|
674
|
-
keys = [x for x in [colorKey, widthKey, labelKey, groupKey] if not x == None]
|
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]
|
675
681
|
temp_dict = Helper.ClusterByKeys(edges, dictionaries, keys, silent=False)
|
676
682
|
dict_clusters = temp_dict["dictionaries"]
|
677
683
|
elements_clusters = temp_dict['elements']
|
@@ -684,6 +690,8 @@ class Plotly:
|
|
684
690
|
if not colorKey == None:
|
685
691
|
d_color = Dictionary.ValueAtKey(d, key=colorKey) or color
|
686
692
|
d_color = Color.AnyToHex(d_color)
|
693
|
+
if not dashKey == None:
|
694
|
+
d_dash = Dictionary.ValueAtKey(d, key=dashKey) or dash
|
687
695
|
if not labelKey == None:
|
688
696
|
labels.append(str(Dictionary.ValueAtKey(d, labelKey, "")))
|
689
697
|
if not widthKey == None:
|
@@ -719,6 +727,10 @@ class Plotly:
|
|
719
727
|
marker_width = width[0]*0.25
|
720
728
|
else:
|
721
729
|
marker_width = width*0.25
|
730
|
+
if dash:
|
731
|
+
dot = "dot"
|
732
|
+
else:
|
733
|
+
dot = "solid"
|
722
734
|
trace = go.Scatter3d(x=x,
|
723
735
|
y=y,
|
724
736
|
z=z,
|
@@ -726,7 +738,7 @@ class Plotly:
|
|
726
738
|
showlegend=showLegend,
|
727
739
|
marker=dict(symbol="circle", size=marker_width, color=color),
|
728
740
|
mode=mode,
|
729
|
-
line=dict(color=d_color, width=width),
|
741
|
+
line=dict(color=d_color, width=width, dash=dot),
|
730
742
|
legendgroup=legendGroup,
|
731
743
|
legendrank=legendRank,
|
732
744
|
text=labels,
|
@@ -747,6 +759,10 @@ class Plotly:
|
|
747
759
|
mode = "lines+text"
|
748
760
|
else:
|
749
761
|
mode = "lines"
|
762
|
+
if dash:
|
763
|
+
dot = "dot"
|
764
|
+
else:
|
765
|
+
dot = "solid"
|
750
766
|
trace = go.Scatter3d(x=x,
|
751
767
|
y=y,
|
752
768
|
z=z,
|
@@ -754,7 +770,7 @@ class Plotly:
|
|
754
770
|
showlegend=showLegend,
|
755
771
|
marker_size=0,
|
756
772
|
mode=mode,
|
757
|
-
line=dict(color=color, width=width),
|
773
|
+
line=dict(color=color, width=width, dash=dot),
|
758
774
|
legendgroup=legendGroup,
|
759
775
|
legendrank=legendRank,
|
760
776
|
text=label,
|
@@ -788,6 +804,8 @@ class Plotly:
|
|
788
804
|
edgeWidthKey=None,
|
789
805
|
edgeColor="black",
|
790
806
|
edgeColorKey=None,
|
807
|
+
edgeDash=False,
|
808
|
+
edgeDashKey=None,
|
791
809
|
edgeLabelKey=None,
|
792
810
|
showEdgeLabel=False,
|
793
811
|
edgeGroupKey=None,
|
@@ -883,6 +901,10 @@ class Plotly:
|
|
883
901
|
The default is "black".
|
884
902
|
edgeColorKey : str , optional
|
885
903
|
The dictionary key under which to find the edge color.The default is None.
|
904
|
+
edgeDash : bool , optional
|
905
|
+
If set to True, the edges are drawn as dashed lines. The default is False.
|
906
|
+
edgeDashKey : str , optional
|
907
|
+
The key under which to find the boolean flag to draw edges as dashed lines. The default is None.
|
886
908
|
edgeLabelKey : str , optional
|
887
909
|
The dictionary key to use to display the edge label. The default is None.
|
888
910
|
edgeGroupKey : str , optional
|
topologicpy/ShapeGrammar.py
CHANGED
@@ -150,7 +150,7 @@ class ShapeGrammar:
|
|
150
150
|
matrix : list
|
151
151
|
The 4x4 transformation matrix that tranforms the output topology to the input topology. If set to None, no transformation is applied. The default is None.
|
152
152
|
silent : bool, optional
|
153
|
-
If True,
|
153
|
+
If set to True, error and warning messages are suppressed. Default is False.
|
154
154
|
|
155
155
|
Returns
|
156
156
|
-------
|
@@ -205,7 +205,7 @@ class ShapeGrammar:
|
|
205
205
|
keys : list , optional
|
206
206
|
The list of dictionary keys to semantically match the rules. The default is None which means dictionaries are not considered.
|
207
207
|
silent : bool, optional
|
208
|
-
If True,
|
208
|
+
If set to True, error and warning messages are suppressed. Default is False.
|
209
209
|
|
210
210
|
Returns
|
211
211
|
-------
|
@@ -258,7 +258,7 @@ class ShapeGrammar:
|
|
258
258
|
tolerance : float, optional
|
259
259
|
The desired Tolerance. Not used here but included for API compatibility. Default is 0.0001.
|
260
260
|
silent : bool, optional
|
261
|
-
If True,
|
261
|
+
If set to True, error and warning messages are suppressed. Default is False.
|
262
262
|
|
263
263
|
Returns
|
264
264
|
-------
|
@@ -395,7 +395,7 @@ class ShapeGrammar:
|
|
395
395
|
output : topologic_core.Topology
|
396
396
|
The output topology
|
397
397
|
silent : bool, optional
|
398
|
-
If True,
|
398
|
+
If set to True, error and warning messages are suppressed. Default is False.
|
399
399
|
|
400
400
|
Returns
|
401
401
|
-------
|
@@ -473,7 +473,7 @@ class ShapeGrammar:
|
|
473
473
|
rule : dict
|
474
474
|
The input rule
|
475
475
|
silent : bool, optional
|
476
|
-
If True,
|
476
|
+
If set to True, error and warning messages are suppressed. Default is False.
|
477
477
|
|
478
478
|
Returns
|
479
479
|
-------
|
@@ -500,7 +500,7 @@ class ShapeGrammar:
|
|
500
500
|
output : topologic_core.Topology
|
501
501
|
The output topology
|
502
502
|
silent : bool, optional
|
503
|
-
If True,
|
503
|
+
If set to True, error and warning messages are suppressed. Default is False.
|
504
504
|
|
505
505
|
Returns
|
506
506
|
-------
|
@@ -534,7 +534,7 @@ class ShapeGrammar:
|
|
534
534
|
rule : dict
|
535
535
|
The input rule
|
536
536
|
silent : bool, optional
|
537
|
-
If True,
|
537
|
+
If set to True, error and warning messages are suppressed. Default is False.
|
538
538
|
|
539
539
|
Returns
|
540
540
|
-------
|
topologicpy/Shell.py
CHANGED
@@ -280,7 +280,7 @@ class Shell():
|
|
280
280
|
tolerance : float , optional
|
281
281
|
The desired tolerance. The default is 0.0001.
|
282
282
|
silent : bool , optional
|
283
|
-
If set to True,
|
283
|
+
If set to True, error and warning messages are suppressed. The default is False.
|
284
284
|
|
285
285
|
Returns
|
286
286
|
-------
|
@@ -392,7 +392,7 @@ class Shell():
|
|
392
392
|
tolerance : float , optional
|
393
393
|
The desired tolerance. The default is 0.0001.
|
394
394
|
silent : bool , optional
|
395
|
-
If set to True,
|
395
|
+
If set to True, error and warning messages are suppressed. The default is False.
|
396
396
|
|
397
397
|
Returns
|
398
398
|
-------
|
@@ -528,7 +528,7 @@ class Shell():
|
|
528
528
|
tolerance : float , optional
|
529
529
|
The desired tolerance. The default is 0.0001.
|
530
530
|
silent : bool , optional
|
531
|
-
If set to True,
|
531
|
+
If set to True, error and warning messages are suppressed. The default is False.
|
532
532
|
|
533
533
|
Returns
|
534
534
|
-------
|
@@ -739,42 +739,6 @@ class Shell():
|
|
739
739
|
_ = shell.Faces(None, faces)
|
740
740
|
return faces
|
741
741
|
|
742
|
-
@staticmethod
|
743
|
-
def IsOnBoundary(shell, vertex, tolerance: float = 0.0001) -> bool:
|
744
|
-
"""
|
745
|
-
Returns True if the input vertex is on the boundary of the input shell. Returns False otherwise. On the boundary is defined as being on the boundary of one of the shell's external or internal boundaries
|
746
|
-
|
747
|
-
Parameters
|
748
|
-
----------
|
749
|
-
shell : topologic_core.Shell
|
750
|
-
The input shell.
|
751
|
-
vertex : topologic_core.Vertex
|
752
|
-
The input vertex.
|
753
|
-
tolerance : float , optional
|
754
|
-
The desired tolerance. The default is 0.0001.
|
755
|
-
|
756
|
-
Returns
|
757
|
-
-------
|
758
|
-
bool
|
759
|
-
Returns True if the input vertex is inside the input shell. Returns False otherwise.
|
760
|
-
|
761
|
-
"""
|
762
|
-
from topologicpy.Vertex import Vertex
|
763
|
-
from topologicpy.Topology import Topology
|
764
|
-
|
765
|
-
if not Topology.IsInstance(shell, "Shell"):
|
766
|
-
return None
|
767
|
-
if not Topology.IsInstance(vertex, "Vertex"):
|
768
|
-
return None
|
769
|
-
boundary = Shell.ExternalBoundary(shell, tolerance=tolerance)
|
770
|
-
if Vertex.IsInternal(vertex, boundary, tolerance=tolerance):
|
771
|
-
return True
|
772
|
-
internal_boundaries = Shell.InternalBoundaries(shell, tolerance=tolerance)
|
773
|
-
for ib in internal_boundaries:
|
774
|
-
if Vertex.IsInternal(vertex, ib, tolerance=tolerance):
|
775
|
-
return True
|
776
|
-
return False
|
777
|
-
|
778
742
|
@staticmethod
|
779
743
|
def HyperbolicParaboloidRectangularDomain(origin= None,
|
780
744
|
llVertex= None,
|
@@ -1097,6 +1061,41 @@ class Shell():
|
|
1097
1061
|
"""
|
1098
1062
|
return shell.IsClosed()
|
1099
1063
|
|
1064
|
+
@staticmethod
|
1065
|
+
def IsOnBoundary(shell, vertex, tolerance: float = 0.0001) -> bool:
|
1066
|
+
"""
|
1067
|
+
Returns True if the input vertex is on the boundary of the input shell. Returns False otherwise. On the boundary is defined as being on the boundary of one of the shell's external or internal boundaries
|
1068
|
+
|
1069
|
+
Parameters
|
1070
|
+
----------
|
1071
|
+
shell : topologic_core.Shell
|
1072
|
+
The input shell.
|
1073
|
+
vertex : topologic_core.Vertex
|
1074
|
+
The input vertex.
|
1075
|
+
tolerance : float , optional
|
1076
|
+
The desired tolerance. The default is 0.0001.
|
1077
|
+
|
1078
|
+
Returns
|
1079
|
+
-------
|
1080
|
+
bool
|
1081
|
+
Returns True if the input vertex is inside the input shell. Returns False otherwise.
|
1082
|
+
|
1083
|
+
"""
|
1084
|
+
from topologicpy.Vertex import Vertex
|
1085
|
+
from topologicpy.Topology import Topology
|
1086
|
+
|
1087
|
+
if not Topology.IsInstance(shell, "Shell"):
|
1088
|
+
return None
|
1089
|
+
if not Topology.IsInstance(vertex, "Vertex"):
|
1090
|
+
return None
|
1091
|
+
boundary = Shell.ExternalBoundary(shell, tolerance=tolerance)
|
1092
|
+
if Vertex.IsInternal(vertex, boundary, tolerance=tolerance):
|
1093
|
+
return True
|
1094
|
+
internal_boundaries = Shell.InternalBoundaries(shell, tolerance=tolerance)
|
1095
|
+
for ib in internal_boundaries:
|
1096
|
+
if Vertex.IsInternal(vertex, ib, tolerance=tolerance):
|
1097
|
+
return True
|
1098
|
+
return False
|
1100
1099
|
|
1101
1100
|
@staticmethod
|
1102
1101
|
def Paraboloid(origin= None, focalLength=0.125, width: float = 1, length: float = 1, uSides: int = 16, vSides: int = 16,
|
@@ -1127,7 +1126,7 @@ class Shell():
|
|
1127
1126
|
tolerance : float , optional
|
1128
1127
|
The desired tolerance. The default is 0.0001.
|
1129
1128
|
silent : bool , optional
|
1130
|
-
If set to True,
|
1129
|
+
If set to True, error and warning messages are suppressed. The default is False.
|
1131
1130
|
|
1132
1131
|
Returns
|
1133
1132
|
-------
|
@@ -1644,62 +1643,6 @@ class Shell():
|
|
1644
1643
|
else:
|
1645
1644
|
return None
|
1646
1645
|
|
1647
|
-
def Skeleton(face, tolerance: float = 0.001):
|
1648
|
-
"""
|
1649
|
-
Creates a shell through a straight skeleton. This method is contributed by 高熙鹏 xipeng gao <gaoxipeng1998@gmail.com>
|
1650
|
-
This algorithm depends on the polyskel code which is included in the library. Polyskel code is found at: https://github.com/Botffy/polyskel
|
1651
|
-
|
1652
|
-
Parameters
|
1653
|
-
----------
|
1654
|
-
face : topologic_core.Face
|
1655
|
-
The input face.
|
1656
|
-
tolerance : float , optional
|
1657
|
-
The desired tolerance. The default is 0.001. (This is set to a larger number as it was found to work better)
|
1658
|
-
|
1659
|
-
Returns
|
1660
|
-
-------
|
1661
|
-
topologic_core.Shell
|
1662
|
-
The created straight skeleton.
|
1663
|
-
|
1664
|
-
"""
|
1665
|
-
from topologicpy.Wire import Wire
|
1666
|
-
from topologicpy.Face import Face
|
1667
|
-
from topologicpy.Topology import Topology
|
1668
|
-
import topologic_core as topologic
|
1669
|
-
import math
|
1670
|
-
|
1671
|
-
if not Topology.IsInstance(face, "Face"):
|
1672
|
-
return None
|
1673
|
-
roof = Wire.Skeleton(face, tolerance=tolerance)
|
1674
|
-
if not (Topology.IsInstance(roof, "Wire") or Topology.IsInstance(roof, "Cluster")):
|
1675
|
-
print("Shell.Skeleton - Error: Could not create base skeleton wire. Returning None.")
|
1676
|
-
return None
|
1677
|
-
br = Wire.BoundingRectangle(roof) #This works even if it is a Cluster not a Wire
|
1678
|
-
if not Topology.IsInstance(br, "Wire"):
|
1679
|
-
print("Shell.Skeleton - Error: Could not create a bounding rectangle wire. Returning None.")
|
1680
|
-
return None
|
1681
|
-
br = Topology.Scale(br, Topology.Centroid(br), 1.5, 1.5, 1)
|
1682
|
-
bf = Face.ByWire(br, tolerance=tolerance)
|
1683
|
-
if not Topology.IsInstance(bf, "Face"):
|
1684
|
-
print("Shell.Skeleton - Error: Could not create a bounding rectangle face. Returning None.")
|
1685
|
-
return None
|
1686
|
-
large_shell = Topology.Boolean(bf, roof, operation="slice", tolerance=tolerance)
|
1687
|
-
if not large_shell:
|
1688
|
-
return None
|
1689
|
-
faces = Topology.Faces(large_shell)
|
1690
|
-
if not faces:
|
1691
|
-
return None
|
1692
|
-
final_faces = []
|
1693
|
-
for f in faces:
|
1694
|
-
internalBoundaries = Face.InternalBoundaries(f)
|
1695
|
-
if len(internalBoundaries) == 0:
|
1696
|
-
final_faces.append(f)
|
1697
|
-
shell = Shell.ByFaces(final_faces, tolerance=tolerance)
|
1698
|
-
if not Topology.IsInstance(shell, "Shell"):
|
1699
|
-
print("Shell.Skeleton - Error: Could not create shell. Returning None.")
|
1700
|
-
return None
|
1701
|
-
return shell
|
1702
|
-
|
1703
1646
|
@staticmethod
|
1704
1647
|
def Simplify(shell, simplifyBoundary: bool = True, mantissa: int = 6, tolerance: float = 0.0001):
|
1705
1648
|
"""
|
@@ -1846,6 +1789,63 @@ class Shell():
|
|
1846
1789
|
final_result = Shell.ByFaces(final_faces, tolerance=tolerance)
|
1847
1790
|
return final_result
|
1848
1791
|
|
1792
|
+
@staticmethod
|
1793
|
+
def Skeleton(face, tolerance: float = 0.001):
|
1794
|
+
"""
|
1795
|
+
Creates a shell through a straight skeleton. This method is contributed by 高熙鹏 xipeng gao <gaoxipeng1998@gmail.com>
|
1796
|
+
This algorithm depends on the polyskel code which is included in the library. Polyskel code is found at: https://github.com/Botffy/polyskel
|
1797
|
+
|
1798
|
+
Parameters
|
1799
|
+
----------
|
1800
|
+
face : topologic_core.Face
|
1801
|
+
The input face.
|
1802
|
+
tolerance : float , optional
|
1803
|
+
The desired tolerance. The default is 0.001. (This is set to a larger number as it was found to work better)
|
1804
|
+
|
1805
|
+
Returns
|
1806
|
+
-------
|
1807
|
+
topologic_core.Shell
|
1808
|
+
The created straight skeleton.
|
1809
|
+
|
1810
|
+
"""
|
1811
|
+
from topologicpy.Wire import Wire
|
1812
|
+
from topologicpy.Face import Face
|
1813
|
+
from topologicpy.Topology import Topology
|
1814
|
+
import topologic_core as topologic
|
1815
|
+
import math
|
1816
|
+
|
1817
|
+
if not Topology.IsInstance(face, "Face"):
|
1818
|
+
return None
|
1819
|
+
roof = Wire.Skeleton(face, tolerance=tolerance)
|
1820
|
+
if not (Topology.IsInstance(roof, "Wire") or Topology.IsInstance(roof, "Cluster")):
|
1821
|
+
print("Shell.Skeleton - Error: Could not create base skeleton wire. Returning None.")
|
1822
|
+
return None
|
1823
|
+
br = Wire.BoundingRectangle(roof) #This works even if it is a Cluster not a Wire
|
1824
|
+
if not Topology.IsInstance(br, "Wire"):
|
1825
|
+
print("Shell.Skeleton - Error: Could not create a bounding rectangle wire. Returning None.")
|
1826
|
+
return None
|
1827
|
+
br = Topology.Scale(br, Topology.Centroid(br), 1.5, 1.5, 1)
|
1828
|
+
bf = Face.ByWire(br, tolerance=tolerance)
|
1829
|
+
if not Topology.IsInstance(bf, "Face"):
|
1830
|
+
print("Shell.Skeleton - Error: Could not create a bounding rectangle face. Returning None.")
|
1831
|
+
return None
|
1832
|
+
large_shell = Topology.Boolean(bf, roof, operation="slice", tolerance=tolerance)
|
1833
|
+
if not large_shell:
|
1834
|
+
return None
|
1835
|
+
faces = Topology.Faces(large_shell)
|
1836
|
+
if not faces:
|
1837
|
+
return None
|
1838
|
+
final_faces = []
|
1839
|
+
for f in faces:
|
1840
|
+
internalBoundaries = Face.InternalBoundaries(f)
|
1841
|
+
if len(internalBoundaries) == 0:
|
1842
|
+
final_faces.append(f)
|
1843
|
+
shell = Shell.ByFaces(final_faces, tolerance=tolerance)
|
1844
|
+
if not Topology.IsInstance(shell, "Shell"):
|
1845
|
+
print("Shell.Skeleton - Error: Could not create shell. Returning None.")
|
1846
|
+
return None
|
1847
|
+
return shell
|
1848
|
+
|
1849
1849
|
@staticmethod
|
1850
1850
|
def Square(origin= None, size: float = 1.0,
|
1851
1851
|
uSides: int = 2, vSides: int = 2, direction: list = [0, 0, 1],
|
@@ -1882,6 +1882,33 @@ class Shell():
|
|
1882
1882
|
uSides=uSides, vSides=vSides, direction=direction,
|
1883
1883
|
placement=placement, tolerance=tolerance)
|
1884
1884
|
|
1885
|
+
@staticmethod
|
1886
|
+
def _grow_connected_group(seed_idx, group_size, adjacency, visited_global):
|
1887
|
+
"""
|
1888
|
+
Attempts to grow a group of the given size starting from seed_idx using adjacency.
|
1889
|
+
Returns a list of indices if successful, else None.
|
1890
|
+
"""
|
1891
|
+
from collections import deque
|
1892
|
+
import random
|
1893
|
+
|
1894
|
+
group = [seed_idx]
|
1895
|
+
visited = set(group)
|
1896
|
+
queue = deque([seed_idx])
|
1897
|
+
|
1898
|
+
while queue and len(group) < group_size:
|
1899
|
+
current = queue.popleft()
|
1900
|
+
neighbors = adjacency.get(current, [])
|
1901
|
+
random.shuffle(neighbors)
|
1902
|
+
for neighbor in neighbors:
|
1903
|
+
if neighbor not in visited and neighbor not in visited_global:
|
1904
|
+
group.append(neighbor)
|
1905
|
+
visited.add(neighbor)
|
1906
|
+
queue.append(neighbor)
|
1907
|
+
if len(group) >= group_size:
|
1908
|
+
break
|
1909
|
+
|
1910
|
+
return group if len(group) == group_size else None
|
1911
|
+
|
1885
1912
|
@staticmethod
|
1886
1913
|
def Vertices(shell) -> list:
|
1887
1914
|
"""
|