mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-13 19:07:57 +00:00
Add tests for IfcGridAxis fixes
- Add test_create_axis_curve.py with three unit tests: basic polyline creation, safe removal of an unshared existing curve, and preservation of a shared curve when only one referencing axis is updated (regression for the shallow-copy duplication bug) - Add feature scenario "Export IFC - with duplicate-of-duplicate grid axis locations preserved" to project.feature, reproducing the case where duplicates of duplicates lost their positions on save/reload
This commit is contained in:
@@ -920,6 +920,21 @@ Scenario: Export IFC - with moved grid axis location synchronised
|
||||
And I load previously saved IFC project
|
||||
Then the object "IfcGridAxis/01" bottom left corner is at "1,-2,0"
|
||||
|
||||
Scenario: Export IFC - with duplicate-of-duplicate grid axis locations preserved
|
||||
Given an empty IFC project
|
||||
And I press "bim.add_grid"
|
||||
And I set "scene.BIMGridProperties.is_locked" to "False"
|
||||
And the object "IfcGridAxis/01" is selected
|
||||
And I duplicate the selected objects
|
||||
And the object "IfcGridAxis/01.001" is moved to "1,0,0"
|
||||
And the object "IfcGridAxis/01.001" is selected
|
||||
And I duplicate the selected objects
|
||||
And the object "IfcGridAxis/01.002" is moved to "2,0,0"
|
||||
When I save IFC project
|
||||
And I load previously saved IFC project
|
||||
Then the object "IfcGridAxis/01.001" bottom left corner is at "1,-2,0"
|
||||
And the object "IfcGridAxis/01.002" bottom left corner is at "2,-2,0"
|
||||
|
||||
Scenario: Export IFC - with changed object scale ignored
|
||||
Given an empty IFC project
|
||||
And I add a cube
|
||||
|
||||
@@ -0,0 +1,88 @@
|
||||
# IfcOpenShell - IFC toolkit and geometry engine
|
||||
# Copyright (C) 2021 Dion Moult <dion@thinkmoult.com>
|
||||
#
|
||||
# This file is part of IfcOpenShell.
|
||||
#
|
||||
# IfcOpenShell is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# IfcOpenShell is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with IfcOpenShell. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import numpy as np
|
||||
|
||||
import ifcopenshell.api.grid
|
||||
import test.bootstrap
|
||||
|
||||
|
||||
class TestCreateAxisCurve(test.bootstrap.IFC4):
|
||||
def make_grid_with_axis(self, axis_tag="A"):
|
||||
grid = self.file.createIfcGrid()
|
||||
grid.ObjectPlacement = self.file.createIfcLocalPlacement(
|
||||
RelativePlacement=self.file.createIfcAxis2Placement3D(
|
||||
Location=self.file.createIfcCartesianPoint([0.0, 0.0, 0.0])
|
||||
)
|
||||
)
|
||||
axis = ifcopenshell.api.grid.create_grid_axis(
|
||||
self.file, axis_tag=axis_tag, same_sense=True, uvw_axes="UAxes", grid=grid
|
||||
)
|
||||
return grid, axis
|
||||
|
||||
def test_creates_a_polyline_axis_curve(self):
|
||||
_, axis = self.make_grid_with_axis()
|
||||
ifcopenshell.api.grid.create_axis_curve(
|
||||
self.file, p1=np.array([0.0, 0.0, 0.0]), p2=np.array([10.0, 0.0, 0.0]), grid_axis=axis
|
||||
)
|
||||
assert axis.AxisCurve is not None
|
||||
assert axis.AxisCurve.is_a("IfcPolyline")
|
||||
assert len(axis.AxisCurve.Points) == 2
|
||||
|
||||
def test_replaces_existing_curve_when_unshared(self):
|
||||
"""Calling create_axis_curve again on the same axis replaces the old curve
|
||||
and removes the old curve from the file when nothing else references it."""
|
||||
_, axis = self.make_grid_with_axis()
|
||||
ifcopenshell.api.grid.create_axis_curve(
|
||||
self.file, p1=np.array([0.0, 0.0, 0.0]), p2=np.array([10.0, 0.0, 0.0]), grid_axis=axis
|
||||
)
|
||||
old_curve_id = axis.AxisCurve.id()
|
||||
ifcopenshell.api.grid.create_axis_curve(
|
||||
self.file, p1=np.array([1.0, 0.0, 0.0]), p2=np.array([11.0, 0.0, 0.0]), grid_axis=axis
|
||||
)
|
||||
assert axis.AxisCurve.id() != old_curve_id
|
||||
assert self.file.by_id(old_curve_id) is None
|
||||
|
||||
def test_does_not_remove_shared_curve(self):
|
||||
"""When two axes share the same AxisCurve (e.g. after a shallow copy during
|
||||
duplication), updating one axis must not destroy the curve still referenced
|
||||
by the other axis."""
|
||||
grid, axis = self.make_grid_with_axis()
|
||||
axis2 = ifcopenshell.api.grid.create_grid_axis(
|
||||
self.file, axis_tag="B", same_sense=True, uvw_axes="UAxes", grid=grid
|
||||
)
|
||||
ifcopenshell.api.grid.create_axis_curve(
|
||||
self.file, p1=np.array([0.0, 0.0, 0.0]), p2=np.array([10.0, 0.0, 0.0]), grid_axis=axis
|
||||
)
|
||||
shared_curve = axis.AxisCurve
|
||||
shared_curve_id = shared_curve.id()
|
||||
# Simulate what copy_class produces: a duplicate axis that shares the
|
||||
# source's AxisCurve rather than having its own copy.
|
||||
axis2.AxisCurve = shared_curve
|
||||
assert self.file.get_total_inverses(shared_curve) == 2
|
||||
|
||||
# Updating axis1's curve must not remove the curve that axis2 still needs.
|
||||
ifcopenshell.api.grid.create_axis_curve(
|
||||
self.file, p1=np.array([1.0, 0.0, 0.0]), p2=np.array([11.0, 0.0, 0.0]), grid_axis=axis
|
||||
)
|
||||
assert axis2.AxisCurve.id() == shared_curve_id
|
||||
assert self.file.by_id(shared_curve_id) is not None
|
||||
|
||||
|
||||
class TestCreateAxisCurveIFC2X3(test.bootstrap.IFC2X3, TestCreateAxisCurve):
|
||||
pass
|
||||
Reference in New Issue
Block a user