topologicpy 0.8.61__py3-none-any.whl → 0.8.71__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/Dictionary.py CHANGED
@@ -885,7 +885,10 @@ class Dictionary():
885
885
  temp_value = attr.StringValue()
886
886
  topologies = None
887
887
  try:
888
- topologies = Topology.ByJSONString(temp_value)
888
+ if is_json_string(temp_value):
889
+ topologies = Topology.ByJSONString(temp_value)
890
+ else:
891
+ topologies = None
889
892
  except:
890
893
  topologies = None
891
894
  if isinstance(topologies, list):
@@ -910,13 +913,21 @@ class Dictionary():
910
913
  elif isinstance(attr, float) or isinstance(attr, int):
911
914
  return attr
912
915
  elif isinstance(attr, str):
913
- topologies = Topology.ByJSONString(attr)
914
916
  if attr == "__NONE__":
915
917
  return None
916
- elif len(topologies) > 1:
917
- return topologies
918
- elif len(topologies) == 1:
919
- return topologies[0]
918
+ topologies = None
919
+ try:
920
+ if is_json_string(attr):
921
+ topologies = Topology.ByJSONString(attr)
922
+ else:
923
+ topologies = None
924
+ except:
925
+ topologies = None
926
+ if isinstance(topologies, list):
927
+ if len(topologies) > 1:
928
+ return topologies
929
+ elif len(topologies) == 1:
930
+ return topologies[0]
920
931
  elif is_json_string(attr):
921
932
  return json_to_dict(attr)
922
933
  else:
topologicpy/Face.py CHANGED
@@ -870,12 +870,14 @@ class Face():
870
870
  print('caller name:', calframe[1][3])
871
871
  return None
872
872
  if not Wire.IsClosed(wire):
873
- if not silent:
874
- print("Face.ByWire - Error: The input wire parameter is not a closed topologic wire. Returning None.")
875
- curframe = inspect.currentframe()
876
- calframe = inspect.getouterframes(curframe, 2)
877
- print('caller name:', calframe[1][3])
878
- return None
873
+ wire = Wire.Close(wire, tolerance=tolerance)
874
+ if not Wire.IsClosed(wire):
875
+ if not silent:
876
+ print("Face.ByWire - Error: The input wire parameter is not a closed topologic wire. Returning None.")
877
+ curframe = inspect.currentframe()
878
+ calframe = inspect.getouterframes(curframe, 2)
879
+ print('caller name:', calframe[1][3])
880
+ return None
879
881
 
880
882
  edges = Wire.Edges(wire)
881
883
  wire = Topology.SelfMerge(Cluster.ByTopologies(edges), tolerance=tolerance)
@@ -1882,53 +1884,24 @@ class Face():
1882
1884
  The created vertex.
1883
1885
 
