From 8afb1b8b3032b54f1b607e9dc9d41f56fca453c5 Mon Sep 17 00:00:00 2001 From: Blender Defender Date: Tue, 30 Jul 2024 13:26:58 +0200 Subject: [PATCH] feat: Display float properties as string properties for more precision in the patch panel This change affects the following recipes: `OffsetObjectPlacements`, `OffsetStoreyElevations`, `SetFalseOrigin`, `SetRefElevation` and `SetWorldCoordinateSystem` --- .../recipes/OffsetObjectPlacements.py | 47 ++++++++++++++----- .../recipes/OffsetStoreyElevations.py | 8 ++-- .../ifcpatch/recipes/SetFalseOrigin.py | 33 ++++++------- .../ifcpatch/recipes/SetRefElevation.py | 8 ++-- .../recipes/SetWorldCoordinateSystem.py | 44 ++++++++++------- 5 files changed, 89 insertions(+), 51 deletions(-) diff --git a/src/ifcpatch/ifcpatch/recipes/OffsetObjectPlacements.py b/src/ifcpatch/ifcpatch/recipes/OffsetObjectPlacements.py index 8582aea6e5..55059e5283 100644 --- a/src/ifcpatch/ifcpatch/recipes/OffsetObjectPlacements.py +++ b/src/ifcpatch/ifcpatch/recipes/OffsetObjectPlacements.py @@ -20,10 +20,23 @@ import math import numpy as np import ifcopenshell import ifcopenshell.util.placement +import typing class Patcher: - def __init__(self, src, file, logger, x=None, y=None, z=None, should_rotate_first=True, ax=None, ay=None, az=None): + def __init__( + self, + src, + file, + logger, + x: typing.Union[str, float] = "0", + y: typing.Union[str, float] = "0", + z: typing.Union[str, float] = "0", + should_rotate_first: bool = True, + ax: typing.Optional[typing.Union[str, float]] = "", + ay: typing.Optional[typing.Union[str, float]] = "", + az: typing.Optional[typing.Union[str, float]] = "", + ): """Offset and rotate all object placements in a model Every physical object in an IFC model has an object placement, a @@ -41,11 +54,11 @@ class Patcher: entire IFC model. :param x: The X coordinate to offset by in project length units. - :type x: float + :type x: typing.Union[str, float] :param y: The Y coordinate to offset by in project length units. - :type y: float + :type y: typing.Union[str, float] :param z: The Z coordinate to offset by in project length units. - :type z: float + :type z: typing.Union[str, float] :param should_rotate_first: Whether or not to rotate first and then translate, or to first translate and rotate afterwards. Defaults to rotate first then translate. @@ -55,13 +68,13 @@ class Patcher: around the Z axis). If all angle parameters are specified, then it is treated as the angle to rotate around the X axis. Angles are in decimal degrees and positive is anticlockwise. - :type ax: float,optional + :type ax: typing.Union[str, float],optional :param ay: An optional angle to rotate by for 3D rotations along the Y axis. Angles are in decimal degrees and positive is anticlockwise. - :type ay: float,optional + :type ay: typing.Union[str, float],optional :param az: An optional angle to rotate by for 3D rotations along the Z axis. Angles are in decimal degrees and positive is anticlockwise. - :type az: float,optional + :type az: typing.Union[str, float],optional Example: @@ -79,13 +92,21 @@ class Patcher: self.src = src self.file = file self.logger = logger - self.x = x - self.y = y - self.z = z + self.x = float(x) + self.y = float(y) + self.z = float(z) self.should_rotate_first = should_rotate_first - self.ax = ax - self.ay = ay - self.az = az + self.ax = None + self.ay = None + self.az = None + + try: + self.ax = float(ax) + self.ay = float(ay) + self.az = float(az) + except Exception: + print("At least one input angle is not specified.") + if self.ax is None: self.angle_type = None elif self.ay is None: diff --git a/src/ifcpatch/ifcpatch/recipes/OffsetStoreyElevations.py b/src/ifcpatch/ifcpatch/recipes/OffsetStoreyElevations.py index 24cc9f6f00..5611b4a126 100644 --- a/src/ifcpatch/ifcpatch/recipes/OffsetStoreyElevations.py +++ b/src/ifcpatch/ifcpatch/recipes/OffsetStoreyElevations.py @@ -16,15 +16,17 @@ # You should have received a copy of the GNU Lesser General Public License # along with IfcPatch. If not, see . +import typing + class Patcher: - def __init__(self, src, file, logger, z=None): + def __init__(self, src, file, logger, z: typing.Union[str, float] = "0"): """Offset building storeys by a particular Z value All objects placed relative to the storeys will also be shifted. :param z: The Z value in project length units to offset storeys by. - :type z: float + :type z: typing.Union[str, float] Example: @@ -36,7 +38,7 @@ class Patcher: self.src = src self.file = file self.logger = logger - self.z = z + self.z = float(z) def patch(self): project = self.file.by_type("IfcProject")[0] diff --git a/src/ifcpatch/ifcpatch/recipes/SetFalseOrigin.py b/src/ifcpatch/ifcpatch/recipes/SetFalseOrigin.py index a67463a586..8657890418 100644 --- a/src/ifcpatch/ifcpatch/recipes/SetFalseOrigin.py +++ b/src/ifcpatch/ifcpatch/recipes/SetFalseOrigin.py @@ -19,6 +19,7 @@ import ifcopenshell import ifcopenshell.api.georeference from ifcpatch.recipes import OffsetObjectPlacements, SetWorldCoordinateSystem +import typing class Patcher: @@ -28,14 +29,14 @@ class Patcher: file, logger, name: str = "EPSG:1234", - x: float = 0, - y: float = 0, - z: float = 0, - e: float = 0, - n: float = 0, - h: float = 0, - gn_angle: float = 0, - rotate_angle: float = 0, + x: typing.Union[str, float] = "0", + y: typing.Union[str, float] = "0", + z: typing.Union[str, float] = "0", + e: typing.Union[str, float] = "0", + n: typing.Union[str, float] = "0", + h: typing.Union[str, float] = "0", + gn_angle: typing.Union[str, float] = "0", + rotate_angle: typing.Union[str, float] = "0", ): """Sets a false origin with a map conversion in a model @@ -62,14 +63,14 @@ class Patcher: self.file = file self.logger = logger self.name = name - self.x = x - self.y = y - self.z = z - self.e = e - self.n = n - self.h = h - self.gn_angle = gn_angle - self.rotate_angle = rotate_angle + self.x = float(x) + self.y = float(y) + self.z = float(z) + self.e = float(e) + self.n = float(n) + self.h = float(h) + self.gn_angle = float(gn_angle) + self.rotate_angle = float(rotate_angle) def patch(self): SetWorldCoordinateSystem.Patcher(self.src, self.file, self.logger, x=0, y=0, z=0, ax=0, ay=0, az=0).patch() diff --git a/src/ifcpatch/ifcpatch/recipes/SetRefElevation.py b/src/ifcpatch/ifcpatch/recipes/SetRefElevation.py index fc83f37ccf..cc1a092aff 100644 --- a/src/ifcpatch/ifcpatch/recipes/SetRefElevation.py +++ b/src/ifcpatch/ifcpatch/recipes/SetRefElevation.py @@ -16,9 +16,11 @@ # You should have received a copy of the GNU Lesser General Public License # along with IfcPatch. If not, see . +import typing + class Patcher: - def __init__(self, src, file, logger, elevation=0): + def __init__(self, src, file, logger, elevation: typing.Union[str, float] = "0"): """Sets the reference elevation of all IfcSites To completely reference model coordinates, a reference elevation should @@ -30,7 +32,7 @@ class Patcher: The reference elevation is simply a numerical attribute. :param elevation: The elevation to set. - :type elevation: float + :type elevation: typing.Union[str, float] Example: @@ -42,7 +44,7 @@ class Patcher: self.src = src self.file = file self.logger = logger - self.elevation = elevation + self.elevation = float(elevation) def patch(self): project = self.file.by_type("IfcProject")[0] diff --git a/src/ifcpatch/ifcpatch/recipes/SetWorldCoordinateSystem.py b/src/ifcpatch/ifcpatch/recipes/SetWorldCoordinateSystem.py index 33624ef169..ff8a4a4043 100644 --- a/src/ifcpatch/ifcpatch/recipes/SetWorldCoordinateSystem.py +++ b/src/ifcpatch/ifcpatch/recipes/SetWorldCoordinateSystem.py @@ -18,29 +18,41 @@ import math import numpy as np +import typing class Patcher: - def __init__(self, src, file, logger, x=None, y=None, z=None, ax=None, ay=None, az=None): + def __init__( + self, + src, + file, + logger, + x: typing.Union[str, float] = "0", + y: typing.Union[str, float] = "0", + z: typing.Union[str, float] = "0", + ax: typing.Union[str, float] = "0", + ay: typing.Union[str, float] = "0", + az: typing.Union[str, float] = "0", + ): """Sets the world coordinate system of the geometric representation context Sets the world coordinate system to whatever you want. :param x: The X coordinate. - :type x: float + :type x: typing.Union[str, float] :param y: The Y coordinate. - :type y: float + :type y: typing.Union[str, float] :param z: The Z coordinate. - :type z: float + :type z: typing.Union[str, float] :param ax: An angle to rotate by for 3D rotations along the X axis. Angles are in decimal degrees and positive is anticlockwise. - :type ax: float + :type ax: typing.Union[str, float] :param ay: An angle to rotate by for 3D rotations along the Y axis. Angles are in decimal degrees and positive is anticlockwise. - :type ay: float + :type ay: typing.Union[str, float] :param az: An angle to rotate by for 3D rotations along the Z axis. Angles are in decimal degrees and positive is anticlockwise. - :type az: float + :type az: typing.Union[str, float] Example: @@ -52,17 +64,17 @@ class Patcher: self.src = src self.file = file self.logger = logger - self.x = x - self.y = y - self.z = z - self.ax = ax - self.ay = ay - self.az = az + self.x = float(x) + self.y = float(y) + self.z = float(z) + self.ax = float(ax) + self.ay = float(ay) + self.az = float(az) def patch(self): rotate = self.identity_matrix() - for arg in (("x", float(self.ax)), ("y", float(self.ay)), ("z", float(self.az))): + for arg in (("x", self.ax), ("y", self.ay), ("z", self.az)): if arg[1]: rotate = getattr(self, f"{arg[0]}_rotation_matrix")(math.radians(arg[1]), rotate) @@ -74,13 +86,13 @@ class Patcher: for context in self.file.by_type("IfcGeometricRepresentationContext", include_subtypes=False): if context.ContextType == "Model": context.WorldCoordinateSystem = self.file.createIfcAxis2Placement3D( - self.file.createIfcCartesianPoint((float(self.x), float(self.y), float(self.z))), + self.file.createIfcCartesianPoint((self.x, self.y, self.z)), self.file.createIfcDirection(z.tolist()), self.file.createIfcDirection(x.tolist()), ) elif context.ContextType == "Plan": context.WorldCoordinateSystem = self.file.createIfcAxis2Placement2D( - self.file.createIfcCartesianPoint((float(self.x), float(self.y), float(self.z))), + self.file.createIfcCartesianPoint((self.x, self.y, self.z)), self.file.createIfcDirection(x.tolist()), )