topologicpy 0.7.26__py3-none-any.whl → 0.7.28__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/Cell.py CHANGED
@@ -99,7 +99,7 @@ class Cell():
99
99
  tolerance : float , optional
100
100
  The desired tolerance. The default is 0.0001.
101
101
  silent : bool , optional
102
- If set to False, error and warning messages are printed. Otherwise, they are not. The default is False.
102
+ If set to True, no error and warning messages are printed. Otherwise, they are. The default is False.
103
103
 
104
104
  Returns
105
105
  -------
@@ -384,7 +384,7 @@ class Cell():
384
384
  tolerance : float , optional
385
385
  The desired tolerance. The default is 0.0001.
386
386
  silent : bool , optional
387
- If set to False, error and warning messages are printed. Otherwise, they are not. The default is False.
387
+ If set to True, no error and warning messages are printed. Otherwise, they are. The default is False.
388
388
 
389
389
  Raises
390
390
  ------
topologicpy/Cluster.py CHANGED
@@ -154,7 +154,8 @@ class Cluster():
154
154
  transferDictionaries : bool , optional
155
155
  If set to True, the dictionaries from the input topologies are merged and transferred to the cluster. Otherwise they are not. The default is False.
156
156
  silent : bool , optional
157
- If set to True, error and warning messages are not displayed. Otherwise, they are. The default is False.
157
+ If set to True, no error and warning messages are printed. Otherwise, they are. The default is False.
158
+
158
159
  Returns
159
160
  -------
160
161
  topologic_core.Cluster
topologicpy/Dictionary.py CHANGED
@@ -162,7 +162,7 @@ class Dictionary():
162
162
  dictionaries : list or comma separated dictionaries
163
163
  The input list of dictionaries to be merged.
164
164
  silent : bool , optional
165
- If set to True, error and warning messages are not displayed. Otherwise, they are. The default is False.
165
+ If set to True, no error and warning messages are printed. Otherwise, they are. The default is False.
166
166
 
167
167
  Returns
168
168
  -------
topologicpy/Edge.py CHANGED
@@ -232,7 +232,7 @@ class Edge():
232
232
  tolerance : float , optional
233
233
  The desired tolerance to decide if an Edge can be created. The default is 0.0001.
234
234
  silent : bool , optional
235
- If set to False, error and warning messages are printed. Otherwise, they are not. The default is False.
235
+ If set to True, no error and warning messages are printed. Otherwise, they are. The default is False.
236
236
 
237
237
  Returns
238
238
  -------
@@ -280,7 +280,7 @@ class Edge():
280
280
  tolerance : float , optional
281
281
  The desired tolerance to decide if an edge can be created. The default is 0.0001.
282
282
  silent : bool , optional
283
- If set to True, error and warning messages are printed. Otherwise, they are not. The default is True.
283
+ If set to True, no error and warning messages are printed. Otherwise, they are. The default is False.
284
284
 
285
285
  Returns
286
286
  -------
@@ -355,6 +355,48 @@ class Edge():
355
355
  return None
356
356
  return Edge.ByStartVertexEndVertex(vertexList[0], vertexList[-1], tolerance=tolerance)
357
357
 
358
+ @staticmethod
359
+ def Connection(edgeA, edgeB, tolerance: float = 0.0001, silent: bool = False):
360
+ """
361
+ Returns the edge representing the connection between the first input edge to the second input edge using the two closest vertices.
362
+
363
+ Parameters
364
+ ----------
365
+ edgeA : topologic_core.Edge
366
+ The first input edge. This edge will be extended to meet edgeB.
367
+ edgeB : topologic_core.Edge
368
+ The second input edge. This edge will be used to extend edgeA.
369
+ silent : bool , optional
370
+ If set to True, no error and warning messages are printed. Otherwise, they are. The default is False.
371
+ tolerance : float , optional
372
+ The desired tolerance. The default is 0.0001.
373
+
374
+ Returns
375
+ -------
376
+ topologic_core.Edge or topologic_core.Wire
377
+ The connected edge. Since it is made of two edges, this method returns a Wire.
378
+
379
+ """
380
+ from topologicpy.Vertex import Vertex
381
+ from topologicpy.Helper import Helper
382
+
383
+ sva = Edge.StartVertex(edgeA)
384
+ eva = Edge.EndVertex(edgeA)
385
+ svb = Edge.StartVertex(edgeB)
386
+ evb = Edge.EndVertex(edgeB)
387
+ v_list = [[sva, svb], [sva, evb], [eva, svb], [eva, evb]]
388
+ distances = []
389
+ for pair in v_list:
390
+ distances.append(Vertex.Distance(pair[0], pair[1]))
391
+ v_list = Helper.Sort(v_list, distances)
392
+ closest_pair = v_list[0]
393
+ return_edge = Edge.ByVertices(closest_pair, silent=silent)
394
+ if return_edge == None:
395
+ if not silent:
396
+ print("Edge.ConnectToEdge - Warning: Could not connect the two edges. Returning None.")
397
+ return None
398
+ return return_edge
399
+
358
400
  @staticmethod
359
401
  def Direction(edge, mantissa: int = 6) -> list:
360
402
  """
@@ -419,6 +461,55 @@ class Edge():
419
461
  vert = None
420
462
  return vert
421
463
 
464
+ @staticmethod
465
+ def Equation2D(edge, mantissa=6):
466
+ """
467
+ Returns the 2D equation of the input edge. This is assumed to be in the XY plane.
468
+
469
+ Parameters
470
+ ----------
471
+ edge : topologic_core.Edge
472
+ The input edge.
473
+ mantissa : int , optional
474
+ The desired length of the mantissa. The default is 6.
475
+
476
+ Returns
477
+ -------
478
+ dict
479
+ The equation of the edge stored in a dictionary. The dictionary has the following keys:
480
+ "slope": The slope of the line. This can be float('inf')
481
+ "x_intercept": The X axis intercept. This can be None.
482
+ "y_intercept": The Y axis intercept. This can be None.
483
+
484
+ """
485
+ from topologicpy.Vertex import Vertex
486
+
487
+ # Extract the start and end vertices
488
+ sv = Edge.StartVertex(edge)
489
+ ev = Edge.EndVertex(edge)
490
+
491
+ # Extract coordinates of the vertices
492
+ x1, y1 = Vertex.X(sv, mantissa=mantissa), Vertex.Y(sv, mantissa=mantissa)
493
+ x2, y2 = Vertex.X(ev, mantissa=mantissa), Vertex.Y(ev, mantissa=mantissa)
494
+
495
+ # Calculate the slope (m) and y-intercept (c)
496
+ if x2 - x1 != 0:
497
+ m = round((y2 - y1) / (x2 - x1), mantissa)
498
+ c = round(y1 - m * x1, mantissa)
499
+ return {
500
+ "slope": m,
501
+ "x_intercept": None,
502
+ "y_intercept": c
503
+ }
504
+ else:
505
+ # The line is vertical, slope is undefined
506
+ return {
507
+ "slope": float('inf'),
508
+ "x_intercept": x1,
509
+ "y_intercept": None
510
+ }
511
+
512
+
422
513
  @staticmethod
423
514
  def Extend(edge, distance: float = 1.0, bothSides: bool = True, reverse: bool = False, tolerance: float = 0.0001):
424
515
  """
@@ -465,7 +556,7 @@ class Edge():
465
556
  return Edge.ByVertices([sve, eve], tolerance=tolerance, silent=True)
466
557
 
467
558
  @staticmethod
