Fix #3682. You can now tag setout points with dynamic xyz / enh values.

This commit is contained in:
Dion Moult
2023-09-07 13:47:54 +10:00
parent 7bca3bcac3
commit 9a34b94568
6 changed files with 209 additions and 137 deletions
@@ -75,6 +75,34 @@ def xyz2enh_ifc4x3(
return (eastings, northings, height)
def auto_xyz2enh(ifc_file, x, y, z):
try:
conversion = ifc_file.by_type("IfcMapConversion")
except:
return (x, y, z)
if not conversion:
return (x, y, z)
conversion = conversion[0]
e = conversion.Eastings or 0
n = conversion.Northings or 0
h = conversion.OrthogonalHeight or 0
xaa = conversion.XAxisAbscissa or 0
xao = conversion.XAxisOrdinate or 0
scale = conversion.Scale or 0
map_unit = conversion.TargetCRS.MapUnit
if map_unit:
# Warning! This definition has changed in IFC4X3 such that map_unit no
# longer affects unit conversion, only the Scale attribute affects unit
# conversion. TODO: consolidate once IFC4X3 confirmed.
project_unit = ifcopenshell.util.unit.get_project_unit(ifc_file, "LENGTHUNIT")
map_prefix = getattr(map_unit, "Prefix", None)
project_prefix = getattr(project_unit, "Prefix", None)
e = ifcopenshell.util.unit.convert(e, map_prefix, map_unit.Name, project_prefix, project_unit.Name)
n = ifcopenshell.util.unit.convert(n, map_prefix, map_unit.Name, project_prefix, project_unit.Name)
h = ifcopenshell.util.unit.convert(h, map_prefix, map_unit.Name, project_prefix, project_unit.Name)
return xyz2enh(x, y, z, e, n, h, xaa, xao, scale)
def auto_z2e(ifc_file, z):
"""Convert a Z coordinate to an elevation using model georeferencing data
@@ -22,6 +22,8 @@ import ifcopenshell.util
import ifcopenshell.util.fm
import ifcopenshell.util.unit
import ifcopenshell.util.element
import ifcopenshell.util.placement
import ifcopenshell.util.geolocation
import ifcopenshell.util.classification
@@ -293,6 +295,8 @@ def set_element_value(ifc_file, element, query, value):
return ifcopenshell.util.schema.reassign_class(ifc_file, element, value)
elif key == "id":
return
elif key in ("x", "y", "z", "easting", "northing", "elevation") and hasattr(element, "ObjectPlacement"):
return
elif isinstance(element, ifcopenshell.entity_instance):
if key == "Name" and element.is_a("IfcMaterialLayerSet"):
key = "LayerSetName" # This oddity in the IFC spec is annoying so we account for it.
@@ -818,6 +822,17 @@ class Selector:
value = ifcopenshell.util.element.get_predefined_type(value)
elif key == "id":
value = value.id()
elif key in ("x", "y", "z", "easting", "northing", "elevation") and hasattr(value, "ObjectPlacement"):
if getattr(value, "ObjectPlacement", None):
matrix = ifcopenshell.util.placement.get_local_placement(value.ObjectPlacement)
xyz = matrix[:,3][:3]
if key in ("x", "y", "z"):
value = xyz["xyz".index(key)]
else:
enh = ifcopenshell.util.geolocation.auto_xyz2enh(element.wrapped_data.file, *xyz)
value = enh[("easting", "northing", "elevation").index(key)]
else:
value = None
elif isinstance(value, ifcopenshell.entity_instance):
if key == "Name" and value.is_a("IfcMaterialLayerSet"):
key = "LayerSetName" # This oddity in the IFC spec is annoying so we account for it.