topologicpy 0.8.30__py3-none-any.whl → 0.8.31__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/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
- print("Topology.ByDXFPath - Error: the input path parameter is not a valid path. Returning None.")
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
- print("Topology.ByDXFPath - Error: the input file parameter is not a valid file. Returning None.")
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['vertices']
3021
- edges = dictionary['edges']
3022
- faces = dictionary['faces']
3023
- cells = dictionary['cells']
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['mode']
2655
+ mode = dictionary.get('mode', 0)
3028
2656
  if transferDictionaries == True:
3029
- vertex_dicts = dictionary['vertex_dicts']
3030
- edge_dicts = dictionary['edge_dicts']
3031
- face_dicts = dictionary['face_dicts']
3032
- cell_dicts = dictionary['cell_dicts']
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)
@@ -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)