topologicpy 0.8.61__py3-none-any.whl → 0.8.72__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
@@ -224,8 +224,17 @@ class Topology():
224
224
  The input topology with the apertures added to it.
225
225
 
226
226
  """
227
+ from topologicpy.Vertex import Vertex
227
228
  from topologicpy.Dictionary import Dictionary
229
+ from topologicpy.BVH import BVH
228
230
 
231
+ def best_candidate(aperture, candidates, tolerance=0.0001):
232
+ ap_iv = Topology.InternalVertex(aperture)
233
+ for candidate in candidates:
234
+ if Vertex.IsInternal(ap_iv, candidate, tolerance=tolerance):
235
+ return candidate
236
+ return None
237
+
229
238
  if not Topology.IsInstance(topology, "Topology"):
230
239
  print("Topology.AddApertures - Error: The input topology parameter is not a valid topology. Returning None.")
231
240
  return None
@@ -248,7 +257,27 @@ class Topology():
248
257
  d = Dictionary.SetValueAtKey(d, "type", "Aperture")
249
258
  aperture = Topology.SetDictionary(aperture, d)
250
259
 
251
- topology = Topology.AddContent(topology, apertures, subTopologyType=subTopologyType, tolerance=tolerance)
260
+ if subTopologyType == "self":
261
+ topology = Topology.AddContent(topology, apertures, subTopologyType=subTopologyType, tolerance=tolerance)
262
+ return topology
263
+ else:
264
+ bvh = BVH.ByTopologies(Topology.SubTopologies(topology, subTopologyType=subTopologyType), silent=True)
265
+ used = []
266
+ for aperture in apertures:
267
+ candidates = BVH.Clashes(bvh, aperture)
268
+ if isinstance(candidates, list):
269
+ if len(candidates) == 0:
270
+ return topology
271
+ elif len(candidates) == 1:
272
+ subTopology = candidates[0]
273
+ if len(candidates) > 0:
274
+ subTopology = best_candidate(aperture, candidates, tolerance=tolerance)
275
+ if Topology.IsInstance(subTopology, "topology"):
276
+ used.append(subTopology)
277
+ if exclusive == True:
278
+ if subTopology in used:
279
+ continue
280
+ subTopology = Topology.AddContent(subTopology, [aperture], subTopologyType="self", tolerance=tolerance)
252
281
  return topology
253
282
 
254
283
  @staticmethod
@@ -273,6 +302,11 @@ class Topology():
273
302
  The input topology with the contents added to it.
274
303
 
275
304
  """
305
+
306
+ from topologicpy.Context import Context
307
+ from topologicpy.Dictionary import Dictionary
308
+
309
+
276
310
  if not Topology.IsInstance(topology, "Topology"):
277
311
  print("Topology.AddContent - Error: the input topology parameter is not a valid topology. Returning None.")
278
312
  return None
@@ -291,11 +325,21 @@ class Topology():
291
325
  if not subTopologyType.lower() in ["self", "cellcomplex", "cell", "shell", "face", "wire", "edge", "vertex"]:
292
326
  print("Topology.AddContent - Error: the input subtopology type parameter is not a recognized type. Returning None.")
293
327
  return None
328
+
329
+ copy_contents = [Topology.Copy(x) for x in contents]
330
+ for i, content in enumerate(contents):
331
+ d = Topology.Dictionary(content)
332
+ copy_contents[i] = Topology.SetDictionary(copy_contents[i], d)
333
+
294
334
  if subTopologyType.lower() == "self":
295
- t = 0
335
+ context = Context.ByTopologyParameters(topology)
336
+ for content in copy_contents:
337
+ content.AddContext(context) # Hook to Core
338
+ topology.AddContent(content) # Hook to Core
296
339
  else:
297
340
  t = Topology.TypeID(subTopologyType)
298
- return topology.AddContents(contents, t)
341
+ topology.AddContents(copy_contents, t) # Hook to Core
342
+ return topology
299
343
 
300
344
  @staticmethod
301
345
  def AddDictionary(topology, dictionary):
@@ -886,7 +930,7 @@ class Topology():
886
930
  for i, eb in enumerate(eb_list):
887
931
  v = Topology.Vertices(eb)[0]
888
932
  if found == False:
889
- if Vertex.IsInternal(v, topologyA_wire) or Vertex.IsInternal(v, topologyB_wire):
933
+ if Vertex.IsInternal(v, topologyA_wire, tolerance=tolerance) or Vertex.IsInternal(v, topologyB_wire, tolerance=tolerance):
890
934
  external_boundary = eb
891
935
  found = True
892
936
  else:
@@ -2686,11 +2730,15 @@ class Topology():
2686
2730
  The list of imported topologies (Warning: the list could contain 0, 1, or many topologies, but this method will always return a list)
2687
2731
 
