/*---------------------------------------------------------------------------------------------
* Copyright (c) Bentley Systems, Incorporated. All rights reserved.
* See LICENSE.md in the project root for license terms and full copyright notice.
*--------------------------------------------------------------------------------------------*/
/** @packageDocumentation
 * @module Views
 */
import { assert } from "@itwin/core-bentley";
import { Matrix3d, Point3d, Vector3d } from "@itwin/core-geometry";
import { ViewState2d, ViewState3d } from "./ViewState";
/** The "pose" for a [View]($docs/learning/frontend/views#viewstate-parameters) describing the viewed area or volume, depending upon whether
 * the view is 2d or 3d.
 * @see [[ViewState.savePose]] to extract a pose from a view and [[ViewState.applyPose]] to apply a pose to a view.
 * @note a ViewPose is immutable.
 * @public
 * @extensions
 */
export class ViewPose {
    /** The time at which this pose was created, if it was saved into a [[Viewport]]'s undo stack. */
    undoTime;
    /** True if the camera is enabled.
     * @see [[ViewPose3d.camera]] to access the camera.
     */
    cameraOn;
    /** Computes the center of the viewed volume. */
    get center() {
        const delta = this.rotation.multiplyTransposeVector(this.extents);
        return this.origin.plusScaled(delta, 0.5);
    }
    /** Returns the target point of the view. This is the same as [[center]] unless [[cameraOn]] is `true`. */
    get target() { return this.center; }
    /** Computes the Z vector of the [[rotation]] matrix. */
    get zVec() { return this.rotation.getRow(2); }
    constructor(cameraOn) {
        this.cameraOn = cameraOn;
    }
}
/** The "pose" for a [[ViewState3d]], including information about the view's [Camera]($common) if it is enabled.
 * @public
 * @extensions
 */
export class ViewPose3d extends ViewPose {
    /** See [[ViewPose.origin]]. */
    origin;
    /** See [[ViewPose.extents]]. */
    extents;
    /** See [[ViewPose.rotation]]. */
    rotation;
    /** The camera parameters of the view.
     * @note This object is meaningful only if [[ViewPose.cameraOn]] is `true`.
     */
    camera;
    /** Construct a pose from the specified 3d view. */
    constructor(view) {
        super(view.isCameraOn);
        this.origin = view.origin.clone();
        this.extents = view.extents.clone();
        this.rotation = view.rotation.clone();
        this.camera = view.camera.clone();
    }
    /** See [[ViewPose.target]]. */
    get target() {
        return this.cameraOn ? this.camera.eye.plusScaled(this.rotation.getRow(2), -1.0 * this.camera.focusDist) : this.center;
    }
    /** See [[ViewPose.equal]]. */
    equal(other) {
        if (!(other instanceof ViewPose3d))
            return false;
        return this.cameraOn === other.cameraOn &&
            this.origin.isAlmostEqual(other.origin) &&
            this.extents.isAlmostEqual(other.extents) &&
            this.rotation.isAlmostEqual(other.rotation) &&
            (!this.cameraOn || this.camera.equals(other.camera));
    }
    /** See [[ViewPose.equalState]]. */
    equalState(view) {
        if (!(view instanceof ViewState3d))
            return false;
        return this.cameraOn === view.isCameraOn &&
            this.origin.isAlmostEqual(view.origin) &&
            this.extents.isAlmostEqual(view.extents) &&
            this.rotation.isAlmostEqual(view.rotation) &&
            (!this.cameraOn || this.camera.equals(view.camera));
    }
}
/** The "pose" for a [[ViewState2d]].
 * @public
 * @extensions
 */
export class ViewPose2d extends ViewPose {
    /** The 2d origin of the view.
     * @see [[ViewState2d.origin]].
     */
    origin2d;
    /** The 2d extents of the view.
     * @see [[ViewState2d.delta]].
     */
    delta;
    /** The rotation of the view.
     * @see [[ViewState2d.angle]].
     */
    angle;
    /** Construct a pose from the specified 2d view. */
    constructor(view) {
        super(false);
        this.origin2d = view.origin.clone();
        this.delta = view.delta.clone();
        this.angle = view.angle.clone();
    }
    /** See [[ViewPose.equal]]. */
    equal(other) {
        if (!(other instanceof ViewPose2d))
            return false;
        return this.origin2d.isAlmostEqual(other.origin) &&
            this.delta.isAlmostEqual(other.delta) &&
            this.angle.isAlmostEqualNoPeriodShift(other.angle);
    }
    /** See [[ViewPose.equalState]]. */
    equalState(view) {
        if (!(view instanceof ViewState2d))
            return false;
        return this.origin2d.isAlmostEqual(view.origin) &&
            this.delta.isAlmostEqual(view.delta) &&
            this.angle.isAlmostEqualNoPeriodShift(view.angle);
    }
    /** See [[ViewPose.origin]]. */
    get origin() {
        return new Point3d(this.origin2d.x, this.origin2d.y);
    }
    /** See [[ViewPose.extents]]. */
    get extents() {
        return new Vector3d(this.delta.x, this.delta.y);
    }
    /** See [[ViewPose.rotation]]. */
    get rotation() {
        const rotation = Matrix3d.createRotationAroundVector(Vector3d.unitZ(), this.angle);
        assert(undefined !== rotation, "rotation around unit vector is always defined");
        return rotation;
    }
}
//# sourceMappingURL=ViewPose.js.map