topologicpy 0.7.2__py3-none-any.whl → 0.7.4__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
@@ -635,25 +635,45 @@ class Edge():
635
635
  if Edge.Length(edgeB) < tolerance:
636
636
  print("Edge.IsCollinear - Error: The length of edgeB is less than the tolerance. Returning None")
637
637
  return None
638
- # Calculate coefficients A, B, C from edgeA
638
+
639
+ # Get start and end points of the first edge
639
640
  start_a = Edge.StartVertex(edgeA)
640
641
  end_a = Edge.EndVertex(edgeA)
641
- A = Vertex.Y(end_a, mantissa=mantissa) - Vertex.Y(start_a, mantissa=mantissa)
642
- B = -(Vertex.X(end_a, mantissa=mantissa) - Vertex.X(start_a, mantissa=mantissa))
643
- norm = np.sqrt(A ** 2 + B ** 2)
644
- A /= norm
645
- B /= norm
646
- C = -(A * Vertex.X(start_a, mantissa=mantissa) + B * Vertex.Y(start_a, mantissa=mantissa))
647
-
648
- # Calculate perpendicular distance for start vertex of edgeB
649
- start_b = Edge.StartVertex(edgeB)
650
- x0, y0 = Vertex.X(start_b, mantissa=mantissa), Vertex.Y(start_b, mantissa=mantissa)
651
- distance_start = abs(A * x0 + B * y0 + C)
642
+ start_a_coords = np.array([Vertex.X(start_a), Vertex.Y(start_a), Vertex.Z(start_a)])
643
+ end_a_coords = np.array(
644
+ [Vertex.X(end_a, mantissa=mantissa), Vertex.Y(end_a, mantissa=mantissa), Vertex.Z(end_a, mantissa=mantissa)])
645
+
646
+ # Calculate the direction vector of the first edge
647
+ direction_a = end_a_coords - start_a_coords
648
+
649
+ # Normalize the direction vector
650
+ norm_a = np.linalg.norm(direction_a)
651
+ if norm_a == 0:
652
+ print("Edge.IsCollinear - Error: Division by zero. Returning None.")
653
+ return None
654
+ direction_a /= norm_a
655
+
656
+ # Function to calculate perpendicular distance from a point to the line defined by a point and direction vector
657
+ def distance_from_line(point, line_point, line_dir):
658
+ point = np.array([Vertex.X(point, mantissa=mantissa), Vertex.Y(point, mantissa=mantissa),
659
+ Vertex.Z(point, mantissa=mantissa)])
660
+ line_point = np.array(line_point)
661
+ diff = point - line_point
662
+ cross_product = np.cross(diff, line_dir)
663
+ line_dir_norm = np.linalg.norm(line_dir)
664
+ if line_dir_norm == 0:
665
+ print("Edge.IsCollinear - Error: Division by zero. Returning None.")
666
+ return None
667
+ distance = np.linalg.norm(cross_product) / np.linalg.norm(line_dir)
668
+ return distance
652
669
 
653
- # Calculate perpendicular distance for end vertex of edgeB
670
+ # Get start and end points of the second edge
671
+ start_b = Edge.StartVertex(edgeB)
654
672
  end_b = Edge.EndVertex(edgeB)
655
- x0, y0 = Vertex.X(end_b, mantissa=mantissa), Vertex.Y(end_b, mantissa=mantissa)
656
- distance_end = abs(A * x0 + B * y0 + C)
673
+
674
+ # Calculate distances for start and end vertices of the second edge to the line defined by the first edge
675
+ distance_start = distance_from_line(start_b, start_a_coords, direction_a)
676
+ distance_end = distance_from_line(end_b, start_a_coords, direction_a)
657
677
 
658
678
  # Check if both distances are within tolerance
659
679
  return bool(distance_start < tolerance) and bool(distance_end < tolerance)
topologicpy/Topology.py CHANGED
@@ -1503,7 +1503,7 @@ class Topology():
1503
1503
  @staticmethod
1504
1504
  def ByBREPPath(path):
