topologicpy 0.8.30__py3-none-any.whl → 0.8.33__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/Graph.py CHANGED
@@ -171,7 +171,7 @@ class WorkerProcess(Process):
171
171
  if self.used[i + self.start_index][j] == 1 or self.used[j][i + self.start_index]:
172
172
  continue
173
173
  if Vertex.Distance(source, destination) > self.tolerance:
174
- edge = Edge.ByVertices([source, destination])
174
+ edge = Edge.ByVertices([source, destination], tolerance=self.tolerance, silent=True)
175
175
  e = Topology.Intersect(edge, face)
176
176
  if Topology.IsInstance(e, "Edge"):
177
177
  edges.append(edge)
@@ -437,7 +437,7 @@ class Graph:
437
437
  for vertex in vertices:
438
438
  graph_vertices, nv = addIfUnique(graph_vertices, vertex, tolerance=tolerance)
439
439
  new_vertices.append(nv)
440
- new_edge = Edge.ByVertices([new_vertices[0], new_vertices[1]], tolerance=tolerance)
440
+ new_edge = Edge.ByVertices([new_vertices[0], new_vertices[1]], tolerance=tolerance, silent=silent)
441
441
  if transferEdgeDictionaries == True:
442
442
  d = Topology.Dictionary(edge)
443
443
  keys = Dictionary.Keys(d)
@@ -10133,6 +10133,153 @@ class Graph:
10133
10133
  edge = Topology.SetDictionary(edge, d)
10134
10134
  return max_flow
10135
10135
 