2688
2732
  """
2733
+ import inspect
2689
2734
  try:
2690
2735
  json_dict = json.loads(string)
2691
2736
  except Exception as e:
2692
2737
  if not silent:
2693
2738
  print(f"Topology.ByJSONString - Error: Could not read the input string: {e}. Returning None.")
2739
+ curframe = inspect.currentframe()
2740
+ calframe = inspect.getouterframes(curframe, 2)
2741
+ print('caller name:', calframe[1][3])
2694
2742
  return None
2695
2743
  return Topology.ByJSONDictionary(json_dict, tolerance=tolerance, silent=silent)
2696
2744
 
@@ -3995,7 +4043,7 @@ class Topology():
3995
4043
  print("Topology.Contents - Error: the input topology parameter is not a valid topology. Returning None.")
3996
4044
  return None
3997
4045
  contents = []
3998
- _ = topology.Contents(contents)
4046
+ _ = topology.Contents(contents) # Hook to Core
3999
4047
  return contents
4000
4048
 
4001
4049
  @staticmethod
@@ -4018,7 +4066,7 @@ class Topology():
4018
4066
  print("Topology.Contexts - Error: the input topology parameter is not a valid topology. Returning None.")
4019
4067
  return None
4020
4068
  contexts = []
4021
- _ = topology.Contexts(contexts)
4069
+ _ = topology.Contexts(contexts) # Hook to Core
4022
4070
  return contexts
4023
4071
 
4024
4072
  @staticmethod
@@ -9734,45 +9782,9 @@ class Topology():
9734
9782
 
9735
9783
  """
9736
9784
  from topologicpy.Vertex import Vertex
9737
- from topologicpy.Dictionary import Dictionary
9738
9785
  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
9786
+ from topologicpy.Dictionary import Dictionary
9787
+ from topologicpy.BVH import BVH
9776
9788
 
9777
9789
  if not Topology.IsInstance(topology, "Topology"):
9778
9790
  print("Topology.TransferDictionariesBySelectors - Error: The input topology parameter is not a valid topology. Returning None.")
@@ -9780,51 +9792,65 @@ class Topology():
9780
9792
  if not isinstance(selectors, list):
9781
9793
  print("Topology.TransferDictionariesBySelectors - Error: The input selectors parameter is not a valid list. Returning None.")
9782
9794
  return None
9783
- if numWorkers == None:
9784
- import multiprocessing
9785
- numWorkers = multiprocessing.cpu_count()*2
9786
9795
  selectors_tmp = [x for x in selectors if Topology.IsInstance(x, "Vertex")]
9787
9796
  if len(selectors_tmp) < 1:
9788
9797
  print("Topology.TransferDictionariesBySelectors - Error: The input selectors do not contain any valid topologies. Returning None.")
9789
9798
  return None
9790
9799
 
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)
9800
+
9801
+ # --------------------------
9802
+ # Collect primitives
9803
+ # --------------------------
9804
+ def collect_cells(topo):
9805
+ if Topology.IsInstance(topo, "cell"):
9806
+ return [topo]
9807
+ else:
9808
+ return Topology.Cells(topo)
9809
+
9810
+ def collect_faces(topo):
9811
+ if Topology.IsInstance(topo, "face"):
9812
+ return [topo]
9813
+ else:
9814
+ return Topology.Faces(topo)
9815
+
9816
+ def collect_edges(topo):
9817
+ if Topology.IsInstance(topo, "edge"):
9818
+ return [topo]
9819
+ else:
9820
+ return Topology.Edges(topo)
9821
+ def collect_vertices(topo):
9822
+ if Topology.IsInstance(topo, "vertex"):
9823
+ return [topo]
9824
+ else:
9825
+ return Topology.Vertices(topo)
9826
+
9827
+ vertices = []
9828
+ edges = []
9829
+ faces = []
9830
+ cells = []
9831
+ if tranVertices:
9832
+ vertices = collect_vertices(topology)
9833
+ if tranEdges:
9834
+ edges = collect_edges(topology)
9835
+ if tranFaces:
9836
+ faces = collect_faces(topology)
9837
+ if tranCells:
9838
+ cells = collect_cells(topology)
9839
+ primitives = []
9840
+ primitives.extend(cells)
9841
+ primitives.extend(faces)
9842
+ primitives.extend(edges)
9843
+ primitives.extend(vertices)
9844
+ cluster = Cluster.ByTopologies(primitives)
9845
+ for s in selectors:
9846
+ status, element = Vertex.IsInternal(s, cluster, identify=True, tolerance=tolerance)
9847
+ if status:
9848
+ d1 = Topology.Dictionary(s)
9849
+ d2 = Topology.Dictionary(element)
9850
+ d3 = Dictionary.ByMergedDictionaries(d1, d2)
9851
+ element = Topology.SetDictionary(element, d3)
9825
9852
  return topology
9826
9853
 
9827
-
9828
9854
  @staticmethod
9829
9855
  def Transform(topology, matrix: list, silent: bool = False):
9830
9856
  """