UNPKG

@itwin/core-common

Version:

iTwin.js components common to frontend and backend

136 lines 6.47 kB
/*--------------------------------------------------------------------------------------------- * 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 */ import { expectDefined, IModelStatus } from "@itwin/core-bentley"; import { Angle, Constant, Matrix3d, Point2d, Point3d, Range2d, Range3d, Transform, Vector3d, YawPitchRollAngles, } from "@itwin/core-geometry"; import { Frustum } from "../Frustum"; import { IModelError } from "../IModelError"; /** The placement of a GeometricElement3d. This includes the origin, orientation, and size (bounding box) of the element. * All geometry of a GeometricElement are relative to its placement. * @public */ export class Placement3d { origin; angles; bbox; constructor(origin, angles, bbox) { this.origin = origin; this.angles = angles; this.bbox = bbox; } /** Get the rotation from local coordinates of this placement to world coordinates. */ get rotation() { return this.angles.toMatrix3d(); } /** Get the transform from local coordinates of this placement to world coordinates. */ get transform() { return Transform.createOriginAndMatrix(this.origin, this.rotation); } /** determine if this is 3d placement */ get is3d() { return true; } /** Create a new Placement3d from a Placement3dProps. */ static fromJSON(json) { const props = json ? json : {}; return new Placement3d(Point3d.fromJSON(props.origin), YawPitchRollAngles.fromJSON(props.angles), Range3d.fromJSON(props.bbox)); } /** Get the 8 corners, in world coordinates, of this placement. */ getWorldCorners(out) { const frust = Frustum.fromRange(this.bbox, out); frust.multiply(this.transform); return frust; } /** Set the contents of this Placement3d from another Placement3d */ setFrom(other) { this.origin.setFrom(other.origin); this.angles.setFrom(other.angles); this.bbox.setFrom(other.bbox); } /** Determine whether this Placement3d is valid. */ get isValid() { return !this.bbox.isNull && Math.max(this.origin.maxAbs(), this.bbox.maxAbs()) < Constant.circumferenceOfEarth; } /** Calculate the axis-aligned bounding box for this placement. */ calculateRange() { const range = new Range3d(); if (!this.isValid) return range; this.transform.multiplyRange(this.bbox, range); // low and high are not allowed to be equal range.ensureMinLengths(); return range; } /** Multiply the Transform of this Placement3d by the specified *other* Transform. * * Specifically `this.angles` is set to the rotation specified by `other.matrix * this.transform.matrix` * and `this.origin` is set to the origin of `other * this.transform`. * * Since the placement transform is local-to-world, this means `other` is a world-to-world transform. * @throws [[IModelError]] if the Transform is invalid for a GeometricElement3d. */ multiplyTransform(other) { const transform = other.multiplyTransformTransform(this.transform); const angles = YawPitchRollAngles.createFromMatrix3d(transform.matrix); if (undefined === angles) throw new IModelError(IModelStatus.BadRequest, "Invalid Transform"); this.angles = angles; this.origin.setFrom(transform.origin); } } /** The placement of a GeometricElement2d. This includes the origin, rotation, and size (bounding box) of the element. * @public */ export class Placement2d { origin; angle; bbox; constructor(origin, angle, bbox) { this.origin = origin; this.angle = angle; this.bbox = bbox; } /** Get the rotation from local coordinates of this placement to world coordinates. */ get rotation() { return expectDefined(Matrix3d.createRotationAroundVector(Vector3d.unitZ(), this.angle)); } /** Get the transform from local coordinates of this placement to world coordinates. */ get transform() { return Transform.createOriginAndMatrix(Point3d.createFrom(this.origin), this.rotation); } /** Create a new Placement2d from a Placement2dProps. */ static fromJSON(json) { const props = json ? json : {}; return new Placement2d(Point2d.fromJSON(props.origin), Angle.fromJSON(props.angle), Range2d.fromJSON(props.bbox)); } /** determine if this is 3d placement */ get is3d() { return false; } /** Get the 8 corners, in world coordinates, of this placement. */ getWorldCorners(out) { const frust = Frustum.fromRange(this.bbox, out); frust.multiply(this.transform); return frust; } /** Determine whether this Placement2d is valid. */ get isValid() { return !this.bbox.isNull && Math.max(this.origin.maxAbs(), this.bbox.maxAbs()) < Constant.circumferenceOfEarth; } /** Set the contents of this Placement2d from another Placement2d */ setFrom(other) { this.origin.setFrom(other.origin); this.angle.setFrom(other.angle); this.bbox.setFrom(other.bbox); } /** Calculate the axis-aligned bounding box for this placement. */ calculateRange() { const range = new Range3d(); if (!this.isValid) return range; this.transform.multiplyRange(Range3d.createRange2d(this.bbox, 0), range); // low and high are not allowed to be equal range.ensureMinLengths(); range.low.z = -1.0; // is the 2dFrustumDepth, which === 1 meter range.high.z = 1.0; return range; } /** Multiply the Transform of this Placement2d by the specified *other* Transform. * @throws [[IModelError]] if the Transform is invalid for a GeometricElement2d. */ multiplyTransform(other) { const transform = other.multiplyTransformTransform(this.transform); const angles = YawPitchRollAngles.createFromMatrix3d(transform.matrix); if ((undefined === angles) || !angles.pitch.isAlmostZero || !angles.roll.isAlmostZero) throw new IModelError(IModelStatus.BadRequest, "Invalid Transform"); this.angle = angles.yaw; this.origin.setFrom(transform.origin); } } //# sourceMappingURL=Placement.js.map