1505
1505
  """
1506
- IMports a topology from a BREP file path.
1506
+ Imports a topology from a BREP file path.
1507
1507
 
1508
1508
  Parameters
1509
1509
  ----------
@@ -1525,7 +1525,172 @@ class Topology():
1525
1525
  print("Topology.ByBREPPath - Error: the BREP file is not a valid file. Returning None.")
1526
1526
  return None
1527
1527
  return Topology.ByBREPFile(file)
1528
-
1528
+
1529
+ @staticmethod
1530
+ def ByDXFFile(file):
1531
+ """
1532
+ Imports a list of topologies from a DXF file.
1533
+ This is an experimental method with limited capabilities.
1534
+
1535
+ Parameters
1536
+ ----------
1537
+ file : a DXF file object
1538
+ The DXF file object.
1539
+
1540
+ Returns
1541
+ -------
1542
+ list
1543
+ The list of imported topologies.
1544
+
1545
+ """
1546
+ from topologicpy.Vertex import Vertex
1547
+ from topologicpy.Edge import Edge
1548
+ from topologicpy.Wire import Wire
1549
+ from topologicpy.Shell import Shell
1550
+ from topologicpy.Cell import Cell
1551
+ from topologicpy.CellComplex import CellComplex
1552
+ from topologicpy.Topology import Topology
1553
+
1554
+ try:
1555
+ import ezdxf
1556
+ except:
1557
+ print("Topology.ByDXFFile - Information: Installing required ezdxf library.")
1558
+ try:
1559
+ os.system("pip install ezdxf")
1560
+ except:
1561
+ os.system("pip install ezdxf --user")
1562
+ try:
1563
+ import ezdxf
1564
+ print("Topology.ByDXFFile - Information: ezdxf library installed successfully.")
1565
+ except:
1566
+ warnings.warn("Topology.ByDXFFile - Error: Could not import ezdxf library. Please install it manually. Returning None.")
1567
+ return None
1568
+
1569
+ if not file:
1570
+ print("Topology.ByDXFFile - Error: the input file parameter is not a valid file. Returning None.")
1571
+ return None
1572
+
1573
+ def convert_entity(entity):
1574
+ entity_type = entity.dxftype()
1575
+ converted_entity = None
1576
+
1577
+ if entity_type == 'POINT':
1578
+ x, y, z = entity.dxf.location.x, entity.dxf.location.y, entity.dxf.location.z
1579
+ converted_entity = Vertex.ByCoordinates(x, y, z)
1580
+
1581
+ elif entity_type == 'LINE':
1582
+ start = Vertex.ByCoordinates(entity.dxf.start.x, entity.dxf.start.y, entity.dxf.start.z)
1583
+ end = Vertex.ByCoordinates(entity.dxf.end.x, entity.dxf.end.y, entity.dxf.end.z)
1584
+ converted_entity = Edge.ByVertices(start, end)
1585
+
1586
+ elif entity_type == 'CIRCLE':
1587
+ origin = Vertex.ByCoordinates(entity.dxf.center.x, entity.dxf.center.y, entity.dxf.center.z)
1588
+ radius = entity.dxf.radius
1589
+ converted_entity = Wire.Circle(origin, radius)
1590
+
1591
+ elif entity_type in ['POLYLINE', 'LWPOLYLINE']:
1592
+ vertices = [Vertex.ByCoordinates(p[0], p[1], p[2]) for p in entity.points()]
1593
+ converted_entity = Wire.ByVertices(vertices)
1594
+
1595
+ elif entity_type == 'ARC':
1596
+ vertices = [Vertex.ByCoordinates(p.x, p.y, p.z) for p in entity.vertices()]
1597
+ converted_entity = Wire.ByVertices(vertices)
1598
+
1599
+ elif entity_type == 'MESH':
1600
+ vertices = [list(v) for v in entity.vertices]
1601
+ faces = [list(face) for face in entity.faces]
1602
+ converted_entity = Topology.SelfMerge(Topology.ByGeometry(vertices=vertices, faces=faces))
1603
+ # Try Cell
1604
+ temp = Cell.ByFaces(Topology.Faces(converted_entity), silent=True)
1605
+ if not Topology.IsInstance(temp, "Cell"):
1606
+ temp = CellComplex.ByFaces(Topology.Faces(converted_entity))
1607
+ if not Topology.IsInstance(temp, "CellComplex"):
1608
+ temp = Shell.ByFaces(Topology.Faces(converted_entity))
1609
+ if not Topology.IsInstance(temp, "Shell"):
1610
+ temp = converted_entity
1611
+ converted_entity = temp
1612
+ return converted_entity
1613
+
1614
+ def convert_insert(entity, file):
1615
+ block_name = entity.dxf.name
1616
+ block = file.blocks.get(block_name)
1617
+ converted_entities = []
1618
+
1619
+ for block_entity in block:
1620
+ converted_entity = convert_entity(block_entity)
1621
+ if converted_entity is not None:
1622
+ converted_entities.append(converted_entity)
1623
+
1624
+ x, y, z = [entity.dxf.insert.x, entity.dxf.insert.y, entity.dxf.insert.z]
1625
+ return [Topology.Translate(obj, x, y, z) for obj in converted_entities]
1626
+
1627
+ def convert_dxf_to_custom_types(file):
1628
+ # Read the DXF file
1629
+ msp = file.modelspace()
1630
+
1631
+ # Store the converted entities
1632
+ converted_entities = []
1633
+
1634
+ # Process each entity in the model space
1635
+ for entity in msp:
1636
+ entity_type = entity.dxftype()
1637
+ if entity_type in ['TEXT', 'MTEXT']:
1638
+ continue # Ignore TEXT and MTEXT
1639
+
1640
+ if entity_type == 'INSERT':
1641
+ converted_entities.extend(convert_insert(entity, file))
1642
+ else:
1643
+ converted_entity = convert_entity(entity)
1644
+ if converted_entity is not None:
1645
+ converted_entities.append(converted_entity)
1646
+
1647
+ return converted_entities
1648
+ converted_entities = convert_dxf_to_custom_types(file)
1649
+ return converted_entities
1650
+
1651
+ @staticmethod
1652
+ def ByDXFPath(path):
1653
+ """
1654
+ Imports a list of topologies from a DXF file path.
1655
+ This is an experimental method with limited capabilities.
1656
+
1657
+ Parameters
1658
+ ----------
1659
+ path : str
1660
+ The path to the DXF file.
1661
+
1662
+ Returns
1663
+ -------
1664
+ list
1665
+ The list of imported topologies.
1666
+
1667
+ """
1668
+ try:
1669
+ import ezdxf
1670
+ except:
1671
+ print("Topology.ExportToDXF - Information: Installing required ezdxf library.")
1672
+ try:
1673
+ os.system("pip install ezdxf")
1674
+ except:
1675
+ os.system("pip install ezdxf --user")
1676
+ try:
1677
+ import ezdxf
1678
+ print("Topology.ByDXFPath - Information: ezdxf library installed successfully.")
1679
+ except:
1680
+ warnings.warn("Topology.ByDXFPath - Error: Could not import ezdxf library. Please install it manually. Returning None.")
1681
+ return None
1682
+ if not path:
1683
+ print("Topology.ByDXFPath - Error: the input path parameter is not a valid path. Returning None.")
1684
+ return None
1685
+ try:
1686
+ file = ezdxf.readfile(path)
1687
+ except:
1688
+ file = None
1689
+ if not file:
1690
+ print("Topology.ByDXFPath - Error: the input file parameter is not a valid file. Returning None.")
1691
+ return None
1692
+ return Topology.ByDXFFile(file)
1693
+
1529
1694
  @staticmethod
1530
1695
  def ByIFCFile(file, transferDictionaries=False, includeTypes=[], excludeTypes=[]):
1531
1696
  """
