Skip to content

Commit edceeaf

Browse files
Krandeclaude
andcommitted
fix(convert): IFC->STEP falls back to OCC when native coverage is incomplete (audit regression)
The native .ifc->step registration overrode OCC with NO fallback, so audit IFC files with IfcExtrudedAreaSolid/CSG/tessellated geometry (or non-proxy elements) failed. native_ifc_to_step now raises on incomplete coverage (products_skipped>0 / faces_dropped>0 / 0 solids); _via_ifc_to_step catches it and uses the OCC writer (_via_ada_to_step). Verified on the IFC fixtures: advanced-brep -> native, swept/CSG/non-proxy -> OCC fallback, none fail (one fixture fails inside OCC itself = pre-existing). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
1 parent 8bb64a9 commit edceeaf

2 files changed

Lines changed: 22 additions & 9 deletions

File tree

src/ada/cadit/step/native_ifc_to_step.py

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,14 @@ def native_ifc_to_step(
4444
stats = adacpp.cad.stream_ifc_to_step(str(ifc_path), str(out_path), deflection=deflection, angular_deg=angular_deg)
4545
if not stats or stats.get("solids_out", 0) <= 0:
4646
raise RuntimeError(f"adacpp native stream_ifc_to_step produced no solids for {ifc_path}: {stats}")
47-
if stats.get("faces_dropped", 0) or stats.get("drop_reasons"):
48-
logger.warning("native IFC->STEP dropped geometry: %s", stats.get("drop_reasons"))
47+
# NO GEOMETRY LEFT BEHIND: the analytic reader only represents B-rep/analytic ng:: geometry. If any
48+
# product carried geometry it couldn't read (IfcExtrudedAreaSolid/CSG/tessellated -> products_skipped),
49+
# OR a face was dropped, the native output is INCOMPLETE — raise so the caller falls back to OCC.
50+
skipped = stats.get("products_skipped", 0)
51+
if skipped or stats.get("faces_dropped", 0) or stats.get("drop_reasons"):
52+
raise RuntimeError(
53+
f"native IFC->STEP incomplete for {ifc_path} (products_skipped={skipped}, "
54+
f"faces_dropped={stats.get('faces_dropped', 0)}, reasons={stats.get('drop_reasons')})"
55+
)
4956
logger.info("adacpp-native IFC->STEP: solids %s/%s -> %s", stats.get("solids_out"), stats.get("solids_in"), out_path)
5057
return stats

src/ada/comms/rest/converter.py

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1770,16 +1770,22 @@ def _via_ifc_to_step(
17701770
17711771
A native IFC advanced-B-rep reader (analytic surfaces/curves + IfcMappedItem instancing) builds
17721772
ng:: neutral geometry which the AP242 STEP emitter re-writes (instances baked). The declared length
1773-
unit is preserved. Raises (so the dispatcher can surface it) if the native verb is absent — the
1774-
generic OCC ifc→step path is the registry default in that case.
1773+
unit is preserved. Falls back to the OCC path (``_via_ada_to_step``) when the native reader can't
1774+
fully cover the file — IFC with IfcExtrudedAreaSolid / CSG / tessellated geometry, or any
1775+
product/face left behind — so no geometry is silently lost.
17751776
"""
1776-
from ada.cadit.step.native_ifc_to_step import native_ifc_to_step
1777+
from ada.cadit.step.native_ifc_to_step import native_ifc_to_step, native_ifc_to_step_available
17771778
from ada.config import logger
17781779

1779-
out_path = pathlib.Path(tempfile.mkstemp(suffix=".step")[1])
1780-
stats = native_ifc_to_step(src_path, out_path, on_progress=on_progress)
1781-
logger.info("native IFC->STEP: %s", stats)
1782-
return out_path
1780+
if native_ifc_to_step_available():
1781+
try:
1782+
out_path = pathlib.Path(tempfile.mkstemp(suffix=".step")[1])
1783+
stats = native_ifc_to_step(src_path, out_path, on_progress=on_progress)
1784+
logger.info("native IFC->STEP: %s", stats)
1785+
return out_path
1786+
except Exception as exc: # noqa: BLE001 - native can't cover this IFC; use the OCC writer
1787+
logger.info("native IFC->STEP unavailable/incomplete (%s); using OCC", exc)
1788+
return _via_ada_to_step(src_path, ".ifc", on_progress)
17831789

17841790

17851791
def _via_step_stream_to_ifc(

0 commit comments

Comments
 (0)