topologicpy 0.8.30__py3-none-any.whl → 0.8.33__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- topologicpy/BVH.py +5 -3
- topologicpy/CSG.py +1 -1
- topologicpy/Cell.py +1105 -12
- topologicpy/CellComplex.py +213 -1
- topologicpy/Cluster.py +4 -2
- topologicpy/Edge.py +61 -28
- topologicpy/Face.py +384 -101
- topologicpy/Graph.py +149 -2
- topologicpy/Plotly.py +0 -1
- topologicpy/ShapeGrammar.py +65 -6
- topologicpy/Topology.py +56 -416
- topologicpy/Vertex.py +1 -1
- topologicpy/Wire.py +95 -45
- topologicpy/version.py +1 -1
- {topologicpy-0.8.30.dist-info → topologicpy-0.8.33.dist-info}/METADATA +1 -1
- {topologicpy-0.8.30.dist-info → topologicpy-0.8.33.dist-info}/RECORD +19 -19
- {topologicpy-0.8.30.dist-info → topologicpy-0.8.33.dist-info}/WHEEL +1 -1
- {topologicpy-0.8.30.dist-info → topologicpy-0.8.33.dist-info}/licenses/LICENSE +0 -0
- {topologicpy-0.8.30.dist-info → topologicpy-0.8.33.dist-info}/top_level.txt +0 -0
topologicpy/Topology.py
CHANGED
@@ -1209,7 +1209,7 @@ class Topology():
|
|
1209
1209
|
|
1210
1210
|
|
1211
1211
|
@staticmethod
|
1212
|
-
def BoundingBox(topology, optimize: int = 0, axes: str ="xyz", mantissa: int = 6, tolerance: float = 0.0001):
|
1212
|
+
def BoundingBox(topology, optimize: int = 0, axes: str ="xyz", mantissa: int = 6, tolerance: float = 0.0001, silent: bool = False):
|
1213
1213
|
"""
|
1214
1214
|
Returns a cell representing a bounding box of the input topology. The returned cell contains a dictionary with keys "xrot", "yrot", and "zrot" that represents rotations around the X, Y, and Z axes. If applied in the order of Z, Y, X, the resulting box will become axis-aligned.
|
1215
1215
|
|
@@ -1225,7 +1225,9 @@ class Topology():
|
|
1225
1225
|
The desired length of the mantissa. The default is 6.
|
1226
1226
|
tolerance : float , optional
|
1227
1227
|
The desired tolerance. The default is 0.0001.
|
1228
|
-
|
1228
|
+
silent : bool , optional
|
1229
|
+
If set to True, no error and warning messages are printed. Otherwise, they are. The default is False.
|
1230
|
+
|
1229
1231
|
Returns
|
1230
1232
|
-------
|
1231
1233
|
topologic_core.Cell or topologic_core.Face
|
@@ -1376,7 +1378,7 @@ class Topology():
|
|
1376
1378
|
vb3 = Vertex.ByCoordinates(x_max, y_max, z_min)
|
1377
1379
|
vb4 = Vertex.ByCoordinates(x_min, y_max, z_min)
|
1378
1380
|
|
1379
|
-
baseWire = Wire.ByVertices([vb1, vb2, vb3, vb4], close=True)
|
1381
|
+
baseWire = Wire.ByVertices([vb1, vb2, vb3, vb4], close=True, tolerance=tolerance, silent=silent)
|
1380
1382
|
baseFace = Face.ByWire(baseWire, tolerance=tolerance)
|
1381
1383
|
if abs(z_max - z_min) <= tolerance:
|
1382
1384
|
box = baseFace
|
@@ -1853,7 +1855,7 @@ class Topology():
|
|
1853
1855
|
return Topology.ByBREPFile(file)
|
1854
1856
|
|
1855
1857
|
@staticmethod
|
1856
|
-
def ByDXFFile(file, sides: int = 16):
|
1858
|
+
def ByDXFFile(file, sides: int = 16, tolerance: float = 0.0001, silent: bool = False):
|
1857
1859
|
"""
|
1858
1860
|
Imports a list of topologies from a DXF file.
|
1859
1861
|
This is an experimental method with limited capabilities.
|
@@ -1864,6 +1866,10 @@ class Topology():
|
|
1864
1866
|
The DXF file object.
|
1865
1867
|
sides : int , optional
|
1866
1868
|
The desired number of sides of splines. The default is 16.
|
1869
|
+
tolerance : float , optional
|
1870
|
+
The desired tolerance. The default is 0.0001.
|
1871
|
+
silent : bool , optional
|
1872
|
+
If set to True, no error and warning messages are printed. Otherwise, they are. The default is False.
|
1867
1873
|
|
1868
1874
|
Returns
|
1869
1875
|
-------
|
@@ -1955,7 +1961,7 @@ class Topology():
|
|
1955
1961
|
vertices.append(Vertex.ByCoordinates(point[0], point[1], point[2]))
|
1956
1962
|
if entity.dxf.hasattr("closed"):
|
1957
1963
|
closed = entity.closed
|
1958
|
-
e = Wire.ByVertices(vertices, close=closed)
|
1964
|
+
e = Wire.ByVertices(vertices, close=closed, tolerance=tolerance, silent=silent)
|
1959
1965
|
e = Topology.SetDictionary(e, d)
|
1960
1966
|
|
1961
1967
|
elif entity_type == 'LWPOLYLINE':
|
@@ -1966,7 +1972,7 @@ class Topology():
|
|
1966
1972
|
close = entity.closed
|
1967
1973
|
else:
|
1968
1974
|
close = False
|
1969
|
-
e = Wire.ByVertices(vertices, close=close)
|
1975
|
+
e = Wire.ByVertices(vertices, close=close, tolerance=tolerance, silent=silent)
|
1970
1976
|
e = Topology.SetDictionary(e, d)
|
1971
1977
|
|
1972
1978
|
elif entity_type == 'CIRCLE':
|
@@ -1980,7 +1986,7 @@ class Topology():
|
|
1980
1986
|
y = center[1] + radius * np.sin(angle)
|
1981
1987
|
z = center[2]
|
1982
1988
|
vertices.append(Vertex.ByCoordinates(x,y,z))
|
1983
|
-
e = Wire.ByVertices(vertices, close=True)
|
1989
|
+
e = Wire.ByVertices(vertices, close=True, tolerance=tolerance, silent=silent)
|
1984
1990
|
e = Topology.SetDictionary(e, d)
|
1985
1991
|
|
1986
1992
|
elif entity_type == 'ARC':
|
@@ -1995,7 +2001,7 @@ class Topology():
|
|
1995
2001
|
y = center[1] + radius * np.sin(angle)
|
1996
2002
|
z = center[2]
|
1997
2003
|
vertices.append(Vertex.ByCoordinates(x,y,z))
|
1998
|
-
e = Wire.ByVertices(vertices, close=False)
|
2004
|
+
e = Wire.ByVertices(vertices, close=False, tolerance=tolerance, silent=silent)
|
1999
2005
|
e = Topology.SetDictionary(e, d)
|
2000
2006
|
|
2001
2007
|
elif entity_type == 'SPLINE':
|
@@ -2005,7 +2011,7 @@ class Topology():
|
|
2005
2011
|
for t in np.linspace(0, ct.max_t, 64):
|
2006
2012
|
point, derivative = ct.derivative(t, 1)
|
2007
2013
|
vertices.append(Vertex.ByCoordinates(list(point)))
|
2008
|
-
converted_entity = Wire.ByVertices(vertices, close=entity.closed)
|
2014
|
+
converted_entity = Wire.ByVertices(vertices, close=entity.closed, tolerance=tolerance, silent=silent)
|
2009
2015
|
vertices = []
|
2010
2016
|
for i in range(sides+1):
|
2011
2017
|
if i == 0:
|
@@ -2016,7 +2022,7 @@ class Topology():
|
|
2016
2022
|
u = float(i)/float(sides)
|
2017
2023
|
vertices.append(Wire.VertexByParameter(converted_entity, u))
|
2018
2024
|
|
2019
|
-
e = Wire.ByVertices(vertices, close=entity.closed)
|
2025
|
+
e = Wire.ByVertices(vertices, close=entity.closed, tolerance=tolerance, silent=silent)
|
2020
2026
|
e = Topology.SetDictionary(e, d)
|
2021
2027
|
|
2022
2028
|
elif entity_type == 'MESH':
|
@@ -2073,7 +2079,7 @@ class Topology():
|
|
2073
2079
|
return converted_entities
|
2074
2080
|
|
2075
2081
|
@staticmethod
|
2076
|
-
def ByDXFPath(path, sides: int = 16):
|
2082
|
+
def ByDXFPath(path, sides: int = 16, tolerance: float = 0.0001, silent: bool = False):
|
2077
2083
|
"""
|
2078
2084
|
Imports a list of topologies from a DXF file path.
|
2079
2085
|
This is an experimental method with limited capabilities.
|
@@ -2084,6 +2090,10 @@ class Topology():
|
|
2084
2090
|
The path to the DXF file.
|
2085
2091
|
sides : int , optional
|
2086
2092
|
The desired number of sides of splines. The default is 16.
|
2093
|
+
tolerance : float , optional
|
2094
|
+
The desired tolerance. The default is 0.0001.
|
2095
|
+
silent : bool , optional
|
2096
|
+
If set to True, no error and warning messages are printed. Otherwise, they are. The default is False.
|
2087
2097
|
|
2088
2098
|
Returns
|
2089
2099
|
-------
|
@@ -2106,16 +2116,18 @@ class Topology():
|
|
2106
2116
|
warnings.warn("Topology.ByDXFPath - Error: Could not import ezdxf library. Please install it manually. Returning None.")
|
2107
2117
|
return None
|
2108
2118
|
if not path:
|
2109
|
-
|
2119
|
+
if not silent:
|
2120
|
+
print("Topology.ByDXFPath - Error: the input path parameter is not a valid path. Returning None.")
|
2110
2121
|
return None
|
2111
2122
|
try:
|
2112
2123
|
file = ezdxf.readfile(path)
|
2113
2124
|
except:
|
2114
2125
|
file = None
|
2115
2126
|
if not file:
|
2116
|
-
|
2127
|
+
if not silent:
|
2128
|
+
print("Topology.ByDXFPath - Error: the input file parameter is not a valid file. Returning None.")
|
2117
2129
|
return None
|
2118
|
-
return Topology.ByDXFFile(file, sides=sides)
|
2130
|
+
return Topology.ByDXFFile(file, sides=sides, tolerance=tolerance, silent=silent)
|
2119
2131
|
|
2120
2132
|
@staticmethod
|
2121
2133
|
def ByIFCFile(ifc_file, includeTypes=[], excludeTypes=[], transferDictionaries=False,
|
@@ -2232,391 +2244,6 @@ class Topology():
|
|
2232
2244
|
|
2233
2245
|
return topologies
|
2234
2246
|
|
2235
|
-
@staticmethod
|
2236
|
-
def _ByIFCFile_old(file, includeTypes=[], excludeTypes=[], transferDictionaries=False, removeCoplanarFaces=False):
|
2237
|
-
"""
|
2238
|
-
Create a topology by importing it from an IFC file.
|
2239
|
-
|
2240
|
-
Parameters
|
2241
|
-
----------
|
2242
|
-
file : file object
|
2243
|
-
The input IFC file.
|
2244
|
-
includeTypes : list , optional
|
2245
|
-
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 [].
|
2246
|
-
excludeTypes : list , optional
|
2247
|
-
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 [].
|
2248
|
-
transferDictionaries : bool , optional
|
2249
|
-
If set to True, the dictionaries from the IFC file will be transferred to the topology. Otherwise, they won't. The default is False.
|
2250
|
-
removeCoplanarFaces : bool , optional
|
2251
|
-
If set to True, coplanar faces are removed. Otherwise they are not. The default is False.
|
2252
|
-
Returns
|
2253
|
-
-------
|
2254
|
-
list
|
2255
|
-
The created list of topologies.
|
2256
|
-
|
2257
|
-
"""
|
2258
|
-
import multiprocessing
|
2259
|
-
from topologicpy.Cluster import Cluster
|
2260
|
-
from topologicpy.Dictionary import Dictionary
|
2261
|
-
import uuid
|
2262
|
-
import random
|
2263
|
-
import hashlib
|
2264
|
-
import re
|
2265
|
-
import numpy as np
|
2266
|
-
|
2267
|
-
try:
|
2268
|
-
import ifcopenshell
|
2269
|
-
import ifcopenshell.geom
|
2270
|
-
except:
|
2271
|
-
print("Topology.ByIFCFile - Warning: Installing required ifcopenshell library.")
|
2272
|
-
try:
|
2273
|
-
os.system("pip install ifcopenshell")
|
2274
|
-
except:
|
2275
|
-
os.system("pip install ifcopenshell --user")
|
2276
|
-
try:
|
2277
|
-
import ifcopenshell
|
2278
|
-
import ifcopenshell.geom
|
2279
|
-
print("Topology.ByIFCFile - Warning: ifcopenshell library installed correctly.")
|
2280
|
-
except:
|
2281
|
-
warnings.warn("Topology.ByIFCFile - Error: Could not import ifcopenshell. Please try to install ifcopenshell manually. Returning None.")
|
2282
|
-
return None
|
2283
|
-
if not file:
|
2284
|
-
print("Topology.ByIFCFile - Error: the input file parameter is not a valid file. Returning None.")
|
2285
|
-
return None
|
2286
|
-
|
2287
|
-
def clean_key(string):
|
2288
|
-
# Replace any character that is not a letter, digit, or underscore with an underscore
|
2289
|
-
cleaned_string = re.sub(r'[^a-zA-Z0-9_]', '_', string)
|
2290
|
-
return cleaned_string
|
2291
|
-
|
2292
|
-
def transform_wall_vertices(wall):
|
2293
|
-
|
2294
|
-
# Relatives Placement abrufen und ausgeben
|
2295
|
-
if wall.ObjectPlacement and wall.ObjectPlacement.RelativePlacement:
|
2296
|
-
relative_placement = wall.ObjectPlacement.RelativePlacement
|
2297
|
-
if relative_placement.is_a('IFCAXIS2PLACEMENT3D'):
|
2298
|
-
location = relative_placement.Location
|
2299
|
-
ref_direction = relative_placement.RefDirection
|
2300
|
-
print("Relative Placement Location:", location.Coordinates)
|
2301
|
-
if ref_direction:
|
2302
|
-
print("Relative Placement RefDirection:", ref_direction.DirectionRatios)
|
2303
|
-
else:
|
2304
|
-
print("Relative Placement RefDirection: None")
|
2305
|
-
|
2306
|
-
# IFCPRODUCTDEFINITIONSHAPE der Wand abrufen
|
2307
|
-
product_definition_shape = wall.Representation
|
2308
|
-
if not product_definition_shape:
|
2309
|
-
print("Keine Repräsentation gefunden.")
|
2310
|
-
return
|
2311
|
-
|
2312
|
-
# Initialisieren von Variablen für Representation Type und Layer-Infos
|
2313
|
-
representation_type = None
|
2314
|
-
diverse_representation = False
|
2315
|
-
layer_details = []
|
2316
|
-
|
2317
|
-
if hasattr(product_definition_shape, 'HasShapeAspects'):
|
2318
|
-
for aspect in product_definition_shape.HasShapeAspects:
|
2319
|
-
for representation in aspect.ShapeRepresentations:
|
2320
|
-
if representation.is_a('IFCSHAPEREPRESENTATION'):
|
2321
|
-
for item in representation.Items:
|
2322
|
-
if item.is_a('IFCEXTRUDEDAREASOLID'):
|
2323
|
-
# Profilbeschreibung abrufen
|
2324
|
-
profile = item.SweptArea
|
2325
|
-
if profile.is_a('IFCARBITRARYCLOSEDPROFILEDEF'):
|
2326
|
-
if not representation_type:
|
2327
|
-
representation_type = "ArbitraryClosedProfil"
|
2328
|
-
elif representation_type != "ArbitraryClosedProfil":
|
2329
|
-
diverse_representation = True
|
2330
|
-
|
2331
|
-
# Profilpunkte abrufen
|
2332
|
-
if hasattr(profile, 'OuterCurve') and profile.OuterCurve.is_a('IFCINDEXEDPOLYCURVE'):
|
2333
|
-
indexed_polycurve = profile.OuterCurve
|
2334
|
-
if hasattr(indexed_polycurve, 'Points') and indexed_polycurve.Points.is_a('IFCCARTESIANPOINTLIST2D'):
|
2335
|
-
point_list_2d = indexed_polycurve.Points
|
2336
|
-
points = point_list_2d.CoordList
|
2337
|
-
layer_info["Profilpunkte"] = points
|
2338
|
-
else:
|
2339
|
-
diverse_representation = True
|
2340
|
-
|
2341
|
-
# Location und RefDirection abrufen
|
2342
|
-
if item.Position.is_a('IFCAXIS2PLACEMENT3D'):
|
2343
|
-
axis_placement = item.Position
|
2344
|
-
location = axis_placement.Location
|
2345
|
-
ref_direction = axis_placement.RefDirection
|
2346
|
-
layer_info["Location"] = location.Coordinates
|
2347
|
-
if ref_direction:
|
2348
|
-
layer_info["RefDirection"] = ref_direction.DirectionRatios
|
2349
|
-
else:
|
2350
|
-
layer_info["RefDirection"] = None
|
2351
|
-
|
2352
|
-
layer_details.append(layer_info)
|
2353
|
-
|
2354
|
-
# Representation Type ausgeben
|
2355
|
-
if diverse_representation:
|
2356
|
-
representation_type = "divers"
|
2357
|
-
print("Representation Type der Wand:", representation_type)
|
2358
|
-
|
2359
|
-
# Layer-Details ausgeben
|
2360
|
-
for index, layer in enumerate(layer_details):
|
2361
|
-
print(f"\nLayer {index + 1} Details:")
|
2362
|
-
print("Material:", layer.get("Material", "Nicht verfügbar"))
|
2363
|
-
print("Extrusionsstärke:", layer.get("Extrusionsstärke", "Nicht verfügbar"))
|
2364
|
-
print("Profilpunkte:", layer.get("Profilpunkte", "Nicht verfügbar"))
|
2365
|
-
print("Location:", layer.get("Location", "Nicht verfügbar"))
|
2366
|
-
print("RefDirection:", layer.get("RefDirection", "Nicht verfügbar"))
|
2367
|
-
|
2368
|
-
|
2369
|
-
|
2370
|
-
|
2371
|
-
|
2372
|
-
|
2373
|
-
def extract_matrix_from_placement(placement):
|
2374
|
-
"""Constructs a transformation matrix from an IFC Local Placement."""
|
2375
|
-
# Initialize identity matrix
|
2376
|
-
matrix = np.identity(4)
|
2377
|
-
|
2378
|
-
# Check if the placement is IfcLocalPlacement
|
2379
|
-
if placement.is_a("IfcLocalPlacement"):
|
2380
|
-
relative_placement = placement.RelativePlacement
|
2381
|
-
|
2382
|
-
if relative_placement.is_a("IfcAxis2Placement3D"):
|
2383
|
-
location = relative_placement.Location.Coordinates
|
2384
|
-
z_dir = relative_placement.Axis.DirectionRatios if relative_placement.Axis else [0, 0, 1]
|
2385
|
-
x_dir = relative_placement.RefDirection.DirectionRatios if relative_placement.RefDirection else [1, 0, 0]
|
2386
|
-
|
2387
|
-
# Compute y direction (cross product of z and x)
|
2388
|
-
y_dir = np.cross(z_dir, x_dir)
|
2389
|
-
|
2390
|
-
# Construct the rotation matrix
|
2391
|
-
rotation_matrix = np.array([
|
2392
|
-
[x_dir[0], y_dir[0], z_dir[0], 0],
|
2393
|
-
[x_dir[1], y_dir[1], z_dir[1], 0],
|
2394
|
-
[x_dir[2], y_dir[2], z_dir[2], 0],
|
2395
|
-
[0, 0, 0, 1]
|
2396
|
-
])
|
2397
|
-
|
2398
|
-
# Translation vector
|
2399
|
-
translation_vector = np.array([
|
2400
|
-
[1, 0, 0, location[0]],
|
2401
|
-
[0, 1, 0, location[1]],
|
2402
|
-
[0, 0, 1, location[2]],
|
2403
|
-
[0, 0, 0, 1]
|
2404
|
-
])
|
2405
|
-
|
2406
|
-
# Combine the rotation matrix and the translation vector
|
2407
|
-
matrix = np.dot(translation_vector, rotation_matrix)
|
2408
|
-
|
2409
|
-
return matrix
|
2410
|
-
|
2411
|
-
def apply_transformation(verts, matrix):
|
2412
|
-
"""Applies a 4x4 transformation matrix to a list of vertices."""
|
2413
|
-
transformed_verts = []
|
2414
|
-
for vert in verts:
|
2415
|
-
print("vert:", vert)
|
2416
|
-
v = np.array([vert[0], vert[1], vert[2], 1.0])
|
2417
|
-
transformed_v = np.dot(matrix, v)
|
2418
|
-
transformed_verts.append([transformed_v[0], transformed_v[1], transformed_v[2]])
|
2419
|
-
return transformed_verts
|
2420
|
-
|
2421
|
-
def get_entity_transformation_matrix(entity):
|
2422
|
-
"""Extracts the transformation matrix from an IFC entity."""
|
2423
|
-
matrix = np.identity(4) # Default to an identity matrix
|
2424
|
-
if hasattr(entity, "ObjectPlacement") and entity.ObjectPlacement:
|
2425
|
-
placement = entity.ObjectPlacement
|
2426
|
-
matrix = extract_matrix_from_placement(placement)
|
2427
|
-
return matrix
|
2428
|
-
|
2429
|
-
# Function to generate a unique random color based on material ID
|
2430
|
-
def generate_color_for_material(material_id):
|
2431
|
-
# Use a hash function to get a consistent "random" seed
|
2432
|
-
hash_object = hashlib.sha1(material_id.encode())
|
2433
|
-
seed = int(hash_object.hexdigest(), 16) % (10 ** 8)
|
2434
|
-
random.seed(seed)
|
2435
|
-
# Generate a random color
|
2436
|
-
r = random.random()
|
2437
|
-
g = random.random()
|
2438
|
-
b = random.random()
|
2439
|
-
return [r, g, b]
|
2440
|
-
|
2441
|
-
# Function to get the material IDs associated with an entity
|
2442
|
-
def get_material_ids_of_entity(entity):
|
2443
|
-
return_dict = {}
|
2444
|
-
material_names = []
|
2445
|
-
material_ids = []
|
2446
|
-
if hasattr(entity, "HasAssociations"):
|
2447
|
-
for association in entity.HasAssociations:
|
2448
|
-
if association.is_a("IfcRelAssociatesMaterial"):
|
2449
|
-
material = association.RelatingMaterial
|
2450
|
-
try:
|
2451
|
-
material_name = material.Name
|
2452
|
-
except:
|
2453
|
-
material_name = material.to_string()
|
2454
|
-
if material.is_a("IfcMaterial"):
|
2455
|
-
material_ids.append(material.id())
|
2456
|
-
material_names.append(material_name)
|
2457
|
-
return_dict[clean_key(material_name)] = material.id
|
2458
|
-
elif material.is_a("IfcMaterialList"):
|
2459
|
-
for mat in material.Materials:
|
2460
|
-
material_ids.append(mat.id())
|
2461
|
-
try:
|
2462
|
-
material_name = mat.Name
|
2463
|
-
except:
|
2464
|
-
material_name = mat.to_string()
|
2465
|
-
material_names.append(material_name)
|
2466
|
-
return_dict[clean_key(material_name)] = mat.id
|
2467
|
-
elif material.is_a("IfcMaterialLayerSetUsage") or material.is_a("IfcMaterialLayerSet"):
|
2468
|
-
for layer in material.ForLayerSet.MaterialLayers:
|
2469
|
-
material_ids.append(layer.Material.id())
|
2470
|
-
try:
|
2471
|
-
material_name = layer.Name
|
2472
|
-
except:
|
2473
|
-
material_name = layer.to_string()
|
2474
|
-
material_names.append(material_name)
|
2475
|
-
return_dict[clean_key(material_name)] = layer.Material.id()
|
2476
|
-
elif material.is_a("IfcMaterialConstituentSet"):
|
2477
|
-
for constituent in material.MaterialConstituents:
|
2478
|
-
material_ids.append(constituent.Material.id())
|
2479
|
-
try:
|
2480
|
-
material_name = constituent.Material.Name
|
2481
|
-
except:
|
2482
|
-
material_name = constituent.Material.to_string()
|
2483
|
-
material_names.append(material_name)
|
2484
|
-
return_dict[clean_key(material_name)] = constituent.Material.id()
|
2485
|
-
|
2486
|
-
return return_dict
|
2487
|
-
|
2488
|
-
def get_wall_layers(wall, matrix=None, transferDictionaries=False):
|
2489
|
-
settings = ifcopenshell.geom.settings()
|
2490
|
-
settings.set("dimensionality", ifcopenshell.ifcopenshell_wrapper.CURVES_SURFACES_AND_SOLIDS)
|
2491
|
-
settings.set(settings.USE_WORLD_COORDS, False)
|
2492
|
-
|
2493
|
-
# IFCPRODUCTDEFINITIONSHAPE der Wand abrufen
|
2494
|
-
product_definition_shape = wall.Representation
|
2495
|
-
if not product_definition_shape:
|
2496
|
-
print("Topology.ByIFCFile - Error: The object has no representation. Returning None")
|
2497
|
-
return None
|
2498
|
-
|
2499
|
-
if hasattr(product_definition_shape, 'HasShapeAspects'):
|
2500
|
-
for aspect in product_definition_shape.HasShapeAspects:
|
2501
|
-
material_name = aspect.Name
|
2502
|
-
for representation in aspect.ShapeRepresentations:
|
2503
|
-
print(dir(representation))
|
2504
|
-
axis_placement = representation.Position
|
2505
|
-
location = axis_placement.Location
|
2506
|
-
ref_direction = axis_placement.RefDirection
|
2507
|
-
print("Location:", location)
|
2508
|
-
print("Direction", ref_direction)
|
2509
|
-
aspect_matrix = get_entity_transformation_matrix(representation)
|
2510
|
-
print("Aspect Matrix:", aspect_matrix)
|
2511
|
-
shape = ifcopenshell.geom.create_shape(settings, representation)
|
2512
|
-
verts = shape.verts
|
2513
|
-
edges = shape.edges
|
2514
|
-
faces = shape.faces
|
2515
|
-
grouped_verts = [ [verts[i], verts[i + 1], verts[i + 2]] for i in range(0, len(verts), 3)]
|
2516
|
-
grouped_verts = apply_transformation(grouped_verts, aspect_matrix)
|
2517
|
-
grouped_edges = [[edges[i], edges[i + 1]] for i in range(0, len(edges), 2)]
|
2518
|
-
grouped_faces = [ [faces[i], faces[i + 1], faces[i + 2]] for i in range(0, len(faces), 3)]
|
2519
|
-
topology = Topology.SelfMerge(Topology.ByGeometry(grouped_verts, grouped_edges, grouped_faces))
|
2520
|
-
#matrix = shape.transformation.matrix
|
2521
|
-
#topology = Topology.Transform(topology, matrix)
|
2522
|
-
d = get_material_ids_of_entity(wall)
|
2523
|
-
material_id = d.get(clean_key(material_name), 0)
|
2524
|
-
if transferDictionaries:
|
2525
|
-
keys = []
|
2526
|
-
values = []
|
2527
|
-
try:
|
2528
|
-
entity_name = entity.Name
|
2529
|
-
except:
|
2530
|
-
entity_name = entity.to_str()
|
2531
|
-
keys.append("TOPOLOGIC_id")
|
2532
|
-
values.append(str(uuid.uuid4()))
|
2533
|
-
keys.append("TOPOLOGIC_name")
|
2534
|
-
values.append(entity_name)
|
2535
|
-
keys.append("TOPOLOGIC_type")
|
2536
|
-
values.append(Topology.TypeAsString(topology))
|
2537
|
-
keys.append("IFC_id")
|
2538
|
-
values.append(str(aspect.id))
|
2539
|
-
#keys.append("IFC_guid")
|
2540
|
-
#values.append(str(aspect.guid))
|
2541
|
-
#keys.append("IFC_unique_id")
|
2542
|
-
#values.append(str(aspect.unique_id))
|
2543
|
-
keys.append("IFC_name")
|
2544
|
-
values.append(entity_name)
|
2545
|
-
#keys.append("IFC_type")
|
2546
|
-
#values.append(aspect.type)
|
2547
|
-
keys.append("IFC_material_id")
|
2548
|
-
values.append(material_id)
|
2549
|
-
keys.append("IFC_material_name")
|
2550
|
-
values.append(material_name)
|
2551
|
-
keys.append("TOPOLOGIC_color")
|
2552
|
-
color = generate_color_for_material(str(material_id))
|
2553
|
-
values.append(color)
|
2554
|
-
d = Dictionary.ByKeysValues(keys, values)
|
2555
|
-
topology = Topology.SetDictionary(topology, d)
|
2556
|
-
|
2557
|
-
return topology
|
2558
|
-
|
2559
|
-
|
2560
|
-
includeTypes = [s.lower() for s in includeTypes]
|
2561
|
-
excludeTypes = [s.lower() for s in excludeTypes]
|
2562
|
-
topologies = []
|
2563
|
-
settings = ifcopenshell.geom.settings()
|
2564
|
-
settings.set("dimensionality", ifcopenshell.ifcopenshell_wrapper.SOLID)
|
2565
|
-
settings.set(settings.USE_WORLD_COORDS, True)
|
2566
|
-
for entity in file.by_type('IfcProduct'): # You might want to refine the types you check
|
2567
|
-
if hasattr(entity, "Representation") and entity.Representation:
|
2568
|
-
print("Number of Representations:", len(entity.Representation.Representations))
|
2569
|
-
for rep in entity.Representation.Representations:
|
2570
|
-
print("Rep:", rep)
|
2571
|
-
print(dir(rep))
|
2572
|
-
matrix = get_entity_transformation_matrix(entity)
|
2573
|
-
print(matrix)
|
2574
|
-
if rep.is_a("IfcShapeRepresentation"):
|
2575
|
-
# Generate the geometry for this entity
|
2576
|
-
shape = ifcopenshell.geom.create_shape(settings, rep)
|
2577
|
-
verts = shape.verts
|
2578
|
-
edges = shape.edges
|
2579
|
-
faces = shape.faces
|
2580
|
-
grouped_verts = [ [verts[i], verts[i + 1], verts[i + 2]] for i in range(0, len(verts), 3)]
|
2581
|
-
#grouped_verts = apply_transformation(grouped_verts, matrix)
|
2582
|
-
grouped_edges = [[edges[i], edges[i + 1]] for i in range(0, len(edges), 2)]
|
2583
|
-
grouped_faces = [ [faces[i], faces[i + 1], faces[i + 2]] for i in range(0, len(faces), 3)]
|
2584
|
-
topology = Topology.SelfMerge(Topology.ByGeometry(grouped_verts, grouped_edges, grouped_faces))
|
2585
|
-
if removeCoplanarFaces:
|
2586
|
-
topology = Topology.RemoveCoplanarFaces(topology)
|
2587
|
-
if transferDictionaries:
|
2588
|
-
keys = []
|
2589
|
-
values = []
|
2590
|
-
keys.append("TOPOLOGIC_id")
|
2591
|
-
values.append(str(uuid.uuid4()))
|
2592
|
-
keys.append("TOPOLOGIC_name")
|
2593
|
-
values.append(shape.name)
|
2594
|
-
keys.append("TOPOLOGIC_type")
|
2595
|
-
values.append(Topology.TypeAsString(topology))
|
2596
|
-
keys.append("IFC_id")
|
2597
|
-
values.append(str(shape.id))
|
2598
|
-
keys.append("IFC_guid")
|
2599
|
-
values.append(str(shape.guid))
|
2600
|
-
keys.append("IFC_unique_id")
|
2601
|
-
values.append(str(shape.unique_id))
|
2602
|
-
keys.append("IFC_name")
|
2603
|
-
values.append(shape.name)
|
2604
|
-
keys.append("IFC_type")
|
2605
|
-
values.append(shape.type)
|
2606
|
-
material_dict = get_material_ids_of_entity(entity)
|
2607
|
-
keys.append("IFC_materials")
|
2608
|
-
values.append(material_dict)
|
2609
|
-
#keys.append("IFC_material_name")
|
2610
|
-
#values.append(material_name)
|
2611
|
-
#keys.append("TOPOLOGIC_color")
|
2612
|
-
#color = generate_color_for_material(str(material_ids))
|
2613
|
-
#values.append(color)
|
2614
|
-
d = Dictionary.ByKeysValues(keys, values)
|
2615
|
-
topology = Topology.SetDictionary(topology, d)
|
2616
|
-
topology = Topology.Transform(topology, matrix)
|
2617
|
-
topologies.append(topology)
|
2618
|
-
return topologies
|
2619
|
-
|
2620
2247
|
@staticmethod
|
2621
2248
|
def ByIFCPath(path, includeTypes=[], excludeTypes=[], transferDictionaries=False, removeCoplanarFaces=False, epsilon=0.0001, tolerance=0.0001):
|
2622
2249
|
"""
|
@@ -3006,6 +2633,7 @@ class Topology():
|
|
3006
2633
|
"""
|
3007
2634
|
from topologicpy.Vertex import Vertex
|
3008
2635
|
from topologicpy.Edge import Edge
|
2636
|
+
from topologicpy.Wire import Wire
|
3009
2637
|
from topologicpy.Face import Face
|
3010
2638
|
from topologicpy.Cell import Cell
|
3011
2639
|
from topologicpy.Cluster import Cluster
|
@@ -3017,19 +2645,19 @@ class Topology():
|
|
3017
2645
|
print("Topology.ByMeshData - Error: The input dictionary parameter is not a valid dictionary. Returning None.")
|
3018
2646
|
return None
|
3019
2647
|
|
3020
|
-
vertices = dictionary
|
3021
|
-
edges = dictionary
|
3022
|
-
faces = dictionary
|
3023
|
-
cells = dictionary
|
2648
|
+
vertices = dictionary.get('vertices', [])
|
2649
|
+
edges = dictionary.get('edges', [])
|
2650
|
+
faces = dictionary.get('faces', [])
|
2651
|
+
cells = dictionary.get('cells', [])
|
3024
2652
|
if not 'mode' in dictionary.keys():
|
3025
2653
|
mode = 0
|
3026
2654
|
else:
|
3027
|
-
mode = dictionary
|
2655
|
+
mode = dictionary.get('mode', 0)
|
3028
2656
|
if transferDictionaries == True:
|
3029
|
-
vertex_dicts = dictionary
|
3030
|
-
edge_dicts = dictionary
|
3031
|
-
face_dicts = dictionary
|
3032
|
-
cell_dicts = dictionary
|
2657
|
+
vertex_dicts = dictionary.get('vertex_dicts', [{}]*len(vertices))
|
2658
|
+
edge_dicts = dictionary.get('edge_dicts', [{}]*len(edges))
|
2659
|
+
face_dicts = dictionary. get('face_dicts', [{}]*len(faces))
|
2660
|
+
cell_dicts = dictionary.get('cell_dicts', [{}]*len(cells))
|
3033
2661
|
else:
|
3034
2662
|
vertex_dicts = [{}]*len(vertices)
|
3035
2663
|
edge_dicts = [{}]*len(edges)
|
@@ -3059,6 +2687,15 @@ class Topology():
|
|
3059
2687
|
if mode == 0:
|
3060
2688
|
face_vertices = [top_verts[v] for v in face]
|
3061
2689
|
top_face = Face.ByVertices(face_vertices, tolerance=tolerance, silent=silent)
|
2690
|
+
if not top_face:
|
2691
|
+
temp_wire = Wire.ByVertices(top_face, tolerance=tolerance, silent=silent)
|
2692
|
+
temp = Face.ByWire(temp_wire, tolerance=tolerance, silent=silent)
|
2693
|
+
if isinstance(temp, list):
|
2694
|
+
for temp_face in temp:
|
2695
|
+
if transferDictionaries:
|
2696
|
+
d = Dictionary.ByPythonDictionary(face_dicts[i])
|
2697
|
+
temp_face = Topology.SetDictionary(temp_face, d, silent=True)
|
2698
|
+
top_faces.append(temp_face)
|
3062
2699
|
else:
|
3063
2700
|
face_edges = [top_edges[e] for e in face]
|
3064
2701
|
top_face = Face.ByEdges(face_edges, tolerance=tolerance, silent=silent)
|
@@ -8260,13 +7897,13 @@ class Topology():
|
|
8260
7897
|
calframe = inspect.getouterframes(curframe, 2)
|
8261
7898
|
print('caller name:', calframe[1][3])
|
8262
7899
|
return topology
|
8263
|
-
if len(dictionary.Keys()) < 1:
|
8264
|
-
|
8265
|
-
|
8266
|
-
|
8267
|
-
|
8268
|
-
|
8269
|
-
|
7900
|
+
# if len(dictionary.Keys()) < 1:
|
7901
|
+
# if not silent:
|
7902
|
+
# print("Topology.SetDictionary - Warning: the input dictionary parameter is empty. Returning original input.")
|
7903
|
+
# curframe = inspect.currentframe()
|
7904
|
+
# calframe = inspect.getouterframes(curframe, 2)
|
7905
|
+
# print('caller name:', calframe[1][3])
|
7906
|
+
# return topology
|
8270
7907
|
_ = topology.SetDictionary(dictionary)
|
8271
7908
|
return topology
|
8272
7909
|
|
@@ -9122,6 +8759,9 @@ class Topology():
|
|
9122
8759
|
The desired number of sides. The default is 16.
|
9123
8760
|
tolerance : float , optional
|
9124
8761
|
The desired tolerance. The default is 0.0001.
|
8762
|
+
silent : bool , optional
|
8763
|
+
If set to True, no error and warning messages are printed. Otherwise, they are. The default is False.
|
8764
|
+
|
9125
8765
|
|
9126
8766
|
Returns
|
9127
8767
|
-------
|
@@ -9154,7 +8794,7 @@ class Topology():
|
|
9154
8794
|
topologies.append(tempTopology)
|
9155
8795
|
returnTopology = None
|
9156
8796
|
if Topology.Type(topology) == Topology.TypeID("Vertex"):
|
9157
|
-
returnTopology = Wire.ByVertices(topologies, False)
|
8797
|
+
returnTopology = Wire.ByVertices(topologies, close=False, tolerance=tolerance, silent=silent)
|
9158
8798
|
elif Topology.Type(topology) == Topology.TypeID("Edge"):
|
9159
8799
|
try:
|
9160
8800
|
returnTopology = Shell.ByWires(topologies,triangulate=triangulate, tolerance=tolerance, silent=True)
|
topologicpy/Vertex.py
CHANGED
@@ -726,7 +726,7 @@ class Vertex():
|
|
726
726
|
return None
|
727
727
|
|
728
728
|
@staticmethod
|
729
|
-
def
|
729
|
+
def EnclosingCells(vertex, topology, exclusive: bool = True, mantissa: int = 6, tolerance: float = 0.0001) -> list:
|
730
730
|
"""
|
731
731
|
Returns the list of Cells found in the input topology that enclose the input vertex.
|
732
732
|
|