mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-09-18 14:31:39 +00:00
ExtractElements: handle IfcProject without RepresentationContexts #8199
The georeferencing fix (e6dc582) iterates IfcProject.RepresentationContexts
unconditionally, but the attribute is OPTIONAL and None on projects without
contexts, crashing every extraction on such files with
TypeError: 'NoneType' object is not iterable.
Also extend the #8199 regression test to assert element placements are
copied verbatim, so extraction can never bake map coordinates into local
placements.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
committed by
Thomas Krijnen
parent
bade0647e8
commit
49de7dbcb1
@@ -110,7 +110,7 @@ class Patcher(ifcpatch.BasePatcher):
|
|||||||
pass
|
pass
|
||||||
if element.is_a("IfcProject"):
|
if element.is_a("IfcProject"):
|
||||||
proj = self.new.add(element)
|
proj = self.new.add(element)
|
||||||
for ctx in element.RepresentationContexts:
|
for ctx in element.RepresentationContexts or ():
|
||||||
for coop in getattr(ctx, 'HasCoordinateOperation', ()):
|
for coop in getattr(ctx, 'HasCoordinateOperation', ()):
|
||||||
self.new.add(coop)
|
self.new.add(coop)
|
||||||
return proj
|
return proj
|
||||||
|
|||||||
@@ -21,10 +21,12 @@ import os
|
|||||||
import ifcopenshell
|
import ifcopenshell
|
||||||
import ifcopenshell.api.aggregate
|
import ifcopenshell.api.aggregate
|
||||||
import ifcopenshell.api.context
|
import ifcopenshell.api.context
|
||||||
|
import ifcopenshell.api.geometry
|
||||||
import ifcopenshell.api.georeference
|
import ifcopenshell.api.georeference
|
||||||
import ifcopenshell.api.root
|
import ifcopenshell.api.root
|
||||||
import ifcopenshell.api.spatial
|
import ifcopenshell.api.spatial
|
||||||
import ifcopenshell.util.element
|
import ifcopenshell.util.element
|
||||||
|
import numpy
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
import ifcpatch
|
import ifcpatch
|
||||||
@@ -96,7 +98,10 @@ class TestExtractElements(test.bootstrap.IFC4):
|
|||||||
self.file,
|
self.file,
|
||||||
coordinate_operation={"Eastings": 100000.0, "Northings": 200000.0},
|
coordinate_operation={"Eastings": 100000.0, "Northings": 200000.0},
|
||||||
)
|
)
|
||||||
ifcopenshell.api.root.create_entity(self.file, ifc_class="IfcWall")
|
wall = ifcopenshell.api.root.create_entity(self.file, ifc_class="IfcWall")
|
||||||
|
matrix = numpy.eye(4)
|
||||||
|
matrix[:3, 3] = [5.0, 10.0, 2.0]
|
||||||
|
ifcopenshell.api.geometry.edit_object_placement(self.file, product=wall, matrix=matrix)
|
||||||
|
|
||||||
output = ifcpatch.execute({"file": self.file, "recipe": "ExtractElements", "arguments": ["IfcWall"]})
|
output = ifcpatch.execute({"file": self.file, "recipe": "ExtractElements", "arguments": ["IfcWall"]})
|
||||||
|
|
||||||
@@ -105,6 +110,11 @@ class TestExtractElements(test.bootstrap.IFC4):
|
|||||||
conversion = output.by_type("IfcMapConversion")[0]
|
conversion = output.by_type("IfcMapConversion")[0]
|
||||||
assert conversion.Eastings == 100000.0
|
assert conversion.Eastings == 100000.0
|
||||||
assert conversion.Northings == 200000.0
|
assert conversion.Northings == 200000.0
|
||||||
|
# Placements must be copied verbatim: extraction must not bake map
|
||||||
|
# coordinates (or any other georeferencing transform) into the local
|
||||||
|
# placements of the extracted elements.
|
||||||
|
wall_new = output.by_type("IfcWall")[0]
|
||||||
|
assert wall_new.ObjectPlacement.RelativePlacement.Location.Coordinates == (5.0, 10.0, 2.0)
|
||||||
|
|
||||||
@pytest.mark.skipif(
|
@pytest.mark.skipif(
|
||||||
"IFC4X3" not in ifcopenshell.ifcopenshell_wrapper.schema_names(),
|
"IFC4X3" not in ifcopenshell.ifcopenshell_wrapper.schema_names(),
|
||||||
|
|||||||
Reference in New Issue
Block a user