2 Commits

Author SHA1 Message Date
Jonathon Broughton fac5601b35 Validate face indices without exception control flow 2026-03-20 17:22:27 +00:00
NLSA cde3a58b08 Update README with project status and contact info
Added project status section indicating active development.
2026-03-20 16:59:27 +01:00
2 changed files with 43 additions and 26 deletions
+4
View File
@@ -1,5 +1,9 @@
# Speckle-Revit to IFC 4.3 Exporter
## 🚧 Project Status: WIP
Hey there! This project is still under active development, so expect changes, bugs, and incomplete features.
If you have any questions or suggestions, dont hesitate to reach out at: **your@email.com**
A [Speckle Automate](https://automate.speckle.dev/) function that converts Speckle Revit models into IFC 4.3 files using [ifcopenshell](https://ifcopenshell.org/). This exporter is specifically designed for models sent to Speckle from Autodesk Revit and relies on Revit-specific object structures, categories, and parameters.
## What It Does
+39 -26
View File
@@ -55,34 +55,47 @@ def build_ifc_facesets(ifc, verts_scaled: list, face_groups: list) -> list:
# Validate faces and remap indices to deduplicated vertex list
valid_faces = [] # list of (idx0+1, idx1+1, ...) tuples (1-based for IFC)
vert_len = len(verts_scaled)
for indices in face_groups:
try:
remapped = []
seen_snaps = set()
degenerate = False
for i in indices:
i3 = i * 3
x = verts_scaled[i3]
y = verts_scaled[i3 + 1]
z = verts_scaled[i3 + 2]
key = (round(x * inv_tol), round(y * inv_tol), round(z * inv_tol))
if key in seen_snaps:
degenerate = True
break
seen_snaps.add(key)
idx = snap_to_idx.get(key)
if idx is None:
idx = len(deduped_verts)
snap_to_idx[key] = idx
deduped_verts.append([x, y, z])
remapped.append(idx + 1) # 1-based for IFC
if degenerate or len(remapped) < 3:
continue
valid_faces.append(remapped)
except Exception:
if indices is None:
continue
if not isinstance(indices, (list, tuple)):
continue
remapped = []
seen_snaps = set()
degenerate = False
invalid = False
for i in indices:
if not isinstance(i, int):
invalid = True
break
i3 = i * 3
if i3 < 0 or i3 + 2 >= vert_len:
invalid = True
break
x = verts_scaled[i3]
y = verts_scaled[i3 + 1]
z = verts_scaled[i3 + 2]
key = (round(x * inv_tol), round(y * inv_tol), round(z * inv_tol))
if key in seen_snaps:
degenerate = True
break
seen_snaps.add(key)
idx = snap_to_idx.get(key)
if idx is None:
idx = len(deduped_verts)
snap_to_idx[key] = idx
deduped_verts.append([x, y, z])
remapped.append(idx + 1) # 1-based for IFC
if invalid or degenerate or len(remapped) < 3:
continue
valid_faces.append(remapped)
if not valid_faces or not deduped_verts:
return []