Fix add_georeferencing silently failing with orphan CRS or conversion

If a file had an IfcProjectedCRS without an IfcCoordinateOperation (or
vice versa), add_georeferencing would return early without creating the
missing entity. This caused edit_georeferencing to crash with IndexError.
Now detects the inconsistent state, cleans up, and recreates both.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Dion Moult
2026-03-25 14:57:10 +11:00
parent db68195310
commit 611273a20a
2 changed files with 31 additions and 1 deletions
@@ -51,6 +51,30 @@ class TestAddGeoreferencing(test.bootstrap.IFC4):
assert len(self.file.by_type("IfcMapConversion")) == 1
assert len(self.file.by_type("IfcProjectedCRS")) == 1
def test_recovering_from_orphan_projected_crs(self):
ifcopenshell.api.root.create_entity(self.file, ifc_class="IfcProject")
ifcopenshell.api.context.add_context(self.file, "Model")
self.file.create_entity("IfcProjectedCRS", Name="EPSG:1234")
assert len(self.file.by_type("IfcProjectedCRS")) == 1
assert len(self.file.by_type("IfcCoordinateOperation")) == 0
ifcopenshell.api.georeference.add_georeferencing(self.file)
assert len(self.file.by_type("IfcMapConversion")) == 1
assert len(self.file.by_type("IfcProjectedCRS")) == 1
def test_recovering_from_orphan_coordinate_operation(self):
ifcopenshell.api.root.create_entity(self.file, ifc_class="IfcProject")
context = ifcopenshell.api.context.add_context(self.file, "Model")
self.file.create_entity("IfcMapConversion", SourceCRS=context, TargetCRS=self.file.create_entity("IfcProjectedCRS", Name="EPSG:1234"))
ifcopenshell.api.georeference.remove_georeferencing(self.file)
# Simulate orphan by re-adding just a conversion without CRS
self.file.create_entity("IfcMapConversion", SourceCRS=context, TargetCRS=self.file.create_entity("IfcProjectedCRS", Name="EPSG:1234"))
self.file.remove(self.file.by_type("IfcProjectedCRS")[0])
assert len(self.file.by_type("IfcProjectedCRS")) == 0
assert len(self.file.by_type("IfcCoordinateOperation")) == 1
ifcopenshell.api.georeference.add_georeferencing(self.file)
assert len(self.file.by_type("IfcMapConversion")) == 1
assert len(self.file.by_type("IfcProjectedCRS")) == 1
class TestAddGeoreferencingIFC2X3(test.bootstrap.IFC2X3):
def test_adding_georeferencing(self):