1884
1886
  """
1885
- def get_uv_radially():
1886
- """
1887
- Generate the points of a grid with a given size n, sorted radially from the center to the periphery.
1888
- n should be an odd number, ensuring that there's a center point (0, 0).
1889
-
1890
- Args:
1891
- n (int): The size of the grid. It should be odd for a clear center point.
1892
-
1893
- Returns:
1894
- list: A list of tuples (x, y) sorted by radial distance from the center (0, 0).
1895
- """
1896
- import math
1897
-
1898
- points = []
1899
- n = 100
1900
- # Iterate over the grid, ranging from -n//2 to n//2
1901
- for x in range(-n//2, n//2 + 1):
1902
- for y in range(-n//2, n//2 + 1):
1903
- points.append((x, y))
1904
-
1905
- # Sort points by their Euclidean distance from the center (0, 0)
1906
- points.sort(key=lambda point: math.sqrt(point[0]**2 + point[1]**2))
1907
- return_points = []
1908
- for p in points:
1909
- new_p = ((p[0]+50)*0.01, (p[1]+50)*0.01)
1910
- return_points.append(new_p)
1911
- return return_points
1912
-
1913
1887
  from topologicpy.Vertex import Vertex
1888
+ from topologicpy.Shell import Shell
1889
+ from topologicpy.Cluster import Cluster
1890
+ from topologicpy.BVH import BVH
1914
1891
  from topologicpy.Topology import Topology
1915
1892
 
1916
- if not Topology.IsInstance(face, "Face"):
1917
- return None
1918
- vert = Topology.Centroid(face)
1919
- if Vertex.IsInternal(vert, face, tolerance=tolerance):
1920
- return vert
1921
- uv_list = get_uv_radially()
1922
- for uv in uv_list:
1923
- u, v = uv
1924
- vert = Face.VertexByParameters(face, u, v)
1925
- if Vertex.IsInternal(vert, face, tolerance=tolerance):
1926
- return vert
1927
- if not silent:
1928
- print("Face.InternalVertex - Warning: Could not find an internal vertex. Returning the first vertex of the face.")
1929
- vert = Topology.Vertices(face)[0]
1930
- #v = topologic.FaceUtility.InternalVertex(face, tolerance) # Hook to Core
1931
- return vert
1893
+ centroid = Topology.Centroid(face)
1894
+ if Vertex.IsInternal(centroid, face):
1895
+ return centroid
1896
+
1897
+ shell = Topology.Triangulate(face)
1898
+ ib = Shell.InternalBoundaries(shell)
1899
+ cluster = Cluster.ByTopologies(ib)
1900
+ edges = Topology.Edges(cluster)
1901
+ bvh = BVH.ByTopologies(edges, tolerance=tolerance, silent=True)
1902
+ nearest_edge = BVH.Nearest(bvh, centroid)
1903
+ return Topology.Centroid(nearest_edge)
1904
+
1932
1905
 
1933
1906
  @staticmethod
1934
1907
  def Invert(face, tolerance: float = 0.0001, silent: bool = False):
topologicpy/Shell.py CHANGED
@@ -1013,12 +1013,15 @@ class Shell():
1013
1013
  @staticmethod
1014
1014
  def InternalBoundaries(shell, tolerance=0.0001):
1015
1015
  """
1016
- Returns the internal boundaries (closed wires) of the input shell. Internal boundaries are considered holes.
1016
+ Returns the internal boundaries of the input shell.
1017
1017
 
1018
1018
  Parameters
1019
1019
  ----------
1020
1020
  shell : topologic_core.Shell
1021
1021
  The input shell.
1022
+ groupKey : str , optional
1023
+ The edge dictionary key under which to save the edge group number. The default is "group".
1024
+ Edges that separate the same faces belong to the same group.
1022
1025
  tolerance : float , optional
1023
1026
  The desired tolerance. Default is 0.0001.
1024
1027
 
@@ -1028,19 +1031,54 @@ class Shell():
1028
1031
  The list of internal boundaries
1029
1032
 
