@itwin/core-backend
Version:
iTwin.js backend components
137 lines • 8.27 kB
JavaScript
;
/*---------------------------------------------------------------------------------------------
* Copyright (c) Bentley Systems, Incorporated. All rights reserved.
* See LICENSE.md in the project root for license terms and full copyright notice.
*--------------------------------------------------------------------------------------------*/
/** @packageDocumentation
* @module ElementGeometry
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.appendTextAnnotationGeometry = appendTextAnnotationGeometry;
const core_common_1 = require("@itwin/core-common");
const core_geometry_1 = require("@itwin/core-geometry");
const core_bentley_1 = require("@itwin/core-bentley");
const TextBlockGeometry_1 = require("./TextBlockGeometry");
const FrameGeometry_1 = require("./FrameGeometry");
const LeaderGeometry_1 = require("./LeaderGeometry");
/** Constructs the TextBlockGeometry and frame geometry and appends the geometry to the provided builder.
* @returns true if the geometry was successfully appended.
* @beta
*/
function appendTextAnnotationGeometry(props) {
const annotation = core_common_1.TextAnnotation.fromJSON(props.annotationProps);
const transform = annotation.computeTransform(props.layout.range, props.textStyleResolver.scaleFactor);
let result = true;
// Construct the TextBlockGeometry
const params = new core_common_1.GeometryParams(props.categoryId, props.subCategoryId);
const entries = (0, TextBlockGeometry_1.produceTextBlockGeometry)(props.layout, transform.clone());
result = result && props.builder.appendTextBlock(entries, params);
// Construct the frame geometry
if (props.textStyleResolver.blockSettings.frame.shape !== "none") {
result = result && (0, FrameGeometry_1.appendFrameToBuilder)(props.builder, props.textStyleResolver.blockSettings.frame, props.layout.range, transform.clone(), params);
}
// Construct the leader geometry
if (annotation.leaders && annotation.leaders.length > 0) {
result = result && (0, LeaderGeometry_1.appendLeadersToBuilder)(props.builder, annotation.leaders, props.layout, transform.clone(), params, props.textStyleResolver);
}
// Construct the debug geometry
if (props.wantDebugGeometry) {
result = result && debugAnchorPoint(props.builder, annotation, props.layout, transform.clone());
result = result && debugRunLayout(props.builder, props.layout, transform.clone());
if (props.textStyleResolver.blockSettings.frame.shape !== "none")
result = result && debugSnapPoints(props.builder, props.textStyleResolver.blockSettings, props.layout.range, transform.clone());
}
return result;
}
;
/**
* Draws the anchor point and margins of the text annotation.
* The anchor point is the point around which the text rotates and is drawn as a blue x (1m by 1m).
* The margins are drawn as a blue box.
* The text range is drawn as a red box.
*/
function debugAnchorPoint(builder, annotation, layout, transform) {
const range = core_geometry_1.Range2d.fromJSON(layout.range);
const debugAnchorPt = transform.multiplyPoint3d(annotation.computeAnchorPoint(range));
// Make it blue
const blueLineParams = new core_common_1.GeometryParams(core_bentley_1.Id64.invalid);
blueLineParams.lineColor = core_common_1.ColorDef.blue;
let result = builder.appendGeometryParamsChange(blueLineParams);
// Draw a blue box to show the element's margin
const marginCorners = range.corners3d(true);
transform.multiplyPoint3dArrayInPlace(marginCorners);
result = result && builder.appendGeometryQuery(core_geometry_1.LineString3d.create(marginCorners));
// Draw a blue x to show the anchor point - Rotation occurs around this point. The x will be 1 m by 1 m.
result = result && builder.appendGeometryQuery(core_geometry_1.LineString3d.create(debugAnchorPt.plusXYZ(-1, -1), debugAnchorPt.plusXYZ(1, 1)));
result = result && builder.appendGeometryQuery(core_geometry_1.LineString3d.create(debugAnchorPt.plusXYZ(1, -1), debugAnchorPt.plusXYZ(-1, 1)));
// Draw a red box to show the text range
const redLineParams = new core_common_1.GeometryParams(core_bentley_1.Id64.invalid);
redLineParams.lineColor = core_common_1.ColorDef.red;
result = result && builder.appendGeometryParamsChange(redLineParams);
const rangeCorners = layout.textRange.corners3d(true);
transform.multiplyPoint3dArrayInPlace(rangeCorners);
result = result && builder.appendGeometryQuery(core_geometry_1.LineString3d.create(rangeCorners));
return result;
}
/** Draws the interval points defined by calling [[computeIntervalPoints]]. The points are shown as black dots 5x larger than the borderWeight */
function debugSnapPoints(builder, style, range, transform) {
if (style.frame.shape === "none")
return false;
const points = (0, FrameGeometry_1.computeIntervalPoints)({ frame: style.frame.shape, range, transform, lineIntervalFactor: 0.5, arcIntervalFactor: 0.25 });
const params = new core_common_1.GeometryParams(core_bentley_1.Id64.invalid);
params.lineColor = core_common_1.ColorDef.black;
params.weight = style.frame.borderWeight * 5; // We want the dots to be bigger than the frame so we can see them.
params.fillDisplay = core_common_1.FillDisplay.Always;
const result = builder.appendGeometryParamsChange(params) && builder.appendGeometryQuery(core_geometry_1.PointString3d.create(points));
return result;
}
/**
* Draws debug geometry for each line and run in a TextBlockLayout.
*
* For each line and run, this function draws boxes to visualize their layout and boundaries.
* Different run types (e.g., text, linebreak, fraction, tab) are assigned distinct colors for clarity.
* This is useful for debugging text layout and alignment issues.
*
* @param builder - The geometry builder to append debug geometry to.
* @param layout - The text block layout containing lines and runs to visualize.
* @param documentTransform - The transform to apply to the entire document.
* @returns True if all debug geometry was successfully appended.
*/
function debugRunLayout(builder, layout, documentTransform) {
let result = true; // Tracks if all geometry was appended successfully
let color = core_common_1.ColorDef.black; // Current color for the run type
let lastColor = color; // Last color used, to minimize param changes
// Map run types to debug colors
const colors = {
"text": core_common_1.ColorDef.fromString("orange"),
"linebreak": core_common_1.ColorDef.fromString("yellow"),
"fraction": core_common_1.ColorDef.fromString("green"),
"tab": core_common_1.ColorDef.fromString("aquamarine"),
"field": core_common_1.ColorDef.fromString("purple"),
};
layout.lines.forEach(line => {
// Apply the line's offset transform
const lineTrans = core_geometry_1.Transform.createTranslationXYZ(line.offsetFromDocument.x, line.offsetFromDocument.y, 0);
documentTransform.multiplyTransformTransform(lineTrans, lineTrans);
line.runs.forEach(run => {
// Determine color for this run type
color = colors[run.source.type] ?? core_common_1.ColorDef.black;
// Only change geometry params if the color changes
if (!lastColor.equals(color)) {
const colorParams = new core_common_1.GeometryParams(core_bentley_1.Id64.invalid);
colorParams.lineColor = color;
result = result && builder.appendGeometryParamsChange(colorParams);
lastColor = color;
}
// Apply the line's offset to the run's offset
const runTrans = core_geometry_1.Transform.createTranslationXYZ(run.offsetFromLine.x, run.offsetFromLine.y, 0);
lineTrans.multiplyTransformTransform(runTrans, runTrans);
// Draw the enclosing range for the run
const runCorners = run.range.corners3d(true);
runTrans.multiplyPoint3dArrayInPlace(runCorners);
result = result && builder.appendGeometryQuery(core_geometry_1.LineString3d.create(runCorners));
});
});
return result;
}
//# sourceMappingURL=TextAnnotationGeometry.js.map