UNPKG

@itwin/core-common

Version:

iTwin.js components common to frontend and backend

130 lines 6.86 kB
"use strict"; /*--------------------------------------------------------------------------------------------- * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ /** @packageDocumentation * @module Annotation */ Object.defineProperty(exports, "__esModule", { value: true }); exports.TextAnnotation = void 0; const core_geometry_1 = require("@itwin/core-geometry"); const TextBlock_1 = require("./TextBlock"); /** * Represents a formatted block of text positioned in 2d or 3d space. * [TextAnnotation2d]($backend) and [TextAnnotation3d]($backend) elements store a single TextAnnotation from which their geometric representation is generated. * Other types of elements may store multiple TextAnnotations, positioned relative to one another. * The annotation's position and orientation relative to the host element's [Placement]($common) is determined as follows: * - First, a bounding box is computed enclosing the contents of the [[textBlock]. * - Then, an "anchor point" is computed based on the bounding box and the [[anchor]] property. The anchor point can be at one of the four corners of the box, in the middle of one of its four * edges, or in the center of the box. * - The [[orientation]] is applied to rotate the box around the anchor point. * - Finally, the [[offset]] is added to the anchor point to apply translation. * @see [produceTextAnnotationGeometry]($backend) to decompose the annotation into a set of geometric primitives suitable for use with [[GeometryStreamBuilder.appendTextBlock]]. * @beta */ class TextAnnotation { /** The rotation of the annotation. * @note When defining an annotation for a [TextAnnotation2d]($backend), only the `yaw` component (rotation around the Z axis) is used. */ orientation; /** The formatted document. */ textBlock; /** Describes how to compute the [[textBlock]]'s anchor point. */ anchor; /** An offset applied to the anchor point that can be used to position annotations within the same geometry stream relative to one another. */ offset; constructor(offset, angles, textBlock, anchor) { this.offset = offset; this.orientation = angles; this.textBlock = textBlock; this.anchor = anchor; } /** Creates a new TextAnnotation. */ static create(args) { const offset = args?.offset ?? new core_geometry_1.Point3d(); const angles = args?.orientation ?? new core_geometry_1.YawPitchRollAngles(); const textBlock = args?.textBlock ?? TextBlock_1.TextBlock.createEmpty(); const anchor = args?.anchor ?? { vertical: "top", horizontal: "left" }; return new TextAnnotation(offset, angles, textBlock, anchor); } /** * Creates a new TextAnnotation instance from its JSON representation. */ static fromJSON(props) { return TextAnnotation.create({ offset: props?.offset ? core_geometry_1.Point3d.fromJSON(props.offset) : undefined, orientation: props?.orientation ? core_geometry_1.YawPitchRollAngles.fromJSON(props.orientation) : undefined, textBlock: props?.textBlock ? TextBlock_1.TextBlock.create(props.textBlock) : undefined, anchor: props?.anchor ? { ...props.anchor } : undefined, }); } /** * Converts this annotation to its JSON representation. */ toJSON() { const props = {}; // Even if the text block is empty, we want to record its style name and overrides, e.g., // so the user can pick up where they left off editing it next time. props.textBlock = this.textBlock.toJSON(); if (!this.offset.isZero) { props.offset = this.offset.toJSON(); } if (!this.orientation.isIdentity()) { props.orientation = this.orientation.toJSON(); } if (this.anchor.vertical !== "top" || this.anchor.horizontal !== "left") { props.anchor = { ...this.anchor }; } return props; } /** Compute the transform that positions and orients this annotation relative to its anchor point, based on the [[textBlock]]'s computed bounding box. * The anchor point is computed as specified by this annotation's [[anchor]] setting. For example, if the text block is anchored * at the bottom left, then the transform will be relative to the bottom-left corner of `textBlockExtents`. * The text block will be rotated around the fixed anchor point according to [[orientation]], then translated by [[offset]]. * The anchor point will coincide with (0, 0, 0) unless an [[offset]] is present. * @param boundingBox A box fully containing the [[textBlock]]. This range should include the margins. * @see [[computeAnchorPoint]] to compute the transform's anchor point. * @see [computeLayoutTextBlockResult]($backend) to lay out a `TextBlock`. */ computeTransform(boundingBox) { const anchorPt = this.computeAnchorPoint(boundingBox); const matrix = this.orientation.toMatrix3d(); const rotation = core_geometry_1.Transform.createFixedPointAndMatrix(anchorPt, matrix); const translation = core_geometry_1.Transform.createTranslation(this.offset.minus(anchorPt)); return translation.multiplyTransformTransform(rotation, rotation); } /** Compute the anchor point of this annotation as specified by [[anchor]]. * @param boundingBox A box fully containing the [[textBlock]]. * @see [[computeTransform]] to compute the transform relative to the anchor point. */ computeAnchorPoint(boundingBox) { let x = boundingBox.low.x; let y = boundingBox.high.y; switch (this.anchor.horizontal) { case "center": x += boundingBox.xLength() / 2; break; case "right": x += boundingBox.xLength(); break; } switch (this.anchor.vertical) { case "middle": y -= boundingBox.yLength() / 2; break; case "bottom": y -= boundingBox.yLength(); break; } return new core_geometry_1.Point3d(x, y, 0); } /** Returns true if this annotation is logically equivalent to `other`. */ equals(other) { return this.anchor.horizontal === other.anchor.horizontal && this.anchor.vertical === other.anchor.vertical && this.orientation.isAlmostEqual(other.orientation) && this.offset.isAlmostEqual(other.offset) && this.textBlock.equals(other.textBlock); } } exports.TextAnnotation = TextAnnotation; //# sourceMappingURL=TextAnnotation.js.map