Files
IfcOpenShell/src/bonsai/test/tool/test_georeference.py
T
2025-06-09 18:03:19 +05:00

310 lines
13 KiB
Python

# Bonsai - OpenBIM Blender Add-on
# Copyright (C) 2021 Dion Moult <dion@thinkmoult.com>
#
# This file is part of Bonsai.
#
# Bonsai is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Bonsai 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 General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Bonsai. If not, see <http://www.gnu.org/licenses/>.
import bpy
import math
import ifcopenshell
import ifcopenshell.api
import ifcopenshell.api.context
import ifcopenshell.api.georeference
import ifcopenshell.api.root
import ifcopenshell.api.unit
import bonsai.core.tool
import bonsai.tool as tool
from mathutils import Vector
from test.bim.bootstrap import NewFile
from bonsai.tool.georeference import Georeference as subject
class TestImplementsTool(NewFile):
def test_run(self):
assert isinstance(subject(), bonsai.core.tool.Georeference)
class TestImportProjectedCRS(NewFile):
def test_importing_nothing_with_no_georeferencing(self):
ifc = ifcopenshell.file()
tool.Ifc.set(ifc)
ifcopenshell.api.root.create_entity(ifc, ifc_class="IfcProject")
ifcopenshell.api.context.add_context(ifc, context_type="Model")
subject.import_projected_crs()
props = tool.Georeference.get_georeference_props()
assert len(props.projected_crs) == 0
def test_importing_projected_crs(self):
ifc = ifcopenshell.file()
tool.Ifc.set(ifc)
ifcopenshell.api.root.create_entity(ifc, ifc_class="IfcProject")
ifcopenshell.api.context.add_context(ifc, context_type="Model")
ifcopenshell.api.georeference.add_georeferencing(ifc)
projected_crs = ifc.by_type("IfcProjectedCRS")[0]
projected_crs.Name = "Name"
projected_crs.Description = "Description"
projected_crs.GeodeticDatum = "GeodeticDatum"
projected_crs.VerticalDatum = "VerticalDatum"
projected_crs.MapProjection = "MapProjection"
projected_crs.MapZone = "MapZone"
unit = ifcopenshell.api.unit.add_si_unit(ifc, unit_type="LENGTHUNIT")
projected_crs.MapUnit = unit
subject.import_projected_crs()
props = tool.Georeference.get_georeference_props()
assert props.projected_crs["Name"].string_value == "Name"
assert props.projected_crs["Description"].string_value == "Description"
assert props.projected_crs["GeodeticDatum"].string_value == "GeodeticDatum"
assert props.projected_crs["VerticalDatum"].string_value == "VerticalDatum"
assert props.projected_crs["MapProjection"].string_value == "MapProjection"
assert props.projected_crs["MapZone"].string_value == "MapZone"
assert props.projected_crs["MapUnit"].enum_value == str(unit.id())
def test_run_ifc2x3(self):
ifc = ifcopenshell.file(schema="IFC2X3")
tool.Ifc.set(ifc)
subject.import_projected_crs()
props = tool.Georeference.get_georeference_props()
assert len(props.projected_crs) == 0
class TestImportCoordinateOperation(NewFile):
def test_importing_nothing_with_no_georeferencing(self):
ifc = ifcopenshell.file()
tool.Ifc.set(ifc)
ifcopenshell.api.root.create_entity(ifc, ifc_class="IfcProject")
ifcopenshell.api.context.add_context(ifc, context_type="Model")
subject.import_coordinate_operation()
props = tool.Georeference.get_georeference_props()
assert len(props.coordinate_operation) == 0
def test_importing_coordinate_operation(self):
ifc = ifcopenshell.file()
tool.Ifc.set(ifc)
ifcopenshell.api.root.create_entity(ifc, ifc_class="IfcProject")
ifcopenshell.api.context.add_context(ifc, context_type="Model")
ifcopenshell.api.georeference.add_georeferencing(ifc)
map_conversion = ifc.by_type("IfcMapConversion")[0]
map_conversion.Eastings = 1
map_conversion.Northings = 2
map_conversion.OrthogonalHeight = 3
map_conversion.XAxisAbscissa = 4
map_conversion.XAxisOrdinate = 5
map_conversion.Scale = 6
subject.import_coordinate_operation()
props = tool.Georeference.get_georeference_props()
assert props.coordinate_operation["Eastings"].string_value == "1.0"
assert props.coordinate_operation["Northings"].string_value == "2.0"
assert props.coordinate_operation["OrthogonalHeight"].string_value == "3.0"
assert props.x_axis_abscissa == "4.0"
assert props.x_axis_ordinate == "5.0"
assert props.grid_north_angle == "-51.3401917"
assert props.coordinate_operation["Scale"].string_value == "6.0"
def test_run_ifc2x3(self):
ifc = ifcopenshell.file(schema="IFC2X3")
tool.Ifc.set(ifc)
subject.import_coordinate_operation()
props = tool.Georeference.get_georeference_props()
assert len(props.coordinate_operation) == 0
class TestImportTrueNorth(NewFile):
def test_detecting_no_true_north(self):
ifc = ifcopenshell.file()
tool.Ifc.set(ifc)
ifcopenshell.api.root.create_entity(ifc, ifc_class="IfcProject")
ifcopenshell.api.context.add_context(ifc, context_type="Model")
subject.import_true_north()
props = tool.Georeference.get_georeference_props()
assert props.true_north_abscissa == "0"
assert props.true_north_ordinate == "1"
assert props.true_north_angle == "0"
def test_run(self):
ifc = ifcopenshell.file()
tool.Ifc.set(ifc)
ifcopenshell.api.root.create_entity(ifc, ifc_class="IfcProject")
context = ifcopenshell.api.context.add_context(ifc, context_type="Model")
context.TrueNorth = ifc.createIfcDirection((1.0, 2.0, 0.0))
subject.import_true_north()
props = tool.Georeference.get_georeference_props()
assert props.true_north_abscissa == "1.0"
assert props.true_north_ordinate == "2.0"
assert props.true_north_angle == "-26.5650512"
class TestExportProjectedCRS(NewFile):
def test_run(self):
TestImportProjectedCRS().test_importing_projected_crs()
assert subject.export_projected_crs() == {
"Name": "Name",
"Description": "Description",
"GeodeticDatum": "GeodeticDatum",
"VerticalDatum": "VerticalDatum",
"MapProjection": "MapProjection",
"MapZone": "MapZone",
"MapUnit": tool.Ifc.get().by_type("IfcNamedUnit")[0],
}
class TestExportCoordinateOperation(NewFile):
def test_run(self):
TestImportCoordinateOperation().test_importing_coordinate_operation()
assert subject.export_coordinate_operation() == {
"Eastings": 1.0,
"Northings": 2.0,
"OrthogonalHeight": 3.0,
"XAxisAbscissa": 4.0,
"XAxisOrdinate": 5.0,
"Scale": 6.0,
}
class TestGetTrueNorthAttributes(NewFile):
def test_run(self):
TestImportTrueNorth().test_run()
assert subject.get_true_north_attributes() == [1.0, 2.0]
class TestEnableEditing(NewFile):
def test_run(self):
props = tool.Georeference.get_georeference_props()
props.is_editing = False
subject.enable_editing()
assert props.is_editing is True
class TestDisableEditing(NewFile):
def test_run(self):
props = tool.Georeference.get_georeference_props()
props.is_editing = True
subject.disable_editing()
assert props.is_editing is False
class TestSetCoordinates(NewFile):
def test_run(self):
props = tool.Georeference.get_georeference_props()
subject.set_coordinates("local", [1.0, 2.0, 3.0])
assert props.local_coordinates == "1.0,2.0,3.0"
subject.set_coordinates("blender", [4.0, 5.0, 6.0])
assert props.blender_coordinates == "4.0,5.0,6.0"
subject.set_coordinates("map", [7.0, 8.0, 9.0])
assert props.map_coordinates == "7.0,8.0,9.0"
class TestGetCoordinates(NewFile):
def test_run(self):
props = tool.Georeference.get_georeference_props()
props.local_coordinates = "1.0,2.0,3.0"
assert subject.get_coordinates("local") == [1.0, 2.0, 3.0]
props.blender_coordinates = "4.0,5.0,6.0"
assert subject.get_coordinates("blender") == [4.0, 5.0, 6.0]
props.map_coordinates = "7.0,8.0,9.0"
assert subject.get_coordinates("map") == [7.0, 8.0, 9.0]
class TestGetCursorLocation(NewFile):
def test_run(self):
ifc = ifcopenshell.file()
tool.Ifc.set(ifc)
ifcopenshell.api.root.create_entity(ifc, ifc_class="IfcProject")
ifcopenshell.api.context.add_context(ifc, context_type="Model")
unit = ifcopenshell.api.unit.add_si_unit(ifc, unit_type="LENGTHUNIT", prefix="MILLI")
ifcopenshell.api.unit.assign_unit(ifc, units=[unit])
assert bpy.context.scene
bpy.context.scene.cursor.location = (1.0, 2.0, 3.0)
assert subject.get_cursor_location() == [1000.0, 2000.0, 3000.0]
class TestXyz2Enh(NewFile):
def test_run(self):
ifc = ifcopenshell.file()
ifcopenshell.api.root.create_entity(ifc, ifc_class="IfcProject")
tool.Ifc.set(ifc)
assert subject.xyz2enh((0.0, 0.0, 0.0)) == (0.0, 0.0, 0.0)
def test_using_the_blender_offset(self):
ifc = ifcopenshell.file()
ifcopenshell.api.root.create_entity(ifc, ifc_class="IfcProject")
tool.Ifc.set(ifc)
props = tool.Georeference.get_georeference_props()
props.has_blender_offset = True
props.blender_offset_x = "1.0"
assert subject.xyz2enh((0.0, 0.0, 0.0)) == (1.0, 0.0, 0.0)
def test_using_the_map_conversion(self):
ifc = ifcopenshell.file()
tool.Ifc.set(ifc)
ifcopenshell.api.root.create_entity(ifc, ifc_class="IfcProject")
ifcopenshell.api.context.add_context(ifc, context_type="Model")
ifcopenshell.api.georeference.add_georeferencing(ifc)
map_conversion = ifc.by_type("IfcMapConversion")[0]
map_conversion.Eastings = 1.0
assert subject.xyz2enh((0.0, 0.0, 0.0)) == (1.0, 0.0, 0.0)
def test_applying_both_blender_offset_and_map_conversion(self):
props = tool.Georeference.get_georeference_props()
props.has_blender_offset = True
props.blender_offset_x = "1.0"
ifc = ifcopenshell.file()
tool.Ifc.set(ifc)
ifcopenshell.api.root.create_entity(ifc, ifc_class="IfcProject")
ifcopenshell.api.context.add_context(ifc, context_type="Model")
ifcopenshell.api.georeference.add_georeferencing(ifc)
map_conversion = ifc.by_type("IfcMapConversion")[0]
map_conversion.Northings = 1.0
assert subject.xyz2enh((0.0, 0.0, 0.0)) == (1.0, 1.0, 0.0)
class TestEnh2Xyz(NewFile):
def test_run(self):
ifc = ifcopenshell.file()
ifcopenshell.api.root.create_entity(ifc, ifc_class="IfcProject")
tool.Ifc.set(ifc)
assert subject.enh2xyz((0.0, 0.0, 0.0)) == (0.0, 0.0, 0.0)
def test_using_the_blender_offset(self):
ifc = ifcopenshell.file()
ifcopenshell.api.root.create_entity(ifc, ifc_class="IfcProject")
tool.Ifc.set(ifc)
props = tool.Georeference.get_georeference_props()
props.has_blender_offset = True
props.blender_offset_x = "1.0"
assert subject.enh2xyz((0.0, 0.0, 0.0)) == (-1.0, 0.0, 0.0)
def test_using_the_map_conversion(self):
ifc = ifcopenshell.file()
tool.Ifc.set(ifc)
ifcopenshell.api.root.create_entity(ifc, ifc_class="IfcProject")
ifcopenshell.api.context.add_context(ifc, context_type="Model")
ifcopenshell.api.georeference.add_georeferencing(ifc)
map_conversion = ifc.by_type("IfcMapConversion")[0]
map_conversion.Eastings = 1.0
assert subject.enh2xyz((0.0, 0.0, 0.0)) == (-1.0, 0.0, 0.0)
def test_applying_both_blender_offset_and_map_conversion(self):
props = tool.Georeference.get_georeference_props()
props.has_blender_offset = True
props.blender_offset_x = "1.0"
ifc = ifcopenshell.file()
tool.Ifc.set(ifc)
ifcopenshell.api.root.create_entity(ifc, ifc_class="IfcProject")
ifcopenshell.api.context.add_context(ifc, context_type="Model")
ifcopenshell.api.georeference.add_georeferencing(ifc)
map_conversion = ifc.by_type("IfcMapConversion")[0]
map_conversion.Northings = 1.0
assert subject.enh2xyz((0.0, 0.0, 0.0)) == (-1.0, -1.0, 0.0)