topologicpy 0.8.29__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/BVH.py +5 -3
- topologicpy/CSG.py +1 -1
- topologicpy/Cell.py +12 -7
- topologicpy/Cluster.py +4 -2
- topologicpy/Edge.py +45 -28
- topologicpy/Face.py +65 -47
- topologicpy/Graph.py +149 -2
- topologicpy/Plotly.py +0 -1
- topologicpy/ShapeGrammar.py +65 -6
- topologicpy/Topology.py +130 -530
- topologicpy/Wire.py +33 -18
- topologicpy/version.py +1 -1
- {topologicpy-0.8.29.dist-info → topologicpy-0.8.31.dist-info}/METADATA +1 -1
- {topologicpy-0.8.29.dist-info → topologicpy-0.8.31.dist-info}/RECORD +17 -17
- {topologicpy-0.8.29.dist-info → topologicpy-0.8.31.dist-info}/WHEEL +1 -1
- {topologicpy-0.8.29.dist-info → topologicpy-0.8.31.dist-info}/licenses/LICENSE +0 -0
- {topologicpy-0.8.29.dist-info → topologicpy-0.8.31.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,29 +2116,29 @@ 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
|
-
def ByIFCFile(
|
2133
|
+
def ByIFCFile(ifc_file, includeTypes=[], excludeTypes=[], transferDictionaries=False,
|
2122
2134
|
removeCoplanarFaces=False,
|
2123
|
-
xMin: float = -0.5, yMin: float = -0.5, zMin: float = -0.5,
|
2124
|
-
xMax: float = 0.5, yMax: float = 0.5, zMax: float = 0.5,
|
2125
2135
|
epsilon=0.0001, tolerance=0.0001, silent=False):
|
2126
2136
|
"""
|
2127
2137
|
Create a topology by importing it from an IFC file.
|
2128
2138
|
|
2129
2139
|
Parameters
|
2130
2140
|
----------
|
2131
|
-
|
2141
|
+
ifc_file : file object
|
2132
2142
|
The input IFC file.
|
2133
2143
|
includeTypes : list , optional
|
2134
2144
|
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 [].
|
@@ -2138,18 +2148,6 @@ class Topology():
|
|
2138
2148
|
If set to True, the dictionaries from the IFC file will be transferred to the topology. Otherwise, they won't. The default is False.
|
2139
2149
|
removeCoplanarFaces : bool , optional
|
2140
2150
|
If set to True, coplanar faces are removed. Otherwise they are not. The default is False.
|
2141
|
-
xMin : float, optional
|
2142
|
-
The desired minimum value to assign for a vertex's X coordinate. The default is -0.5.
|
2143
|
-
yMin : float, optional
|
2144
|
-
The desired minimum value to assign for a vertex's Y coordinate. The default is -0.5.
|
2145
|
-
zMin : float, optional
|
2146
|
-
The desired minimum value to assign for a vertex's Z coordinate. The default is -0.5.
|
2147
|
-
xMax : float, optional
|
2148
|
-
The desired maximum value to assign for a vertex's X coordinate. The default is 0.5.
|
2149
|
-
yMax : float, optional
|
2150
|
-
The desired maximum value to assign for a vertex's Y coordinate. The default is 0.5.
|
2151
|
-
zMax : float, optional
|
2152
|
-
The desired maximum value to assign for a vertex's Z coordinate. The default is 0.5.
|
2153
2151
|
epsilon : float , optional
|
2154
2152
|
The desired epsilon (another form of tolerance) for finding if two faces are coplanar. The default is 0.01.
|
2155
2153
|
tolerance : float , optional
|
@@ -2162,503 +2160,88 @@ class Topology():
|
|
2162
2160
|
The created list of topologies.
|
2163
2161
|
|
2164
2162
|
"""
|
2163
|
+
import multiprocessing
|
2165
2164
|
import ifcopenshell
|
2166
2165
|
import ifcopenshell.geom
|
2167
|
-
from topologicpy.Vertex import Vertex
|
2168
|
-
from topologicpy.Wire import Wire
|
2169
2166
|
from topologicpy.Face import Face
|
2170
2167
|
from topologicpy.Cluster import Cluster
|
2171
2168
|
from topologicpy.Topology import Topology
|
2172
2169
|
from topologicpy.Dictionary import Dictionary
|
2173
|
-
|
2174
|
-
|
2175
|
-
|
2176
|
-
|
2177
|
-
|
2178
|
-
|
2179
|
-
|
2180
|
-
exclude = [t.lower() for t in excludeTypes]
|
2181
|
-
return (not include or is_a in include) and (is_a not in exclude)
|
2182
|
-
|
2183
|
-
with ThreadPoolExecutor() as executor:
|
2184
|
-
products = list(file.by_type("IfcProduct"))
|
2185
|
-
valid_entities = list(executor.map(lambda p: p if is_valid(p) else None, products))
|
2186
|
-
valid_entities = [e for e in valid_entities if e is not None]
|
2187
|
-
|
2170
|
+
|
2171
|
+
# 1 Guard against including and excluding the same types
|
2172
|
+
includeTypes = [s.lower() for s in includeTypes]
|
2173
|
+
excludeTypes = [s.lower() for s in excludeTypes]
|
2174
|
+
if len(includeTypes) > 0 and len(excludeTypes) > 0:
|
2175
|
+
excludeTypes = [s for s in excludeTypes if s not in includeTypes]
|
2176
|
+
# 2 Setup geometry settings
|
2188
2177
|
settings = ifcopenshell.geom.settings()
|
2189
2178
|
settings.set(settings.USE_WORLD_COORDS, True)
|
2179
|
+
# A string representation of the OCC representation
|
2180
|
+
settings.set("iterator-output", ifcopenshell.ifcopenshell_wrapper.NATIVE)
|
2181
|
+
# A string representation of the OCC representation
|
2190
2182
|
settings.set("iterator-output", ifcopenshell.ifcopenshell_wrapper.SERIALIZED)
|
2183
|
+
|
2184
|
+
# 3 Create iterator
|
2185
|
+
it = ifcopenshell.geom.iterator(settings, ifc_file, multiprocessing.cpu_count())
|
2186
|
+
if not it.initialize():
|
2187
|
+
if not silent:
|
2188
|
+
print("Topology.ByIFCFile")
|
2189
|
+
raise RuntimeError("Geometry iterator failed to initialize")
|
2191
2190
|
|
2191
|
+
# 4) Loop over shapes
|
2192
2192
|
topologies = []
|
2193
|
-
|
2194
|
-
|
2195
|
-
|
2196
|
-
|
2197
|
-
|
2198
|
-
if
|
2199
|
-
|
2200
|
-
topology = Topology.ByBREPString(
|
2201
|
-
|
2202
|
-
|
2203
|
-
|
2204
|
-
|
2193
|
+
|
2194
|
+
while True:
|
2195
|
+
shape = it.get()
|
2196
|
+
element = ifc_file.by_guid(shape.guid)
|
2197
|
+
element_type = element.is_a().lower()
|
2198
|
+
if ((element_type in includeTypes) or (len(includeTypes) == 0)) and ((not element_type in excludeTypes) or (len(excludeTypes) == 0)):
|
2199
|
+
geom = shape.geometry
|
2200
|
+
topology = Topology.ByBREPString(geom.brep_data)
|
2201
|
+
faces = Topology.Faces(topology)
|
2202
|
+
new_faces = []
|
2203
|
+
for face in faces:
|
2204
|
+
eb = Face.ExternalBoundary(face)
|
2205
|
+
ib = Face.InternalBoundaries(face)
|
2206
|
+
f = Face.ByWires(eb, ib)
|
2207
|
+
new_faces.append(f)
|
2208
|
+
topology = Topology.SelfMerge(Cluster.ByTopologies(new_faces))
|
2205
2209
|
if removeCoplanarFaces:
|
2206
2210
|
topology = Topology.RemoveCoplanarFaces(topology, epsilon=epsilon, tolerance=tolerance)
|
2207
|
-
|
2208
|
-
|
2209
|
-
|
2210
|
-
|
2211
|
-
|
2212
|
-
|
2213
|
-
|
2214
|
-
|
2215
|
-
|
2216
|
-
|
2217
|
-
|
2218
|
-
|
2219
|
-
|
2220
|
-
|
2221
|
-
|
2222
|
-
|
2223
|
-
|
2224
|
-
|
2225
|
-
|
2226
|
-
|
2227
|
-
|
2228
|
-
|
2229
|
-
|
2230
|
-
|
2231
|
-
|
2232
|
-
|
2233
|
-
|
2234
|
-
|
2235
|
-
psets[key] = props
|
2236
|
-
|
2237
|
-
final_dict = Dictionary.ByPythonDictionary(entity_dict)
|
2238
|
-
if psets:
|
2239
|
-
pset_dict = Dictionary.ByPythonDictionary(psets)
|
2240
|
-
final_dict = Dictionary.ByMergedDictionaries([final_dict, pset_dict])
|
2241
|
-
|
2242
|
-
topology = Topology.SetDictionary(topology, final_dict)
|
2243
|
-
|
2244
|
-
topologies.append(topology)
|
2245
|
-
|
2246
|
-
final_topologies = []
|
2247
|
-
for topology in topologies:
|
2248
|
-
faces = []
|
2249
|
-
|
2250
|
-
for w in Topology.Wires(topology):
|
2251
|
-
# Skip trivial wires (e.g. edges)
|
2252
|
-
if len(Topology.Vertices(w)) < 3:
|
2253
|
-
continue
|
2254
|
-
|
2255
|
-
# Only attempt face creation if the wire is closed
|
2256
|
-
if Wire.IsClosed(w) and Wire.IsManifold(w):
|
2257
|
-
f = Face.ByWire(w)
|
2258
|
-
if f:
|
2259
|
-
faces.append(f)
|
2260
|
-
continue
|
2261
|
-
|
2262
|
-
# fallback: keep wire
|
2263
|
-
faces.append(w)
|
2264
|
-
|
2265
|
-
# Avoid unnecessary Cluster/SelfMerge if there's only one face
|
2266
|
-
if len(faces) == 1:
|
2267
|
-
final_topology = faces[0]
|
2268
|
-
else:
|
2269
|
-
final_topology = Topology.SelfMerge(Cluster.ByTopologies(faces))
|
2270
|
-
if final_topology == None:
|
2271
|
-
final_topology = Cluster.ByTopologies(faces)
|
2272
|
-
if transferDictionaries:
|
2273
|
-
d = Topology.Dictionary(topology)
|
2274
|
-
final_topology = Topology.SetDictionary(final_topology, d)
|
2275
|
-
|
2276
|
-
final_topologies.append(final_topology)
|
2277
|
-
return final_topologies
|
2278
|
-
|
2279
|
-
@staticmethod
|
2280
|
-
def _ByIFCFile_old(file, includeTypes=[], excludeTypes=[], transferDictionaries=False, removeCoplanarFaces=False):
|
2281
|
-
"""
|
2282
|
-
Create a topology by importing it from an IFC file.
|
2283
|
-
|
2284
|
-
Parameters
|
2285
|
-
----------
|
2286
|
-
file : file object
|
2287
|
-
The input IFC file.
|
2288
|
-
includeTypes : list , optional
|
2289
|
-
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 [].
|
2290
|
-
excludeTypes : list , optional
|
2291
|
-
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 [].
|
2292
|
-
transferDictionaries : bool , optional
|
2293
|
-
If set to True, the dictionaries from the IFC file will be transferred to the topology. Otherwise, they won't. The default is False.
|
2294
|
-
removeCoplanarFaces : bool , optional
|
2295
|
-
If set to True, coplanar faces are removed. Otherwise they are not. The default is False.
|
2296
|
-
Returns
|
2297
|
-
-------
|
2298
|
-
list
|
2299
|
-
The created list of topologies.
|
2300
|
-
|
2301
|
-
"""
|
2302
|
-
import multiprocessing
|
2303
|
-
from topologicpy.Cluster import Cluster
|
2304
|
-
from topologicpy.Dictionary import Dictionary
|
2305
|
-
import uuid
|
2306
|
-
import random
|
2307
|
-
import hashlib
|
2308
|
-
import re
|
2309
|
-
import numpy as np
|
2310
|
-
|
2311
|
-
try:
|
2312
|
-
import ifcopenshell
|
2313
|
-
import ifcopenshell.geom
|
2314
|
-
except:
|
2315
|
-
print("Topology.ByIFCFile - Warning: Installing required ifcopenshell library.")
|
2316
|
-
try:
|
2317
|
-
os.system("pip install ifcopenshell")
|
2318
|
-
except:
|
2319
|
-
os.system("pip install ifcopenshell --user")
|
2320
|
-
try:
|
2321
|
-
import ifcopenshell
|
2322
|
-
import ifcopenshell.geom
|
2323
|
-
print("Topology.ByIFCFile - Warning: ifcopenshell library installed correctly.")
|
2324
|
-
except:
|
2325
|
-
warnings.warn("Topology.ByIFCFile - Error: Could not import ifcopenshell. Please try to install ifcopenshell manually. Returning None.")
|
2326
|
-
return None
|
2327
|
-
if not file:
|
2328
|
-
print("Topology.ByIFCFile - Error: the input file parameter is not a valid file. Returning None.")
|
2329
|
-
return None
|
2330
|
-
|
2331
|
-
def clean_key(string):
|
2332
|
-
# Replace any character that is not a letter, digit, or underscore with an underscore
|
2333
|
-
cleaned_string = re.sub(r'[^a-zA-Z0-9_]', '_', string)
|
2334
|
-
return cleaned_string
|
2335
|
-
|
2336
|
-
def transform_wall_vertices(wall):
|
2337
|
-
|
2338
|
-
# Relatives Placement abrufen und ausgeben
|
2339
|
-
if wall.ObjectPlacement and wall.ObjectPlacement.RelativePlacement:
|
2340
|
-
relative_placement = wall.ObjectPlacement.RelativePlacement
|
2341
|
-
if relative_placement.is_a('IFCAXIS2PLACEMENT3D'):
|
2342
|
-
location = relative_placement.Location
|
2343
|
-
ref_direction = relative_placement.RefDirection
|
2344
|
-
print("Relative Placement Location:", location.Coordinates)
|
2345
|
-
if ref_direction:
|
2346
|
-
print("Relative Placement RefDirection:", ref_direction.DirectionRatios)
|
2347
|
-
else:
|
2348
|
-
print("Relative Placement RefDirection: None")
|
2349
|
-
|
2350
|
-
# IFCPRODUCTDEFINITIONSHAPE der Wand abrufen
|
2351
|
-
product_definition_shape = wall.Representation
|
2352
|
-
if not product_definition_shape:
|
2353
|
-
print("Keine Repräsentation gefunden.")
|
2354
|
-
return
|
2355
|
-
|
2356
|
-
# Initialisieren von Variablen für Representation Type und Layer-Infos
|
2357
|
-
representation_type = None
|
2358
|
-
diverse_representation = False
|
2359
|
-
layer_details = []
|
2360
|
-
|
2361
|
-
if hasattr(product_definition_shape, 'HasShapeAspects'):
|
2362
|
-
for aspect in product_definition_shape.HasShapeAspects:
|
2363
|
-
for representation in aspect.ShapeRepresentations:
|
2364
|
-
if representation.is_a('IFCSHAPEREPRESENTATION'):
|
2365
|
-
for item in representation.Items:
|
2366
|
-
if item.is_a('IFCEXTRUDEDAREASOLID'):
|
2367
|
-
# Profilbeschreibung abrufen
|
2368
|
-
profile = item.SweptArea
|
2369
|
-
if profile.is_a('IFCARBITRARYCLOSEDPROFILEDEF'):
|
2370
|
-
if not representation_type:
|
2371
|
-
representation_type = "ArbitraryClosedProfil"
|
2372
|
-
elif representation_type != "ArbitraryClosedProfil":
|
2373
|
-
diverse_representation = True
|
2374
|
-
|
2375
|
-
# Profilpunkte abrufen
|
2376
|
-
if hasattr(profile, 'OuterCurve') and profile.OuterCurve.is_a('IFCINDEXEDPOLYCURVE'):
|
2377
|
-
indexed_polycurve = profile.OuterCurve
|
2378
|
-
if hasattr(indexed_polycurve, 'Points') and indexed_polycurve.Points.is_a('IFCCARTESIANPOINTLIST2D'):
|
2379
|
-
point_list_2d = indexed_polycurve.Points
|
2380
|
-
points = point_list_2d.CoordList
|
2381
|
-
layer_info["Profilpunkte"] = points
|
2382
|
-
else:
|
2383
|
-
diverse_representation = True
|
2384
|
-
|
2385
|
-
# Location und RefDirection abrufen
|
2386
|
-
if item.Position.is_a('IFCAXIS2PLACEMENT3D'):
|
2387
|
-
axis_placement = item.Position
|
2388
|
-
location = axis_placement.Location
|
2389
|
-
ref_direction = axis_placement.RefDirection
|
2390
|
-
layer_info["Location"] = location.Coordinates
|
2391
|
-
if ref_direction:
|
2392
|
-
layer_info["RefDirection"] = ref_direction.DirectionRatios
|
2393
|
-
else:
|
2394
|
-
layer_info["RefDirection"] = None
|
2395
|
-
|
2396
|
-
layer_details.append(layer_info)
|
2397
|
-
|
2398
|
-
# Representation Type ausgeben
|
2399
|
-
if diverse_representation:
|
2400
|
-
representation_type = "divers"
|
2401
|
-
print("Representation Type der Wand:", representation_type)
|
2402
|
-
|
2403
|
-
# Layer-Details ausgeben
|
2404
|
-
for index, layer in enumerate(layer_details):
|
2405
|
-
print(f"\nLayer {index + 1} Details:")
|
2406
|
-
print("Material:", layer.get("Material", "Nicht verfügbar"))
|
2407
|
-
print("Extrusionsstärke:", layer.get("Extrusionsstärke", "Nicht verfügbar"))
|
2408
|
-
print("Profilpunkte:", layer.get("Profilpunkte", "Nicht verfügbar"))
|
2409
|
-
print("Location:", layer.get("Location", "Nicht verfügbar"))
|
2410
|
-
print("RefDirection:", layer.get("RefDirection", "Nicht verfügbar"))
|
2411
|
-
|
2412
|
-
|
2413
|
-
|
2414
|
-
|
2415
|
-
|
2416
|
-
|
2417
|
-
def extract_matrix_from_placement(placement):
|
2418
|
-
"""Constructs a transformation matrix from an IFC Local Placement."""
|
2419
|
-
# Initialize identity matrix
|
2420
|
-
matrix = np.identity(4)
|
2421
|
-
|
2422
|
-
# Check if the placement is IfcLocalPlacement
|
2423
|
-
if placement.is_a("IfcLocalPlacement"):
|
2424
|
-
relative_placement = placement.RelativePlacement
|
2425
|
-
|
2426
|
-
if relative_placement.is_a("IfcAxis2Placement3D"):
|
2427
|
-
location = relative_placement.Location.Coordinates
|
2428
|
-
z_dir = relative_placement.Axis.DirectionRatios if relative_placement.Axis else [0, 0, 1]
|
2429
|
-
x_dir = relative_placement.RefDirection.DirectionRatios if relative_placement.RefDirection else [1, 0, 0]
|
2430
|
-
|
2431
|
-
# Compute y direction (cross product of z and x)
|
2432
|
-
y_dir = np.cross(z_dir, x_dir)
|
2211
|
+
if transferDictionaries:
|
2212
|
+
element_dict = {
|
2213
|
+
"TOPOLOGIC_id": str(Topology.UUID(topology)),
|
2214
|
+
"TOPOLOGIC_name": getattr(element, 'Name', "Untitled"),
|
2215
|
+
"TOPOLOGIC_type": Topology.TypeAsString(topology),
|
2216
|
+
"IFC_global_id": getattr(element, 'GlobalId', 0),
|
2217
|
+
"IFC_name": getattr(element, 'Name', "Untitled"),
|
2218
|
+
"IFC_type": element_type
|
2219
|
+
}
|
2220
|
+
|
2221
|
+
# Optionally add property sets
|
2222
|
+
psets = {}
|
2223
|
+
if hasattr(element, 'IsDefinedBy'):
|
2224
|
+
for rel in element.IsDefinedBy:
|
2225
|
+
if rel.is_a('IfcRelDefinesByProperties'):
|
2226
|
+
pdef = rel.RelatingPropertyDefinition
|
2227
|
+
if pdef and pdef.is_a('IfcPropertySet'):
|
2228
|
+
key = f"IFC_{pdef.Name}"
|
2229
|
+
props = {}
|
2230
|
+
for prop in pdef.HasProperties:
|
2231
|
+
if prop.is_a('IfcPropertySingleValue') and prop.NominalValue:
|
2232
|
+
props[f"IFC_{prop.Name}"] = prop.NominalValue.wrappedValue
|
2233
|
+
psets[key] = props
|
2234
|
+
|
2235
|
+
final_dict = Dictionary.ByPythonDictionary(element_dict)
|
2236
|
+
if psets:
|
2237
|
+
pset_dict = Dictionary.ByPythonDictionary(psets)
|
2238
|
+
final_dict = Dictionary.ByMergedDictionaries([final_dict, pset_dict])
|
2433
2239
|
|
2434
|
-
|
2435
|
-
|
2436
|
-
|
2437
|
-
|
2438
|
-
[x_dir[2], y_dir[2], z_dir[2], 0],
|
2439
|
-
[0, 0, 0, 1]
|
2440
|
-
])
|
2441
|
-
|
2442
|
-
# Translation vector
|
2443
|
-
translation_vector = np.array([
|
2444
|
-
[1, 0, 0, location[0]],
|
2445
|
-
[0, 1, 0, location[1]],
|
2446
|
-
[0, 0, 1, location[2]],
|
2447
|
-
[0, 0, 0, 1]
|
2448
|
-
])
|
2449
|
-
|
2450
|
-
# Combine the rotation matrix and the translation vector
|
2451
|
-
matrix = np.dot(translation_vector, rotation_matrix)
|
2452
|
-
|
2453
|
-
return matrix
|
2454
|
-
|
2455
|
-
def apply_transformation(verts, matrix):
|
2456
|
-
"""Applies a 4x4 transformation matrix to a list of vertices."""
|
2457
|
-
transformed_verts = []
|
2458
|
-
for vert in verts:
|
2459
|
-
print("vert:", vert)
|
2460
|
-
v = np.array([vert[0], vert[1], vert[2], 1.0])
|
2461
|
-
transformed_v = np.dot(matrix, v)
|
2462
|
-
transformed_verts.append([transformed_v[0], transformed_v[1], transformed_v[2]])
|
2463
|
-
return transformed_verts
|
2464
|
-
|
2465
|
-
def get_entity_transformation_matrix(entity):
|
2466
|
-
"""Extracts the transformation matrix from an IFC entity."""
|
2467
|
-
matrix = np.identity(4) # Default to an identity matrix
|
2468
|
-
if hasattr(entity, "ObjectPlacement") and entity.ObjectPlacement:
|
2469
|
-
placement = entity.ObjectPlacement
|
2470
|
-
matrix = extract_matrix_from_placement(placement)
|
2471
|
-
return matrix
|
2472
|
-
|
2473
|
-
# Function to generate a unique random color based on material ID
|
2474
|
-
def generate_color_for_material(material_id):
|
2475
|
-
# Use a hash function to get a consistent "random" seed
|
2476
|
-
hash_object = hashlib.sha1(material_id.encode())
|
2477
|
-
seed = int(hash_object.hexdigest(), 16) % (10 ** 8)
|
2478
|
-
random.seed(seed)
|
2479
|
-
# Generate a random color
|
2480
|
-
r = random.random()
|
2481
|
-
g = random.random()
|
2482
|
-
b = random.random()
|
2483
|
-
return [r, g, b]
|
2484
|
-
|
2485
|
-
# Function to get the material IDs associated with an entity
|
2486
|
-
def get_material_ids_of_entity(entity):
|
2487
|
-
return_dict = {}
|
2488
|
-
material_names = []
|
2489
|
-
material_ids = []
|
2490
|
-
if hasattr(entity, "HasAssociations"):
|
2491
|
-
for association in entity.HasAssociations:
|
2492
|
-
if association.is_a("IfcRelAssociatesMaterial"):
|
2493
|
-
material = association.RelatingMaterial
|
2494
|
-
try:
|
2495
|
-
material_name = material.Name
|
2496
|
-
except:
|
2497
|
-
material_name = material.to_string()
|
2498
|
-
if material.is_a("IfcMaterial"):
|
2499
|
-
material_ids.append(material.id())
|
2500
|
-
material_names.append(material_name)
|
2501
|
-
return_dict[clean_key(material_name)] = material.id
|
2502
|
-
elif material.is_a("IfcMaterialList"):
|
2503
|
-
for mat in material.Materials:
|
2504
|
-
material_ids.append(mat.id())
|
2505
|
-
try:
|
2506
|
-
material_name = mat.Name
|
2507
|
-
except:
|
2508
|
-
material_name = mat.to_string()
|
2509
|
-
material_names.append(material_name)
|
2510
|
-
return_dict[clean_key(material_name)] = mat.id
|
2511
|
-
elif material.is_a("IfcMaterialLayerSetUsage") or material.is_a("IfcMaterialLayerSet"):
|
2512
|
-
for layer in material.ForLayerSet.MaterialLayers:
|
2513
|
-
material_ids.append(layer.Material.id())
|
2514
|
-
try:
|
2515
|
-
material_name = layer.Name
|
2516
|
-
except:
|
2517
|
-
material_name = layer.to_string()
|
2518
|
-
material_names.append(material_name)
|
2519
|
-
return_dict[clean_key(material_name)] = layer.Material.id()
|
2520
|
-
elif material.is_a("IfcMaterialConstituentSet"):
|
2521
|
-
for constituent in material.MaterialConstituents:
|
2522
|
-
material_ids.append(constituent.Material.id())
|
2523
|
-
try:
|
2524
|
-
material_name = constituent.Material.Name
|
2525
|
-
except:
|
2526
|
-
material_name = constituent.Material.to_string()
|
2527
|
-
material_names.append(material_name)
|
2528
|
-
return_dict[clean_key(material_name)] = constituent.Material.id()
|
2529
|
-
|
2530
|
-
return return_dict
|
2531
|
-
|
2532
|
-
def get_wall_layers(wall, matrix=None, transferDictionaries=False):
|
2533
|
-
settings = ifcopenshell.geom.settings()
|
2534
|
-
settings.set("dimensionality", ifcopenshell.ifcopenshell_wrapper.CURVES_SURFACES_AND_SOLIDS)
|
2535
|
-
settings.set(settings.USE_WORLD_COORDS, False)
|
2536
|
-
|
2537
|
-
# IFCPRODUCTDEFINITIONSHAPE der Wand abrufen
|
2538
|
-
product_definition_shape = wall.Representation
|
2539
|
-
if not product_definition_shape:
|
2540
|
-
print("Topology.ByIFCFile - Error: The object has no representation. Returning None")
|
2541
|
-
return None
|
2240
|
+
topology = Topology.SetDictionary(topology, final_dict)
|
2241
|
+
topologies.append(topology)
|
2242
|
+
if not it.next():
|
2243
|
+
break
|
2542
2244
|
|
2543
|
-
if hasattr(product_definition_shape, 'HasShapeAspects'):
|
2544
|
-
for aspect in product_definition_shape.HasShapeAspects:
|
2545
|
-
material_name = aspect.Name
|
2546
|
-
for representation in aspect.ShapeRepresentations:
|
2547
|
-
print(dir(representation))
|
2548
|
-
axis_placement = representation.Position
|
2549
|
-
location = axis_placement.Location
|
2550
|
-
ref_direction = axis_placement.RefDirection
|
2551
|
-
print("Location:", location)
|
2552
|
-
print("Direction", ref_direction)
|
2553
|
-
aspect_matrix = get_entity_transformation_matrix(representation)
|
2554
|
-
print("Aspect Matrix:", aspect_matrix)
|
2555
|
-
shape = ifcopenshell.geom.create_shape(settings, representation)
|
2556
|
-
verts = shape.verts
|
2557
|
-
edges = shape.edges
|
2558
|
-
faces = shape.faces
|
2559
|
-
grouped_verts = [ [verts[i], verts[i + 1], verts[i + 2]] for i in range(0, len(verts), 3)]
|
2560
|
-
grouped_verts = apply_transformation(grouped_verts, aspect_matrix)
|
2561
|
-
grouped_edges = [[edges[i], edges[i + 1]] for i in range(0, len(edges), 2)]
|
2562
|
-
grouped_faces = [ [faces[i], faces[i + 1], faces[i + 2]] for i in range(0, len(faces), 3)]
|
2563
|
-
topology = Topology.SelfMerge(Topology.ByGeometry(grouped_verts, grouped_edges, grouped_faces))
|
2564
|
-
#matrix = shape.transformation.matrix
|
2565
|
-
#topology = Topology.Transform(topology, matrix)
|
2566
|
-
d = get_material_ids_of_entity(wall)
|
2567
|
-
material_id = d.get(clean_key(material_name), 0)
|
2568
|
-
if transferDictionaries:
|
2569
|
-
keys = []
|
2570
|
-
values = []
|
2571
|
-
try:
|
2572
|
-
entity_name = entity.Name
|
2573
|
-
except:
|
2574
|
-
entity_name = entity.to_str()
|
2575
|
-
keys.append("TOPOLOGIC_id")
|
2576
|
-
values.append(str(uuid.uuid4()))
|
2577
|
-
keys.append("TOPOLOGIC_name")
|
2578
|
-
values.append(entity_name)
|
2579
|
-
keys.append("TOPOLOGIC_type")
|
2580
|
-
values.append(Topology.TypeAsString(topology))
|
2581
|
-
keys.append("IFC_id")
|
2582
|
-
values.append(str(aspect.id))
|
2583
|
-
#keys.append("IFC_guid")
|
2584
|
-
#values.append(str(aspect.guid))
|
2585
|
-
#keys.append("IFC_unique_id")
|
2586
|
-
#values.append(str(aspect.unique_id))
|
2587
|
-
keys.append("IFC_name")
|
2588
|
-
values.append(entity_name)
|
2589
|
-
#keys.append("IFC_type")
|
2590
|
-
#values.append(aspect.type)
|
2591
|
-
keys.append("IFC_material_id")
|
2592
|
-
values.append(material_id)
|
2593
|
-
keys.append("IFC_material_name")
|
2594
|
-
values.append(material_name)
|
2595
|
-
keys.append("TOPOLOGIC_color")
|
2596
|
-
color = generate_color_for_material(str(material_id))
|
2597
|
-
values.append(color)
|
2598
|
-
d = Dictionary.ByKeysValues(keys, values)
|
2599
|
-
topology = Topology.SetDictionary(topology, d)
|
2600
|
-
|
2601
|
-
return topology
|
2602
|
-
|
2603
|
-
|
2604
|
-
includeTypes = [s.lower() for s in includeTypes]
|
2605
|
-
excludeTypes = [s.lower() for s in excludeTypes]
|
2606
|
-
topologies = []
|
2607
|
-
settings = ifcopenshell.geom.settings()
|
2608
|
-
settings.set("dimensionality", ifcopenshell.ifcopenshell_wrapper.SOLID)
|
2609
|
-
settings.set(settings.USE_WORLD_COORDS, True)
|
2610
|
-
for entity in file.by_type('IfcProduct'): # You might want to refine the types you check
|
2611
|
-
if hasattr(entity, "Representation") and entity.Representation:
|
2612
|
-
print("Number of Representations:", len(entity.Representation.Representations))
|
2613
|
-
for rep in entity.Representation.Representations:
|
2614
|
-
print("Rep:", rep)
|
2615
|
-
print(dir(rep))
|
2616
|
-
matrix = get_entity_transformation_matrix(entity)
|
2617
|
-
print(matrix)
|
2618
|
-
if rep.is_a("IfcShapeRepresentation"):
|
2619
|
-
# Generate the geometry for this entity
|
2620
|
-
shape = ifcopenshell.geom.create_shape(settings, rep)
|
2621
|
-
verts = shape.verts
|
2622
|
-
edges = shape.edges
|
2623
|
-
faces = shape.faces
|
2624
|
-
grouped_verts = [ [verts[i], verts[i + 1], verts[i + 2]] for i in range(0, len(verts), 3)]
|
2625
|
-
#grouped_verts = apply_transformation(grouped_verts, matrix)
|
2626
|
-
grouped_edges = [[edges[i], edges[i + 1]] for i in range(0, len(edges), 2)]
|
2627
|
-
grouped_faces = [ [faces[i], faces[i + 1], faces[i + 2]] for i in range(0, len(faces), 3)]
|
2628
|
-
topology = Topology.SelfMerge(Topology.ByGeometry(grouped_verts, grouped_edges, grouped_faces))
|
2629
|
-
if removeCoplanarFaces:
|
2630
|
-
topology = Topology.RemoveCoplanarFaces(topology)
|
2631
|
-
if transferDictionaries:
|
2632
|
-
keys = []
|
2633
|
-
values = []
|
2634
|
-
keys.append("TOPOLOGIC_id")
|
2635
|
-
values.append(str(uuid.uuid4()))
|
2636
|
-
keys.append("TOPOLOGIC_name")
|
2637
|
-
values.append(shape.name)
|
2638
|
-
keys.append("TOPOLOGIC_type")
|
2639
|
-
values.append(Topology.TypeAsString(topology))
|
2640
|
-
keys.append("IFC_id")
|
2641
|
-
values.append(str(shape.id))
|
2642
|
-
keys.append("IFC_guid")
|
2643
|
-
values.append(str(shape.guid))
|
2644
|
-
keys.append("IFC_unique_id")
|
2645
|
-
values.append(str(shape.unique_id))
|
2646
|
-
keys.append("IFC_name")
|
2647
|
-
values.append(shape.name)
|
2648
|
-
keys.append("IFC_type")
|
2649
|
-
values.append(shape.type)
|
2650
|
-
material_dict = get_material_ids_of_entity(entity)
|
2651
|
-
keys.append("IFC_materials")
|
2652
|
-
values.append(material_dict)
|
2653
|
-
#keys.append("IFC_material_name")
|
2654
|
-
#values.append(material_name)
|
2655
|
-
#keys.append("TOPOLOGIC_color")
|
2656
|
-
#color = generate_color_for_material(str(material_ids))
|
2657
|
-
#values.append(color)
|
2658
|
-
d = Dictionary.ByKeysValues(keys, values)
|
2659
|
-
topology = Topology.SetDictionary(topology, d)
|
2660
|
-
topology = Topology.Transform(topology, matrix)
|
2661
|
-
topologies.append(topology)
|
2662
2245
|
return topologies
|
2663
2246
|
|
2664
2247
|
@staticmethod
|
@@ -3050,6 +2633,7 @@ class Topology():
|
|
3050
2633
|
"""
|
3051
2634
|
from topologicpy.Vertex import Vertex
|
3052
2635
|
from topologicpy.Edge import Edge
|
2636
|
+
from topologicpy.Wire import Wire
|
3053
2637
|
from topologicpy.Face import Face
|
3054
2638
|
from topologicpy.Cell import Cell
|
3055
2639
|
from topologicpy.Cluster import Cluster
|
@@ -3061,19 +2645,19 @@ class Topology():
|
|
3061
2645
|
print("Topology.ByMeshData - Error: The input dictionary parameter is not a valid dictionary. Returning None.")
|
3062
2646
|
return None
|
3063
2647
|
|
3064
|
-
vertices = dictionary
|
3065
|
-
edges = dictionary
|
3066
|
-
faces = dictionary
|
3067
|
-
cells = dictionary
|
2648
|
+
vertices = dictionary.get('vertices', [])
|
2649
|
+
edges = dictionary.get('edges', [])
|
2650
|
+
faces = dictionary.get('faces', [])
|
2651
|
+
cells = dictionary.get('cells', [])
|
3068
2652
|
if not 'mode' in dictionary.keys():
|
3069
2653
|
mode = 0
|
3070
2654
|
else:
|
3071
|
-
mode = dictionary
|
2655
|
+
mode = dictionary.get('mode', 0)
|
3072
2656
|
if transferDictionaries == True:
|
3073
|
-
vertex_dicts = dictionary
|
3074
|
-
edge_dicts = dictionary
|
3075
|
-
face_dicts = dictionary
|
3076
|
-
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))
|
3077
2661
|
else:
|
3078
2662
|
vertex_dicts = [{}]*len(vertices)
|
3079
2663
|
edge_dicts = [{}]*len(edges)
|
@@ -3103,6 +2687,15 @@ class Topology():
|
|
3103
2687
|
if mode == 0:
|
3104
2688
|
face_vertices = [top_verts[v] for v in face]
|
3105
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)
|
3106
2699
|
else:
|
3107
2700
|
face_edges = [top_edges[e] for e in face]
|
3108
2701
|
top_face = Face.ByEdges(face_edges, tolerance=tolerance, silent=silent)
|
@@ -6590,15 +6183,19 @@ class Topology():
|
|
6590
6183
|
return False, None
|
6591
6184
|
# Done with Exclusion Tests.
|
6592
6185
|
|
6593
|
-
|
6594
|
-
|
6595
|
-
|
6596
|
-
largest_faces_a = Topology.LargestFaces(topologyA)
|
6597
|
-
largest_faces_b = Topology.LargestFaces(topologyB)
|
6186
|
+
if Topology.IsInstance(topologyA, "face"):
|
6187
|
+
largest_faces_a = [topologyA]
|
6188
|
+
largest_faces_b = [topologyB]
|
6598
6189
|
else:
|
6599
|
-
|
6600
|
-
|
6601
|
-
|
6190
|
+
faces_a = Topology.Faces(topologyA)
|
6191
|
+
faces_b = Topology.Faces(topologyB)
|
6192
|
+
if len(faces_a) > 0 and len(faces_b) > 0:
|
6193
|
+
largest_faces_a = Topology.LargestFaces(topologyA)
|
6194
|
+
largest_faces_b = Topology.LargestFaces(topologyB)
|
6195
|
+
else:
|
6196
|
+
if not silent:
|
6197
|
+
print("Topology.IsSimilar - Error: The topologies do not have faces. Returning None.")
|
6198
|
+
return False, None
|
6602
6199
|
|
6603
6200
|
# Process largest faces
|
6604
6201
|
for face_a in largest_faces_a:
|
@@ -9162,6 +8759,9 @@ class Topology():
|
|
9162
8759
|
The desired number of sides. The default is 16.
|
9163
8760
|
tolerance : float , optional
|
9164
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
|
+
|
9165
8765
|
|
9166
8766
|
Returns
|
9167
8767
|
-------
|
@@ -9194,7 +8794,7 @@ class Topology():
|
|
9194
8794
|
topologies.append(tempTopology)
|
9195
8795
|
returnTopology = None
|
9196
8796
|
if Topology.Type(topology) == Topology.TypeID("Vertex"):
|
9197
|
-
returnTopology = Wire.ByVertices(topologies, False)
|
8797
|
+
returnTopology = Wire.ByVertices(topologies, close=False, tolerance=tolerance, silent=silent)
|
9198
8798
|
elif Topology.Type(topology) == Topology.TypeID("Edge"):
|
9199
8799
|
try:
|
9200
8800
|
returnTopology = Shell.ByWires(topologies,triangulate=triangulate, tolerance=tolerance, silent=True)
|