10136
+ @staticmethod
10137
+ def MergeVertices(graph, *vertices, targetVertex=None, transferDictionaries: bool = True, tolerance: float = 0.0001, silent: bool = False):
10138
+ """
10139
+ Merges the input vertices into one vertex and reconnects all edges to the new vertex.
10140
+ If two of the input vertices are the end points of the same edge, that edge is deleted.
10141
+
10142
+ Parameters
10143
+ ----------
10144
+ graph : topologic_core.Graph
10145
+ The input graph.
10146
+ *vertices : topologic_core.Vertex
10147
+ Two or more instances of `topologic_core.Topology` to be processed.
10148
+ targetVertex : topologic_core.Vertex, optional
10149
+ The target vertex to merge into. If None, a centroid is computed. Default is None.
10150
+ transferDictionaries : bool, optional
10151
+ If True, the dictionaries of all input vertices (including the target vertex if given) are merged. Default is True.
10152
+ tolerance : float , optional
10153
+ The desired tolerance. The default is 0.0001.
10154
+ silent : bool , optional
10155
+ If set to True, no error and warning messages are printed. Otherwise, they are. The default is False.
10156
+
10157
+ Returns
10158
+ -------
10159
+ topologic_core.Graph
10160
+ A new graph with the vertices merged and edges updated.
10161
+ """
10162
+ from topologicpy.Cluster import Cluster
10163
+ from topologicpy.Topology import Topology
10164
+ from topologicpy.Edge import Edge
10165
+ from topologicpy.Dictionary import Dictionary
10166
+ from topologicpy.Helper import Helper
10167
+ import inspect
10168
+
10169
+ if not Topology.IsInstance(graph, "Graph"):
10170
+ print("Graph:", graph)
10171
+ if not silent:
10172
+ print("Graph.MergeVertices - Error: The input graph is not valid. Returning None.")
10173
+ return None
10174
+
10175
+ if len(vertices) == 0:
10176
+ if not silent:
10177
+ print("Graph.MergeVertices - Error: The input vertices parameter is an empty list. Returning None.")
10178
+ curframe = inspect.currentframe()
10179
+ calframe = inspect.getouterframes(curframe, 2)
10180
+ print('caller name:', calframe[1][3])
10181
+ return None
10182
+ if len(vertices) == 1:
10183
+ vertices = vertices[0]
10184
+ if isinstance(vertices, list):
10185
+ if len(vertices) == 0:
10186
+ if not silent:
10187
+ print("Graph.MergeVertices - Error: The input topologies parameter is an empty list. Returning None.")
10188
+ curframe = inspect.currentframe()
10189
+ calframe = inspect.getouterframes(curframe, 2)
10190
+ print('caller name:', calframe[1][3])
10191
+ return None
10192
+ else:
10193
+ vertexList = [x for x in vertices if Topology.IsInstance(x, "Topology")]
10194
+ if len(vertexList) == 0:
10195
+ if not silent:
10196
+ print("Graph.MergeVertices - Error: The input topologies parameter does not contain any valid vertices. Returning None.")
10197
+ curframe = inspect.currentframe()
10198
+ calframe = inspect.getouterframes(curframe, 2)
10199
+ print('caller name:', calframe[1][3])
10200
+ return None
10201
+ else:
10202
+ if not silent:
10203
+ print("Graph.MergeVertices - Error: The input vertices parameter contains only one vertex. Returning None.")
10204
+ curframe = inspect.currentframe()
10205
+ calframe = inspect.getouterframes(curframe, 2)
10206
+ print('caller name:', calframe[1][3])
10207
+ return None
10208
+ else:
10209
+ vertexList = Helper.Flatten(list(vertices))
10210
+ vertexList = [x for x in vertexList if Topology.IsInstance(x, "Vertex")]
10211
+ if len(vertexList) == 0:
10212
+ if not silent:
10213
+ print("Graph.MergeVertices - Error: The input parameters do not contain any valid vertices. Returning None.")
10214
+ curframe = inspect.currentframe()
10215
+ calframe = inspect.getouterframes(curframe, 2)
10216
+ print('caller name:', calframe[1][3])
10217
+ return None
10218
+
10219
+ # Step 1: gather all vertices and edges
10220
+ all_vertices = Graph.Vertices(graph)
10221
+ all_edges = Graph.Edges(graph)
10222
+
10223
+ # Step 2: determine merged vertex
10224
+ dictionaries = []
10225
+ if targetVertex and Topology.IsInstance(targetVertex, "Vertex"):
10226
+ merged_vertex = targetVertex
10227
+ if targetVertex not in all_vertices:
10228
+ all_vertices.append(targetVertex)
10229
+ dictionaries.append(Topology.Dictionary(targetVertex))
10230
+ else:
10231
+ # Compute centroid
10232
+ merged_vertex = Topology.Centroid(Cluster.ByTopologies(vertexList))
10233
+
10234
+ # Step 3: collect dictionaries
10235
+ if transferDictionaries:
10236
+ for v in vertexList:
10237
+ d = Topology.Dictionary(v)
10238
+ dictionaries.append(d)
10239
+ merged_dict = Dictionary.ByMergedDictionaries(*dictionaries)
10240
+ merged_vertex = Topology.SetDictionary(merged_vertex, merged_dict, silent=True)
10241
+
10242
+ # Step 4: remove merged vertices from all_vertices
10243
+ for v in vertexList:
10244
+ for gv in all_vertices:
10245
+ if Topology.IsSame(v, gv):
10246
+ all_vertices.remove(gv)
10247
+ break
10248
+
10249
+ # Step 5: rebuild edge list
10250
+ new_edges = []
10251
+ seen = set()
10252
+ for edge in all_edges:
10253
+ sv = Edge.StartVertex(edge)
10254
+ ev = Edge.EndVertex(edge)
10255
+
10256
+ sv_merged = any(Topology.IsSame(sv, v) for v in vertexList)
10257
+ ev_merged = any(Topology.IsSame(ev, v) for v in vertexList)
10258
+
10259
+ if sv_merged and ev_merged:
10260
+ continue # Remove edges between merged vertices
10261
+
10262
+ new_sv = merged_vertex if sv_merged else sv
10263
+ new_ev = merged_vertex if ev_merged else ev
10264
+
10265
+ if Topology.IsSame(new_sv, new_ev):
10266
+ continue # Avoid self-loop
10267
+
10268
+ key = tuple(sorted([Topology.UUID(new_sv), Topology.UUID(new_ev)]))
10269
+ if key in seen:
10270
+ continue
10271
+ seen.add(key)
10272
+
10273
+ new_edge = Edge.ByVertices([new_sv, new_ev])
10274
+ if Topology.IsInstance(new_edge, "edge"):
10275
+ d = Topology.Dictionary(edge)
10276
+ if d:
10277
+ new_edge = Topology.SetDictionary(new_edge, d, silent=True)
10278
+ new_edges.append(new_edge)
10279
+
10280
+ all_vertices.append(merged_vertex)
10281
+ return Graph.ByVerticesEdges(all_vertices, new_edges)
10282
+
10136
10283
  @staticmethod
10137
10284
  def MeshData(graph, mantissa: int = 6, tolerance: float = 0.0001):
10138
10285
  """
topologicpy/Plotly.py CHANGED
@@ -730,7 +730,6 @@ class Plotly:
730
730
  legendgroup=legendGroup,
731
731
  legendrank=legendRank,
732
732
  text=labels,
733
- customdata=labels,
734
733
  hoverinfo='text',
735
734
  hovertext=labels)
736
735
  traces.append(trace)
@@ -384,7 +384,7 @@ class ShapeGrammar:
384
384
 
385
385
  return result_output
386
386
 
387
- def FigureByInputOutput(self, input, output, silent: bool = False):
387
+ def ClusterByInputOutput(self, input, output, silent: bool = False):
388
388
  """