468
- def ExtendToEdge(edgeA, edgeB, mantissa: int = 6, tolerance: float = 0.0001, silent: bool = False):
559
+ def ExtendToEdge(edgeA, edgeB, mantissa: int = 6, step: bool = True, tolerance: float = 0.0001, silent: bool = False):
469
560
  """
470
561
  Extends the first input edge to meet the second input edge.
471
562
 
@@ -480,17 +571,19 @@ class Edge():
480
571
  tolerance : float , optional
481
572
  The desired tolerance. The default is 0.0001.
482
573
  silent : bool , optional
483
- If set to True, not error or warning messages are printed. Otherwise, they are. The default is False.
574
+ If set to True, no error and warning messages are printed. Otherwise, they are. The default is False.
484
575
 
485
576
  Returns
486
577
  -------
487
578
  topologic_core.Edge
488
- The trimmed edge.
579
+ The extended edge.
489
580
 
490
581
  """
491
582
  from topologicpy.Vertex import Vertex
492
583
  from topologicpy.Vector import Vector
584
+ from topologicpy.Cluster import Cluster
493
585
  from topologicpy.Topology import Topology
586
+ from topologicpy.Helper import Helper
494
587
 
495
588
  if not Topology.IsInstance(edgeA, "Edge"):
496
589
  if not silent:
@@ -504,10 +597,15 @@ class Edge():
504
597
  if not silent:
505
598
  print("Edge.ExtendToEdge - Error: The input edges are not coplanar. Returning the original edge.")
506
599
  return edgeA
600
+ if Edge.IsCollinear(edgeA, edgeB, tolerance=tolerance):
601
+ if not silent:
602
+ print("Edge.ExtendToEdge - Warning: The input edges are collinear. Connecting the edges instead. Check return value.")
603
+ return Edge.ConnectToEdge(edgeA, edgeB, tolerance=tolerance)
507
604
  if Edge.IsParallel(edgeA, edgeB, tolerance=tolerance):
508
605
  if not silent:
509
- print("Edge.ExtendToEdge - Error: The input edges are parallel. Returning the original edge.")
510
- return edgeA
606
+ print("Edge.ExtendToEdge - Warning: The input edges are parallel. Connecting the edges instead. Returning a Wire.")
607
+ return Edge.ConnectToEdge(edgeA, edgeB, tolerance=tolerance)
608
+
511
609
 
512
610
  sva = Edge.StartVertex(edgeA)
513
611
  eva = Edge.EndVertex(edgeA)
@@ -532,8 +630,9 @@ class Edge():
532
630
  intVertex = Topology.Intersect(new_edge, edgeB, tolerance=tolerance)
533
631
  if intVertex:
534
632
  return Edge.ByVertices([v1, intVertex], tolerance=tolerance, silent=True)
535
- print("Edge.ExtendToEdge - Error: The operation failed. Returning None.")
536
- return None
633
+ if not silent:
634
+ print("Edge.ExtendToEdge - Warning: The operation failed. Connecting the edges instead. Returning a Wire.")
635
+ return Edge.ConnectToEdge(edgeA, edgeB, tolerance=tolerance)
537
636
 
538
637
  @staticmethod
539
638
  def ExternalBoundary(edge):
@@ -613,6 +712,70 @@ class Edge():
613
712
  return i
614
713
  return None
615
714
 
715
+ @staticmethod
716
+ def Intersect2D(edgeA, edgeB, silent: bool = False, mantissa: int = 6, tolerance: float = 0.0001):
717
+ """
718
+ Returns the intersection vertex of the two input edges. This is assumed to be in the XY plane.
719
+ The intersection vertex does not necessarily fall within the extents of either edge.
720
+
721
+ Parameters
722
+ ----------
723
+ edgeA : topologic_core.Edge
724
+ The first input edge.
725
+ edgeB : topologic_core.Edge
726
+ The second input edge.
727
+ silent : bool , optional
728
+ If set to True, no error and warning messages are printed. Otherwise, they are. The default is False.
729
+ mantissa : int , optional
730
+ The desired length of the mantissa. The default is 6.
731
+
732
+ Returns
733
+ -------
734
+ topologic_core.Vertex
735
+ The intersection vertex or None if the edges are parallel or collinear.
736
+
737
+ """
738
+ from topologicpy.Vertex import Vertex
739
+ from topologicpy.Helper import Helper
740
+ from topologicpy.Cluster import Cluster
741
+ from topologicpy.Topology import Topology
742
+
743
+ sva = Edge.StartVertex(edgeA)
744
+ eva = Edge.EndVertex(edgeA)
745
+ svb = Edge.StartVertex(edgeB)
746
+ evb = Edge.EndVertex(edgeB)
747
+ v_list = [[sva, svb], [sva, evb], [eva, svb], [eva, evb]]
748
+ distances = []
749
+ for pair in v_list:
750
+ distances.append(Vertex.Distance(pair[0], pair[1]))
751
+ v_list = Helper.Sort(v_list, distances)
752
+ closest_pair = v_list[0]
753
+ if Vertex.Distance(closest_pair[0], closest_pair[1]) < tolerance:
754
+ return Topology.Centroid(Cluster.ByTopologies(closest_pair))
755
+
756
+ if Edge.IsCollinear(edgeA, edgeB, tolerance=tolerance):
757
+ if not silent:
758
+ print("Edge.Intersect2D - Error: The input edges are collinear and overlapping. An intersection vertex cannot be found. Returning None.")
759
+ return None
760
+ if Edge.IsParallel(edgeA, edgeB, tolerance=tolerance):
761
+ if not silent:
762
+ print("Edge.Intersect2D - Error: The input edges are parallel. An intersection vertex cannot be found. Returning None.")
763
+ return None
764
+
765
+ eq1 = Edge.Equation2D(edgeA, mantissa=mantissa)
766
+ eq2 = Edge.Equation2D(edgeB, mantissa=mantissa)
767
+ if eq1["slope"] == float('inf'):
768
+ x = eq1["x_intercept"]
769
+ y = eq2["slope"] * x + eq2["y_intercept"]
770
+ elif eq2["slope"] == float('inf'):
771
+ x = eq2["x_intercept"]
772
+ y = eq1["slope"] * x + eq1["y_intercept"]
773
+ else:
774
+ x = (eq2["y_intercept"] - eq1["y_intercept"]) / (eq1["slope"] - eq2["slope"])
775
+ y = eq1["slope"] * x + eq1["y_intercept"]
776
+
777
+ return Vertex.ByCoordinates(x,y,0)
778
+
616
779
  @staticmethod
617
780
  def IsCollinear(edgeA, edgeB, mantissa: int = 6, tolerance: float = 0.0001) -> bool:
618
781
  """
@@ -936,11 +1099,11 @@ class Edge():
936
1099
  if not Topology.IsInstance(edge, "Edge"):
937
1100
  print("Edge.Normal - Error: The input edge parameter is not a valid edge. Returning None.")
938
1101
  return None
939
- normal_edge = Edge.NormalAsEdge(edge, length=1.0, u=0.5, angle=angle)
1102
+ normal_edge = Edge.NormalEdge(edge, length=1.0, u=0.5, angle=angle)
940
1103
  return Edge.Direction(normal_edge)
941
1104
 
942
1105
  @staticmethod
943
- def NormalAsEdge(edge, length: float = 1.0, u: float = 0.5, angle: float = 0.0):
1106
+ def NormalEdge(edge, length: float = 1.0, u: float = 0.5, angle: float = 0.0):
944
1107
  """
945
1108
  Returns the normal (perpendicular) vector to the input edge as an edge.
946
1109
 
@@ -996,10 +1159,10 @@ class Edge():
996
1159
  return start_vertex, list(normal_end_vertex)
997
1160
 
998
1161
  if not Topology.IsInstance(edge, "Edge"):
999
- print("Edge.NormalAsEdge - Error: The input edge parameter is not a valid edge. Returning None.")
1162
+ print("Edge.NormalEdge - Error: The input edge parameter is not a valid edge. Returning None.")
1000
1163
  return None
1001
1164
  if length <= 0.0:
1002
- print("Edge.NormalAsEdge - Error: The input length parameter is not a positive number greater than zero. Returning None.")
1165
+ print("Edge.NormalEdge - Error: The input length parameter is not a positive number greater than zero. Returning None.")
1003
1166
  return None