1030
1033
  """
1034
+ from topologicpy.Wire import Wire
1031
1035
  from topologicpy.Cluster import Cluster
1032
1036
  from topologicpy.Topology import Topology
1033
- edges = []
1034
- _ = shell.Edges(None, edges)
1037
+ from topologicpy.Dictionary import Dictionary
1038
+ faces = Shell.Faces(shell)
1039
+ for i, f in enumerate(faces):
1040
+ d = Topology.Dictionary(f)
1041
+ d = Dictionary.SetValueAtKey(d, "__id__", i)
1042
+ f = Topology.SetDictionary(f, d)
1043
+
1044
+ edges = Topology.Edges(shell)
1035
1045
  ibEdges = []
1046
+ groups = []
1036
1047
  for anEdge in edges:
1037
- faces = []
1038
- _ = anEdge.Faces(shell, faces)
1048
+ faces = Topology.SuperTopologies(anEdge, shell, topologyType="face")
1039
1049
  if len(faces) > 1:
1050
+ d = Topology.Dictionary(anEdge)
1051
+ ids = []
1052
+ for aFace in faces:
1053
+ face_d = Topology.Dictionary(aFace)
1054
+ ids.append(Dictionary.ValueAtKey(face_d, "__id__", -1))
1055
+ ids.sort()
1056
+ ids = str(ids)
1057
+ groups.append(ids)
1058
+ d = Dictionary.SetValueAtKey(d, "__group__", ids)
1059
+ anEdge = Topology.SetDictionary(anEdge, d)
1040
1060
  ibEdges.append(anEdge)
1041
- returnTopology = Topology.SelfMerge(Cluster.ByTopologies(ibEdges), tolerance=tolerance)
1042
- wires = Topology.Wires(returnTopology)
1043
- return wires
1061
+ for aFace in faces:
1062
+ face_d = Topology.Dictionary(aFace)
1063
+ face_d = Dictionary.RemoveKey(face_d, "__id__")
1064
+
1065
+ groups = list(set(groups))
1066
+ for edge in ibEdges:
1067
+ d = Topology.Dictionary(edge)
1068
+ id = groups.index(Dictionary.ValueAtKey(d, "__group__"))
1069
+ d = Dictionary.SetValueAtKey(d, "__group__", id)
1070
+ edge_groups = []
1071
+ for group in groups:
1072
+ edge_group = Topology.Filter(ibEdges, searchType="equal to", key="__group__", value=group)['filtered']
1073
+ edge_groups.append(edge_group)
1074
+ final_groups = []
1075
+ for edge_group in edge_groups:
1076
+ final_groups.append(Topology.SelfMerge(Cluster.ByTopologies(edge_group, silent=True), tolerance=tolerance))
1077
+ for edge in ibEdges:
1078
+ d = Topology.Dictionary(edge)
1079
+ d = Dictionary.RemoveKey(d, "__group__")
1080
+ edge = Topology.SetDictionary(edge, d)
1081
+ return final_groups
1044
1082
 
1045
1083
 
1046
1084
  @staticmethod
@@ -1750,8 +1788,7 @@ class Shell():
1750
1788
  else:
1751
1789
  return f
1752
1790
  elif Topology.IsInstance(ext_boundary, "Cluster"):
1753
- wires = []
1754
- _ = ext_boundary.Wires(None, wires)
1791
+ wires = Topology.Wires(ext_boundary)
1755
1792
  faces = []
1756
1793
  areas = []
1757
1794
  for aWire in wires:
@@ -1770,8 +1807,7 @@ class Shell():
1770
1807
  temp_wires = []
1771
1808
  _ = int_boundary.Wires(None, temp_wires)
1772
1809
  int_wires.append(Topology.RemoveCollinearEdges(temp_wires[0], angTolerance))
1773
- temp_wires = []
1774
- _ = ext_boundary.Wires(None, temp_wires)
1810
+ temp_wires = Topology.Wire(ext_boundary)
1775
1811
  ext_wire = Topology.RemoveCollinearEdges(temp_wires[0], angTolerance)
1776
1812
  try:
1777
1813
  return Face.ByWires(ext_wire, int_wires, tolerance=tolerance)
@@ -2067,7 +2103,7 @@ class Shell():
2067
2103
  if not Topology.IsInstance(shell, "Shell"):
2068
2104
  return None
2069
2105
  vertices = []
2070
- _ = shell.Vertices(None, vertices)
2106
+ _ = shell.Vertices(None, vertices) # Hook to core
2071
2107
  return vertices
2072
2108
 
2073
2109
  @staticmethod
@@ -2205,7 +2241,7 @@ class Shell():
2205
2241
  if not Topology.IsInstance(shell, "Shell"):
2206
2242
  return None
2207
2243
  wires = []
2208
- _ = shell.Wires(None, wires)
2244
+ _ = shell.Wires(None, wires) # Hook to core
2209
2245
  return wires
2210
2246
 
2211
2247
 
topologicpy/Topology.py CHANGED
@@ -225,6 +225,7 @@ class Topology():
225
225
 
226
226
  """
227
227
  from topologicpy.Dictionary import Dictionary
228
+ from topologicpy.BVH import BVH
228
229
 
229
230
  if not Topology.IsInstance(topology, "Topology"):
230
231
  print("Topology.AddApertures - Error: The input topology parameter is not a valid topology. Returning None.")
