topologicpy 0.7.27__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/Edge.py CHANGED
@@ -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
 
@@ -485,12 +576,14 @@ class Edge():
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)
@@ -533,8 +631,8 @@ class Edge():
533
631
  if intVertex:
534
632
  return Edge.ByVertices([v1, intVertex], tolerance=tolerance, silent=True)
535
633
  if not silent:
536
- print("Edge.ExtendToEdge - Error: The operation failed. Returning None.")
537
- return None
634
+ print("Edge.ExtendToEdge - Warning: The operation failed. Connecting the edges instead. Returning a Wire.")
635
+ return Edge.ConnectToEdge(edgeA, edgeB, tolerance=tolerance)
538
636
 
539
637
  @staticmethod
540
638
  def ExternalBoundary(edge):
@@ -614,6 +712,70 @@ class Edge():
614
712
  return i
615
713
  return None
616
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
+
617
779
  @staticmethod
618
780
  def IsCollinear(edgeA, edgeB, mantissa: int = 6, tolerance: float = 0.0001) -> bool:
619
781
  """
topologicpy/Wire.py CHANGED
@@ -348,20 +348,21 @@ class Wire(Topology):
348
348
  if not silent:
349
349
  print("Wire.ByOffset - Error: The input wire parameter is not a valid wire. Returning None.")
350
350
  return None
351
+
351
352
  origin = Vertex.Origin()
352
353
  temp_vertices = [Topology.Vertices(wire)[0], Topology.Vertices(wire)[1], Topology.Centroid(wire)]
353
354
  temp_face = Face.ByWire(Wire.ByVertices(temp_vertices, close=True))
354
- temp_normal_edge = Face.NormalEdge(temp_face, length=4)
355
355
  temp_normal = Face.Normal(temp_face)
356
356
  flat_wire = Topology.Flatten(wire, direction=temp_normal, origin=origin)
357
357
  normal = Face.Normal(temp_face)
358
358
  if normal[2] < 0:
359
359
  wire = Wire.Reverse(wire, transferDictionaries=True)
360
360
  flat_wire = Topology.Flatten(wire, direction=normal, origin=origin)
361
- original_edges = Topology.Edges(wire)
362
361
  edges = Topology.Edges(flat_wire)
363
362
  offsets = []
364
363
  offset_edges = []
364
+ final_vertices = []
365
+ bisectors_list = []
365
366
  for edge in edges:
366
367
  d = Topology.Dictionary(edge)
367
368
  d_offset = Dictionary.ValueAtKey(d, offsetKey)
@@ -369,77 +370,68 @@ class Wire(Topology):
369
370
  d_offset = offset
370
371
  offsets.append(d_offset)
371
372
  offset_edge = Edge.ByOffset2D(edge, d_offset)
372
- offset_edge = Edge.Extend(offset_edge, distance=Edge.Length(offset_edge)*4)
373
373
  offset_edges.append(offset_edge)
374
374
  o_edges = []
375
375
  for i in range(len(edges)):
376
376
  edge_a = edges[i]
377
377
  o_edge_a = offset_edges[i]
378
+ v_a = Edge.StartVertex(edges[i])
378
379
  if i == 0:
379
380
  if Wire.IsClosed(wire) == False:
380
- ex_start = offsets[i]
381
- ex_end = offsets[i+1]
382
- prev_edge = Edge.NormalEdge(edges[i], u=0, length=5+Edge.Length(edges[i])+offsets[i])
383
- direc = Edge.Direction(prev_edge)
384
- prev_edge = Topology.TranslateByDirectionDistance(prev_edge, distance=Edge.Length(prev_edge)*0.5, direction=Vector.Reverse(direc))
385
- next_edge = offset_edges[i+1]
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))
386
385
  else:
387
- ex_start = offsets[-1]
388
- ex_end = offsets[i+1]
389
386
  prev_edge = offset_edges[-1]
390
- next_edge = offset_edges[i+1]
391
- elif i == len(edges)-1:
392
- if Wire.IsClosed(wire) == False:
393
- ex_start = offsets[i-1]
394
- ex_end = offsets[i]
395
- prev_edge = offset_edges[i-1]
396
- next_edge = Edge.NormalEdge(edges[i], u=1, length=Edge.Length(edges[i]))
397
- else:
398
- ex_start = offsets[i-1]
399
- ex_end = offsets[0]
400
- prev_edge = offset_edges[i-1]
401
- next_edge = offset_edges[0]
402
387
  else:
403
- ex_start = offsets[i-1]
404
- ex_end = offsets[i+1]
405
388
  prev_edge = offset_edges[i-1]
406
- next_edge = offset_edges[i+1]
407
- temp_edge = Edge.TrimByEdge(o_edge_a, prev_edge, reverse=True, tolerance=tolerance) or o_edge_a
408
- temp_edge = Edge.TrimByEdge(temp_edge, next_edge, reverse=True, tolerance=tolerance) or temp_edge
409
- temp_edge = Edge.ExtendToEdge(temp_edge, next_edge, tolerance=tolerance, silent=False) or temp_edge
410
- temp_edge = Edge.ExtendToEdge(temp_edge, prev_edge, tolerance=tolerance, silent=False) or temp_edge
411
- if temp_edge:
412
- temp_edge = Edge.Reverse(temp_edge)
413
- if bisectors:
414
- if abs(ex_start) > tolerance and abs(offsets[i]) > tolerance :
415
- sv1 = Edge.StartVertex(edge_a)
416
- sv2 = Edge.StartVertex(temp_edge)
417
- bisector = Edge.ByVertices(sv1, sv2)
418
- o_edges.append(bisector)
419
- if i == len(edges)-1:
420
- ev1 = Edge.EndVertex(edge_a)
421
- ev2 = Edge.EndVertex(temp_edge)
422
- bisector = Edge.ByVertices(ev1, ev2)
423
- o_edges.append(bisector)
424
- o_edges.append(temp_edge)
425
- cluster = Cluster.ByTopologies(o_edges)
426
- vertices = Topology.Vertices(cluster)
427
- verts = [Vertex.Coordinates(v) for v in vertices]
428
- geo = Topology.Geometry(cluster)
429
- eds = geo['edges']
430
- verts = geo['vertices']
431
- vertices = [Vertex.ByCoordinates(coord) for coord in verts]
432
- vertices = Vertex.Fuse(vertices, tolerance=tolerance)
433
- verts = [Vertex.Coordinates(v, mantissa=4) for v in vertices]
434
- return_wire = Topology.SelfMerge(Topology.ByGeometry(vertices=verts, edges=eds, faces=[]), tolerance=tolerance)
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
+
425
+ return_wire = Wire.ByVertices(final_vertices, close=Wire.IsClosed(wire))
426
+ if bisectors == True:
427
+ return_wire = Topology.SelfMerge(Cluster.ByTopologies(bisectors_list+Topology.Edges(return_wire)))
435
428
  if not Topology.IsInstance(return_wire, "Wire"):
436
429
  if not silent:
437
- print(return_wire)
438
430
  print("Wire.ByOffset - Warning: The resulting wire is not well-formed, please check your offsets.")
439
431
  else:
440
432
  if not Wire.IsManifold(return_wire) and bisectors == False:
441
433
  if not silent:
442
- print("Wire.ByOffset - Warning: The resulting wire is not well-formed, please check your offsets.")
434
+ print("Wire.ByOffset - Warning: The resulting wire is non-manifold, please check your offsets.")
443
435
  return_wire = Topology.Unflatten(return_wire, direction=normal, origin=origin)
444
436
  return return_wire
445
437
 
topologicpy/version.py CHANGED
@@ -1 +1 @@
1
- __version__ = '0.7.27'
1
+ __version__ = '0.7.28'
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: topologicpy
3
- Version: 0.7.27
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
@@ -7,7 +7,7 @@ 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
9
  topologicpy/Dictionary.py,sha256=KqJ29YyE23Y3Xc6XmKLSCZXRfBvm-OEOxlMZ4dt-rfM,27094
10
- topologicpy/Edge.py,sha256=4Ok25UtwFB9Wu32lfcvNeldTYGZ6MMGIU-_qsPrBmwQ,58424
10
+ topologicpy/Edge.py,sha256=vhYHkobSLGSWV-oe2oJFFDobqFToDyb7s71yQ840AAA,65166
11
11
  topologicpy/EnergyModel.py,sha256=ni0H1JgvLl1-q90yK9Sm1qj5P1fTuidlimEIcwuj6qE,53287
12
12
  topologicpy/Face.py,sha256=u-DPS5guhzfwxZUuUNYqtPJG6OdeHpY1XQHRSKn6rqk,110148
13
13
  topologicpy/Graph.py,sha256=ZU4etwhj6-_JUci3-CK5AoMUoFaTMtVvRWdSHW52SR0,391660
@@ -24,11 +24,11 @@ topologicpy/Sun.py,sha256=_gZfVyH0SDLQmmt775UeeAJ_BtwXO1STQnUMV1qkU0s,37161
24
24
  topologicpy/Topology.py,sha256=Z-zddTGL_wkQmhrkXlredpQxx7Myd4Xp-yNw2d95iks,361647
25
25
  topologicpy/Vector.py,sha256=WQQUbwrg7VKImtxuBUi2i-FRiPT77WlrzLP05gdXKM8,33079
26
26
  topologicpy/Vertex.py,sha256=xnCoPG7BTKBG-JU3C0e11KcpDJbDt9t1Ahj4f5Ul13I,71151
27
- topologicpy/Wire.py,sha256=CBSJlkJ9VcH-OaD3MRdr--637mc6yUNmDrHcoih2kZM,148075
27
+ topologicpy/Wire.py,sha256=mxwx6170ylBnSP2CRAuUZ6xWtISR-frAG5QAVMtS_ZE,147316
28
28
  topologicpy/__init__.py,sha256=D7ky87CAQMiS2KE6YLvcTLkTgA2PY7rASe6Z23pjp9k,872
29
- topologicpy/version.py,sha256=EGarFuMvAZwQ5J027Oe6eX7nnDQVQjAGSr5X1azQ_es,23
30
- topologicpy-0.7.27.dist-info/LICENSE,sha256=BRNw73R2WdDBICtwhI3wm3cxsaVqLTAGuRwrTltcfxs,1068
31
- topologicpy-0.7.27.dist-info/METADATA,sha256=ofrlCW4SD94Qw0h5_6CIufST2V0M711KzAkrr8lduio,10916
32
- topologicpy-0.7.27.dist-info/WHEEL,sha256=Z4pYXqR_rTB7OWNDYFOm1qRk0RX6GFP2o8LgvP453Hk,91
33
- topologicpy-0.7.27.dist-info/top_level.txt,sha256=J30bDzW92Ob7hw3zA8V34Jlp-vvsfIkGzkr8sqvb4Uw,12
34
- topologicpy-0.7.27.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.3.0)
2
+ Generator: setuptools (71.0.4)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5