1004
1167
  edge_direction = Edge.Direction(edge)
1005
1168
  x, y, z = edge_direction
@@ -1062,7 +1225,7 @@ class Edge():
1062
1225
  mantissa : int , optional
1063
1226
  The desired length of the mantissa. The default is 6.
1064
1227
  silent : bool , optional
1065
- If set to False, error and warning messages are printed. Otherwise, they are not. The default is False.
1228
+ If set to True, no error and warning messages are printed. Otherwise, they are. The default is False.
1066
1229
 
1067
1230
  Returns
1068
1231
  -------
@@ -1238,7 +1401,7 @@ class Edge():
1238
1401
  tolerance : float , optional
1239
1402
  The desired tolerance. The default is 0.0001.
1240
1403
  silent : bool , optional
1241
- If set to True, not error or warning messages are printed. Otherwise, they are. The default is False.
1404
+ If set to True, no error and warning messages are printed. Otherwise, they are. The default is False.
1242
1405
 
1243
1406
  Returns
1244
1407
  -------
topologicpy/Face.py CHANGED
@@ -563,8 +563,8 @@ class Face():
563
563
  The input wire.
564
564
  tolerance : float , optional
565
565
  The desired tolerance. The default is 0.0001.
566
- silent : bool , optional
567
- If set to False, error and warning messages are printed. Otherwise, they are not. The default is False.
566
+ silent : bool , optional
567
+ If set to True, no error and warning messages are printed. Otherwise, they are. The default is False.
568
568
 
569
569
  Returns
570
570
  -------
@@ -652,7 +652,7 @@ class Face():
652
652
  tolerance : float , optional
653
653
  The desired tolerance. The default is 0.0001.
654
654
  silent : bool , optional
655
- If set to False, error messages are printed. Otherwise, they are not. The default is False.
655
+ If set to True, no error and warning messages are printed. Otherwise, they are. The default is False.
656
656
 
657
657
  Returns
658
658
  -------
@@ -695,7 +695,7 @@ class Face():
695
695
  tolerance : float , optional
696
696
  The desired tolerance. The default is 0.0001.
697
697
  silent : bool , optional
698
- If set to False, error messages are printed. Otherwise, they are not. The default is False.
698
+ If set to True, no error and warning messages are printed. Otherwise, they are. The default is False.
699
699
 
700
700
  Returns
701
701
  -------
@@ -1123,7 +1123,7 @@ class Face():
1123
1123
  tolerance : float , optional
1124
1124
  The desired tolerance. The default is 0.0001.
1125
1125
  silent : bool , optional
1126
- If set to False, error and warning messages are printed. Otherwise, they are not. The default is False.
1126
+ If set to True, no error and warning messages are printed. Otherwise, they are. The default is False.
1127
1127
 
1128
1128
  Returns
1129
1129
  -------
topologicpy/Graph.py CHANGED
@@ -3991,8 +3991,8 @@ class Graph:
3991
3991
  maxColors : int , optional
3992
3992
  The desired maximum number of colors to test against. The default is 3.
3993
3993
  silent : bool , optional
3994
- If set to False, error and warning messages are printed. Otherwise, they are not. The default is False.
3995
-
3994
+ If set to True, no error and warning messages are printed. Otherwise, they are. The default is False.
3995
+
3996
3996
  Returns
3997
3997
  -------
3998
3998
  int
topologicpy/Shell.py CHANGED
@@ -389,8 +389,8 @@ class Shell():
389
389
  tolerance : float , optional
390
390
  The desired tolerance. The default is 0.0001.
391
391
  silent : bool , optional
392
- If set to False, error and warning messages are printed. Otherwise, they are not. The default is False.
393
-
392
+ If set to True, no error and warning messages are printed. Otherwise, they are. The default is False.
393
+
394
394
  Returns
395
395
  -------
396
396
  topologic_core.Shell
@@ -485,7 +485,7 @@ class Shell():
485
485
  tolerance : float , optional
486
486
  The desired tolerance. The default is 0.0001.
487
487
  silent : bool , optional
488
- If set to False, error and warning messages are printed. Otherwise, they are not. The default is False.
488
+ If set to True, no error and warning messages are printed. Otherwise, they are. The default is False.
489
489
 
490
490
  Returns
491
491
  -------
topologicpy/Topology.py CHANGED
@@ -999,8 +999,6 @@ class Topology():
999
999
  else:
1000
1000
  cellsB_2.append(cellB)
1001
1001
 
1002
- print("cellsA_2", cellsA_2)
1003
- print("cellsB_2", cellsB_2)
1004
1002
  for cellA in cellsA_2:
1005
1003
  for cellB in cellsB_2:
1006
1004
  cellC = cellA.Intersect(cellB)
@@ -2036,7 +2034,7 @@ class Topology():
2036
2034
  try:
2037
2035
  import ezdxf
2038
2036
  except:
2039
- print("Topology.ExportToDXF - Information: Installing required ezdxf library.")
2037
+ print("Topology.ByDXFPath - Information: Installing required ezdxf library.")
2040
2038
  try:
2041
2039
  os.system("pip install ezdxf")
2042
2040
  except:
@@ -6525,7 +6523,7 @@ class Topology():
6525
6523
  return return_topology
6526
6524
 
6527
6525
  @staticmethod
6528
- def SetDictionary(topology, dictionary):
6526
+ def SetDictionary(topology, dictionary, silent=False):
6529
6527
  """
6530
6528
  Sets the input topology's dictionary to the input dictionary
6531
6529
 
@@ -6535,6 +6533,8 @@ class Topology():
6535
6533
  The input topology.
6536
6534
  dictionary : topologic_core.Dictionary
6537
6535
  The input dictionary.
6536
+ silent : bool , optional
6537
+ If set to True, no error and warning messages are printed. Otherwise, they are. The default is False.
6538
6538
 
6539
6539
  Returns
6540
6540
  -------
@@ -6545,15 +6545,18 @@ class Topology():
6545
6545
  from topologicpy.Dictionary import Dictionary
6546
6546
 
6547
6547
  if not Topology.IsInstance(topology, "Topology") and not Topology.IsInstance(topology, "Graph"):
6548
- print("Topology.SetDictionary - Error: the input topology parameter is not a valid topology or graph. Returning None.")
6548
+ if not silent:
6549
+ print("Topology.SetDictionary - Error: the input topology parameter is not a valid topology or graph. Returning None.")
6549
6550
  return None
6550
6551
  if isinstance(dictionary, dict):
6551
6552
  dictionary = Dictionary.ByPythonDictionary(dictionary)
6552
6553
  if not Topology.IsInstance(dictionary, "Dictionary"):
6553
- print("Topology.SetDictionary - Warning: the input dictionary parameter is not a valid dictionary. Returning original input.")
6554
+ if not silent:
6555
+ print("Topology.SetDictionary - Warning: the input dictionary parameter is not a valid dictionary. Returning original input.")
6554
6556
  return topology
6555
6557
  if len(dictionary.Keys()) < 1:
6556
- print("Topology.SetDictionary - Warning: the input dictionary parameter is empty. Returning original input.")
6558
+ if not silent:
6559
+ print("Topology.SetDictionary - Warning: the input dictionary parameter is empty. Returning original input.")
6557
6560
  return topology
6558
6561
  _ = topology.SetDictionary(dictionary)
6559
6562
  return topology
topologicpy/Vertex.py CHANGED
@@ -1008,7 +1008,7 @@ class Vertex():
1008
1008
  tolerance : float , optional
1009
1009
  The tolerance for computing if the input vertex is external to the input topology. The default is 0.0001.
1010
1010
  silent : bool , optional
1011
- If set to False, error and warning messages are printed. Otherwise, they are not. The default is False.
1011
+ If set to True, no error and warning messages are printed. Otherwise, they are. The default is False.
1012
1012
 
1013
1013
  Returns
1014
1014
  -------
@@ -1042,7 +1042,7 @@ class Vertex():
1042
1042
  tolerance : float , optional
1043
1043
  The tolerance for computing if the input vertex is internal to the input topology. The default is 0.0001.
1044
1044
  silent : bool , optional
1045
- If set to False, error and warning messages are printed. Otherwise, they are not. The default is False.
1045
+ If set to True, no error and warning messages are printed. Otherwise, they are. The default is False.
1046
1046
 
1047
1047
  Returns
1048
1048
  -------
@@ -1153,7 +1153,7 @@ class Vertex():
1153
1153
  tolerance : float , optional
1154
1154
  The tolerance for computing if the input vertex is peripheral to the input topology. The default is 0.0001.
1155
1155
  silent : bool , optional
1156
- If set to False, error and warning messages are printed. Otherwise, they are not. The default is False.
1156
+ If set to True, no error and warning messages are printed. Otherwise, they are. The default is False.
1157
1157
 
1158
1158
  Returns
1159
1159
  -------
topologicpy/Wire.py CHANGED
@@ -49,96 +49,66 @@ class Wire(Topology):
49
49
 
50
50
  """