@@ -248,7 +249,23 @@ class Topology():
248
249
  d = Dictionary.SetValueAtKey(d, "type", "Aperture")
249
250
  aperture = Topology.SetDictionary(aperture, d)
250
251
 
251
- topology = Topology.AddContent(topology, apertures, subTopologyType=subTopologyType, tolerance=tolerance)
252
+ if subTopologyType == "self":
253
+ topology = Topology.AddContent(topology, apertures, subTopologyType=subTopologyType, tolerance=tolerance)
254
+ return topology
255
+ else:
256
+ bvh = BVH.ByTopologies(Topology.SubTopologies(topology, subTopologyType=subTopologyType), silent=True)
257
+ used = []
258
+ for aperture in apertures:
259
+ result = BVH.Clashes(bvh, aperture)
260
+ if isinstance(result, list):
261
+ if len(result) > 0:
262
+ subTopology = result[0]
263
+ if Topology.IsInstance(subTopology, "topology"):
264
+ used.append(subTopology)
265
+ if exclusive == True:
266
+ if subTopology in used:
267
+ continue
268
+ subTopology = Topology.AddContent(subTopology, [aperture], subTopologyType="self", tolerance=tolerance)
252
269
  return topology
253
270
 
254
271
  @staticmethod
@@ -273,6 +290,9 @@ class Topology():
273
290
  The input topology with the contents added to it.
274
291
 
275
292
  """
293
+
294
+ from topologicpy.Context import Context
295
+
276
296
  if not Topology.IsInstance(topology, "Topology"):
277
297
  print("Topology.AddContent - Error: the input topology parameter is not a valid topology. Returning None.")
278
298
  return None
@@ -292,10 +312,14 @@ class Topology():
292
312
  print("Topology.AddContent - Error: the input subtopology type parameter is not a recognized type. Returning None.")
293
313
  return None
294
314
  if subTopologyType.lower() == "self":
295
- t = 0
315
+ context = Context.ByTopologyParameters(topology)
316
+ for content in contents:
317
+ content.AddContext(context) # Hook to Core
318
+ topology.AddContent(content) # Hook to Core
296
319
  else:
297
320
  t = Topology.TypeID(subTopologyType)
298
- return topology.AddContents(contents, t)
321
+ topology.AddContents(contents, t) # Hook to Core
322
+ return topology
299
323
 
300
324
  @staticmethod
301
325
  def AddDictionary(topology, dictionary):
@@ -886,7 +910,7 @@ class Topology():
886
910
  for i, eb in enumerate(eb_list):
887
911
  v = Topology.Vertices(eb)[0]
888
912
  if found == False:
889
- if Vertex.IsInternal(v, topologyA_wire) or Vertex.IsInternal(v, topologyB_wire):
913
+ if Vertex.IsInternal(v, topologyA_wire, tolerance=tolerance) or Vertex.IsInternal(v, topologyB_wire, tolerance=tolerance):
890
914
  external_boundary = eb
891
915
  found = True
892
916
  else:
@@ -2686,11 +2710,15 @@ class Topology():
2686
2710
  The list of imported topologies (Warning: the list could contain 0, 1, or many topologies, but this method will always return a list)
2687
2711
 
2688
2712
  """
2713
+ import inspect
2689
2714
  try:
2690
2715
  json_dict = json.loads(string)
2691
2716
  except Exception as e:
2692
2717
  if not silent:
2693
2718
  print(f"Topology.ByJSONString - Error: Could not read the input string: {e}. Returning None.")
2719
+ curframe = inspect.currentframe()
2720
+ calframe = inspect.getouterframes(curframe, 2)
2721
+ print('caller name:', calframe[1][3])
2694
2722
  return None
2695
2723
  return Topology.ByJSONDictionary(json_dict, tolerance=tolerance, silent=silent)
2696
2724
 
@@ -3995,7 +4023,7 @@ class Topology():
3995
4023
  print("Topology.Contents - Error: the input topology parameter is not a valid topology. Returning None.")
3996
4024
  return None
