Commit Graph

1 Commits

Author SHA1 Message Date
Gorgious56 f710929e9e ifcpatch Migrate: defensive IFC4/IFC4X3 -> IFC2X3 downgrade
The Migrate recipe previously crashed mid-loop with the cryptic
`RuntimeError: Entity with name '' not found in schema 'IFC2X3'` when
asked to downgrade an IFC4 or IFC4X3 file to IFC2X3 — the
class_4_to_2x3 mapping marks IFC4-only geometry / element classes with
an empty-string sentinel and the old code blindly forwarded that to
create_entity. Real files routinely contain IfcPolygonalFaceSet,
IfcTriangulatedFaceSet, IfcIndexedPolyCurve, IfcLamp, IfcPipeSegment,
IfcGeographicElement, etc.

The recipe now runs a preprocessing pipeline when the target is IFC2X3
and the source is IFC4 or IFC4X3:

- DowngradeIndexedPolyCurve flattens IfcIndexedPolyCurve to IfcPolyline
  for the whole file (arcs included — see below).
- IfcPolygonalFaceSet / IfcTriangulatedFaceSet are converted directly
  to IfcFacetedBrep at the entity level via
  ifcopenshell.util.shape_builder.polygonal_face_set_to_faceted_brep,
  preserving topology including IfcIndexedPolygonalFaceWithVoids inner
  bounds. IfcShapeRepresentation carriers have their RepresentationType
  tag updated from "Tessellation" to "Brep".
- Orphan source-only geometry instances (left over after the rewires)
  are purged iteratively via
  geometry_classes_introduced_after(target, source).

The Migrator is invoked with fallback_element_to_proxy=True so
IFC4-only IfcElement subclasses (IfcLamp, IfcPipeSegment,
IfcGeographicElement, ...) become IfcBuildingElementProxy in the
output. A post-pass encodes "<OriginalClass>/<PredefinedType>" into
ObjectType (e.g. "IfcLamp/COMPACTFLUORESCENT") when ObjectType is
empty, so the lost subclass identity survives the downgrade as
searchable text.

The migration loop now collects per-entity failures into a list rather
than crashing on the first; a summary RuntimeError fires at end if any
failed, naming up to 20 with their inverse references. Successful
migrations log a single count line via self.logger.

DowngradeIndexedPolyCurve extended:
- Arc segments (IfcArcIndex) are flattened via
  ifcopenshell.util.shape_builder.arc_to_polyline_points with
  ARC_SUBDIVISION=16 chord points per arc.
- Multi-index IfcLineIndex segments handled correctly.
- Absent Segments list (IFC4 polyline-through-all-coords case) handled.

Test coverage: 11 tests across the two recipes covering all four
preprocessing branches, the IFC4X3 source gate, the ObjectType
encoding (incl. author-supplied ObjectType preservation), the summary
RuntimeError shape, and the arc subdivision.

Generated with the assistance of an AI coding tool.
2026-06-23 09:33:03 +02:00