51
51
  from topologicpy.Vertex import Vertex
52
- from topologicpy.Face import Face
53
- from topologicpy.Topology import Topology
52
+ from topologicpy.Edge import Edge
53
+ from topologicpy.Wire import Wire
54
+ from topologicpy.Vector import Vector
55
+ import numpy as np
56
+
54
57
 
55
- def segmented_arc(x1, y1, x2, y2, x3, y3, sides):
56
- import math
58
+ def calculate_circle_center_and_radius(sv, mv, ev):
57
59
  """
58
- Generates a segmented arc passing through the three given points.
59
-
60
- Arguments:
61
- x1, y1: Coordinates of the first point
62
- x2, y2: Coordinates of the second point
63
- x3, y3: Coordinates of the third point
64
- sides: Number of sides to divide the arc
65
-
60
+ Calculate the center and radius of the circle passing through three points.
61
+
62
+ Parameters:
63
+ sv (tuple): The start vertex as (x, y, z).
64
+ mv (tuple): The middle vertex as (x, y, z).
65
+ ev (tuple): The end vertex as (x, y, z).
66
+
66
67
  Returns:
67
- List of tuples [x, y] representing the segmented arc passing through the points
68
+ tuple: The center of the circle as (x, y, z) and the radius.
68
69
  """
69
-
70
- # Calculate the center of the circle
71
- A = x2 - x1
72
- B = y2 - y1
73
- C = x3 - x1
74
- D = y3 - y1
75
- E = A * (x1 + x2) + B * (y1 + y2)
76
- F = C * (x1 + x3) + D * (y1 + y3)
77
- G = 2 * (A * (y3 - y2) - B * (x3 - x2))
78
- if G == 0:
79
- center_x = 0
80
- center_y = 0
81
- else:
82
- center_x = (D * E - B * F) / G
83
- center_y = (A * F - C * E) / G
84
-
85
- # Calculate the radius of the circle
86
- radius = math.sqrt((center_x - x1) ** 2 + (center_y - y1) ** 2)
87
-
88
- # Calculate the angles between the center and the three points
89
- angle1 = math.atan2(y1 - center_y, x1 - center_x)
90
- angle3 = math.atan2(y3 - center_y, x3 - center_x)
91
-
92
- # Calculate the angle between points 1 and 3
93
- angle13 = (angle3 - angle1) % (2 * math.pi)
94
- if angle13 < 0:
95
- angle13 += 2 * math.pi
96
-
97
- # Determine the direction of the arc based on the angle between points 1 and 3
98
- if angle13 < math.pi:
99
- start_angle = angle3
100
- end_angle = angle1
101
- else:
102
- start_angle = angle1
103
- end_angle = angle3
104
-
105
- # Calculate the angle increment
106
- angle_increment = (end_angle - start_angle) / sides
107
-
108
- # Generate the points of the arc passing through the points
109
- arc_points = []
110
- for i in range(sides + 1):
111
- angle = start_angle + i * angle_increment
112
- x = center_x + radius * math.cos(angle)
113
- y = center_y + radius * math.sin(angle)
114
- arc_points.append([x, y])
115
-
116
- return arc_points
117
- if not Topology.IsInstance(startVertex, "Vertex"):
118
- print("Wire.Arc - Error: The startVertex parameter is not a valid vertex. Returning None.")
119
- return None
120
- if not Topology.IsInstance(middleVertex, "Vertex"):
121
- print("Wire.Arc - Error: The middleVertex parameter is not a valid vertex. Returning None.")
122
- return None
123
- if not Topology.IsInstance(endVertex, "Vertex"):
124
- print("Wire.Arc - Error: The endVertex parameter is not a valid vertex. Returning None.")
125
- return None
126
- if Vertex.AreCollinear([startVertex, middleVertex, endVertex], tolerance = tolerance):
127
- return Wire.ByVertices([startVertex, middleVertex, endVertex], close=False)
70
+ # Convert points to numpy arrays for easier manipulation
71
+ A = np.array(sv)
72
+ B = np.array(mv)
73
+ C = np.array(ev)
74
+
75
+ # Calculate the lengths of the sides of the triangle
76
+ a = np.linalg.norm(B - C)
77
+ b = np.linalg.norm(C - A)
78
+ c = np.linalg.norm(A - B)
79
+
80
+ # Calculate the circumcenter using the formula
81
+ D = 2 * (A[0] * (B[1] - C[1]) + B[0] * (C[1] - A[1]) + C[0] * (A[1] - B[1]))
82
+ Ux = ((A[0]**2 + A[1]**2) * (B[1] - C[1]) + (B[0]**2 + B[1]**2) * (C[1] - A[1]) + (C[0]**2 + C[1]**2) * (A[1] - B[1])) / D
83
+ Uy = ((A[0]**2 + A[1]**2) * (C[0] - B[0]) + (B[0]**2 + B[1]**2) * (A[0] - C[0]) + (C[0]**2 + C[1]**2) * (B[0] - A[0])) / D
84
+ center = np.array([Ux, Uy, A[2]])
85
+
86
+ # Calculate the radius
87
+ radius = np.linalg.norm(center - A)
88
+
89
+ return center, radius
128
90
 
129
- w = Wire.ByVertices([startVertex, middleVertex, endVertex], close=True)
130
- f = Face.ByWire(w, tolerance=tolerance)
131
- normal = Face.Normal(f)
132
- flat_w = Topology.Flatten(w, origin=startVertex, direction=normal)
133
- v1, v2, v3 = Topology.Vertices(flat_w)
134
- x1, y1, z1 = Vertex.Coordinates(v1)
135
- x2, y2, z2 = Vertex.Coordinates(v2)
136
- x3, y3, z3 = Vertex.Coordinates(v3)
137
- arc_points = segmented_arc(x1, y1, x2, y2, x3, y3, sides)
138
- arc_verts = [Vertex.ByCoordinates(coord[0], coord[1], 0) for coord in arc_points]
139
- arc = Wire.ByVertices(arc_verts, close=close)
140
- # Unflatten the arc
141
- arc = Topology.Unflatten(arc, origin=startVertex, direction=normal)
91
+
92
+ e2 = Edge.ByVertices(middleVertex, endVertex)
93
+
94
+ center, radius = calculate_circle_center_and_radius(Vertex.Coordinates(startVertex), Vertex.Coordinates(middleVertex), Vertex.Coordinates(endVertex))
95
+ center = Vertex.ByCoordinates(list(center))
96
+
97
+ e1 = Edge.ByVertices(center, startVertex)
98
+ e2 = Edge.ByVertices(center, endVertex)
99
+ ang1 = Vector.CompassAngle(Vector.North(), Edge.Direction(e1))
100
+ ang2 = Vector.CompassAngle(Vector.North(), Edge.Direction(e2))
101
+ arc1 = Wire.Circle(origin=center, radius=radius, fromAngle=ang1, toAngle=ang2, sides=sides*4, close=False)
102
+ arc2 = Wire.Circle(origin=center, radius=radius, fromAngle=ang2, toAngle=ang1, sides=sides*4, close=False)
103
+ if Vertex.IsInternal(middleVertex, arc1):
104
+ arc = arc1
105
+ else:
106
+ arc = arc2
107
+ final_vertices = []
108
+ for i in range(sides+1):
109
+ v = Wire.VertexByParameter(arc, float(i)/float(sides))
110
+ final_vertices.append(v)
111
+ arc = Wire.ByVertices(final_vertices, close=close)
142
112
  return arc
