mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-09-27 10:51:13 +00:00
New utility functions for automatic local to global elevation conversions and easier unit conversions
This commit is contained in:
@@ -18,6 +18,8 @@
|
|||||||
|
|
||||||
import math
|
import math
|
||||||
import numpy as np
|
import numpy as np
|
||||||
|
import ifcopenshell
|
||||||
|
import ifcopenshell.util.unit
|
||||||
|
|
||||||
|
|
||||||
def dms2dd(degrees, minutes, seconds, ms=0):
|
def dms2dd(degrees, minutes, seconds, ms=0):
|
||||||
@@ -52,6 +54,45 @@ def xyz2enh(x, y, z, eastings, northings, orthogonal_height, x_axis_abscissa, x_
|
|||||||
return (eastings, northings, height)
|
return (eastings, northings, height)
|
||||||
|
|
||||||
|
|
||||||
|
def auto_z2e(ifc_file, z):
|
||||||
|
"""Convert a Z coordinate to an elevation using model georeferencing data
|
||||||
|
|
||||||
|
The necessary georeferencing map conversion is automatically detected from
|
||||||
|
the IFC map conversion parameters present in the IFC model. If no map
|
||||||
|
conversion is present, then the Z coordinate is returned unchanged.
|
||||||
|
|
||||||
|
:param ifc_file: The IFC file
|
||||||
|
:type ifc_file: ifcopenshell.file.file
|
||||||
|
:param z: The Z local engineering coordinate provided in project length units.
|
||||||
|
:type z: float
|
||||||
|
:return: The elevation in project length units.
|
||||||
|
:rtype: float
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
conversion = ifc_file.by_type("IfcMapConversion")
|
||||||
|
except:
|
||||||
|
return z
|
||||||
|
if not conversion or not conversion[0].OrthogonalHeight:
|
||||||
|
return z
|
||||||
|
conversion = conversion[0]
|
||||||
|
h = conversion.OrthogonalHeight
|
||||||
|
map_unit = conversion.TargetCRS.MapUnit
|
||||||
|
if map_unit:
|
||||||
|
project_unit = ifcopenshell.util.unit.get_project_unit(ifc_file, "LENGTHUNIT")
|
||||||
|
h = ifcopenshell.util.unit.convert(
|
||||||
|
h,
|
||||||
|
getattr(map_unit, "Prefix", None),
|
||||||
|
map_unit.Name,
|
||||||
|
getattr(project_unit, "Prefix", None),
|
||||||
|
project_unit.Name,
|
||||||
|
)
|
||||||
|
return z2e(z, h)
|
||||||
|
|
||||||
|
|
||||||
|
def z2e(z, h):
|
||||||
|
return z + h
|
||||||
|
|
||||||
|
|
||||||
def enh2xyz(e, n, h, eastings, northings, orthogonal_height, x_axis_abscissa, x_axis_ordinate, scale=None):
|
def enh2xyz(e, n, h, eastings, northings, orthogonal_height, x_axis_abscissa, x_axis_ordinate, scale=None):
|
||||||
if scale is None:
|
if scale is None:
|
||||||
scale = 1.0
|
scale = 1.0
|
||||||
|
|||||||
@@ -325,6 +325,25 @@ def get_unit_assignment(ifc_file):
|
|||||||
return unit_assignments[0]
|
return unit_assignments[0]
|
||||||
|
|
||||||
|
|
||||||
|
def get_project_unit(ifc_file, unit_type):
|
||||||
|
"""Get the default project unit of a particular unit type
|
||||||
|
|
||||||
|
:param ifc_file: The IFC file.
|
||||||
|
:type ifc_file: ifcopenshell.file.file
|
||||||
|
:param unit_type: The type of unit, taken from the list of IFC unit types,
|
||||||
|
such as "LENGTHUNIT".
|
||||||
|
:type unit_type: str
|
||||||
|
:return: The IFC unit entity, or nothing if there is no default project unit
|
||||||
|
defined.
|
||||||
|
:rtype: ifcopenshell.entity_instance,None
|
||||||
|
"""
|
||||||
|
unit_assignment = get_unit_assignment(ifc_file)
|
||||||
|
if unit_assignment:
|
||||||
|
for unit in unit_assignment.Units or []:
|
||||||
|
if getattr(unit, "UnitType", None) == unit_type:
|
||||||
|
return unit
|
||||||
|
|
||||||
|
|
||||||
def get_property_unit(prop, ifc_file):
|
def get_property_unit(prop, ifc_file):
|
||||||
unit = getattr(prop, "Unit", None)
|
unit = getattr(prop, "Unit", None)
|
||||||
if unit:
|
if unit:
|
||||||
@@ -431,19 +450,42 @@ def get_unit_symbol(unit):
|
|||||||
return "?"
|
return "?"
|
||||||
|
|
||||||
|
|
||||||
|
def convert_unit(value, from_unit, to_unit):
|
||||||
|
"""Convert from one unit to another unit
|
||||||
|
|
||||||
|
:param value: The numeric value you want to convert
|
||||||
|
:type value: float
|
||||||
|
:param from_unit: The IfcNamedUnit to confirm from.
|
||||||
|
:type from_unit: ifcopenshell.entity_instance.entity_instance
|
||||||
|
:param to_unit: The IfcNamedUnit to confirm from.
|
||||||
|
:type to_unit: ifcopenshell.entity_instance.entity_instance
|
||||||
|
:return: The converted value.
|
||||||
|
:rtype: float
|
||||||
|
"""
|
||||||
|
return convert(
|
||||||
|
value, getattr(from_unit, "Prefix", None), from_unit.Name, getattr(to_unit, "Prefix", None), to_unit.Name
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def convert(value, from_prefix, from_unit, to_prefix, to_unit):
|
def convert(value, from_prefix, from_unit, to_prefix, to_unit):
|
||||||
"""Converts between length, area, and volume units
|
"""Converts between length, area, and volume units
|
||||||
|
|
||||||
|
In this case, you manually specify the names and (optionally) prefixes to
|
||||||
|
convert to and from. In case you want to automatically convert to units
|
||||||
|
already available as IFC entities, consider using convert_unit() instead.
|
||||||
|
|
||||||
:param value: The numeric value you want to convert
|
:param value: The numeric value you want to convert
|
||||||
:type value: float
|
:type value: float
|
||||||
:param from_prefix: A prefix from IfcSIPrefix. Can be None.
|
:param from_prefix: A prefix from IfcSIPrefix. Can be None.
|
||||||
:type from_prefix: string
|
:type from_prefix: str,optional
|
||||||
:param from_unit: IfcSIUnitName or IfcConversionBasedUnit.Name
|
:param from_unit: IfcSIUnitName or IfcConversionBasedUnit.Name
|
||||||
:type from_unit: string
|
:type from_unit: str
|
||||||
:param to_prefix: A prefix from IfcSIPrefix. Can be None.
|
:param to_prefix: A prefix from IfcSIPrefix. Can be None.
|
||||||
:type to_prefix: string
|
:type to_prefix: str,optional
|
||||||
:param to_unit: IfcSIUnitName or IfcConversionBasedUnit.Name
|
:param to_unit: IfcSIUnitName or IfcConversionBasedUnit.Name
|
||||||
:type to_unit: string
|
:type to_unit: str
|
||||||
|
:return: The converted value.
|
||||||
|
:rtype: float
|
||||||
"""
|
"""
|
||||||
if from_unit in si_conversions:
|
if from_unit in si_conversions:
|
||||||
value *= si_conversions[from_unit]
|
value *= si_conversions[from_unit]
|
||||||
|
|||||||
Reference in New Issue
Block a user