/*---------------------------------------------------------------------------------------------
* Copyright (c) Bentley Systems, Incorporated. All rights reserved.
* See LICENSE.md in the project root for license terms and full copyright notice.
*--------------------------------------------------------------------------------------------*/
/** @packageDocumentation
 * @module Geometry
 */
// cspell:ignore Helmert
import { Angle, AxisIndex, Geometry, Matrix3d, Transform, Vector3d } from "@itwin/core-geometry";
/** An affine transformation with an additional Z Offset.
 *  The equations are:
 *  given a = scale * cos(rotation) and b = scale * sin(rotation)
 *  X = a * x - b * y + translationX
 *  Y = b * x + a * y + translationY
 *  Z = z + translationZ
 *
 *  Note that the class only implements the definition and not the operation.
 *  @public
 */
export class Helmert2DWithZOffset {
    /** The X post translation */
    translationX;
    /** The Y post-translation */
    translationY;
    /** The Z post-translation or Z offset*/
    translationZ;
    /** The rotation in the trigonometric (CCW) direction in degrees. */
    rotDeg;
    /** The scale. This scale applies to both X and Y axises. Does not apply to Z. */
    scale;
    constructor(data) {
        if (data) {
            this.translationX = data.translationX;
            this.translationY = data.translationY;
            this.translationZ = data.translationZ;
            this.rotDeg = data.rotDeg;
            this.scale = data.scale;
        }
    }
    /** Creates an Helmert Transform from JSON representation.
     * @public */
    static fromJSON(data) {
        return new Helmert2DWithZOffset(data);
    }
    /** Creates a JSON from the Helmert Transform definition
     * @public */
    toJSON() {
        return { translationX: this.translationX, translationY: this.translationY, translationZ: this.translationZ, rotDeg: this.rotDeg, scale: this.scale };
    }
    /** Compares two Helmert2DWithZOffset objects applying a minuscule tolerance.
     *  @public */
    equals(other) {
        return (Math.abs(this.translationX - other.translationX) < Geometry.smallMetricDistance &&
            Math.abs(this.translationY - other.translationY) < Geometry.smallMetricDistance &&
            Math.abs(this.translationZ - other.translationZ) < Geometry.smallMetricDistance &&
            Math.abs(this.rotDeg - other.rotDeg) < Geometry.smallAngleDegrees &&
            Math.abs(this.scale - other.scale) < Geometry.smallFraction);
    }
    /** Convert Helmert2DWithZOffset object into Transfrom object
     * @public */
    convertHelmertToTransform() {
        const rotationXY = Matrix3d.createRotationAroundAxisIndex(AxisIndex.Z, Angle.createDegrees(this?.rotDeg));
        rotationXY.scaleColumnsInPlace(this.scale, this.scale, 1.0);
        const translation = Vector3d.create(this.translationX, this.translationY, this.translationZ);
        const helmertTransform = Transform.createRefs(translation, rotationXY);
        return helmertTransform;
    }
}
/** Additional Transform implementation.
 *  An additional transform is a transformation that can apply to either the horizontal or vertical coordinates of a
 *  geographic CRS. The transformation is applied after the latitude/longitude have been projected thus the process
 *  is applied to the result Cartesian coordinates of the projection process.
 *  @public
*/
export class AdditionalTransform {
    /** The properties of a 2D Helmert transform with Z offset if one is defined. */
    helmert2DWithZOffset;
    constructor(data) {
        if (data)
            this.helmert2DWithZOffset = data.helmert2DWithZOffset ? Helmert2DWithZOffset.fromJSON(data.helmert2DWithZOffset) : undefined;
    }
    /** Creates an Additional Transform from JSON representation.
     * @public */
    static fromJSON(data) {
        return new AdditionalTransform(data);
    }
    /** Creates a JSON from the Additional Transform definition
     * @public */
    toJSON() {
        return { helmert2DWithZOffset: this.helmert2DWithZOffset };
    }
    /** Compares two additional transforms applying a minuscule tolerance to comparing numbers.
     *  @public */
    equals(other) {
        if ((this.helmert2DWithZOffset === undefined) !== (other.helmert2DWithZOffset === undefined))
            return false;
        // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
        if (this.helmert2DWithZOffset && !this.helmert2DWithZOffset.equals(other.helmert2DWithZOffset))
            return false;
        return true;
    }
}
//# sourceMappingURL=AdditionalTransform.js.map