389
389
  Returns the Plotly figure of the input and output topologies as a rule.
390
390
 
@@ -407,15 +407,14 @@ class ShapeGrammar:
407
407
  from topologicpy.Topology import Topology
408
408
  from topologicpy.Dictionary import Dictionary
409
409
  from topologicpy.Cluster import Cluster
410
- from topologicpy.Plotly import Plotly
411
410
 
412
411
  if not Topology.IsInstance(input, "Topology"):
413
412
  if not silent:
414
- print("ShapeGrammar.DrawInputOutput - Error: The input topology parameter is not a valid topology. Returning None.")
413
+ print("ShapeGrammar.ClusterByInputOutput - Error: The input topology parameter is not a valid topology. Returning None.")
415
414
  return None
416
415
  if not Topology.IsInstance(output, "Topology"):
417
416
  if not silent:
418
- print("ShapeGrammar.DrawInputOutput - Error: The output topology parameter is not a valid topology. Returning None.")
417
+ print("ShapeGrammar.ClusterByInputOutput - Error: The output topology parameter is not a valid topology. Returning None.")
419
418
  return None
420
419
 
421
420
  input_bb = Topology.BoundingBox(input)
@@ -463,6 +462,65 @@ class ShapeGrammar:
463
462
  cone = Topology.Translate(cone, 1.65, 0, 0)
464
463
  cluster = Cluster.ByTopologies([temp_input, temp_output, cyl, cone])
465
464
  cluster = Topology.Place(cluster, originA=Topology.Centroid(cluster), originB=Vertex.Origin())
465
+ return cluster
466
+
467
+ def ClusterByRule(self, rule, silent: bool = False):
468
+ """
469
+ Returns the Plotly figure of the input rule.
470
+
471
+ Parameters
472
+ ----------
473
+ rule : dict
474
+ The input rule
475
+ silent : bool, optional
476
+ If True, suppresses error/warning messages. Default is False.
477
+
478
+ Returns
479
+ -------
480
+ topologic_core.Cluster
481
+ The created rule cluster
482
+ """
483
+
484
+ if not isinstance(rule, dict):
485
+ if not silent:
486
+ print("ShapeGrammar.ClusterByRule - Error: The input rule parameter is not a valid rule. Returning None.")
487
+ return None
488
+ input = rule["input"]
489
+ output = self.ApplyRule(input, rule)
490
+ return self.ClusterByInputOutput(input, output, silent=silent)
491
+
492
+ def FigureByInputOutput(self, input, output, silent: bool = False):
493
+ """
494
+ Returns the Plotly figure of the input and output topologies as a rule.
495
+
496
+ Parameters
497
+ ----------
498
+ input : topologic_core.Topology
499
+ The input topology
500
+ output : topologic_core.Topology
501
+ The output topology
502
+ silent : bool, optional
503
+ If True, suppresses error/warning messages. Default is False.
504
+
505
+ Returns
506
+ -------
507
+ Plotly.Figure
508
+ The created plotly figure.
509
+ """
510
+
511
+ from topologicpy.Topology import Topology
512
+ from topologicpy.Plotly import Plotly
513
+
514
+ if not Topology.IsInstance(input, "Topology"):
515
+ if not silent:
516
+ print("ShapeGrammar.FigureByInputOutput - Error: The input topology parameter is not a valid topology. Returning None.")
517
+ return None
518
+ if not Topology.IsInstance(output, "Topology"):
519
+ if not silent:
520
+ print("ShapeGrammar.FigureByInputOutput - Error: The output topology parameter is not a valid topology. Returning None.")
521
+ return None
522
+
523
+ cluster = self.ClusterByInputOutput(input, output, silent=silent)
466
524
  data = Plotly.DataByTopology(cluster)
467
525
  fig = Plotly.FigureByData(data)
468
526
  return fig
@@ -480,7 +538,8 @@ class ShapeGrammar:
480
538
 
481
539
  Returns
482
540
  -------
483
- This function does not return a value
541
+ Plotly.Figure
542
+ The create plotly figure
484
543
  """
485
544
  from topologicpy.Topology import Topology
486
545
  if not isinstance(rule, dict):
@@ -489,4 +548,4 @@ class ShapeGrammar:
489
548
  return None
490
549
  input = rule["input"]
491
550
  output = self.ApplyRule(input, rule)
492
- return self.FigureByInputOutput(input, output)
551
+ return self.FigureByInputOutput(input, output, silent=silent)