143
113
 
144
114
  @staticmethod
@@ -340,9 +310,9 @@ class Wire(Topology):
340
310
  return Wire.ByEdges(edges, tolerance=tolerance)
341
311
 
342
312
  @staticmethod
343
- def ByOffset(wire, offset: float = 1.0, bisectors: bool = False, tolerance: float = 0.0001):
313
+ def ByOffset(wire, offset: float = 1.0, offsetKey: str = "offset", bisectors: bool = False, tolerance: float = 0.0001, silent: bool = False):
344
314
  """
345
- Creates an offset wire from the input wire. A positive offset value results in an offset to the interior of the anti-clockwise wire.
315
+ Creates an offset wire from the input wire. A positive offset value results in an offset to the interior of an anti-clockwise wire.
346
316
 
347
317
  Parameters
348
318
  ----------
@@ -350,10 +320,14 @@ class Wire(Topology):
350
320
  The input wire.
351
321
  offset : float , optional
352
322
  The desired offset distance. The default is 1.0.
323
+ offsetKey : str , optional
324
+ The edge dictionary key under which to find the offset value. If a value cannot be found, the offset input parameter value is used instead. The default is "offset".
353
325
  bisectors : bool , optional
354
326
  If set to True, The bisectors (seams) edges will be included in the returned wire. The default is False.
355
327
  tolerance : float , optional
356
328
  The desired tolerance. The default is 0.0001.
329
+ silent : bool , optional
330
+ If set to True, no error and warning messages are printed. Otherwise, they are. The default is False.
357
331
 
358
332
  Returns
359
333
  -------
@@ -361,74 +335,104 @@ class Wire(Topology):
361
335
  The created wire.
362
336
 
363
337
  """
364
- def compute_h(alpha, offset):
365
- import math
366
- alpha = math.radians(alpha) *0.5
367
- h = offset/math.cos(alpha)
368
- return h
369
-
370
338
  from topologicpy.Vertex import Vertex
371
339
  from topologicpy.Edge import Edge
372
340
  from topologicpy.Face import Face
341
+ from topologicpy.Dictionary import Dictionary
342
+ from topologicpy.Wire import Wire
373
343
  from topologicpy.Cluster import Cluster
374
344
  from topologicpy.Topology import Topology
375
345
  from topologicpy.Vector import Vector
376
- import math
377
346
 
378
347
  if not Topology.IsInstance(wire, "Wire"):
379
- print("Wire.ByOffset - Error: The input wire parameter is not a valid wire. Returning None")
380
- return None
381
- if abs(offset) < tolerance:
382
- return wire
383
- vertices = Topology.Vertices(wire)
384
- if len(vertices) < 3:
385
- print("Wire.ByOffset - Error: The input wire parameter contains less than three vertices. Cannot proceed. Returning None")
386
- return None
387
- if not Wire.IsClosed(wire):
388
- w = Wire.ByVertices(vertices, close=True)
389
- else:
390
- w = wire
391
- three_vertices = Wire.Vertices(w)[0:3]
392
- temp_w = Wire.ByVertices(three_vertices, close=True)
393
- flat_face = Face.ByWire(temp_w, tolerance=tolerance)
348
+ if not silent:
349
+ print("Wire.ByOffset - Error: The input wire parameter is not a valid wire. Returning None.")
350
+ return None
351
+
394
352
  origin = Vertex.Origin()
395
- normal = Face.Normal(flat_face)
396
- flat_wire = Topology.Flatten(w, origin=origin, direction=normal)
397
- edges = Wire.Edges(flat_wire)
398
- vertices = Wire.Vertices(flat_wire)
399
- int_angles = Wire.InteriorAngles(flat_wire)
400
- bisector_list = []
353
+ temp_vertices = [Topology.Vertices(wire)[0], Topology.Vertices(wire)[1], Topology.Centroid(wire)]
354
+ temp_face = Face.ByWire(Wire.ByVertices(temp_vertices, close=True))
355
+ temp_normal = Face.Normal(temp_face)
356
+ flat_wire = Topology.Flatten(wire, direction=temp_normal, origin=origin)
357
+ normal = Face.Normal(temp_face)
358
+ if normal[2] < 0:
359
+ wire = Wire.Reverse(wire, transferDictionaries=True)
360
+ flat_wire = Topology.Flatten(wire, direction=normal, origin=origin)
361
+ edges = Topology.Edges(flat_wire)
362
+ offsets = []
363
+ offset_edges = []
401
364
  final_vertices = []
402
- for i in range(len(vertices)):
403
- v_edges = Topology.SuperTopologies(vertices[i], flat_wire, topologyType="edge")
404
- if len(v_edges) < 2:
405
- continue
406
- bisector = Edge.Bisect(v_edges[0], v_edges[1], length=offset, placement=1)
407
- if int_angles[i] > 180:
408
- bisector = Topology.TranslateByDirectionDistance(bisector, Vector.Reverse(Edge.Direction(bisector)), distance=abs(offset))
409
- bisector = Edge.Reverse(bisector)
410
-
411
- h = abs(compute_h(180-int_angles[i], abs(offset)))
412
- bisector = Edge.SetLength(bisector, length=h, bothSides=False)
413
- final_vertices.append(Edge.EndVertex(bisector))
414
- bisector_list.append(bisector)
365
+ bisectors_list = []
366
+ for edge in edges:
367
+ d = Topology.Dictionary(edge)
368
+ d_offset = Dictionary.ValueAtKey(d, offsetKey)
369
+ if d_offset == None:
370
+ d_offset = offset
371
+ offsets.append(d_offset)
372
+ offset_edge = Edge.ByOffset2D(edge, d_offset)
373
+ offset_edges.append(offset_edge)
374
+ o_edges = []
375
+ for i in range(len(edges)):
376
+ edge_a = edges[i]
377
+ o_edge_a = offset_edges[i]
378
+ v_a = Edge.StartVertex(edges[i])
379
+ if i == 0:
380
+ if Wire.IsClosed(wire) == False:
381
+ v1 = Edge.StartVertex(offset_edges[0])
382
+ final_vertices.append(v1)
383
+ if bisectors == True:
384
+ bisectors_list.append(Edge.ByVertices(v_a, v1))
385
+ else:
386
+ prev_edge = offset_edges[-1]
387
+ else:
388
+ prev_edge = offset_edges[i-1]
389
+ v1 = Edge.Intersect2D(prev_edge, o_edge_a, silent=True)
390
+ if Topology.IsInstance(v1, "Vertex"):
391
+ if bisectors == True:
392
+ bisectors_list.append(Edge.ByVertices(v_a, v1))
393
+ final_vertices.append(v1)
394
+ else:
395
+ connection = Edge.Connection(prev_edge, o_edge_a)
396
+ if Topology.IsInstance(connection, "Edge"):
397
+ v1_1 = Edge.StartVertex(connection)
398
+ v1_2 = Edge.EndVertex(connection)
399
+ bisectors_list.append(Edge.ByVertices(v_a, v1_1))
400
+ bisectors_list.append(Edge.ByVertices(v_a, v1_2))
401
+ final_vertices.append(v1_1)
402
+ final_vertices.append(v1_2)
403
+ if Wire.IsClosed(wire) == False:
404
+ v_a = Edge.EndVertex(edges[-1])
405
+ v1 = Edge.EndVertex(offset_edges[-1])
406
+ final_vertices.append(v1)
407
+ if bisectors == True:
408
+ bisectors_list.append(Edge.ByVertices(v_a, v1))
409
+ else:
410
+ v1 = Edge.Intersect2D(o_edge_a, offset_edges[0], silent=True)
411
+ if Topology.IsInstance(v1, "Vertex"):
412
+ if bisectors == True:
413
+ bisectors_list.append(Edge.ByVertices(Edge.StartVertex(edges[0]), v1))
414
+ final_vertices.append(v1)
415
+ else:
416
+ connection = Edge.Connection(offset_edges[0], o_edge_a)
417
+ if Topology.IsInstance(connection, "Edge"):
418
+ v1_1 = Edge.StartVertex(connection)
419
+ v1_2 = Edge.EndVertex(connection)
420
+ bisectors_list.append(Edge.ByVertices(v_a, v1_1))
421
+ bisectors_list.append(Edge.ByVertices(v_a, v1_2))
422
+ final_vertices.append(v1_1)
423
+ final_vertices.append(v1_2)
424
+
415
425
  return_wire = Wire.ByVertices(final_vertices, close=Wire.IsClosed(wire))