3997
4025
  contents = []
3998
- _ = topology.Contents(contents)
4026
+ _ = topology.Contents(contents) # Hook to Core
3999
4027
  return contents
4000
4028
 
4001
4029
  @staticmethod
@@ -4018,7 +4046,7 @@ class Topology():
4018
4046
  print("Topology.Contexts - Error: the input topology parameter is not a valid topology. Returning None.")
4019
4047
  return None
4020
4048
  contexts = []
4021
- _ = topology.Contexts(contexts)
4049
+ _ = topology.Contexts(contexts) # Hook to Core
4022
4050
  return contexts
4023
4051
 
4024
4052
  @staticmethod
@@ -9734,45 +9762,9 @@ class Topology():
9734
9762
 
9735
9763
  """
9736
9764
  from topologicpy.Vertex import Vertex
9737
- from topologicpy.Dictionary import Dictionary
9738
9765
  from topologicpy.Cluster import Cluster
9739
- from topologicpy.Plotly import Plotly
9740
-
9741
-
9742
- def transfer_dictionaries_by_selectors(object, selectors, tranVertices=False, tranEdges=False, tranFaces=False, tranCells=False, tolerance=0.0001):
9743
- if tranVertices == True:
9744
- vertices = Topology.Vertices(object)
9745
- for vertex in vertices:
9746
- for selector in selectors:
9747
- d = Vertex.Distance(selector, vertex)
9748
- if d <= tolerance:
9749
- vertex = Topology.SetDictionary(vertex, Topology.Dictionary(selector), silent=True)
9750
- break
9751
- if tranEdges == True:
9752
- edges = Topology.Edges(object)
9753
- for selector in selectors:
9754
- for edge in edges:
9755
- d = Vertex.Distance(selector, edge)
9756
- if d <= tolerance:
9757
-
9758
- edge = Topology.SetDictionary(edge, Topology.Dictionary(selector), silent=True)
9759
- break
9760
- if tranFaces == True:
9761
- faces = Topology.Faces(object)
9762
- for face in faces:
9763
- for selector in selectors:
9764
- d = Vertex.Distance(selector, face)
9765
- if d <= tolerance:
9766
- face = Topology.SetDictionary(face, Topology.Dictionary(selector), silent=True)
9767
- break
9768
- if tranCells == True:
9769
- cells = Topology.Cells(object)
9770
- for cell in cells:
9771
- for selector in selectors:
9772
- if Vertex.IsInternal(selector, cell):
9773
- cell = Topology.SetDictionary(cell, Topology.Dictionary(selector), silent=True)
9774
- break
9775
- return object
9766
+ from topologicpy.Dictionary import Dictionary
9767
+ from topologicpy.BVH import BVH
9776
9768
 
9777
9769
  if not Topology.IsInstance(topology, "Topology"):
9778
9770
  print("Topology.TransferDictionariesBySelectors - Error: The input topology parameter is not a valid topology. Returning None.")
@@ -9780,51 +9772,65 @@ class Topology():
9780
9772
  if not isinstance(selectors, list):
9781
9773
  print("Topology.TransferDictionariesBySelectors - Error: The input selectors parameter is not a valid list. Returning None.")
9782
9774
  return None
9783
- if numWorkers == None:
9784
- import multiprocessing
9785
- numWorkers = multiprocessing.cpu_count()*2
9786
9775
  selectors_tmp = [x for x in selectors if Topology.IsInstance(x, "Vertex")]
9787
9776
  if len(selectors_tmp) < 1:
9788
9777
  print("Topology.TransferDictionariesBySelectors - Error: The input selectors do not contain any valid topologies. Returning None.")
9789
9778
  return None
9790
9779
 
9791
- if numWorkers == 1:
9792
- return transfer_dictionaries_by_selectors(topology, selectors, tranVertices=tranVertices, tranEdges=tranEdges, tranFaces=tranFaces, tranCells=tranCells, tolerance=tolerance)
9793
- sinkEdges = []
9794
- sinkFaces = []
9795
- sinkCells = []
9796
- hidimSink = Topology.HighestType(topology)
9797
- if tranVertices == True:
9798
- sinkVertices = []
9799
- if Topology.Type(topology) == Topology.TypeID("Vertex"):
9800
- sinkVertices.append(topology)
9801
- elif hidimSink >= Topology.TypeID("Vertex"):
9802
- sinkVertices = Topology.Vertices(topology)
9803
- _ = Topology.TransferDictionaries(selectors, sinkVertices, tolerance=tolerance, numWorkers=numWorkers)
9804
- if tranEdges == True:
9805
- sinkEdges = []
9806
- if Topology.Type(topology) == Topology.TypeID("Edge"):
9807
- sinkEdges.append(topology)
9808
- elif hidimSink >= Topology.TypeID("Edge"):
9809
- topology.Edges(None, sinkEdges)
9810
- _ = Topology.TransferDictionaries(selectors, sinkEdges, tolerance=tolerance, numWorkers=numWorkers)
9811
- if tranFaces == True:
9812
- sinkFaces = []
9813
- if Topology.Type(topology) == Topology.TypeID("Face"):
9814
- sinkFaces.append(topology)
9815
- elif hidimSink >= Topology.TypeID("Face"):
9816
- topology.Faces(None, sinkFaces)
9817
- _ = Topology.TransferDictionaries(selectors, sinkFaces, tolerance=tolerance, numWorkers=numWorkers)
9818
- if tranCells == True:
9819
- sinkCells = []
9820
- if Topology.IsInstance(topology, "Cell"):
9821
- sinkCells = [topology]
9822
- elif hidimSink >= Topology.TypeID("Cell"):
9823
- sinkCells = Topology.Cells(topology)
9824
- _ = Topology.TransferDictionaries(selectors, sinkCells, tolerance=tolerance, numWorkers=numWorkers)
9780
+
9781
+ # --------------------------
9782
+ # Collect primitives
9783
+ # --------------------------
9784
+ def collect_cells(topo):
9785
+ if Topology.IsInstance(topo, "cell"):
9786
+ return [topo]
9787
+ else:
9788
+ return Topology.Cells(topo)
9789
+
9790
+ def collect_faces(topo):
9791
+ if Topology.IsInstance(topo, "face"):
9792
+ return [topo]
9793
+ else:
9794
+ return Topology.Faces(topo)
9795
+
9796
+ def collect_edges(topo):
9797
+ if Topology.IsInstance(topo, "edge"):
9798
+ return [topo]
9799
+ else:
9800
+ return Topology.Edges(topo)
9801
+ def collect_vertices(topo):
9802
+ if Topology.IsInstance(topo, "vertex"):
9803
+ return [topo]
9804
+ else:
9805
+ return Topology.Vertices(topo)
9806
+
9807
+ vertices = []
9808
+ edges = []
9809
+ faces = []
9810
+ cells = []
9811
+ if tranVertices:
9812
+ vertices = collect_vertices(topology)
9813
+ if tranEdges:
9814
+ edges = collect_edges(topology)
9815
+ if tranFaces:
9816
+ faces = collect_faces(topology)
9817
+ if tranCells:
9818
+ cells = collect_cells(topology)
9819
+ primitives = []
9820
+ primitives.extend(cells)
9821
+ primitives.extend(faces)
9822
+ primitives.extend(edges)
9823
+ primitives.extend(vertices)
9824
+ cluster = Cluster.ByTopologies(primitives)
9825
+ for s in selectors:
9826
+ status, element = Vertex.IsInternal(s, cluster, identify=True, tolerance=tolerance)
9827
+ if status:
9828
+ d1 = Topology.Dictionary(s)
9829
+ d2 = Topology.Dictionary(element)
9830
+ d3 = Dictionary.ByMergedDictionaries(d1, d2)
9831
+ element = Topology.SetDictionary(element, d3)
9825
9832
  return topology
9826
9833
 
9827
-
9828
9834
  @staticmethod
9829
9835
  def Transform(topology, matrix: list, silent: bool = False):
9830
9836
  """