UNPKG

@itwin/core-backend

Version:
310 lines • 19.5 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 ElementGeometry */ Object.defineProperty(exports, "__esModule", { value: true }); exports.LineStyleDefinition = void 0; const core_bentley_1 = require("@itwin/core-bentley"); const core_common_1 = require("@itwin/core-common"); const EditTxn_1 = require("./EditTxn"); const Element_1 = require("./Element"); const Symbols_1 = require("./internal/Symbols"); function getLinePixelsLineCode(linePixels) { switch (linePixels) { case core_common_1.LinePixels.Code1: return 1; case core_common_1.LinePixels.Code2: return 2; case core_common_1.LinePixels.Code3: return 3; case core_common_1.LinePixels.Code4: return 4; case core_common_1.LinePixels.Code5: return 5; case core_common_1.LinePixels.Code6: return 6; case core_common_1.LinePixels.Code7: return 7; default: return -1; // Invalid value... } } /** A line style definition is a uniquely named pattern that repeats as it is displayed along a curve path. In the absence of a line style, curve display is limited to solid lines with a width in pixels. * There are three varieties of line styles: * - A style described by a stroke pattern (series of dashes and gaps) that may also include symbol graphics. * - A style using pre-defined pixel bit patterns [[LinePixels]] for dashed display (Code1-Code7). * - A style that uses a texture. * * A definition is defined by one or more components. A component is saved as a "file property" and can be referenced by other components. The line style definition references a component * by file property id and type and is saved as a dictionary element. * @public */ var LineStyleDefinition; (function (LineStyleDefinition) { /** Line style component type identifiers */ let ComponentType; (function (ComponentType) { /** Component type for [[LineStyleDefinition.PointSymbolProps]] */ ComponentType[ComponentType["PointSymbol"] = 1] = "PointSymbol"; /** Component type for [[LineStyleDefinition.CompoundProps]] */ ComponentType[ComponentType["Compound"] = 2] = "Compound"; /** Component type for [[LineStyleDefinition.StrokePatternProps]] */ ComponentType[ComponentType["StrokePattern"] = 3] = "StrokePattern"; /** Component type for [[LineStyleDefinition.StrokePointProps]] */ ComponentType[ComponentType["StrokePoint"] = 4] = "StrokePoint"; /** Component type for [[LinePixels]], never saved as a file property */ ComponentType[ComponentType["Internal"] = 6] = "Internal"; /** Component type for [[LineStyleDefinition.RasterImageProps]] */ ComponentType[ComponentType["RasterImage"] = 7] = "RasterImage"; })(ComponentType = LineStyleDefinition.ComponentType || (LineStyleDefinition.ComponentType = {})); /** Mask of values for StrokeMode */ let StrokeMode; (function (StrokeMode) { /** Stroke represents a blank space */ StrokeMode[StrokeMode["Gap"] = 0] = "Gap"; /** Stroke represents a solid dash */ StrokeMode[StrokeMode["Dash"] = 1] = "Dash"; /** Treat stroke as rigid and continue past a corner to complete the stroke as opposed to breaking at the corner */ StrokeMode[StrokeMode["Ray"] = 2] = "Ray"; /** Stroke length can be stretched when [[LineStyleDefinition.StrokePatternOptions.Iteration]] and [[LineStyleDefinition.StrokePatternOptions.AutoPhase]] options are set, applicable to both Gap and Dash strokes */ StrokeMode[StrokeMode["Scale"] = 4] = "Scale"; /** Invert stroke in first stroke pattern */ StrokeMode[StrokeMode["FirstInvert"] = 8] = "FirstInvert"; /** Invert stroke in last stroke pattern */ StrokeMode[StrokeMode["LastInvert"] = 16] = "LastInvert"; })(StrokeMode = LineStyleDefinition.StrokeMode || (LineStyleDefinition.StrokeMode = {})); /** Define constant width or tapered strokes with distance specified in meters */ let StrokeWidth; (function (StrokeWidth) { /** Stroke draws as one pixel wide line */ StrokeWidth[StrokeWidth["None"] = 0] = "None"; /** Half [[LineStyleDefinition.StrokeProps.orgWidth]] and [[LineStyleDefinition.StrokeProps.endWidth]] applied to left side of stroke */ StrokeWidth[StrokeWidth["Left"] = 1] = "Left"; /** Half [[LineStyleDefinition.StrokeProps.orgWidth]] and [[LineStyleDefinition.StrokeProps.endWidth]] applied to right side of stroke */ StrokeWidth[StrokeWidth["Right"] = 2] = "Right"; /** Half [[LineStyleDefinition.StrokeProps.orgWidth]] and [[LineStyleDefinition.StrokeProps.endWidth]] applied to both sides of stroke */ StrokeWidth[StrokeWidth["Full"] = 3] = "Full"; })(StrokeWidth = LineStyleDefinition.StrokeWidth || (LineStyleDefinition.StrokeWidth = {})); /** Controls appearance of stroke end caps. If StrokeCap is >= Hexagon, the end cap is stroked as an arc and the value of * StrokeCap indicates the number of vectors in the arc. */ let StrokeCap; (function (StrokeCap) { /** Stroke displays as a closed polygon */ StrokeCap[StrokeCap["Closed"] = 0] = "Closed"; /** Stroke displays lines at specified width instead of a polygon */ StrokeCap[StrokeCap["Open"] = 1] = "Open"; /** Stroke length extended by half the stroke width */ StrokeCap[StrokeCap["Extended"] = 2] = "Extended"; /** Stroke end cap is a hexagon */ StrokeCap[StrokeCap["Hexagon"] = 3] = "Hexagon"; /** Stroke end cap is an octagon */ StrokeCap[StrokeCap["Octagon"] = 4] = "Octagon"; /** Stroke end cap is a decagon */ StrokeCap[StrokeCap["Decagon"] = 5] = "Decagon"; /** Stroke end cap is an arc */ StrokeCap[StrokeCap["Arc"] = 30] = "Arc"; })(StrokeCap = LineStyleDefinition.StrokeCap || (LineStyleDefinition.StrokeCap = {})); /** Options to control how stroke pattern is applied to underlying curve */ let StrokePatternOptions; (function (StrokePatternOptions) { /** Use default stroke behavior */ StrokePatternOptions[StrokePatternOptions["None"] = 0] = "None"; /** [[LineStyleDefinition.StrokePatternProps.phase]] represents fractional distance into first stroke of pattern */ StrokePatternOptions[StrokePatternOptions["AutoPhase"] = 1] = "AutoPhase"; /** Use [[LineStyleDefinition.StrokePatternProps.maxIter]] to limit the number of iterations of the stroke pattern */ StrokePatternOptions[StrokePatternOptions["Iteration"] = 8] = "Iteration"; /** Single segment mode restarts the stroke pattern at corners instead of continuing around corners */ StrokePatternOptions[StrokePatternOptions["Segment"] = 16] = "Segment"; /** Center the line style and stretch the ends */ StrokePatternOptions[StrokePatternOptions["CenterStretch"] = 32] = "CenterStretch"; })(StrokePatternOptions = LineStyleDefinition.StrokePatternOptions || (LineStyleDefinition.StrokePatternOptions = {})); /** Flags to identify point symbol behavior */ let PointSymbolFlags; (function (PointSymbolFlags) { /** Default symbol behavior */ PointSymbolFlags[PointSymbolFlags["None"] = 0] = "None"; /** Symbol includes 3d geometry */ PointSymbolFlags[PointSymbolFlags["Is3d"] = 1] = "Is3d"; /** Symbol does not allow scaling */ PointSymbolFlags[PointSymbolFlags["NoScale"] = 2] = "NoScale"; })(PointSymbolFlags = LineStyleDefinition.PointSymbolFlags || (LineStyleDefinition.PointSymbolFlags = {})); /** Symbol options for location, orientation, and behavior */ let SymbolOptions; (function (SymbolOptions) { /** No point symbol */ SymbolOptions[SymbolOptions["None"] = 0] = "None"; /** Symbol at origin of stroke */ SymbolOptions[SymbolOptions["Origin"] = 1] = "Origin"; /** Symbol at end of stroke */ SymbolOptions[SymbolOptions["End"] = 2] = "End"; /** symbol at center of stroke */ SymbolOptions[SymbolOptions["Center"] = 3] = "Center"; /** Symbol at curve start point */ SymbolOptions[SymbolOptions["CurveOrigin"] = 4] = "CurveOrigin"; /** Symbol at curve end point */ SymbolOptions[SymbolOptions["CurveEnd"] = 8] = "CurveEnd"; /** Symbol at each vertex */ SymbolOptions[SymbolOptions["CurveVertex"] = 16] = "CurveVertex"; /** Adjust symbol rotation left->right */ SymbolOptions[SymbolOptions["AdjustRotation"] = 32] = "AdjustRotation"; /** Angle of symbol not relative to stroke direction */ SymbolOptions[SymbolOptions["AbsoluteRotation"] = 64] = "AbsoluteRotation"; /** No scale on variable strokes */ SymbolOptions[SymbolOptions["NoScale"] = 256] = "NoScale"; /** No clip on partial strokes */ SymbolOptions[SymbolOptions["NoClip"] = 512] = "NoClip"; /** No partial strokes */ SymbolOptions[SymbolOptions["NoPartial"] = 1024] = "NoPartial"; /** Project partial origin */ SymbolOptions[SymbolOptions["ProjectOrigin"] = 2048] = "ProjectOrigin"; /** Use color from symbol instead of inheriting curve color */ SymbolOptions[SymbolOptions["UseColor"] = 16384] = "UseColor"; /** Use weight from symbol instead of inheriting curve weight */ SymbolOptions[SymbolOptions["UseWeight"] = 32768] = "UseWeight"; })(SymbolOptions = LineStyleDefinition.SymbolOptions || (LineStyleDefinition.SymbolOptions = {})); /** Flags to describe a style or control style behavior */ let StyleFlags; (function (StyleFlags) { /** Use defaults */ StyleFlags[StyleFlags["None"] = 0] = "None"; /** Only snap to center line and not individual strokes and symbols of line style */ StyleFlags[StyleFlags["NoSnap"] = 4] = "NoSnap"; /** Style represents a continuous line with width (determined by looking at components if not set) */ StyleFlags[StyleFlags["Continuous"] = 8] = "Continuous"; /** Style represents physical geometry and should be scaled as such */ StyleFlags[StyleFlags["Physical"] = 128] = "Physical"; })(StyleFlags = LineStyleDefinition.StyleFlags || (LineStyleDefinition.StyleFlags = {})); /** Helper methods for creating and querying line styles */ class Utils { static createStrokePatternComponent(txnOrIModel, props) { const txn = txnOrIModel instanceof EditTxn_1.EditTxn ? txnOrIModel : txnOrIModel[Symbols_1._implicitTxn]; const fileProps = { name: "LineCodeV1", namespace: "dgn_LStyle" }; fileProps.id = txn.iModel.queryNextAvailableFileProperty(fileProps); txn.saveFileProperty(fileProps, JSON.stringify(props)); return { compId: fileProps.id, compType: ComponentType.StrokePattern }; } static createPointSymbolComponent(txnOrIModel, props) { const txn = txnOrIModel instanceof EditTxn_1.EditTxn ? txnOrIModel : txnOrIModel[Symbols_1._implicitTxn]; const iModel = txn.iModel; // if part extents weren't supplied, set them up now. if (!props.baseX && !props.baseY && !props.baseZ && !props.sizeX && !props.sizeY && !props.sizeZ) { const geomPart = iModel.elements.getElement(props.geomPartId); if (!geomPart) return undefined; props.baseX = geomPart.bbox.low.x; props.baseY = geomPart.bbox.low.y; props.baseZ = geomPart.bbox.low.z; props.sizeX = geomPart.bbox.high.x; props.sizeY = geomPart.bbox.high.y; props.sizeZ = geomPart.bbox.high.z; } const fileProps = { name: "PointSymV1", namespace: "dgn_LStyle" }; fileProps.id = iModel.queryNextAvailableFileProperty(fileProps); txn.saveFileProperty(fileProps, JSON.stringify(props)); return { compId: fileProps.id, compType: ComponentType.PointSymbol }; } static createStrokePointComponent(txnOrIModel, props) { const txn = txnOrIModel instanceof EditTxn_1.EditTxn ? txnOrIModel : txnOrIModel[Symbols_1._implicitTxn]; const fileProps = { name: "LinePointV1", namespace: "dgn_LStyle" }; fileProps.id = txn.iModel.queryNextAvailableFileProperty(fileProps); txn.saveFileProperty(fileProps, JSON.stringify(props)); return { compId: fileProps.id, compType: ComponentType.StrokePoint }; } static createCompoundComponent(txnOrIModel, props) { const txn = txnOrIModel instanceof EditTxn_1.EditTxn ? txnOrIModel : txnOrIModel[Symbols_1._implicitTxn]; const fileProps = { name: "CompoundV1", namespace: "dgn_LStyle" }; fileProps.id = txn.iModel.queryNextAvailableFileProperty(fileProps); txn.saveFileProperty(fileProps, JSON.stringify(props)); return { compId: fileProps.id, compType: ComponentType.Compound }; } static createRasterComponent(txnOrIModel, props, image) { const txn = txnOrIModel instanceof EditTxn_1.EditTxn ? txnOrIModel : txnOrIModel[Symbols_1._implicitTxn]; const iModel = txn.iModel; const rasterFileProps = { name: "RasterImageV1", namespace: "dgn_LStyle" }; rasterFileProps.id = iModel.queryNextAvailableFileProperty(rasterFileProps); txn.saveFileProperty(rasterFileProps, undefined, image); props.imageId = rasterFileProps.id; const fileProps = { name: "RasterComponentV1", namespace: "dgn_LStyle" }; fileProps.id = iModel.queryNextAvailableFileProperty(fileProps); txn.saveFileProperty(fileProps, JSON.stringify(props)); return { compId: fileProps.id, compType: ComponentType.RasterImage }; } /** Query for an existing line style with the supplied name. */ static queryStyle(imodel, scopeModelId, name) { return imodel.elements.queryElementIdByCode(Element_1.LineStyle.createCode(imodel, scopeModelId, name)); } static createStyle(txnOrIModel, scopeModelId, name, props) { const txn = txnOrIModel instanceof EditTxn_1.EditTxn ? txnOrIModel : txnOrIModel[Symbols_1._implicitTxn]; const imodel = txn.iModel; if (undefined === props.flags) props.flags = StyleFlags.NoSnap; // If flags weren't supplied, default to not snapping to stroke geometry. const lsProps = { classFullName: "BisCore:LineStyle", model: scopeModelId, code: Element_1.LineStyle.createCode(imodel, scopeModelId, name), data: JSON.stringify(props), }; return txn.insertElement(lsProps); } /** Get the name that can be use to query for an existing continuous line style. */ static getContinuousStyleName(width) { if (width === undefined) return "Continuous"; return `Continuous-${width}`; } /** Query for a continuous line style that can be used to create curves with physical width instead of weight in pixels and create one if it does not already exist. * There are 2 ways to define a continuous line style: * - Width is not specified in the style itself and instead will be supplied as an override for each curve that is drawn. * - Defined using [[LineStyleDefinition.ComponentType.Internal]] with component id 0 [[LinePixels.Solid]] which has special behavior of being affected by width overrides. * - Width is specified in the style. * - Defined using a single stroke component that is a long dash. * @param txn Optional explicit EditTxn to use if the style must be created. * @throws [[IModelError]] if unable to insert the line style definition element. * @beta */ static getOrCreateContinuousStyle(imodel, scopeModelId, width, txn) { const writeTxn = txn ?? imodel[Symbols_1._implicitTxn]; const name = this.getContinuousStyleName(width); const lsId = this.queryStyle(imodel, scopeModelId, name); if (undefined !== lsId) return lsId; if (width === undefined) return this.createStyle(writeTxn, scopeModelId, name, { compId: 0, compType: ComponentType.Internal, flags: StyleFlags.Continuous | StyleFlags.NoSnap }); const strokePatternData = this.createStrokePatternComponent(writeTxn, { descr: name, strokes: [{ length: 1e37, orgWidth: width, strokeMode: StrokeMode.Dash, widthMode: StrokeWidth.Full }] }); if (undefined === strokePatternData) throw new core_common_1.IModelError(core_bentley_1.IModelStatus.BadArg, "Unable to insert stroke component"); return this.createStyle(writeTxn, scopeModelId, name, { compId: strokePatternData.compId, compType: strokePatternData.compType, flags: StyleFlags.Continuous | StyleFlags.NoSnap }); } /** Get the name that can be use to query for an existing [[LinePixels]] line style. * @note Returns undefined for line pixels value that is not Code1 to Code7. */ static getLinePixelsStyleName(linePixels) { const lineCode = getLinePixelsLineCode(linePixels); if (-1 === lineCode) return undefined; return `LinePixelsCodeNumber-${lineCode}`; } /** Query for a line style using the supplied [[LinePixels]] value (Code1-Code7) and create one if it does not already exist. * Most applications should instead use [[createStrokePatternComponent]] to define a style with physical dash and gap lengths. * Unlike other components, [[LineStyleDefinition.ComponentType.Internal]] uses the line code as the compId instead of a file property id. * @param txn Optional explicit EditTxn to use if the style must be created. * @throws [[IModelError]] if supplied an invalid [[LinePixels]] value or if unable to insert the line style definition element. * @beta */ static getOrCreateLinePixelsStyle(imodel, scopeModelId, linePixels, txn) { const lineCode = getLinePixelsLineCode(linePixels); if (-1 === lineCode) throw new core_common_1.IModelError(core_bentley_1.IModelStatus.BadArg, "Invalid LinePixels"); const name = `LinePixelsCodeNumber-${lineCode}`; const lsId = this.queryStyle(imodel, scopeModelId, name); return (undefined === lsId ? this.createStyle(txn ?? imodel[Symbols_1._implicitTxn], scopeModelId, name, { compId: lineCode, compType: ComponentType.Internal }) : lsId); } } LineStyleDefinition.Utils = Utils; })(LineStyleDefinition || (exports.LineStyleDefinition = LineStyleDefinition = {})); //# sourceMappingURL=LineStyle.js.map