topologicpy 0.7.50__py3-none-any.whl → 0.7.52__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/Color.py +1 -1
- topologicpy/Dictionary.py +0 -2
- topologicpy/Face.py +5 -3
- topologicpy/Graph.py +6 -0
- topologicpy/Plotly.py +38 -41
- topologicpy/Topology.py +745 -54
- topologicpy/Wire.py +102 -23
- topologicpy/version.py +1 -1
- {topologicpy-0.7.50.dist-info → topologicpy-0.7.52.dist-info}/METADATA +1 -1
- {topologicpy-0.7.50.dist-info → topologicpy-0.7.52.dist-info}/RECORD +13 -13
- {topologicpy-0.7.50.dist-info → topologicpy-0.7.52.dist-info}/WHEEL +1 -1
- {topologicpy-0.7.50.dist-info → topologicpy-0.7.52.dist-info}/LICENSE +0 -0
- {topologicpy-0.7.50.dist-info → topologicpy-0.7.52.dist-info}/top_level.txt +0 -0
topologicpy/Topology.py
CHANGED
@@ -1477,8 +1477,144 @@ class Topology():
|
|
1477
1477
|
st = None
|
1478
1478
|
return st
|
1479
1479
|
|
1480
|
+
|
1481
|
+
@staticmethod
|
1482
|
+
def ByGeometry(vertices=[], edges=[], faces=[], topologyType = None, tolerance=0.0001):
|
1483
|
+
"""
|
1484
|
+
Create a topology by the input lists of vertices, edges, and faces.
|
1485
|
+
|
1486
|
+
Parameters
|
1487
|
+
----------
|
1488
|
+
vertices : list
|
1489
|
+
The input list of vertices in the form of [x, y, z]
|
1490
|
+
edges : list , optional
|
1491
|
+
The input list of edges in the form of [i, j] where i and j are vertex indices.
|
1492
|
+
faces : list , optional
|
1493
|
+
The input list of faces in the form of [i, j, k, l, ...] where the items in the list are vertex indices. The face is assumed to be closed to the last vertex is connected to the first vertex automatically.
|
1494
|
+
topologyType : str , optional
|
1495
|
+
The desired topology type. The options are: "Vertex", "Edge", "Wire", "Face", "Shell", "Cell", "CellComplex". If set to None, a "Cluster" will be returned. The default is None.
|
1496
|
+
tolerance : float , optional
|
1497
|
+
The desired tolerance. The default is 0.0001.
|
1498
|
+
|
1499
|
+
Returns
|
1500
|
+
-------
|
1501
|
+
topology : topologic_core.Topology
|
1502
|
+
The created topology. The topology will have a dictionary embedded in it that records the input attributes (color, id, lengthUnit, name, type)
|
1503
|
+
|
1504
|
+
"""
|
1505
|
+
from topologicpy.Vertex import Vertex
|
1506
|
+
from topologicpy.Edge import Edge
|
1507
|
+
from topologicpy.Wire import Wire
|
1508
|
+
from topologicpy.Face import Face
|
1509
|
+
from topologicpy.Shell import Shell
|
1510
|
+
from topologicpy.Cell import Cell
|
1511
|
+
from topologicpy.CellComplex import CellComplex
|
1512
|
+
from topologicpy.Cluster import Cluster
|
1513
|
+
|
1514
|
+
def topologyByFaces(faces, topologyType, tolerance):
|
1515
|
+
if len(faces) == 1:
|
1516
|
+
return faces[0]
|
1517
|
+
|
1518
|
+
output = None
|
1519
|
+
if topologyType == "cell":
|
1520
|
+
c = Cell.ByFaces(faces, tolerance=tolerance)
|
1521
|
+
if Topology.IsInstance(c, "Cell"):
|
1522
|
+
output = c
|
1523
|
+
else:
|
1524
|
+
cc = CellComplex.ByFaces(faces, tolerance=tolerance)
|
1525
|
+
if Topology.IsInstance(cc, "CellComplex"):
|
1526
|
+
output = CellComplex.ExternalBoundary(cc)
|
1527
|
+
elif topologyType == "cellcomplex":
|
1528
|
+
output = CellComplex.ByFaces(faces, tolerance=tolerance)
|
1529
|
+
if Topology.IsInstance(output, "CellComplex"):
|
1530
|
+
cells = Topology.Cells(output)
|
1531
|
+
if len(cells) == 1:
|
1532
|
+
output = cells[0]
|
1533
|
+
else:
|
1534
|
+
output = Cluster.ByTopologies(faces)
|
1535
|
+
elif topologyType == "shell":
|
1536
|
+
output = Shell.ByFaces(faces, tolerance=tolerance) # This can return a list
|
1537
|
+
if Topology.IsInstance(output, "Shell"):
|
1538
|
+
return output
|
1539
|
+
elif topologyType == None:
|
1540
|
+
output = Cluster.ByTopologies(faces)
|
1541
|
+
|
1542
|
+
return output
|
1543
|
+
|
1544
|
+
def topologyByEdges(edges, topologyType):
|
1545
|
+
if len(edges) == 1:
|
1546
|
+
return edges[0]
|
1547
|
+
|
1548
|
+
output = Cluster.ByTopologies(edges)
|
1549
|
+
if topologyType.lower() == "wire":
|
1550
|
+
output = Topology.SelfMerge(output, tolerance=tolerance)
|
1551
|
+
if Topology.IsInstance(output, "Wire"):
|
1552
|
+
return output
|
1553
|
+
return None
|
1554
|
+
return output
|
1555
|
+
|
1556
|
+
vertices = [v for v in vertices if v]
|
1557
|
+
edges = [e for e in edges if e]
|
1558
|
+
faces = [f for f in faces if f]
|
1559
|
+
|
1560
|
+
if not vertices:
|
1561
|
+
return None
|
1562
|
+
|
1563
|
+
topVerts = [Vertex.ByCoordinates(v[0], v[1], v[2]) for v in vertices]
|
1564
|
+
topEdges = []
|
1565
|
+
topFaces = []
|
1566
|
+
|
1567
|
+
if not topologyType == None:
|
1568
|
+
topologyType = topologyType.lower()
|
1569
|
+
|
1570
|
+
if topologyType == "vertex":
|
1571
|
+
if len(topVerts) >= 1:
|
1572
|
+
return topVerts[0]
|
1573
|
+
else:
|
1574
|
+
return None
|
1575
|
+
elif topologyType == "edge":
|
1576
|
+
if len(edges) >= 1 and len(vertices) >= 2:
|
1577
|
+
return Edge.ByVertices(topVerts[edges[0][0]], topVerts[edges[0][1]], tolerance=tolerance)
|
1578
|
+
else:
|
1579
|
+
return None
|
1580
|
+
|
1581
|
+
if topologyType == "wire" and edges:
|
1582
|
+
topEdges = [Edge.ByVertices([topVerts[e[0]], topVerts[e[1]]], tolerance=tolerance) for e in edges]
|
1583
|
+
if topEdges:
|
1584
|
+
returnTopology = topologyByEdges(topEdges, topologyType)
|
1585
|
+
elif faces:
|
1586
|
+
for aFace in faces:
|
1587
|
+
faceEdges = [Edge.ByVertices([topVerts[aFace[i]], topVerts[aFace[i + 1]]], tolerance=tolerance) for i in range(len(aFace) - 1)]
|
1588
|
+
# Connect the last vertex to the first one
|
1589
|
+
faceEdges.append(Edge.ByVertices([topVerts[aFace[-1]], topVerts[aFace[0]]], tolerance=tolerance))
|
1590
|
+
|
1591
|
+
if len(faceEdges) > 2:
|
1592
|
+
faceWire = Wire.ByEdges(faceEdges, tolerance=tolerance)
|
1593
|
+
try:
|
1594
|
+
topFace = Face.ByWire(faceWire, tolerance=tolerance, silent=True)
|
1595
|
+
if Topology.IsInstance(topFace, "Face"):
|
1596
|
+
topFaces.append(topFace)
|
1597
|
+
elif isinstance(topFace, list):
|
1598
|
+
topFaces.extend(topFace)
|
1599
|
+
except:
|
1600
|
+
pass
|
1601
|
+
if topFaces:
|
1602
|
+
returnTopology = topologyByFaces(topFaces, topologyType=topologyType, tolerance=tolerance)
|
1603
|
+
elif edges:
|
1604
|
+
topEdges = [Edge.ByVertices([topVerts[e[0]], topVerts[e[1]]], tolerance=tolerance) for e in edges]
|
1605
|
+
if topEdges:
|
1606
|
+
returnTopology = topologyByEdges(topEdges, topologyType)
|
1607
|
+
else:
|
1608
|
+
returnTopology = Cluster.ByTopologies(topVerts)
|
1609
|
+
return returnTopology
|
1610
|
+
|
1611
|
+
|
1612
|
+
|
1613
|
+
|
1614
|
+
|
1615
|
+
|
1480
1616
|
@staticmethod
|
1481
|
-
def
|
1617
|
+
def ByGeometry_old(vertices=[], edges=[], faces=[], color=[1.0, 1.0, 1.0, 1.0], id=None, name=None, lengthUnit="METERS", outputMode="default", tolerance=0.0001):
|
1482
1618
|
"""
|
1483
1619
|
Create a topology by the input lists of vertices, edges, and faces.
|
1484
1620
|
|
@@ -2201,7 +2337,215 @@ class Topology():
|
|
2201
2337
|
return Topology.ByDXFFile(file, sides=sides)
|
2202
2338
|
|
2203
2339
|
@staticmethod
|
2204
|
-
def ByIFCFile(file, includeTypes=[], excludeTypes=[], transferDictionaries=False, removeCoplanarFaces=False):
|
2340
|
+
def ByIFCFile(file, includeTypes=[], excludeTypes=[], transferDictionaries=False, removeCoplanarFaces=False, epsilon=0.0001, tolerance=0.0001):
|
2341
|
+
"""
|
2342
|
+
Create a list of topologies by importing them from an IFC file.
|
2343
|
+
|
2344
|
+
Parameters
|
2345
|
+
----------
|
2346
|
+
file : file object
|
2347
|
+
The input IFC file.
|
2348
|
+
includeTypes : list , optional
|
2349
|
+
The list of IFC object types to include. It is case insensitive. If set to an empty list, all types are included. The default is [].
|
2350
|
+
excludeTypes : list , optional
|
2351
|
+
The list of IFC object types to exclude. It is case insensitive. If set to an empty list, no types are excluded. The default is [].
|
2352
|
+
transferDictionaries : bool , optional
|
2353
|
+
If set to True, the dictionaries from the IFC file will be transferred to the topology. Otherwise, they won't. The default is False.
|
2354
|
+
removeCoplanarFaces : bool , optional
|
2355
|
+
If set to True, coplanar faces are removed. Otherwise they are not. The default is False.
|
2356
|
+
epsilon : float , optional
|
2357
|
+
The desired epsilon (another form of tolerance) for finding if two faces are coplanar. The default is 0.0001.
|
2358
|
+
tolerance : float , optional
|
2359
|
+
The desired tolerance. The default is 0.0001.
|
2360
|
+
Returns
|
2361
|
+
-------
|
2362
|
+
list
|
2363
|
+
The created list of topologies.
|
2364
|
+
|
2365
|
+
"""
|
2366
|
+
|
2367
|
+
import ifcopenshell
|
2368
|
+
from topologicpy.Dictionary import Dictionary
|
2369
|
+
|
2370
|
+
def get_psets(entity):
|
2371
|
+
# Initialize the PSET dictionary for this entity
|
2372
|
+
psets = {}
|
2373
|
+
|
2374
|
+
# Check if the entity has a GlobalId
|
2375
|
+
if not hasattr(entity, 'GlobalId'):
|
2376
|
+
raise ValueError("The provided entity does not have a GlobalId.")
|
2377
|
+
|
2378
|
+
# Get the property sets related to this entity
|
2379
|
+
for definition in entity.IsDefinedBy:
|
2380
|
+
if definition.is_a('IfcRelDefinesByProperties'):
|
2381
|
+
property_set = definition.RelatingPropertyDefinition
|
2382
|
+
|
2383
|
+
# Check if it is a property set
|
2384
|
+
if property_set.is_a('IfcPropertySet'):
|
2385
|
+
pset_name = "IFC_"+property_set.Name
|
2386
|
+
|
2387
|
+
# Dictionary to hold individual properties
|
2388
|
+
properties = {}
|
2389
|
+
|
2390
|
+
# Iterate over the properties in the PSET
|
2391
|
+
for prop in property_set.HasProperties:
|
2392
|
+
if prop.is_a('IfcPropertySingleValue'):
|
2393
|
+
# Get the property name and value
|
2394
|
+
prop_name = "IFC_"+prop.Name
|
2395
|
+
prop_value = prop.NominalValue.wrappedValue if prop.NominalValue else None
|
2396
|
+
properties[prop_name] = prop_value
|
2397
|
+
|
2398
|
+
# Add this PSET to the dictionary for this entity
|
2399
|
+
psets[pset_name] = properties
|
2400
|
+
return psets
|
2401
|
+
|
2402
|
+
def get_color_transparency_material(entity):
|
2403
|
+
import random
|
2404
|
+
|
2405
|
+
# Set default Material Name and ID
|
2406
|
+
material_list = []
|
2407
|
+
# Set default transparency based on entity type or material
|
2408
|
+
default_transparency = 0.0
|
2409
|
+
|
2410
|
+
# Check if the entity is an opening or made of glass
|
2411
|
+
is_a = entity.is_a().lower()
|
2412
|
+
if "opening" in is_a or "window" in is_a or "door" in is_a or "space" in is_a:
|
2413
|
+
default_transparency = 0.7
|
2414
|
+
elif "space" in is_a:
|
2415
|
+
default_transparency = 0.8
|
2416
|
+
|
2417
|
+
# Check if the entity has constituent materials (e.g., glass)
|
2418
|
+
else:
|
2419
|
+
# Check for associated materials (ConstituentMaterial or direct material assignment)
|
2420
|
+
materials_checked = False
|
2421
|
+
if hasattr(entity, 'HasAssociations'):
|
2422
|
+
for rel in entity.HasAssociations:
|
2423
|
+
if rel.is_a('IfcRelAssociatesMaterial'):
|
2424
|
+
material = rel.RelatingMaterial
|
2425
|
+
if material.is_a('IfcMaterial') and 'glass' in material.Name.lower():
|
2426
|
+
default_transparency = 0.5
|
2427
|
+
materials_checked = True
|
2428
|
+
elif material.is_a('IfcMaterialLayerSetUsage'):
|
2429
|
+
material_layers = material.ForLayerSet.MaterialLayers
|
2430
|
+
for layer in material_layers:
|
2431
|
+
material_list.append(layer.Material.Name)
|
2432
|
+
if 'glass' in layer.Material.Name.lower():
|
2433
|
+
default_transparency = 0.5
|
2434
|
+
materials_checked = True
|
2435
|
+
|
2436
|
+
# Check for ConstituentMaterial if available
|
2437
|
+
if hasattr(entity, 'HasAssociations') and not materials_checked:
|
2438
|
+
for rel in entity.HasAssociations:
|
2439
|
+
if rel.is_a('IfcRelAssociatesMaterial'):
|
2440
|
+
material = rel.RelatingMaterial
|
2441
|
+
if material.is_a('IfcMaterialConstituentSet'):
|
2442
|
+
for constituent in material.MaterialConstituents:
|
2443
|
+
material_list.append(constituent.Material.Name)
|
2444
|
+
if 'glass' in constituent.Material.Name.lower():
|
2445
|
+
default_transparency = 0.5
|
2446
|
+
materials_checked = True
|
2447
|
+
|
2448
|
+
# Check if the entity has ShapeAspects with associated materials or styles
|
2449
|
+
if hasattr(entity, 'HasShapeAspects') and not materials_checked:
|
2450
|
+
for shape_aspect in entity.HasShapeAspects:
|
2451
|
+
if hasattr(shape_aspect, 'StyledByItem') and shape_aspect.StyledByItem:
|
2452
|
+
for styled_item in shape_aspect.StyledByItem:
|
2453
|
+
for style in styled_item.Styles:
|
2454
|
+
if style.is_a('IfcSurfaceStyle'):
|
2455
|
+
for surface_style in style.Styles:
|
2456
|
+
if surface_style.is_a('IfcSurfaceStyleRendering'):
|
2457
|
+
transparency = getattr(surface_style, 'Transparency', default_transparency)
|
2458
|
+
if transparency > 0:
|
2459
|
+
default_transparency = transparency
|
2460
|
+
|
2461
|
+
# Try to get the actual color and transparency if defined
|
2462
|
+
if hasattr(entity, 'Representation') and entity.Representation:
|
2463
|
+
for rep in entity.Representation.Representations:
|
2464
|
+
for item in rep.Items:
|
2465
|
+
if hasattr(item, 'StyledByItem') and item.StyledByItem:
|
2466
|
+
for styled_item in item.StyledByItem:
|
2467
|
+
if hasattr(styled_item, 'Styles'):
|
2468
|
+
for style in styled_item.Styles:
|
2469
|
+
if style.is_a('IfcSurfaceStyle'):
|
2470
|
+
for surface_style in style.Styles:
|
2471
|
+
if surface_style.is_a('IfcSurfaceStyleRendering'):
|
2472
|
+
color = surface_style.SurfaceColour
|
2473
|
+
transparency = getattr(surface_style, 'Transparency', default_transparency)
|
2474
|
+
return (color.Red*255, color.Green*255, color.Blue*255), transparency, material_list
|
2475
|
+
|
2476
|
+
# If no color is defined, return a consistent random color based on the entity type
|
2477
|
+
if "wall" in is_a:
|
2478
|
+
color = (175, 175, 175)
|
2479
|
+
elif "slab" in is_a:
|
2480
|
+
color = (200, 200, 200)
|
2481
|
+
elif "space" in is_a:
|
2482
|
+
color = (250, 250, 250)
|
2483
|
+
else:
|
2484
|
+
random.seed(hash(is_a))
|
2485
|
+
color = (random.random(), random.random(), random.random())
|
2486
|
+
|
2487
|
+
return color, default_transparency, material_list
|
2488
|
+
|
2489
|
+
def convert_to_topology(entity, settings):
|
2490
|
+
if hasattr(entity, "Representation") and entity.Representation:
|
2491
|
+
for rep in entity.Representation.Representations:
|
2492
|
+
if rep.is_a("IfcShapeRepresentation"):
|
2493
|
+
# Generate the geometry for this entity
|
2494
|
+
shape = ifcopenshell.geom.create_shape(settings, entity)
|
2495
|
+
shape_geometry = shape.geometry
|
2496
|
+
verts = shape_geometry.verts
|
2497
|
+
verts = [ [verts[i], verts[i + 1], verts[i + 2]] for i in range(0, len(verts), 3)]
|
2498
|
+
edges = shape_geometry.edges
|
2499
|
+
edges = [[edges[i], edges[i + 1]] for i in range(0, len(edges), 2)]
|
2500
|
+
faces = shape_geometry.faces
|
2501
|
+
faces = [ [faces[i], faces[i + 1], faces[i + 2]] for i in range(0, len(faces), 3)]
|
2502
|
+
# Convert geometry to Topologic format
|
2503
|
+
#shape_topology = ifc_to_topologic_geometry(verts, edges, faces)
|
2504
|
+
#shape_topology = Topology.SelfMerge(Topology.ByGeometry(verts, edges, faces))
|
2505
|
+
shape_topology = Topology.ByGeometry(verts, edges, faces, topologyType="CellComplex")
|
2506
|
+
if removeCoplanarFaces == True:
|
2507
|
+
shape_topology = Topology.RemoveCoplanarFaces(shape_topology, epsilon=0.0001)
|
2508
|
+
|
2509
|
+
# Store relevant information
|
2510
|
+
color, transparency, material_list = get_color_transparency_material(entity)
|
2511
|
+
entity_dict = {
|
2512
|
+
"TOPOLOGIC_id": str(Topology.UUID(shape_topology)),
|
2513
|
+
"TOPOLOGIC_name": getattr(entity, 'Name', "Untitled"),
|
2514
|
+
"TOPOLOGIC_type": Topology.TypeAsString(shape_topology),
|
2515
|
+
"TOPOLOGIC_color": color,
|
2516
|
+
"TOPOLOGIC_opacity": 1.0 - transparency,
|
2517
|
+
"IFC_global_id": getattr(entity, 'GlobalId', 0),
|
2518
|
+
"IFC_name": getattr(entity, 'Name', "Untitled"),
|
2519
|
+
"IFC_type": entity.is_a(),
|
2520
|
+
"IFC_material_list": material_list,
|
2521
|
+
}
|
2522
|
+
topology_dict = Dictionary.ByPythonDictionary(entity_dict)
|
2523
|
+
# Get PSETs dictionary
|
2524
|
+
pset_python_dict = get_psets(entity)
|
2525
|
+
pset_dict = Dictionary.ByPythonDictionary(pset_python_dict)
|
2526
|
+
topology_dict = Dictionary.ByMergedDictionaries([topology_dict, pset_dict])
|
2527
|
+
shape_topology = Topology.SetDictionary(shape_topology, topology_dict)
|
2528
|
+
return shape_topology
|
2529
|
+
return None
|
2530
|
+
|
2531
|
+
# Main Code
|
2532
|
+
topologies = []
|
2533
|
+
settings = ifcopenshell.geom.settings()
|
2534
|
+
settings.set("dimensionality", ifcopenshell.ifcopenshell_wrapper.SOLID)
|
2535
|
+
settings.set(settings.USE_WORLD_COORDS, True)
|
2536
|
+
products = file.by_type("IfcProduct")
|
2537
|
+
entities = []
|
2538
|
+
for product in products:
|
2539
|
+
is_a = product.is_a()
|
2540
|
+
if (is_a in includeTypes or len(includeTypes) == 0) and (not is_a in excludeTypes):
|
2541
|
+
entities.append(product)
|
2542
|
+
topologies = []
|
2543
|
+
for entity in entities:
|
2544
|
+
topologies.append(convert_to_topology(entity, settings))
|
2545
|
+
return topologies
|
2546
|
+
|
2547
|
+
@staticmethod
|
2548
|
+
def _ByIFCFile_old(file, includeTypes=[], excludeTypes=[], transferDictionaries=False, removeCoplanarFaces=False):
|
2205
2549
|
"""
|
2206
2550
|
Create a topology by importing it from an IFC file.
|
2207
2551
|
|
@@ -2229,7 +2573,9 @@ class Topology():
|
|
2229
2573
|
import uuid
|
2230
2574
|
import random
|
2231
2575
|
import hashlib
|
2232
|
-
|
2576
|
+
import re
|
2577
|
+
import numpy as np
|
2578
|
+
|
2233
2579
|
try:
|
2234
2580
|
import ifcopenshell
|
2235
2581
|
import ifcopenshell.geom
|
@@ -2250,6 +2596,148 @@ class Topology():
|
|
2250
2596
|
print("Topology.ByIFCFile - Error: the input file parameter is not a valid file. Returning None.")
|
2251
2597
|
return None
|
2252
2598
|
|
2599
|
+
def clean_key(string):
|
2600
|
+
# Replace any character that is not a letter, digit, or underscore with an underscore
|
2601
|
+
cleaned_string = re.sub(r'[^a-zA-Z0-9_]', '_', string)
|
2602
|
+
return cleaned_string
|
2603
|
+
|
2604
|
+
def transform_wall_vertices(wall):
|
2605
|
+
|
2606
|
+
# Relatives Placement abrufen und ausgeben
|
2607
|
+
if wall.ObjectPlacement and wall.ObjectPlacement.RelativePlacement:
|
2608
|
+
relative_placement = wall.ObjectPlacement.RelativePlacement
|
2609
|
+
if relative_placement.is_a('IFCAXIS2PLACEMENT3D'):
|
2610
|
+
location = relative_placement.Location
|
2611
|
+
ref_direction = relative_placement.RefDirection
|
2612
|
+
print("Relative Placement Location:", location.Coordinates)
|
2613
|
+
if ref_direction:
|
2614
|
+
print("Relative Placement RefDirection:", ref_direction.DirectionRatios)
|
2615
|
+
else:
|
2616
|
+
print("Relative Placement RefDirection: None")
|
2617
|
+
|
2618
|
+
# IFCPRODUCTDEFINITIONSHAPE der Wand abrufen
|
2619
|
+
product_definition_shape = wall.Representation
|
2620
|
+
if not product_definition_shape:
|
2621
|
+
print("Keine Repräsentation gefunden.")
|
2622
|
+
return
|
2623
|
+
|
2624
|
+
# Initialisieren von Variablen für Representation Type und Layer-Infos
|
2625
|
+
representation_type = None
|
2626
|
+
diverse_representation = False
|
2627
|
+
layer_details = []
|
2628
|
+
|
2629
|
+
if hasattr(product_definition_shape, 'HasShapeAspects'):
|
2630
|
+
for aspect in product_definition_shape.HasShapeAspects:
|
2631
|
+
for representation in aspect.ShapeRepresentations:
|
2632
|
+
if representation.is_a('IFCSHAPEREPRESENTATION'):
|
2633
|
+
for item in representation.Items:
|
2634
|
+
if item.is_a('IFCEXTRUDEDAREASOLID'):
|
2635
|
+
# Profilbeschreibung abrufen
|
2636
|
+
profile = item.SweptArea
|
2637
|
+
if profile.is_a('IFCARBITRARYCLOSEDPROFILEDEF'):
|
2638
|
+
if not representation_type:
|
2639
|
+
representation_type = "ArbitraryClosedProfil"
|
2640
|
+
elif representation_type != "ArbitraryClosedProfil":
|
2641
|
+
diverse_representation = True
|
2642
|
+
|
2643
|
+
# Profilpunkte abrufen
|
2644
|
+
if hasattr(profile, 'OuterCurve') and profile.OuterCurve.is_a('IFCINDEXEDPOLYCURVE'):
|
2645
|
+
indexed_polycurve = profile.OuterCurve
|
2646
|
+
if hasattr(indexed_polycurve, 'Points') and indexed_polycurve.Points.is_a('IFCCARTESIANPOINTLIST2D'):
|
2647
|
+
point_list_2d = indexed_polycurve.Points
|
2648
|
+
points = point_list_2d.CoordList
|
2649
|
+
layer_info["Profilpunkte"] = points
|
2650
|
+
else:
|
2651
|
+
diverse_representation = True
|
2652
|
+
|
2653
|
+
# Location und RefDirection abrufen
|
2654
|
+
if item.Position.is_a('IFCAXIS2PLACEMENT3D'):
|
2655
|
+
axis_placement = item.Position
|
2656
|
+
location = axis_placement.Location
|
2657
|
+
ref_direction = axis_placement.RefDirection
|
2658
|
+
layer_info["Location"] = location.Coordinates
|
2659
|
+
if ref_direction:
|
2660
|
+
layer_info["RefDirection"] = ref_direction.DirectionRatios
|
2661
|
+
else:
|
2662
|
+
layer_info["RefDirection"] = None
|
2663
|
+
|
2664
|
+
layer_details.append(layer_info)
|
2665
|
+
|
2666
|
+
# Representation Type ausgeben
|
2667
|
+
if diverse_representation:
|
2668
|
+
representation_type = "divers"
|
2669
|
+
print("Representation Type der Wand:", representation_type)
|
2670
|
+
|
2671
|
+
# Layer-Details ausgeben
|
2672
|
+
for index, layer in enumerate(layer_details):
|
2673
|
+
print(f"\nLayer {index + 1} Details:")
|
2674
|
+
print("Material:", layer.get("Material", "Nicht verfügbar"))
|
2675
|
+
print("Extrusionsstärke:", layer.get("Extrusionsstärke", "Nicht verfügbar"))
|
2676
|
+
print("Profilpunkte:", layer.get("Profilpunkte", "Nicht verfügbar"))
|
2677
|
+
print("Location:", layer.get("Location", "Nicht verfügbar"))
|
2678
|
+
print("RefDirection:", layer.get("RefDirection", "Nicht verfügbar"))
|
2679
|
+
|
2680
|
+
|
2681
|
+
|
2682
|
+
|
2683
|
+
|
2684
|
+
|
2685
|
+
def extract_matrix_from_placement(placement):
|
2686
|
+
"""Constructs a transformation matrix from an IFC Local Placement."""
|
2687
|
+
# Initialize identity matrix
|
2688
|
+
matrix = np.identity(4)
|
2689
|
+
|
2690
|
+
# Check if the placement is IfcLocalPlacement
|
2691
|
+
if placement.is_a("IfcLocalPlacement"):
|
2692
|
+
relative_placement = placement.RelativePlacement
|
2693
|
+
|
2694
|
+
if relative_placement.is_a("IfcAxis2Placement3D"):
|
2695
|
+
location = relative_placement.Location.Coordinates
|
2696
|
+
z_dir = relative_placement.Axis.DirectionRatios if relative_placement.Axis else [0, 0, 1]
|
2697
|
+
x_dir = relative_placement.RefDirection.DirectionRatios if relative_placement.RefDirection else [1, 0, 0]
|
2698
|
+
|
2699
|
+
# Compute y direction (cross product of z and x)
|
2700
|
+
y_dir = np.cross(z_dir, x_dir)
|
2701
|
+
|
2702
|
+
# Construct the rotation matrix
|
2703
|
+
rotation_matrix = np.array([
|
2704
|
+
[x_dir[0], y_dir[0], z_dir[0], 0],
|
2705
|
+
[x_dir[1], y_dir[1], z_dir[1], 0],
|
2706
|
+
[x_dir[2], y_dir[2], z_dir[2], 0],
|
2707
|
+
[0, 0, 0, 1]
|
2708
|
+
])
|
2709
|
+
|
2710
|
+
# Translation vector
|
2711
|
+
translation_vector = np.array([
|
2712
|
+
[1, 0, 0, location[0]],
|
2713
|
+
[0, 1, 0, location[1]],
|
2714
|
+
[0, 0, 1, location[2]],
|
2715
|
+
[0, 0, 0, 1]
|
2716
|
+
])
|
2717
|
+
|
2718
|
+
# Combine the rotation matrix and the translation vector
|
2719
|
+
matrix = np.dot(translation_vector, rotation_matrix)
|
2720
|
+
|
2721
|
+
return matrix
|
2722
|
+
|
2723
|
+
def apply_transformation(verts, matrix):
|
2724
|
+
"""Applies a 4x4 transformation matrix to a list of vertices."""
|
2725
|
+
transformed_verts = []
|
2726
|
+
for vert in verts:
|
2727
|
+
print("vert:", vert)
|
2728
|
+
v = np.array([vert[0], vert[1], vert[2], 1.0])
|
2729
|
+
transformed_v = np.dot(matrix, v)
|
2730
|
+
transformed_verts.append([transformed_v[0], transformed_v[1], transformed_v[2]])
|
2731
|
+
return transformed_verts
|
2732
|
+
|
2733
|
+
def get_entity_transformation_matrix(entity):
|
2734
|
+
"""Extracts the transformation matrix from an IFC entity."""
|
2735
|
+
matrix = np.identity(4) # Default to an identity matrix
|
2736
|
+
if hasattr(entity, "ObjectPlacement") and entity.ObjectPlacement:
|
2737
|
+
placement = entity.ObjectPlacement
|
2738
|
+
matrix = extract_matrix_from_placement(placement)
|
2739
|
+
return matrix
|
2740
|
+
|
2253
2741
|
# Function to generate a unique random color based on material ID
|
2254
2742
|
def generate_color_for_material(material_id):
|
2255
2743
|
# Use a hash function to get a consistent "random" seed
|
@@ -2264,88 +2752,185 @@ class Topology():
|
|
2264
2752
|
|
2265
2753
|
# Function to get the material IDs associated with an entity
|
2266
2754
|
def get_material_ids_of_entity(entity):
|
2267
|
-
|
2755
|
+
return_dict = {}
|
2756
|
+
material_names = []
|
2268
2757
|
material_ids = []
|
2269
2758
|
if hasattr(entity, "HasAssociations"):
|
2270
2759
|
for association in entity.HasAssociations:
|
2271
2760
|
if association.is_a("IfcRelAssociatesMaterial"):
|
2272
2761
|
material = association.RelatingMaterial
|
2273
|
-
|
2762
|
+
try:
|
2763
|
+
material_name = material.Name
|
2764
|
+
except:
|
2765
|
+
material_name = material.to_string()
|
2274
2766
|
if material.is_a("IfcMaterial"):
|
2275
2767
|
material_ids.append(material.id())
|
2768
|
+
material_names.append(material_name)
|
2769
|
+
return_dict[clean_key(material_name)] = material.id
|
2276
2770
|
elif material.is_a("IfcMaterialList"):
|
2277
2771
|
for mat in material.Materials:
|
2278
2772
|
material_ids.append(mat.id())
|
2773
|
+
try:
|
2774
|
+
material_name = mat.Name
|
2775
|
+
except:
|
2776
|
+
material_name = mat.to_string()
|
2777
|
+
material_names.append(material_name)
|
2778
|
+
return_dict[clean_key(material_name)] = mat.id
|
2279
2779
|
elif material.is_a("IfcMaterialLayerSetUsage") or material.is_a("IfcMaterialLayerSet"):
|
2280
2780
|
for layer in material.ForLayerSet.MaterialLayers:
|
2281
2781
|
material_ids.append(layer.Material.id())
|
2782
|
+
try:
|
2783
|
+
material_name = layer.Name
|
2784
|
+
except:
|
2785
|
+
material_name = layer.to_string()
|
2786
|
+
material_names.append(material_name)
|
2787
|
+
return_dict[clean_key(material_name)] = layer.Material.id()
|
2282
2788
|
elif material.is_a("IfcMaterialConstituentSet"):
|
2283
2789
|
for constituent in material.MaterialConstituents:
|
2284
2790
|
material_ids.append(constituent.Material.id())
|
2791
|
+
try:
|
2792
|
+
material_name = constituent.Material.Name
|
2793
|
+
except:
|
2794
|
+
material_name = constituent.Material.to_string()
|
2795
|
+
material_names.append(material_name)
|
2796
|
+
return_dict[clean_key(material_name)] = constituent.Material.id()
|
2285
2797
|
|
2286
|
-
return
|
2287
|
-
|
2798
|
+
return return_dict
|
2288
2799
|
|
2289
|
-
|
2290
|
-
|
2291
|
-
|
2292
|
-
|
2293
|
-
|
2294
|
-
|
2295
|
-
|
2296
|
-
|
2297
|
-
|
2298
|
-
|
2299
|
-
|
2300
|
-
|
2301
|
-
|
2302
|
-
|
2303
|
-
|
2304
|
-
|
2305
|
-
|
2306
|
-
|
2307
|
-
|
2800
|
+
def get_wall_layers(wall, matrix=None, transferDictionaries=False):
|
2801
|
+
settings = ifcopenshell.geom.settings()
|
2802
|
+
settings.set("dimensionality", ifcopenshell.ifcopenshell_wrapper.CURVES_SURFACES_AND_SOLIDS)
|
2803
|
+
settings.set(settings.USE_WORLD_COORDS, False)
|
2804
|
+
|
2805
|
+
# IFCPRODUCTDEFINITIONSHAPE der Wand abrufen
|
2806
|
+
product_definition_shape = wall.Representation
|
2807
|
+
if not product_definition_shape:
|
2808
|
+
print("Topology.ByIFCFile - Error: The object has no representation. Returning None")
|
2809
|
+
return None
|
2810
|
+
|
2811
|
+
if hasattr(product_definition_shape, 'HasShapeAspects'):
|
2812
|
+
for aspect in product_definition_shape.HasShapeAspects:
|
2813
|
+
material_name = aspect.Name
|
2814
|
+
for representation in aspect.ShapeRepresentations:
|
2815
|
+
print(dir(representation))
|
2816
|
+
axis_placement = representation.Position
|
2817
|
+
location = axis_placement.Location
|
2818
|
+
ref_direction = axis_placement.RefDirection
|
2819
|
+
print("Location:", location)
|
2820
|
+
print("Direction", ref_direction)
|
2821
|
+
aspect_matrix = get_entity_transformation_matrix(representation)
|
2822
|
+
print("Aspect Matrix:", aspect_matrix)
|
2823
|
+
shape = ifcopenshell.geom.create_shape(settings, representation)
|
2824
|
+
verts = shape.verts
|
2825
|
+
edges = shape.edges
|
2826
|
+
faces = shape.faces
|
2308
2827
|
grouped_verts = [ [verts[i], verts[i + 1], verts[i + 2]] for i in range(0, len(verts), 3)]
|
2828
|
+
grouped_verts = apply_transformation(grouped_verts, aspect_matrix)
|
2309
2829
|
grouped_edges = [[edges[i], edges[i + 1]] for i in range(0, len(edges), 2)]
|
2310
2830
|
grouped_faces = [ [faces[i], faces[i + 1], faces[i + 2]] for i in range(0, len(faces), 3)]
|
2311
2831
|
topology = Topology.SelfMerge(Topology.ByGeometry(grouped_verts, grouped_edges, grouped_faces))
|
2312
|
-
|
2313
|
-
|
2314
|
-
|
2832
|
+
#matrix = shape.transformation.matrix
|
2833
|
+
#topology = Topology.Transform(topology, matrix)
|
2834
|
+
d = get_material_ids_of_entity(wall)
|
2835
|
+
material_id = d.get(clean_key(material_name), 0)
|
2315
2836
|
if transferDictionaries:
|
2316
2837
|
keys = []
|
2317
2838
|
values = []
|
2839
|
+
try:
|
2840
|
+
entity_name = entity.Name
|
2841
|
+
except:
|
2842
|
+
entity_name = entity.to_str()
|
2318
2843
|
keys.append("TOPOLOGIC_id")
|
2319
2844
|
values.append(str(uuid.uuid4()))
|
2320
2845
|
keys.append("TOPOLOGIC_name")
|
2321
|
-
values.append(
|
2846
|
+
values.append(entity_name)
|
2322
2847
|
keys.append("TOPOLOGIC_type")
|
2323
2848
|
values.append(Topology.TypeAsString(topology))
|
2324
2849
|
keys.append("IFC_id")
|
2325
|
-
values.append(str(
|
2326
|
-
keys.append("IFC_guid")
|
2327
|
-
values.append(str(
|
2328
|
-
keys.append("IFC_unique_id")
|
2329
|
-
values.append(str(
|
2850
|
+
values.append(str(aspect.id))
|
2851
|
+
#keys.append("IFC_guid")
|
2852
|
+
#values.append(str(aspect.guid))
|
2853
|
+
#keys.append("IFC_unique_id")
|
2854
|
+
#values.append(str(aspect.unique_id))
|
2330
2855
|
keys.append("IFC_name")
|
2331
|
-
values.append(
|
2332
|
-
keys.append("IFC_type")
|
2333
|
-
values.append(
|
2334
|
-
|
2335
|
-
|
2336
|
-
values.append(material_ids)
|
2856
|
+
values.append(entity_name)
|
2857
|
+
#keys.append("IFC_type")
|
2858
|
+
#values.append(aspect.type)
|
2859
|
+
keys.append("IFC_material_id")
|
2860
|
+
values.append(material_id)
|
2337
2861
|
keys.append("IFC_material_name")
|
2338
2862
|
values.append(material_name)
|
2339
2863
|
keys.append("TOPOLOGIC_color")
|
2340
|
-
color = generate_color_for_material(str(
|
2864
|
+
color = generate_color_for_material(str(material_id))
|
2341
2865
|
values.append(color)
|
2342
2866
|
d = Dictionary.ByKeysValues(keys, values)
|
2343
2867
|
topology = Topology.SetDictionary(topology, d)
|
2344
|
-
|
2868
|
+
|
2869
|
+
return topology
|
2870
|
+
|
2871
|
+
|
2872
|
+
includeTypes = [s.lower() for s in includeTypes]
|
2873
|
+
excludeTypes = [s.lower() for s in excludeTypes]
|
2874
|
+
topologies = []
|
2875
|
+
settings = ifcopenshell.geom.settings()
|
2876
|
+
settings.set("dimensionality", ifcopenshell.ifcopenshell_wrapper.SOLID)
|
2877
|
+
settings.set(settings.USE_WORLD_COORDS, True)
|
2878
|
+
for entity in file.by_type('IfcProduct'): # You might want to refine the types you check
|
2879
|
+
if hasattr(entity, "Representation") and entity.Representation:
|
2880
|
+
print("Number of Representations:", len(entity.Representation.Representations))
|
2881
|
+
for rep in entity.Representation.Representations:
|
2882
|
+
print("Rep:", rep)
|
2883
|
+
print(dir(rep))
|
2884
|
+
matrix = get_entity_transformation_matrix(entity)
|
2885
|
+
print(matrix)
|
2886
|
+
if rep.is_a("IfcShapeRepresentation"):
|
2887
|
+
# Generate the geometry for this entity
|
2888
|
+
shape = ifcopenshell.geom.create_shape(settings, rep)
|
2889
|
+
verts = shape.verts
|
2890
|
+
edges = shape.edges
|
2891
|
+
faces = shape.faces
|
2892
|
+
grouped_verts = [ [verts[i], verts[i + 1], verts[i + 2]] for i in range(0, len(verts), 3)]
|
2893
|
+
#grouped_verts = apply_transformation(grouped_verts, matrix)
|
2894
|
+
grouped_edges = [[edges[i], edges[i + 1]] for i in range(0, len(edges), 2)]
|
2895
|
+
grouped_faces = [ [faces[i], faces[i + 1], faces[i + 2]] for i in range(0, len(faces), 3)]
|
2896
|
+
topology = Topology.SelfMerge(Topology.ByGeometry(grouped_verts, grouped_edges, grouped_faces))
|
2897
|
+
if removeCoplanarFaces:
|
2898
|
+
topology = Topology.RemoveCoplanarFaces(topology)
|
2899
|
+
if transferDictionaries:
|
2900
|
+
keys = []
|
2901
|
+
values = []
|
2902
|
+
keys.append("TOPOLOGIC_id")
|
2903
|
+
values.append(str(uuid.uuid4()))
|
2904
|
+
keys.append("TOPOLOGIC_name")
|
2905
|
+
values.append(shape.name)
|
2906
|
+
keys.append("TOPOLOGIC_type")
|
2907
|
+
values.append(Topology.TypeAsString(topology))
|
2908
|
+
keys.append("IFC_id")
|
2909
|
+
values.append(str(shape.id))
|
2910
|
+
keys.append("IFC_guid")
|
2911
|
+
values.append(str(shape.guid))
|
2912
|
+
keys.append("IFC_unique_id")
|
2913
|
+
values.append(str(shape.unique_id))
|
2914
|
+
keys.append("IFC_name")
|
2915
|
+
values.append(shape.name)
|
2916
|
+
keys.append("IFC_type")
|
2917
|
+
values.append(shape.type)
|
2918
|
+
material_dict = get_material_ids_of_entity(entity)
|
2919
|
+
keys.append("IFC_materials")
|
2920
|
+
values.append(material_dict)
|
2921
|
+
#keys.append("IFC_material_name")
|
2922
|
+
#values.append(material_name)
|
2923
|
+
#keys.append("TOPOLOGIC_color")
|
2924
|
+
#color = generate_color_for_material(str(material_ids))
|
2925
|
+
#values.append(color)
|
2926
|
+
d = Dictionary.ByKeysValues(keys, values)
|
2927
|
+
topology = Topology.SetDictionary(topology, d)
|
2928
|
+
topology = Topology.Transform(topology, matrix)
|
2929
|
+
topologies.append(topology)
|
2345
2930
|
return topologies
|
2346
2931
|
|
2347
2932
|
@staticmethod
|
2348
|
-
def ByIFCPath(path, includeTypes=[], excludeTypes=[], transferDictionaries=False, removeCoplanarFaces=False):
|
2933
|
+
def ByIFCPath(path, includeTypes=[], excludeTypes=[], transferDictionaries=False, removeCoplanarFaces=False, epsilon=0.0001, tolerance=0.0001):
|
2349
2934
|
"""
|
2350
2935
|
Create a topology by importing it from an IFC file path.
|
2351
2936
|
|
@@ -2361,7 +2946,10 @@ class Topology():
|
|
2361
2946
|
If set to True, the dictionaries from the IFC file will be transferred to the topology. Otherwise, they won't. The default is False.
|
2362
2947
|
removeCoplanarFaces : bool , optional
|
2363
2948
|
If set to True, coplanar faces are removed. Otherwise they are not. The default is False.
|
2364
|
-
|
2949
|
+
epsilon : float , optional
|
2950
|
+
The desired epsilon (another form of tolerance) for finding if two faces are coplanar. The default is 0.0001.
|
2951
|
+
tolerance : float , optional
|
2952
|
+
The desired tolerance. The default is 0.0001.
|
2365
2953
|
Returns
|
2366
2954
|
-------
|
2367
2955
|
list
|
@@ -2380,7 +2968,7 @@ class Topology():
|
|
2380
2968
|
if not file:
|
2381
2969
|
print("Topology.ByIFCPath - Error: the input file parameter is not a valid file. Returning None.")
|
2382
2970
|
return None
|
2383
|
-
return Topology.ByIFCFile(file, includeTypes=includeTypes, excludeTypes=excludeTypes, transferDictionaries=transferDictionaries, removeCoplanarFaces=removeCoplanarFaces)
|
2971
|
+
return Topology.ByIFCFile(file, includeTypes=includeTypes, excludeTypes=excludeTypes, transferDictionaries=transferDictionaries, removeCoplanarFaces=removeCoplanarFaces, epsilon=epsilon, tolerance=tolerance)
|
2384
2972
|
|
2385
2973
|
'''
|
2386
2974
|
@staticmethod
|
@@ -5504,6 +6092,20 @@ class Topology():
|
|
5504
6092
|
flat_topology = Topology.Translate(topology, -Vertex.X(origin, mantissa=mantissa), -Vertex.Y(origin, mantissa=mantissa), -Vertex.Z(origin, mantissa=mantissa))
|
5505
6093
|
tran_mat = Vector.TransformationMatrix(direction, up)
|
5506
6094
|
flat_topology = Topology.Transform(flat_topology, tran_mat)
|
6095
|
+
flat_topology = Topology.SetDictionary(flat_topology, Topology.Dictionary(topology), silent=True)
|
6096
|
+
flat_vertices = Topology.Vertices(flat_topology)
|
6097
|
+
vertices = Topology.Vertices(topology)
|
6098
|
+
flat_edges = Topology.Edges(flat_topology)
|
6099
|
+
edges = Topology.Edges(topology)
|
6100
|
+
faces = []
|
6101
|
+
flat_faces = []
|
6102
|
+
if Topology.IsInstance(topology, "Face"):
|
6103
|
+
flat_faces = Topology.Faces(flat_topology)
|
6104
|
+
faces = Topology.Faces(topology)
|
6105
|
+
elements = vertices+edges+faces
|
6106
|
+
flat_elements = flat_vertices+flat_edges+flat_faces
|
6107
|
+
for i, f, in enumerate(flat_elements):
|
6108
|
+
f = Topology.SetDictionary(f, Topology.Dictionary(elements[i]), silent=True)
|
5507
6109
|
return flat_topology
|
5508
6110
|
|
5509
6111
|
@staticmethod
|
@@ -6950,20 +7552,30 @@ class Topology():
|
|
6950
7552
|
|
6951
7553
|
"""
|
6952
7554
|
from topologicpy.Dictionary import Dictionary
|
7555
|
+
import inspect
|
6953
7556
|
|
6954
7557
|
if not Topology.IsInstance(topology, "Topology") and not Topology.IsInstance(topology, "Graph"):
|
6955
7558
|
if not silent:
|
6956
7559
|
print("Topology.SetDictionary - Error: the input topology parameter is not a valid topology or graph. Returning None.")
|
7560
|
+
curframe = inspect.currentframe()
|
7561
|
+
calframe = inspect.getouterframes(curframe, 2)
|
7562
|
+
print('caller name:', calframe[1][3])
|
6957
7563
|
return None
|
6958
7564
|
if isinstance(dictionary, dict):
|
6959
7565
|
dictionary = Dictionary.ByPythonDictionary(dictionary)
|
6960
7566
|
if not Topology.IsInstance(dictionary, "Dictionary"):
|
6961
7567
|
if not silent:
|
6962
7568
|
print("Topology.SetDictionary - Warning: the input dictionary parameter is not a valid dictionary. Returning original input.")
|
7569
|
+
curframe = inspect.currentframe()
|
7570
|
+
calframe = inspect.getouterframes(curframe, 2)
|
7571
|
+
print('caller name:', calframe[1][3])
|
6963
7572
|
return topology
|
6964
7573
|
if len(dictionary.Keys()) < 1:
|
6965
7574
|
if not silent:
|
6966
7575
|
print("Topology.SetDictionary - Warning: the input dictionary parameter is empty. Returning original input.")
|
7576
|
+
curframe = inspect.currentframe()
|
7577
|
+
calframe = inspect.getouterframes(curframe, 2)
|
7578
|
+
print('caller name:', calframe[1][3])
|
6967
7579
|
return topology
|
6968
7580
|
_ = topology.SetDictionary(dictionary)
|
6969
7581
|
return topology
|
@@ -7166,13 +7778,15 @@ class Topology():
|
|
7166
7778
|
colorKey = "color",
|
7167
7779
|
opacityKey = "opacity",
|
7168
7780
|
showVertices=True, vertexSize=1.1, vertexColor="black",
|
7169
|
-
vertexLabelKey=None,
|
7781
|
+
vertexLabelKey=None, showVertexLabel= False,
|
7782
|
+
vertexGroupKey=None, vertexGroups=[],
|
7170
7783
|
vertexMinGroup=None, vertexMaxGroup=None,
|
7171
7784
|
showVertexLegend=False, vertexLegendLabel="Topology Vertices", vertexLegendRank=1,
|
7172
7785
|
vertexLegendGroup=1,
|
7173
7786
|
|
7174
7787
|
showEdges=True, edgeWidth=1, edgeColor="black",
|
7175
|
-
edgeLabelKey=None,
|
7788
|
+
edgeLabelKey=None, showEdgeLabel = False,
|
7789
|
+
edgeGroupKey=None, edgeGroups=[],
|
7176
7790
|
edgeMinGroup=None, edgeMaxGroup=None,
|
7177
7791
|
showEdgeLegend=False, edgeLegendLabel="Topology Edges", edgeLegendRank=2,
|
7178
7792
|
edgeLegendGroup=2,
|
@@ -7217,6 +7831,8 @@ class Topology():
|
|
7217
7831
|
The default is "black".
|
7218
7832
|
vertexLabelKey : str , optional
|
7219
7833
|
The dictionary key to use to display the vertex label. The default is None.
|
7834
|
+
showVertexLabels : bool , optional
|
7835
|
+
If set to True, the vertex labels are shown permenantely on screen. Otherwise, they are not. The default is False.
|
7220
7836
|
vertexGroupKey : str , optional
|
7221
7837
|
The dictionary key to use to display the vertex group. The default is None.
|
7222
7838
|
vertexGroups : list , optional
|
@@ -7248,6 +7864,8 @@ class Topology():
|
|
7248
7864
|
The default is "black".
|
7249
7865
|
edgeLabelKey : str , optional
|
7250
7866
|
The dictionary key to use to display the edge label. The default is None.
|
7867
|
+
showEdgeLabels : bool , optional
|
7868
|
+
If set to True, the edge labels are shown permenantely on screen. Otherwise, they are not. The default is False.
|
7251
7869
|
edgeGroupKey : str , optional
|
7252
7870
|
The dictionary key to use to display the edge group. The default is None.
|
7253
7871
|
edgeGroups : list , optional
|
@@ -7400,12 +8018,12 @@ class Topology():
|
|
7400
8018
|
faceOpacity = Dictionary.ValueAtKey(d, opacityKey) or faceOpacity
|
7401
8019
|
data += Plotly.DataByTopology(topology=topology,
|
7402
8020
|
showVertices=showVertices, vertexSize=vertexSize, vertexColor=vertexColor,
|
7403
|
-
vertexLabelKey=vertexLabelKey, vertexGroupKey=vertexGroupKey, vertexGroups=vertexGroups,
|
8021
|
+
vertexLabelKey=vertexLabelKey, showVertexLabel=showVertexLabel, vertexGroupKey=vertexGroupKey, vertexGroups=vertexGroups,
|
7404
8022
|
vertexMinGroup=vertexMinGroup, vertexMaxGroup=vertexMaxGroup,
|
7405
8023
|
showVertexLegend=showVertexLegend, vertexLegendLabel=vertexLegendLabel, vertexLegendRank=vertexLegendRank,
|
7406
8024
|
vertexLegendGroup=vertexLegendGroup,
|
7407
8025
|
showEdges=showEdges, edgeWidth=edgeWidth, edgeColor=edgeColor,
|
7408
|
-
edgeLabelKey=edgeLabelKey, edgeGroupKey=edgeGroupKey, edgeGroups=edgeGroups,
|
8026
|
+
edgeLabelKey=edgeLabelKey, showEdgeLabel=showEdgeLabel, edgeGroupKey=edgeGroupKey, edgeGroups=edgeGroups,
|
7409
8027
|
edgeMinGroup=edgeMinGroup, edgeMaxGroup=edgeMaxGroup,
|
7410
8028
|
showEdgeLegend=showEdgeLegend, edgeLegendLabel=edgeLegendLabel, edgeLegendRank=edgeLegendRank,
|
7411
8029
|
edgeLegendGroup=edgeLegendGroup,
|
@@ -7784,6 +8402,21 @@ class Topology():
|
|
7784
8402
|
tran_mat = Vector.TransformationMatrix(up, direction)
|
7785
8403
|
unflat_topology = Topology.Transform(topology, tran_mat)
|
7786
8404
|
unflat_topology = Topology.Translate(unflat_topology, Vertex.X(origin), Vertex.Y(origin), Vertex.Z(origin))
|
8405
|
+
|
8406
|
+
unflat_topology = Topology.SetDictionary(unflat_topology, Topology.Dictionary(topology), silent=True)
|
8407
|
+
unflat_vertices = Topology.Vertices(unflat_topology)
|
8408
|
+
vertices = Topology.Vertices(topology)
|
8409
|
+
unflat_edges = Topology.Edges(unflat_topology)
|
8410
|
+
edges = Topology.Edges(topology)
|
8411
|
+
faces = []
|
8412
|
+
unflat_faces = []
|
8413
|
+
if Topology.IsInstance(topology, "Face"):
|
8414
|
+
unflat_faces = Topology.Faces(unflat_topology)
|
8415
|
+
faces = Topology.Faces(topology)
|
8416
|
+
elements = vertices+edges+faces
|
8417
|
+
unflat_elements = unflat_vertices+unflat_edges+unflat_faces
|
8418
|
+
for i, f, in enumerate(unflat_elements):
|
8419
|
+
f = Topology.SetDictionary(f, Topology.Dictionary(elements[i]), silent=True)
|
7787
8420
|
return unflat_topology
|
7788
8421
|
|
7789
8422
|
@staticmethod
|
@@ -8145,8 +8778,8 @@ class Topology():
|
|
8145
8778
|
tolerance : float , optional
|
8146
8779
|
The desired tolerance. The default is 0.0001.
|
8147
8780
|
numWorkers : int , optional
|
8148
|
-
Number of workers run in parallel to process.
|
8149
|
-
|
8781
|
+
Number of workers run in parallel to process. If you set it to 1, no parallel processing will take place.
|
8782
|
+
The default is None which causes the algorithm to use twice the number of cpu cores in the host computer.
|
8150
8783
|
Returns
|
8151
8784
|
-------
|
8152
8785
|
Topology
|
@@ -8157,6 +8790,42 @@ class Topology():
|
|
8157
8790
|
from topologicpy.Dictionary import Dictionary
|
8158
8791
|
from topologicpy.Cluster import Cluster
|
8159
8792
|
from topologicpy.Plotly import Plotly
|
8793
|
+
|
8794
|
+
|
8795
|
+
def transfer_dictionaries_by_selectors(object, selectors, tranVertices=False, tranEdges=False, tranFaces=False, tranCells=False, tolerance=0.0001):
|
8796
|
+
if tranVertices == True:
|
8797
|
+
vertices = Topology.Vertices(object)
|
8798
|
+
for vertex in vertices:
|
8799
|
+
for selector in selectors:
|
8800
|
+
d = Vertex.Distance(selector, vertex)
|
8801
|
+
if d < tolerance:
|
8802
|
+
vertex = Topology.SetDictionary(vertex, Topology.Dictionary(selector))
|
8803
|
+
break
|
8804
|
+
if tranEdges == True:
|
8805
|
+
edges = Topology.Edges(object)
|
8806
|
+
for selector in selectors:
|
8807
|
+
for edge in edges:
|
8808
|
+
d = Vertex.Distance(selector, edge)
|
8809
|
+
if d < tolerance:
|
8810
|
+
edge = Topology.SetDictionary(edge, Topology.Dictionary(selector), silent=True)
|
8811
|
+
break
|
8812
|
+
if tranFaces == True:
|
8813
|
+
faces = Topology.Faces(object)
|
8814
|
+
for face in faces:
|
8815
|
+
for selector in selectors:
|
8816
|
+
d = Vertex.Distance(selector, face)
|
8817
|
+
if d < tolerance:
|
8818
|
+
face = Topology.SetDictionary(face, Topology.Dictionary(selector), silent=True)
|
8819
|
+
break
|
8820
|
+
if tranCells == True:
|
8821
|
+
cells = Topology.Cells(object)
|
8822
|
+
for cell in cells:
|
8823
|
+
for selector in selectors:
|
8824
|
+
if Vertex.IsInternal(selector, cell):
|
8825
|
+
cell = Topology.SetDictionary(cell, Topology.Dictionary(selector), silent=True)
|
8826
|
+
break
|
8827
|
+
return object
|
8828
|
+
|
8160
8829
|
if not Topology.IsInstance(topology, "Topology"):
|
8161
8830
|
print("Topology.TransferDictionariesBySelectors - Error: The input topology parameter is not a valid topology. Returning None.")
|
8162
8831
|
return None
|
@@ -8170,6 +8839,9 @@ class Topology():
|
|
8170
8839
|
if len(selectors_tmp) < 1:
|
8171
8840
|
print("Topology.TransferDictionariesBySelectors - Error: The input selectors do not contain any valid topologies. Returning None.")
|
8172
8841
|
return None
|
8842
|
+
|
8843
|
+
if numWorkers == 1:
|
8844
|
+
return transfer_dictionaries_by_selectors(topology, selectors, tranVertices=tranVertices, tranEdges=tranEdges, tranFaces=tranFaces, tranCells=tranCells, tolerance=tolerance)
|
8173
8845
|
sinkEdges = []
|
8174
8846
|
sinkFaces = []
|
8175
8847
|
sinkCells = []
|
@@ -8538,11 +9210,30 @@ class Topology():
|
|
8538
9210
|
|
8539
9211
|
"""
|
8540
9212
|
import uuid
|
9213
|
+
from topologicpy.Dictionary import Dictionary
|
8541
9214
|
|
8542
9215
|
predefined_namespace_dns = uuid.UUID('6ba7b810-9dad-11d1-80b4-00c04fd430c8')
|
8543
9216
|
namespace_uuid = uuid.uuid5(predefined_namespace_dns, namespace)
|
8544
|
-
|
8545
|
-
|
9217
|
+
cellComplexes = Topology.CellComplexes(topology)
|
9218
|
+
cells = Topology.Cells(topology)
|
9219
|
+
Shells = Topology.Shells(topology)
|
9220
|
+
Faces = Topology.Faces(topology)
|
9221
|
+
Wires = Topology.Wires(topology)
|
9222
|
+
Edges = Topology.Edges(topology)
|
9223
|
+
Vertices = Topology.Vertices(topology)
|
9224
|
+
Apertures = Topology.Apertures(topology, subTopologyType="all")
|
9225
|
+
subTopologies = cellComplexes+cells+Shells+Faces+Wires+Edges+Vertices+Apertures
|
9226
|
+
dictionaries = [Dictionary.PythonDictionary(Topology.Dictionary(topology))]
|
9227
|
+
dictionaries += [Dictionary.PythonDictionary(Topology.Dictionary(s)) for s in subTopologies]
|
9228
|
+
dict_str = str(dictionaries)
|
9229
|
+
top_geom = Topology.Geometry(topology, mantissa=6)
|
9230
|
+
verts_str = str(top_geom['vertices'])
|
9231
|
+
edges_str = str(top_geom['edges'])
|
9232
|
+
faces_str = str(top_geom['faces'])
|
9233
|
+
geo_str = verts_str+edges_str+faces_str
|
9234
|
+
final_str = geo_str+dict_str
|
9235
|
+
uuid_str = uuid.uuid5(namespace_uuid, final_str)
|
9236
|
+
return str(uuid_str)
|
8546
9237
|
|
8547
9238
|
@staticmethod
|
8548
9239
|
def View3D(*topologies, uuid = None, nameKey="name", colorKey="color", opacityKey="opacity", defaultColor=[256,256,256], defaultOpacity=0.5, transposeAxes: bool = True, mode: int = 0, meshSize: float = None, overwrite: bool = False, mantissa: int = 6, tolerance: float = 0.0001):
|