mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-09-12 06:32:09 +00:00
Fix bugs in geocoding and geolocation MicroMVDs.
This commit is contained in:
@@ -1,14 +1,24 @@
|
|||||||
from behave import step
|
from behave import step
|
||||||
from utils import IfcFile, assert_attribute, assert_type
|
from utils import IfcFile, assert_attribute, assert_type
|
||||||
|
|
||||||
def check_geocode_attribute(guid, ifc_class, name, value):
|
|
||||||
|
def get_ifc_class_from_spatial_type(spatial_type):
|
||||||
|
if spatial_type == 'site':
|
||||||
|
return 'IfcSite'
|
||||||
|
elif spatial_type == 'building':
|
||||||
|
return 'IfcBuilding'
|
||||||
|
return 'IfcFacility'
|
||||||
|
|
||||||
|
|
||||||
|
def check_geocode_attribute(guid, spatial_type, name, value):
|
||||||
element = IfcFile.by_guid(guid)
|
element = IfcFile.by_guid(guid)
|
||||||
assert_type(element, ifc_class)
|
assert_type(element, get_ifc_class_from_spatial_type(spatial_type))
|
||||||
assert_attribute(element, name, value)
|
assert_attribute(element, name, value)
|
||||||
|
|
||||||
|
|
||||||
def check_geocode_address(guid, ifc_class, name, value):
|
def check_geocode_address(guid, spatial_type, name, value):
|
||||||
element = IfcFile.by_guid(guid)
|
element = IfcFile.by_guid(guid)
|
||||||
|
ifc_class = get_ifc_class_from_spatial_type(spatial_type)
|
||||||
assert_type(element, ifc_class)
|
assert_type(element, ifc_class)
|
||||||
if ifc_class == 'IfcSite':
|
if ifc_class == 'IfcSite':
|
||||||
address_name = 'SiteAddress'
|
address_name = 'SiteAddress'
|
||||||
@@ -20,50 +30,48 @@ def check_geocode_address(guid, ifc_class, name, value):
|
|||||||
|
|
||||||
use_step_matcher('re')
|
use_step_matcher('re')
|
||||||
@step('The (site|building|facility) (?P<guid>.*) has a name of (?P<name>.*)')
|
@step('The (site|building|facility) (?P<guid>.*) has a name of (?P<name>.*)')
|
||||||
def step_impl(context, _unused, guid, name):
|
def step_impl(context, spatial_type, guid, name):
|
||||||
check_geocode_attribute(guid, 'IfcSite', 'Name', name)
|
check_geocode_attribute(guid, spatial_type, 'Name', name)
|
||||||
|
|
||||||
|
|
||||||
@step('The (site|building|facility) (?P<guid>.*) has a description of (?P<description>.*)')
|
@step('The (site|building|facility) (?P<guid>.*) has a description of "(?P<description>.*)"')
|
||||||
def step_impl(context, _unused, guid, description):
|
def step_impl(context, spatial_type, guid, description):
|
||||||
check_geocode_attribute(guid, 'IfcSite', 'Description', description)
|
check_geocode_attribute(guid, spatial_type, 'Description', description)
|
||||||
|
|
||||||
|
|
||||||
@step('The (site|building) (?P<guid>.*) has a land title number of (?P<land_title_number>.*)')
|
|
||||||
def step_impl(context, _unused, guid, land_title_number):
|
|
||||||
check_geocode_attribute(guid, 'IfcSite', 'LandTitleNumber', land_title_number)
|
|
||||||
|
|
||||||
|
@step('The site (?P<guid>.*) has a land title number of (?P<land_title_number>.*)')
|
||||||
|
def step_impl(context, guid, land_title_number):
|
||||||
|
check_geocode_attribute(guid, 'site', 'LandTitleNumber', land_title_number)
|
||||||
|
|
||||||
@step('The (site|building) (?P<guid>.*) has the address "(?P<address_lines>.*)"')
|
@step('The (site|building) (?P<guid>.*) has the address "(?P<address_lines>.*)"')
|
||||||
def step_impl(context, _unused, guid, address_lines):
|
def step_impl(context, spatial_type, guid, address_lines):
|
||||||
check_geocode_address(guid, 'IfcSite', 'AddressLines', address_lines.split('\\n'))
|
check_geocode_address(guid, spatial_type, 'AddressLines', address_lines.split('\\n'))
|
||||||
|
|
||||||
|
|
||||||
@step('The (site|building) (?P<guid>.*) has a postal box of (?P<postal_box>.*)')
|
@step('The (site|building) (?P<guid>.*) has a postal box of (?P<postal_box>.*)')
|
||||||
def step_impl(context, _unused, guid, postal_box):
|
def step_impl(context, spatial_type, guid, postal_box):
|
||||||
check_geocode_address(guid, 'IfcSite', 'PostalBox', postal_box)
|
check_geocode_address(guid, spatial_type, 'PostalBox', postal_box)
|
||||||
|
|
||||||
|
|
||||||
@step('The (site|building) (?P<guid>.*) is in the town (?P<town>.*)')
|
@step('The (site|building) (?P<guid>.*) is in the town (?P<town>.*)')
|
||||||
def step_impl(context, _unused, guid, town):
|
def step_impl(context, spatial_type, guid, town):
|
||||||
check_geocode_address(guid, 'IfcSite', 'Town', town)
|
check_geocode_address(guid, spatial_type, 'Town', town)
|
||||||
|
|
||||||
|
|
||||||
@step('The (site|building) (?P<guid>.*) is in the region (?P<region>.*)')
|
@step('The (site|building) (?P<guid>.*) is in the region (?P<region>.*)')
|
||||||
def step_impl(context, _unused, guid, region):
|
def step_impl(context, spatial_type, guid, region):
|
||||||
check_geocode_address(guid, 'IfcSite', 'Region', region)
|
check_geocode_address(guid, spatial_type, 'Region', region)
|
||||||
|
|
||||||
|
|
||||||
@step('The (site|building) (?P<guid>.*) has a post code of (?P<post_code>.*)')
|
@step('The (site|building) (?P<guid>.*) has a post code of (?P<post_code>.*)')
|
||||||
def step_impl(context, _unused, guid, post_code):
|
def step_impl(context, spatial_type, guid, post_code):
|
||||||
check_geocode_address(guid, 'IfcSite', 'PostalCode', post_code)
|
check_geocode_address(guid, spatial_type, 'PostalCode', post_code)
|
||||||
|
|
||||||
|
|
||||||
@step('The (site|building) (?P<guid>.*) is in the country (?P<country>.*)')
|
@step('The (site|building) (?P<guid>.*) is in the country (?P<country>.*)')
|
||||||
def step_impl(context, _unused, guid, country):
|
def step_impl(context, spatial_type, guid, country):
|
||||||
check_geocode_address(guid, 'IfcSite', 'Country', country)
|
check_geocode_address(guid, spatial_type, 'Country', country)
|
||||||
|
|
||||||
|
|
||||||
@step('The (site|building) (?P<guid>.*) has an address description of (?P<description>.*)')
|
@step('The (site|building) (?P<guid>.*) has an address description of "(?P<description>.*)"')
|
||||||
def step_impl(context, _unused, guid, description):
|
def step_impl(context, spatial_type, guid, description):
|
||||||
check_geocode_address(guid, 'IfcSite', 'Description', description)
|
check_geocode_address(guid, spatial_type, 'Description', description)
|
||||||
|
|||||||
@@ -109,6 +109,8 @@ def step_impl(context, unit):
|
|||||||
assert_pset(site, 'EPset_ProjectedCRS', 'MapUnit', unit)
|
assert_pset(site, 'EPset_ProjectedCRS', 'MapUnit', unit)
|
||||||
return
|
return
|
||||||
actual_value = check_ifc4_geolocation('IfcProjectedCRS', 'MapUnit', should_assert=False)
|
actual_value = check_ifc4_geolocation('IfcProjectedCRS', 'MapUnit', should_assert=False)
|
||||||
|
if not actual_value:
|
||||||
|
assert False, 'A unit was not provided in the projected CRS'
|
||||||
if actual_value.is_a('IfcSIUnit'):
|
if actual_value.is_a('IfcSIUnit'):
|
||||||
prefix = actual_value.Prefix if actual_value.Prefix else ''
|
prefix = actual_value.Prefix if actual_value.Prefix else ''
|
||||||
actual_value = prefix + actual_value.Name
|
actual_value = prefix + actual_value.Name
|
||||||
@@ -162,7 +164,7 @@ def step_impl(context, number):
|
|||||||
return check_ifc2x3_geolocation('EPset_MapConversion', 'Height', number)
|
return check_ifc2x3_geolocation('EPset_MapConversion', 'Height', number)
|
||||||
abscissa = check_ifc4_geolocation('IfcMapConversion', 'XAxisAbscissa', should_assert=False)
|
abscissa = check_ifc4_geolocation('IfcMapConversion', 'XAxisAbscissa', should_assert=False)
|
||||||
ordinate = check_ifc4_geolocation('IfcMapConversion', 'XAxisOrdinate', should_assert=False)
|
ordinate = check_ifc4_geolocation('IfcMapConversion', 'XAxisOrdinate', should_assert=False)
|
||||||
actual_value = round(ifcopenshell.util.geolocation.xy2angle(abscissa, ordinate) * -1, 3)
|
actual_value = round(ifcopenshell.util.geolocation.xy2angle(abscissa, ordinate), 3)
|
||||||
value = round(number, 3)
|
value = round(number, 3)
|
||||||
assert actual_value == value, 'We expected a value of "{}" but instead got "{}"'.format(value, actual_value)
|
assert actual_value == value, 'We expected a value of "{}" but instead got "{}"'.format(value, actual_value)
|
||||||
|
|
||||||
@@ -183,7 +185,8 @@ def step_impl(context, guid, number):
|
|||||||
site = IfcFile.by_guid(guid)
|
site = IfcFile.by_guid(guid)
|
||||||
if not site.is_a('IfcSite'):
|
if not site.is_a('IfcSite'):
|
||||||
assert False, 'The element {} is not an IfcSite'.format(site)
|
assert False, 'The element {} is not an IfcSite'.format(site)
|
||||||
number = ifcopenshell.util.geolocation.dd2dms(number)
|
ref = assert_attribute(site, 'RefLongitude')
|
||||||
|
number = ifcopenshell.util.geolocation.dd2dms(number, use_ms=(len(ref) == 4))
|
||||||
assert_attribute(site, 'RefLongitude', number)
|
assert_attribute(site, 'RefLongitude', number)
|
||||||
|
|
||||||
|
|
||||||
@@ -193,7 +196,8 @@ def step_impl(context, guid, number):
|
|||||||
site = IfcFile.by_guid(guid)
|
site = IfcFile.by_guid(guid)
|
||||||
if not site.is_a('IfcSite'):
|
if not site.is_a('IfcSite'):
|
||||||
assert False, 'The element {} is not an IfcSite'.format(site)
|
assert False, 'The element {} is not an IfcSite'.format(site)
|
||||||
number = ifcopenshell.util.geolocation.dd2dms(number)
|
ref = assert_attribute(site, 'RefLatitude')
|
||||||
|
number = ifcopenshell.util.geolocation.dd2dms(number, use_ms=(len(ref) == 4))
|
||||||
assert_attribute(site, 'RefLatitude', number)
|
assert_attribute(site, 'RefLatitude', number)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ def assert_attribute(element, name, value=None):
|
|||||||
if not value:
|
if not value:
|
||||||
if getattr(element, name) is None:
|
if getattr(element, name) is None:
|
||||||
assert False, 'The element {} does not have a value for the attribute {}'.format(element, name)
|
assert False, 'The element {} does not have a value for the attribute {}'.format(element, name)
|
||||||
return
|
return getattr(element, name)
|
||||||
if value == 'NULL':
|
if value == 'NULL':
|
||||||
value = None
|
value = None
|
||||||
actual_value = getattr(element, name)
|
actual_value = getattr(element, name)
|
||||||
|
|||||||
@@ -1,17 +1,21 @@
|
|||||||
import math
|
import math
|
||||||
|
|
||||||
def dms2dd(degrees, minutes, seconds, milliseconds=0):
|
def dms2dd(degrees, minutes, seconds, ms=0):
|
||||||
dd = float(degrees) + float(minutes)/60.0 + float(seconds)/(3600.0) + float(milliseconds/3600000.0)
|
dd = float(degrees) + float(minutes)/60.0 + float(seconds)/(3600.0) + float(ms/3600000000.0)
|
||||||
return dd
|
return dd
|
||||||
|
|
||||||
def dd2dms(dd):
|
def dd2dms(dd, use_ms=False):
|
||||||
dd = float(dd)
|
dd = float(dd)
|
||||||
sign = 1 if dd >= 0 else -1
|
sign = 1 if dd >= 0 else -1
|
||||||
dd = abs(dd)
|
dd = abs(dd)
|
||||||
minutes, seconds = divmod(dd*3600, 60)
|
if use_ms:
|
||||||
|
seconds, ms = divmod(dd*60*60*1000000, 1000000)
|
||||||
|
minutes, seconds = divmod(dd*60*60, 60)
|
||||||
degrees, minutes = divmod(minutes, 60)
|
degrees, minutes = divmod(minutes, 60)
|
||||||
if dd < 0:
|
if dd < 0:
|
||||||
degrees = -degrees
|
degrees = -degrees
|
||||||
|
if use_ms:
|
||||||
|
return (int(degrees) * sign, int(minutes) * sign, int(seconds) * sign, int(ms) * sign)
|
||||||
return (int(degrees) * sign, int(minutes) * sign, int(seconds) * sign)
|
return (int(degrees) * sign, int(minutes) * sign, int(seconds) * sign)
|
||||||
|
|
||||||
def xyz2enh(x, y, z, eastings, northings, orthogonal_height, x_axis_abscissa, x_axis_ordinate, scale=None):
|
def xyz2enh(x, y, z, eastings, northings, orthogonal_height, x_axis_abscissa, x_axis_ordinate, scale=None):
|
||||||
|
|||||||
Reference in New Issue
Block a user