Implement WCS consideration in XYZ <-> ENH conversions.

This commit is contained in:
Dion Moult
2024-06-24 18:20:07 +10:00
parent ac58e6b8b2
commit 7a36c05c30
6 changed files with 142 additions and 39 deletions
@@ -81,28 +81,32 @@ def edit_georeferencing(
if not (project := file.by_type("IfcProject")):
return
project = project[0]
if crs := ifcopenshell.util.element.get_pset(project, "ePSet_ProjectedCRS"):
crs = file.by_id(crs["id"])
for k, v in projected_crs.items():
if k == "Description":
v = file.createIfcText(v)
elif k == "Name":
v = file.createIfcLabel(v)
else:
v = file.createIfcIdentifier(v)
ifcopenshell.api.pset.edit_pset(file, crs, properties=projected_crs)
if conversion := ifcopenshell.util.element.get_pset(project, "ePSet_MapConversion"):
conversion = file.by_id(conversion["id"])
for k, v in coordinate_operation.items():
if k in ("XAxisAbscissa", "XAxisOrdinate", "Scale"):
v = file.createIfcReal(v)
else:
v = file.createIfcLengthMeasure(v)
ifcopenshell.api.pset.edit_pset(file, conversion, properties=coordinate_operation)
if projected_crs:
if crs := ifcopenshell.util.element.get_pset(project, "ePSet_ProjectedCRS"):
crs = file.by_id(crs["id"])
for k, v in projected_crs.items():
if k == "Description":
v = file.createIfcText(v)
elif k == "Name":
v = file.createIfcLabel(v)
else:
v = file.createIfcIdentifier(v)
ifcopenshell.api.pset.edit_pset(file, crs, properties=projected_crs)
if coordinate_operation:
if conversion := ifcopenshell.util.element.get_pset(project, "ePSet_MapConversion"):
conversion = file.by_id(conversion["id"])
for k, v in coordinate_operation.items():
if k in ("XAxisAbscissa", "XAxisOrdinate", "Scale"):
v = file.createIfcReal(v)
else:
v = file.createIfcLengthMeasure(v)
ifcopenshell.api.pset.edit_pset(file, conversion, properties=coordinate_operation)
return
conversion = file.by_type("IfcCoordinateOperation")[0]
crs = file.by_type("IfcProjectedCRS")[0]
for name, value in coordinate_operation.items():
setattr(conversion, name, value)
for name, value in projected_crs.items():
setattr(crs, name, value)
if projected_crs:
crs = file.by_type("IfcProjectedCRS")[0]
for name, value in projected_crs.items():
setattr(crs, name, value)
if coordinate_operation:
conversion = file.by_type("IfcCoordinateOperation")[0]
for name, value in coordinate_operation.items():
setattr(conversion, name, value)
@@ -50,26 +50,26 @@ def edit_true_north(file: ifcopenshell.file, true_north: Optional[Union[tuple[fl
# This unsets true north
ifcopenshell.api.run("georeference.edit_true_north", model, true_north=None)
"""
if not true_north:
return
if true_north is None:
pass
elif isinstance(true_north, (float, int)):
if isinstance(true_north, (float, int)):
x, y = ifcopenshell.util.geolocation.angle2yaxis(true_north)
else:
elif true_north is not None:
x, y = true_north
for context in file.by_type("IfcGeometricRepresentationContext", include_subtypes=False):
if context.TrueNorth and true_north is None:
old_true_north = context.TrueNorth
context.TrueNorth = None
if not file.get_total_inverses(old_true_north):
ifcopenshell.util.element.remove_deep2(file, old_true_north)
continue
if context.TrueNorth:
if file.get_total_inverses(context.TrueNorth) != 1:
context.TrueNorth = file.create_entity("IfcDirection")
else:
context.TrueNorth = file.create_entity("IfcDirection")
direction = context.TrueNorth
if true_north is None:
context.TrueNorth = None
elif context.CoordinateSpaceDimension == 2:
if context.CoordinateSpaceDimension == 2:
direction.DirectionRatios = (x, y)
else:
direction.DirectionRatios = (x, y, 0.0)
@@ -33,9 +33,19 @@ def edit_wcs(
) -> None:
"""Edits the WCS for all geometric contexts to a translation and rotation
It's recommended to leave the WCS at 0,0,0. You should generally not be
setting it to any value. Instead, your project's origin should use a
coordinate operation to convert to the projected CRS.
Typically, a project's local engineering origin (0, 0, 0) has a coordinate
operation (e.g. map conversion) to a projected CRS. If a WCS is provided,
the coordinate operation is relative to the WCS, not the local engineering
origin.
For example, if I have an IfcSite with a placement at (10, 0, 0) and a map
conversion of (50, 0, 0), my IfcSite's local XYZ is at (10, 0, 0) with an
ENH (Easting, Northing, Height) of (60, 0, 0).
If I then define by WCS at (15, 0, 0), my IfcSite's local XYZ is still at
(10, 0, 0) but its ENH is now at (45, 0, 0).
It's recommended to leave the WCS at 0,0,0. Please :)
:param x: The X translation of the WCS
:param y: The Y translation of the WCS