416
- vertices = Topology.Vertices(return_wire)
417
- if not Wire.IsClosed(wire):
418
- sv = Topology.Vertices(flat_wire)[0]
419
- ev = Topology.Vertices(flat_wire)[-1]
420
- first_edge = Topology.SuperTopologies(sv, flat_wire, topologyType="edge")[0]
421
- first_normal = Edge.NormalAsEdge(first_edge, length=abs(offset), u = 0)
422
- last_edge = Topology.SuperTopologies(ev, flat_wire, topologyType="edge")[0]
423
- last_normal = Edge.NormalAsEdge(last_edge, length=abs(offset), u = 1.0)
424
- sv1 = Edge.EndVertex(first_normal)
425
- ev1 = Edge.EndVertex(last_normal)
426
- vertices = [sv1] + vertices[1:-1] + [ev1]
427
- bisector_list = [first_normal] + bisector_list[1:-1] + [last_normal]
428
- return_wire = Wire.ByVertices(vertices, close=Wire.IsClosed(wire))
429
- if bisectors:
430
- return_wire = Topology.SelfMerge(Cluster.ByTopologies(bisector_list, Topology.Edges(return_wire)))
431
- return_wire = Topology.Unflatten(return_wire, origin=origin, direction=normal)
426
+ if bisectors == True:
427
+ return_wire = Topology.SelfMerge(Cluster.ByTopologies(bisectors_list+Topology.Edges(return_wire)))
428
+ if not Topology.IsInstance(return_wire, "Wire"):
429
+ if not silent:
430
+ print("Wire.ByOffset - Warning: The resulting wire is not well-formed, please check your offsets.")
431
+ else:
432
+ if not Wire.IsManifold(return_wire) and bisectors == False:
433
+ if not silent:
434
+ print("Wire.ByOffset - Warning: The resulting wire is non-manifold, please check your offsets.")
435
+ return_wire = Topology.Unflatten(return_wire, direction=normal, origin=origin)
432
436
  return return_wire
433
437
 
434
438
  @staticmethod
@@ -1274,7 +1278,7 @@ class Wire(Topology):
1274
1278
  return Cluster.ByTopologies([v for v in Topology.Vertices(wire) if (Vertex.Degree(v, wire, topologyType="edge") == 1)])
1275
1279
 
1276
1280
  @staticmethod
1277
- def Fillet(wire, radius: float = 0, radiusKey: str = None, tolerance: float = 0.0001, silent: bool = False):
1281
+ def Fillet(wire, radius: float = 0, sides: int = 16, radiusKey: str = None, tolerance: float = 0.0001, silent: bool = False):
1278
1282
  """
1279
1283
  Fillets (rounds) the interior and exterior corners of the input wire given the input radius. See https://en.wikipedia.org/wiki/Fillet_(mechanics)
1280
1284
 
@@ -1286,10 +1290,12 @@ class Wire(Topology):
1286
1290
  The desired radius of the fillet.
1287
1291
  radiusKey : str , optional
1288
1292
  If specified, the dictionary of the vertices will be queried for this key to specify the desired fillet radius. The default is None.
1293
+ sides : int , optional
1294
+ The number of sides (segments) of the fillet. The default is 16.
1289
1295
  tolerance : float , optional
1290
1296
  The desired tolerance. The default is 0.0001.
1291
1297
  silent : bool , optional
1292
- If set to False, error and warning messages are printed. Otherwise, they are not. The default is False.
1298
+ If set to True, no error and warning messages are printed. Otherwise, they are. The default is False.
1293
1299
 
1294
1300
  Returns
1295
1301
  -------
@@ -1316,7 +1322,6 @@ class Wire(Topology):
1316
1322
  from topologicpy.Edge import Edge
1317
1323
  from topologicpy.Wire import Wire
1318
1324
  from topologicpy.Face import Face
1319
- from topologicpy.Cluster import Cluster
1320
1325
  from topologicpy.Topology import Topology
1321
1326
  from topologicpy.Vector import Vector
1322
1327
  from topologicpy.Dictionary import Dictionary
@@ -1340,7 +1345,6 @@ class Wire(Topology):
1340
1345
  flat_wire = Topology.Flatten(wire, origin=Vertex.Origin(), direction=normal)
1341
1346
  vertices = Topology.Vertices(flat_wire)
1342
1347
  final_vertices = []
1343
- fillets = []
1344
1348
  for v in vertices:
1345
1349
  radius = orig_radius
1346
1350
  edges = Topology.SuperTopologies(v, flat_wire, topologyType="edge")
@@ -1374,22 +1378,11 @@ class Wire(Topology):
1374
1378
  v1 = Topology.TranslateByDirectionDistance(v, dir1, a)
1375
1379
  center = Topology.TranslateByDirectionDistance(v, dir_bisector, h)
1376
1380
  v2 = Topology.TranslateByDirectionDistance(v, dir2, a)
1377
- r1 = Edge.ByVertices(center, v1)
1378
- dir1 = Edge.Direction(r1)
1379
- r2 = Edge.ByVertices(center, v2)
1380
- dir2 = Edge.Direction(r2)
1381
- compass1 = Vector.CompassAngle(Vector.East(), dir1)*-1
1382
- compass2 = Vector.CompassAngle(Vector.East(), dir2)*-1
1383
- if compass2 < compass1:
1384
- temp = compass2
1385
- compass2 = compass1
1386
- compass1 = temp
1387
- w1 = Wire.Circle(origin=center, radius=radius, fromAngle=compass1, toAngle=compass2, close=False)
1388
- w2 = Wire.Circle(origin=center, radius=radius, fromAngle=compass2, toAngle=compass1, close=False)
1389
- if Wire.Length(w1) < Wire.Length(w2):
1390
- fillet = w1
1391
- else:
1392
- fillet = w2
1381
+ fillet = Wire.Circle(origin=center, radius=radius, close=True)
1382
+ bisector = Edge.ByVertices(v, center)
1383
+ mid_vertex = Topology.Slice(bisector, fillet)
1384
+ mid_vertex = Topology.Vertices(mid_vertex)[1]
1385
+ fillet = Wire.Arc(v1, mid_vertex, v2, sides=sides, close= False)
1393
1386
  f_sv = Wire.StartVertex(fillet)
1394
1387
  if Vertex.Distance(f_sv, edge1) < Vertex.Distance(f_sv, edge0):
1395
1388
  fillet = Wire.Reverse(fillet)
@@ -1869,7 +1862,7 @@ class Wire(Topology):
1869
1862
  tolerance : float , optional
1870
1863
  The desired tolerance. The default is 0.0001.
1871
1864
  silent : bool , optional
1872
- If set to False, error and warning messages are printed. Otherwise, they are not. The default is False.
1865
+ If set to True, no error and warning messages are printed. Otherwise, they are. The default is False.
1873
1866
 
1874
1867
  Returns
1875
1868
  -------
@@ -2071,7 +2064,7 @@ class Wire(Topology):
2071
2064
  return return_normal
2072
2065
 
2073
2066
  @staticmethod
2074
- def OrientEdges(wire, vertexA, tolerance=0.0001):
2067
+ def OrientEdges(wire, vertexA, transferDictionaries = False, tolerance=0.0001):
2075
2068
  """