@@ -1648,7 +1813,6 @@ class Topology():
1648
1813
  try:
1649
1814
  file = ifcopenshell.open(path)
1650
1815
  except:
1651
- print("Topology.ByIFCPath - Error: the input file parameter is not a valid file. Returning None.")
1652
1816
  file = None
1653
1817
  if not file:
1654
1818
  print("Topology.ByIFCPath - Error: the input file parameter is not a valid file. Returning None.")
@@ -3199,6 +3363,146 @@ class Topology():
3199
3363
  return True
3200
3364
  return False
3201
3365
 
3366
+
3367
+ def ExportToDXF(topologies, path, overwrite=False):
3368
+ """
3369
+ Exports the input topology to a DXF file. See https://en.wikipedia.org/wiki/AutoCAD_DXF.
3370
+ THe DXF version is 'R2010'
3371
+ This is experimental and only geometry is exported.
3372
+
3373
+ Parameters
3374
+ ----------
3375
+ topologies : list or topologic_core.Topology
3376
+ The input list of topologies. This can also be a single topologic_core.Topology.
3377
+ path : str
3378
+ The input file path.
3379
+ overwrite : bool , optional
3380
+ If set to True the ouptut file will overwrite any pre-existing file. Otherwise, it won't. The default is False.
3381
+
3382
+ Returns
3383
+ -------
3384
+ bool
3385
+ True if the export operation is successful. False otherwise.
3386
+
3387
+ """
3388
+ import os
3389
+ import warnings
3390
+
3391
+ try:
3392
+ import ezdxf
3393
+ except:
3394
+ print("Topology.ExportToDXF - Information: Installing required ezdxf library.")
3395
+ try:
3396
+ os.system("pip install ezdxf")
3397
+ except:
3398
+ os.system("pip install ezdxf --user")
3399
+ try:
3400
+ import ezdxf
3401
+ print("Topology.ExportToDXF - Information: ezdxf library installed successfully.")
3402
+ except:
3403
+ warnings.warn("Topology.ExportToDXF - Error: Could not import ezdxf library. Please install it manually. Returning None.")
3404
+ return None
3405
+
3406
+ from topologicpy.Vertex import Vertex
3407
+ from topologicpy.Edge import Edge
3408
+ from topologicpy.Cluster import Cluster
3409
+ from topologicpy.Topology import Topology
3410
+
3411
+ from os.path import exists
3412
+ if not isinstance(topologies, list):
3413
+ topologies = [topologies]
3414
+ topologies = [topology for topology in topologies if Topology.IsInstance(topology, "Topology")]
3415
+ if len(topologies) < 1:
3416
+ print("Topology.ExportToDXF - Error: The inupt list parameter topologies does not contain any valid topologies. Returning None.")
3417
+ # Make sure the file extension is .brep
3418
+ ext = path[len(path)-4:len(path)]
3419
+ if ext.lower() != ".dxf":
3420
+ path = path+".dxf"
3421
+ if not overwrite and exists(path):
3422
+ print("Topology.ExportToDXF - Error: a file already exists at the specified path and overwrite is set to False. Returning None.")
3423
+ return None
3424
+
3425
+ def add_vertices(vertices, msp):
3426
+ for v in vertices:
3427
+ if Topology.IsInstance(v, "Vertex"):
3428
+ msp.add_point((Vertex.X(v), Vertex.Y(v), Vertex.Z(v)))
3429
+ def add_edges(edges, msp):
3430
+ for e in edges:
3431
+ if Topology.IsInstance(e, "Edge"):
3432
+ sv = Edge.StartVertex(e)
3433
+ ev = Edge.EndVertex(e)
3434
+ start = (Vertex.X(sv), Vertex.Y(sv), Vertex.Z(sv))
3435
+ end = (Vertex.X(ev), Vertex.Y(ev), Vertex.Z(ev))
3436
+ msp.add_line(start, end)
3437
+ def add_wires(wires, msp):
3438
+ for i, w in enumerate(wires):
3439
+ if Topology.IsInstance(w, "Wire"):
3440
+ block_name = "Wire_"+str(i+1).zfill(3)
3441
+ block = doc.blocks.new(name=block_name)
3442
+ # Add edges to the block
3443
+ edges = Topology.Edges(w)
3444
+ for edge in edges:
3445
+ sv = Edge.StartVertex(edge)
3446
+ ev = Edge.EndVertex(edge)
3447
+ start = (Vertex.X(sv), Vertex.Y(sv), Vertex.Z(sv))
3448
+ end = (Vertex.X(ev), Vertex.Y(ev), Vertex.Z(ev))
3449
+ block.add_line(start, end)
3450
+ # Insert the block into the model space
3451
+ msp.add_blockref(block_name, insert=(0, 0, 0))
3452
+ def add_meshes(meshes, msp):
3453
+ for m in meshes:
3454
+ data = Topology.Geometry(m)
3455
+ vertices = data['vertices']
3456
+ faces = data['faces']
3457
+ mesh = msp.add_mesh()
3458
+ mesh.dxf.subdivision_levels = 0
3459
+ with mesh.edit_data() as mesh_data:
3460
+ mesh_data.vertices = vertices
3461
+ mesh_data.faces = faces
3462
+ # Create a new DXF document
3463
+ doc = ezdxf.new(dxfversion='R2010')
3464
+ msp = doc.modelspace()
3465
+ i = 1
3466
+ for topology in topologies:
3467
+ if Topology.IsInstance(topology, "Vertex"):
3468
+ add_vertices([topology], msp)
3469
+ elif Topology.IsInstance(topology, "Edge"):
3470
+ add_edges([topology], msp)
3471
+ elif Topology.IsInstance(topology, "Wire"):
3472
+ add_wires([topology], msp)
3473
+ elif Topology.IsInstance(topology, "Face"):
3474
+ add_meshes([topology], msp)
3475
+ elif Topology.IsInstance(topology, "Shell"):
3476
+ add_meshes([topology], msp)
3477
+ elif Topology.IsInstance(topology, "Cell"):
3478
+ add_meshes([topology], msp)
3479
+ elif Topology.IsInstance(topology, "CellComplex"):
3480
+ add_meshes([topology], msp)
3481
+ elif Topology.IsInstance(topology, "Cluster"):
3482
+ cellComplexes = Topology.CellComplexes(topology)
3483
+ add_meshes(cellComplexes, msp)
3484
+ cells = Cluster.FreeCells(topology)
3485
+ add_meshes(cells, msp)
3486
+ shells = Cluster.FreeShells(topology)
3487
+ add_meshes(shells, msp)
3488
+ faces = Cluster.FreeFaces(topology)
3489
+ add_meshes(faces, msp)
3490
+ wires = Cluster.FreeWires(topology)
3491
+ add_wires(wires, msp)
3492
+ edges = Cluster.FreeEdges(topology)
3493
+ add_edges(edges, msp)
3494
+ vertices = Cluster.FreeVertices(topology)
3495
+ add_vertices(vertices, msp)
3496
+
3497
+ # Save the DXF document
3498
+ status = False
3499
+ try:
3500
+ doc.saveas(path)
3501
+ status = True
3502
+ except:
3503
+ status = False
3504
+ return status
3505
+
3202
3506
  '''
3203
3507
  @staticmethod
3204
3508
  def ExportToIPFS(topology, url, port, user, password):
topologicpy/version.py CHANGED
@@ -1 +1 @@
1
- __version__ = '0.7.2'
1
+ __version__ = '0.7.4'
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: topologicpy
3
- Version: 0.7.2
3
+ Version: 0.7.4
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: GNU AFFERO GENERAL PUBLIC LICENSE
@@ -6,7 +6,7 @@ topologicpy/Color.py,sha256=UlmRcCSOhqcM_OyMWz4t3Kr75KcgXDhz3uctAJ2n7Ic,18031
6
6
  topologicpy/Context.py,sha256=ppApYKngZZCQBFWaxIMi2z2dokY23c935IDCBosxDAE,3055
7
7
  topologicpy/DGL.py,sha256=RpkLnAzjg6arY7cEMs2pDFYzRdkerVg1Wbm9hcE3QaM,138991
8
8
  topologicpy/Dictionary.py,sha256=pMbfE2RYGCNpVr2x58qiHRc-aBWnp1jLlyzwS9nz6-w,25891
9
- topologicpy/Edge.py,sha256=ktCp2VgBj-QvrUQ0oagTZG2QErth9cilzaBhhHeYNB8,50321
9
+ topologicpy/Edge.py,sha256=jbJHyPHlLF94RkUKL479B4dPC202K0Xd7bQsPcFwoHc,51296
10
10
  topologicpy/EnergyModel.py,sha256=UBLim01lZLikVQmJAHEeja-KvF4tgzTxsSxwNDaezz4,52500
11
11
  topologicpy/Face.py,sha256=BOU6hN-4uCaXW_lbvuOlntrz_Q0jEiL5tIHAFuqWw_U,97195
12
12
  topologicpy/Graph.py,sha256=GsWySXL-cTd7bl-QWpl3Aw9Hr0KyACzIa4iRenTB63s,368030
@@ -20,14 +20,14 @@ topologicpy/Polyskel.py,sha256=MYHKFOQBlUNqoUhAdOcKRIHpSk0dWWVrZgXK34NkvFM,15936
20
20
  topologicpy/Shell.py,sha256=6hidTQ6MW5q_es-WbTeI_yt7Sd7BMxWU_qfoherVZhE,74343
21
21
  topologicpy/Speckle.py,sha256=rUS6PCaxIjEF5_fUruxvMH47FMKg-ohcoU0qAUb-yNM,14267
22
22
  topologicpy/Sun.py,sha256=3tYb8kssU882lE1gEWg2mxDvCCY_LAVElkyUT6wa-ZU,36935
23
- topologicpy/Topology.py,sha256=oXZZGGklFeVMIcKorVXM5RFMbCnoYcjdrScTIodSQng,292911
23
+ topologicpy/Topology.py,sha256=qyk9y3pdsvU_hCLESBsWwN6zM_P5BBirEdhvuxnjkHM,305348
24
24
  topologicpy/Vector.py,sha256=FHbrCb9GVLOUV_kqcplh4D88CVxlID6qX_wEQOw4rD0,29565
25
25
  topologicpy/Vertex.py,sha256=YgbbCcqABvb97z2-yEytpp5T3yoZPlQplR_vMQkQ9OA,65180
26
26
  topologicpy/Wire.py,sha256=MUEboxo11kMgwnZySSkwiyzBG2wv0wPiinf2cW4UVv8,138424
27
27
  topologicpy/__init__.py,sha256=D7ky87CAQMiS2KE6YLvcTLkTgA2PY7rASe6Z23pjp9k,872
28
- topologicpy/version.py,sha256=0eAFjnFVSWI6_301EfFzaXJIiwNScF9GpeINoCLd-XM,22
29
- topologicpy-0.7.2.dist-info/LICENSE,sha256=TfPDBt3ar0uv_f9cqCDMZ5rIzW3CY8anRRd4PkL6ejs,34522
30
- topologicpy-0.7.2.dist-info/METADATA,sha256=mUXBHGbD8IpLymaCvTw5wyJmhssEstUU57P6bXuYFkk,46950
31
- topologicpy-0.7.2.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
32
- topologicpy-0.7.2.dist-info/top_level.txt,sha256=J30bDzW92Ob7hw3zA8V34Jlp-vvsfIkGzkr8sqvb4Uw,12
33
- topologicpy-0.7.2.dist-info/RECORD,,
28
+ topologicpy/version.py,sha256=lBlBxbnftiADKPpC3XRA3jUPjRsVclCd3P95aQ33p_g,22
29
+ topologicpy-0.7.4.dist-info/LICENSE,sha256=TfPDBt3ar0uv_f9cqCDMZ5rIzW3CY8anRRd4PkL6ejs,34522
30
+ topologicpy-0.7.4.dist-info/METADATA,sha256=ELxHFRNJM71bITDzS-ZmOxF5xDaS3PuoxphPYTZ7HOQ,46950
31
+ topologicpy-0.7.4.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
32
+ topologicpy-0.7.4.dist-info/top_level.txt,sha256=J30bDzW92Ob7hw3zA8V34Jlp-vvsfIkGzkr8sqvb4Uw,12
33
+ topologicpy-0.7.4.dist-info/RECORD,,