2076
2069
  Returns a correctly oriented head-to-tail version of the input wire. The input wire must be manifold.
2077
2070
 
@@ -2081,6 +2074,8 @@ class Wire(Topology):
2081
2074
  The input wire.
2082
2075
  vertexA : topologic_core.Vertex
2083
2076
  The desired start vertex of the wire.
2077
+ transferDictionaries : bool , optional
2078
+ If set to True, the dictionaries of the original wire are transfered to the new wire. Otherwise, they are not. The default is False.
2084
2079
  tolerance : float, optional
2085
2080
  The desired tolerance. The default is 0.0001.
2086
2081
 
@@ -2092,6 +2087,8 @@ class Wire(Topology):
2092
2087
  """
2093
2088
  from topologicpy.Vertex import Vertex
2094
2089
  from topologicpy.Edge import Edge
2090
+ from topologicpy.Dictionary import Dictionary
2091
+ from topologicpy.Topology import Topology
2095
2092
 
2096
2093
  if not Topology.IsInstance(wire, "Wire"):
2097
2094
  print("Wire.OrientEdges - Error: The input wire parameter is not a valid wire. Returning None.")
@@ -2104,6 +2101,15 @@ class Wire(Topology):
2104
2101
  return None
2105
2102
  oriented_edges = []
2106
2103
  remaining_edges = Topology.Edges(wire)
2104
+ original_vertices = Topology.Vertices(wire)
2105
+ if transferDictionaries:
2106
+ edge_selectors = []
2107
+ for i, e_s in enumerate(remaining_edges):
2108
+ s = Topology.Centroid(e_s)
2109
+ d = Topology.Dictionary(e_s)
2110
+ s = Topology.SetDictionary(s, d)
2111
+ edge_selectors.append(s)
2112
+
2107
2113
  current_vertex = vertexA
2108
2114
  while remaining_edges:
2109
2115
  next_edge = None
@@ -2126,7 +2132,12 @@ class Wire(Topology):
2126
2132
  for i, edge in enumerate(oriented_edges):
2127
2133
  vertices.append(Edge.EndVertex(edge))
2128
2134
 
2129
- return Wire.ByVertices(vertices, close=Wire.IsClosed(wire))
2135
+ return_wire = Wire.ByVertices(vertices, close=Wire.IsClosed(wire))
2136
+ if transferDictionaries:
2137
+ return_wire = Topology.TransferDictionariesBySelectors(return_wire, selectors=edge_selectors, tranEdges=True)
2138
+ return_wire = Topology.TransferDictionariesBySelectors(return_wire, selectors=original_vertices, tranVertices=True)
2139
+ return_wire = Topology.SetDictionary(return_wire, Topology.Dictionary(wire), silent=True)
2140
+ return return_wire
2130
2141
 
2131
2142
  @staticmethod
2132
2143
  def Planarize(wire, origin= None, mantissa: int = 6, tolerance: float = 0.0001):
@@ -2420,7 +2431,7 @@ class Wire(Topology):
2420
2431
  return wire
2421
2432
 
2422
2433
  @staticmethod
2423
- def Reverse(wire, tolerance: float = 0.0001):
2434
+ def Reverse(wire, transferDictionaries = False, tolerance: float = 0.0001):
2424
2435
  """
2425
2436
  Creates a wire that has the reverse direction of the input wire.
2426
2437
 
@@ -2428,6 +2439,8 @@ class Wire(Topology):
2428
2439
  ----------
2429
2440
  wire : topologic_core.Wire
2430
2441
  The input wire.
2442
+ transferDictionaries : bool , optional
2443
+ If set to True the dictionaries of the input wire are transferred to the new wire. Othwerwise, they are not. The default is False.
2431
2444
  tolerance : float , optional
2432
2445
  The desired tolerance. The default is 0.0001.
2433
2446
 
@@ -2446,10 +2459,23 @@ class Wire(Topology):
2446
2459
  print("Wire.Reverse - Error: The input wire parameter is not a manifold wire. Returning None.")
2447
2460
  return None
2448
2461
 
2462
+ original_vertices = Topology.Vertices(wire)
2463
+ edges = Topology.Edges(wire)
2464
+ if transferDictionaries:
2465
+ edge_selectors = []
2466
+ for i, e_s in enumerate(edges):
2467
+ s = Topology.Centroid(e_s)
2468
+ d = Topology.Dictionary(e_s)
2469
+ s = Topology.SetDictionary(s, d)
2470
+ edge_selectors.append(s)
2449
2471
  vertices = Topology.Vertices(wire)
2450
2472
  vertices.reverse()
2451
- new_wire = Wire.ByVertices(vertices, close=Wire.IsClosed(wire), tolerance=tolerance)
2452
- return new_wire
2473
+ return_wire = Wire.ByVertices(vertices, close=Wire.IsClosed(wire), tolerance=tolerance)
2474
+ if transferDictionaries:
2475
+ return_wire = Topology.TransferDictionariesBySelectors(return_wire, selectors=edge_selectors, tranEdges=True)
2476
+ return_wire = Topology.TransferDictionariesBySelectors(return_wire, selectors=original_vertices, tranVertices=True)
2477
+ return_wire = Topology.SetDictionary(return_wire, Topology.Dictionary(wire), silent=True)
2478
+ return return_wire
2453
2479
 
2454
2480
  @staticmethod
2455
2481
  def Roof(face, angle: float = 45, tolerance: float = 0.001):
@@ -3365,13 +3391,13 @@ class Wire(Topology):
3365
3391
  from topologicpy.Edge import Edge
3366
3392
 
3367
3393
  if not Topology.IsInstance(wire, "Wire"):
3368
- print("Wire.VertexAtParameter - Error: The input wire parameter is not a valid topologic wire. Returning None.")
3394
+ print("Wire.VertexByParameter - Error: The input wire parameter is not a valid topologic wire. Returning None.")
3369
3395
  return None
3370
3396
  if u < 0 or u > 1:
3371
- print("Wire.VertexAtParameter - Error: The input u parameter is not within the valid range of [0, 1]. Returning None.")
3397
+ print("Wire.VertexByParameter - Error: The input u parameter is not within the valid range of [0, 1]. Returning None.")
3372
3398
  return None
3373
3399
  if not Wire.IsManifold(wire):
3374
- print("Wire.VertexAtParameter - Error: The input wire parameter is non-manifold. Returning None.")
3400
+ print("Wire.VertexByParameter - Error: The input wire parameter is non-manifold. Returning None.")
3375
3401
  return None
3376
3402
 
3377
3403
  if u == 0:
topologicpy/version.py CHANGED
@@ -1 +1 @@
1
- __version__ = '0.7.26'
1
+ __version__ = '0.7.28'
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: topologicpy
3
- Version: 0.7.26
3
+ Version: 0.7.28
4
4
  Summary: An Advanced Spatial Modelling and Analysis Software Library for Architecture, Engineering, and Construction.
5
5
  Author-email: Wassim Jabi <wassim.jabi@gmail.com>
6
6
  License: MIT License
@@ -1,16 +1,16 @@
1
1
  topologicpy/ANN.py,sha256=A7k3RZ6rVccLLzJhQMz_5xaDUnLJDgJMQTtnG_Bsc-s,49166
2
2
  topologicpy/Aperture.py,sha256=p9pUzTQSBWoUaDiug1V1R1hnEIEwYSXFg2t7iRAmNRY,2723
3
- topologicpy/Cell.py,sha256=NjcKAqZywkr7DouYP4MGLhG6grWrXYfEpzDgUN-qAC0,99802
3
+ topologicpy/Cell.py,sha256=c6LeEY6-gMNByIHGC_rb2wm9ogg93VhwYK3zJ8IB78U,99798
4
4
  topologicpy/CellComplex.py,sha256=x474N-lo1krpdIGrWRAFRdDup5a_1V-mLORTS6ZGZ7M,48227
5
- topologicpy/Cluster.py,sha256=mwQVNXnh20VHms0ZqPzTROP8bUdVt8CTKtaNobAqHsE,54993
5
+ topologicpy/Cluster.py,sha256=TZXuxzdaUr6OHSWnjWpjCOMlVj6YHBH8aUVbDVsncVA,54999
6
6
  topologicpy/Color.py,sha256=UlmRcCSOhqcM_OyMWz4t3Kr75KcgXDhz3uctAJ2n7Ic,18031
7
7
  topologicpy/Context.py,sha256=ppApYKngZZCQBFWaxIMi2z2dokY23c935IDCBosxDAE,3055
8
8
  topologicpy/DGL.py,sha256=Dd6O08D-vSxpjHYgKm45JpKiaeGvWlg1BRMzYMAXGNc,138991
9
- topologicpy/Dictionary.py,sha256=4VtIT1p4UHWButzRUnajj16V0DY-d5RaENbXLNTbCYU,27097
10
- topologicpy/Edge.py,sha256=H5UVhdQ9hjBdipx0AL6U8XQXula_1pBajFB_JI_LIak,58409
9
+ topologicpy/Dictionary.py,sha256=KqJ29YyE23Y3Xc6XmKLSCZXRfBvm-OEOxlMZ4dt-rfM,27094
10
+ topologicpy/Edge.py,sha256=vhYHkobSLGSWV-oe2oJFFDobqFToDyb7s71yQ840AAA,65166
11
11
  topologicpy/EnergyModel.py,sha256=ni0H1JgvLl1-q90yK9Sm1qj5P1fTuidlimEIcwuj6qE,53287
12
- topologicpy/Face.py,sha256=gJNOzaTBxMcd71A-FAzQ3sQFKbsL35cpkGzgtNu6tmo,110131
13
- topologicpy/Graph.py,sha256=rYUhw7XP6LVogbIZfAsrYEZoilN1BabloZHdcWskrMo,391663
12
+ topologicpy/Face.py,sha256=u-DPS5guhzfwxZUuUNYqtPJG6OdeHpY1XQHRSKn6rqk,110148
13
+ topologicpy/Graph.py,sha256=ZU4etwhj6-_JUci3-CK5AoMUoFaTMtVvRWdSHW52SR0,391660
14
14
  topologicpy/Grid.py,sha256=Q-2WNBkvIsJks7pbGkzzkRWVB4fTMYgWipG3lcDXbpE,18496
15
15
  topologicpy/Helper.py,sha256=mLwJmhyc-d-JqW82MBf7JwM91zWHVx8RzOmndPWHm-k,17717
16
16
  topologicpy/Honeybee.py,sha256=vcBECJlgWVjNNdD9ZmjNik_pA1Y_ZNoOorsQb2CiyGA,21965
@@ -18,17 +18,17 @@ topologicpy/Matrix.py,sha256=umgR7An919-wGInXJ1wpqnoQ2jCPdyMe2rcWTZ16upk,8079
18
18
  topologicpy/Neo4j.py,sha256=Gy2PS4Ky8BNhohKreoV4zgzW9OXCjhSwiZF_Aq21_wU,19589
19
19
  topologicpy/Plotly.py,sha256=iJ7zCoe2V1PqGH7GzTTvSfCXY5aRCG0fdYf4Sh6igZ8,98844
20
20
  topologicpy/Polyskel.py,sha256=4R5_DEdfrmi-4gR6axHNoHTCSAE2TCekOyN8jvb7bHQ,19722
21
- topologicpy/Shell.py,sha256=szuwRbQeHH9jd2X-DA9UhYAL_mzgfr_ctGrrQL2reWg,79917
21
+ topologicpy/Shell.py,sha256=n91gViexVMcH3Iors6xeC_Wnn38E40KLqKq5MXQiDU4,79912
22
22
  topologicpy/Speckle.py,sha256=rUS6PCaxIjEF5_fUruxvMH47FMKg-ohcoU0qAUb-yNM,14267
23
23
  topologicpy/Sun.py,sha256=_gZfVyH0SDLQmmt775UeeAJ_BtwXO1STQnUMV1qkU0s,37161
24
- topologicpy/Topology.py,sha256=PkuCetAUADmEuu17-R19ACoub7iZijA8S_v3t0YLL3s,361467
24
+ topologicpy/Topology.py,sha256=Z-zddTGL_wkQmhrkXlredpQxx7Myd4Xp-yNw2d95iks,361647
25
25
  topologicpy/Vector.py,sha256=WQQUbwrg7VKImtxuBUi2i-FRiPT77WlrzLP05gdXKM8,33079
26
- topologicpy/Vertex.py,sha256=deOrCOvvGJYAludUE4Tm_L4Bx0ykQzO_ddnYSrUzsBs,71157
27
- topologicpy/Wire.py,sha256=_-0s6lFCStTGEjK5M-_w79UCQoPVFH1Ou8PdH_urvT0,145180
26
+ topologicpy/Vertex.py,sha256=xnCoPG7BTKBG-JU3C0e11KcpDJbDt9t1Ahj4f5Ul13I,71151
27
+ topologicpy/Wire.py,sha256=mxwx6170ylBnSP2CRAuUZ6xWtISR-frAG5QAVMtS_ZE,147316
28
28
  topologicpy/__init__.py,sha256=D7ky87CAQMiS2KE6YLvcTLkTgA2PY7rASe6Z23pjp9k,872
29
- topologicpy/version.py,sha256=mExVIZTppRZKivnNYLkY3fXqANuLsLtYbD1gMqdgaXM,23
30
- topologicpy-0.7.26.dist-info/LICENSE,sha256=BRNw73R2WdDBICtwhI3wm3cxsaVqLTAGuRwrTltcfxs,1068
31
- topologicpy-0.7.26.dist-info/METADATA,sha256=s84QUjxqFTjnzTZGzBs-L1GzOLxH63nzrUVVx7DrC2I,10916
32
- topologicpy-0.7.26.dist-info/WHEEL,sha256=y4mX-SOX4fYIkonsAGA5N0Oy-8_gI4FXw5HNI1xqvWg,91
33
- topologicpy-0.7.26.dist-info/top_level.txt,sha256=J30bDzW92Ob7hw3zA8V34Jlp-vvsfIkGzkr8sqvb4Uw,12
34
- topologicpy-0.7.26.dist-info/RECORD,,
29
+ topologicpy/version.py,sha256=wuEtkjyrjapFyP-8kysuud97ywxtz0wWW7TfbCk_q1g,23
30
+ topologicpy-0.7.28.dist-info/LICENSE,sha256=BRNw73R2WdDBICtwhI3wm3cxsaVqLTAGuRwrTltcfxs,1068
31
+ topologicpy-0.7.28.dist-info/METADATA,sha256=5Q_QWybjO0mzQG8ikrtZ6g9s2IQ3n1-0l4at8o8yJeI,10916
32
+ topologicpy-0.7.28.dist-info/WHEEL,sha256=rWxmBtp7hEUqVLOnTaDOPpR-cZpCDkzhhcBce-Zyd5k,91
33
+ topologicpy-0.7.28.dist-info/top_level.txt,sha256=J30bDzW92Ob7hw3zA8V34Jlp-vvsfIkGzkr8sqvb4Uw,12
34
+ topologicpy-0.7.28.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (70.2.0)
2
+ Generator: setuptools (71.0.4)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5