UNPKG

@itwin/core-common

Version:

iTwin.js components common to frontend and backend

188 lines • 9.99 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 Rendering */ Object.defineProperty(exports, "__esModule", { value: true }); exports.FeatureTable = exports.BatchType = exports.PackedFeature = exports.ModelFeature = exports.Feature = void 0; const core_bentley_1 = require("@itwin/core-bentley"); const GeometryParams_1 = require("./GeometryParams"); const PackedFeatureTable_1 = require("./internal/PackedFeatureTable"); /** Describes a discrete entity within a batched [RenderGraphic]($frontend) that can be * grouped with other such entities in a [[FeatureTable]]. * Features roughly correlate to elements: a [Tile]($frontend)'s graphics combines geometry from every * [GeometricElement]($backend) that intersects the tile's volume, so each element produces at least one feature. * However, an element's geometry stream can contain geometry belonging to multiple different combinations of [SubCategory]($backend) and * [[GeometryClass]], so an individual element may produce more than one feature. * @see [[FeatureOverrides]] for customizing the appearance of individual features. * @public */ class Feature { elementId; subCategoryId; geometryClass; constructor(elementId = core_bentley_1.Id64.invalid, subCategoryId = core_bentley_1.Id64.invalid, geometryClass = GeometryParams_1.GeometryClass.Primary) { this.elementId = elementId; this.subCategoryId = subCategoryId; this.geometryClass = geometryClass; } get isDefined() { return !core_bentley_1.Id64.isInvalid(this.elementId) || !core_bentley_1.Id64.isInvalid(this.subCategoryId) || this.geometryClass !== GeometryParams_1.GeometryClass.Primary; } get isUndefined() { return !this.isDefined; } /** Returns true if this feature is equivalent to the supplied feature. */ equals(other) { return 0 === this.compare(other); } /** Performs ordinal comparison of this feature with another. * @param rhs The feature to compare with. * @returns zero if the features are equivalent, a negative value if this feature compares as "less than" `rhs`, or a positive value if this feature compares "greater than" `rhs`. */ compare(rhs) { if (this === rhs) return 0; let cmp = (0, core_bentley_1.compareNumbers)(this.geometryClass, rhs.geometryClass); if (0 === cmp) { cmp = (0, core_bentley_1.compareStrings)(this.elementId, rhs.elementId); if (0 === cmp) { cmp = (0, core_bentley_1.compareStrings)(this.subCategoryId, rhs.subCategoryId); } } return cmp; } } exports.Feature = Feature; /** @public */ var ModelFeature; (function (ModelFeature) { /** Create a ModelFeature of [[GeometryClass.Primary]] with all invalid Ids. * This is primarily useful for creating a `result` argument for [[RenderFeatureTable.findFeature]] and [[RenderFeatureTable.getFeature]]. */ function create() { return { modelId: core_bentley_1.Id64.invalid, elementId: core_bentley_1.Id64.invalid, subCategoryId: core_bentley_1.Id64.invalid, geometryClass: GeometryParams_1.GeometryClass.Primary, }; } ModelFeature.create = create; /** Returns `true` if any of `feature`'s properties differ from the defaults (invalid Ids and [[GeometryClass.Primary]]). */ function isDefined(feature) { return !core_bentley_1.Id64.isInvalid(feature.modelId) || !core_bentley_1.Id64.isInvalid(feature.elementId) || !core_bentley_1.Id64.isInvalid(feature.subCategoryId) || feature.geometryClass !== GeometryParams_1.GeometryClass.Primary; } ModelFeature.isDefined = isDefined; /** @alpha */ function unpack(packed, result, unpackedModelId) { result.modelId = unpackedModelId ?? core_bentley_1.Id64.fromUint32PairObject(packed.modelId); result.elementId = core_bentley_1.Id64.fromUint32PairObject(packed.elementId); result.subCategoryId = core_bentley_1.Id64.fromUint32PairObject(packed.subCategoryId); result.geometryClass = packed.geometryClass; return result; } ModelFeature.unpack = unpack; })(ModelFeature || (exports.ModelFeature = ModelFeature = {})); /** @public */ var PackedFeature; (function (PackedFeature) { /** Create a PackedFeature of [[GeometryClass.Primary]] with all invalid Ids. * This is primarily useful for creating a `result` argument for [[RenderFeatureTable.getPackedFeature]]. */ function create() { const pair = { upper: 0, lower: 0 }; return { modelId: { ...pair }, elementId: { ...pair }, subCategoryId: { ...pair }, geometryClass: GeometryParams_1.GeometryClass.Primary, animationNodeId: 0, }; } PackedFeature.create = create; /** Create a PackedFeatureWithIndex of [[GeometryClass.Primary]] with all invalid Ids and an index of zero. * This is primarily useful for creating a reusable `output` argument for [[RenderFeatureTable.iterable]]. */ function createWithIndex() { const result = create(); result.index = 0; return result; } PackedFeature.createWithIndex = createWithIndex; })(PackedFeature || (exports.PackedFeature = PackedFeature = {})); /** Describes the type of a 'batch' of graphics representing multiple [[Feature]]s. * The most commonly-encountered batches are Tiles, which can be of either Primary or * Classifier type. * @public * @extensions */ var BatchType; (function (BatchType) { /** This batch contains graphics derived from a model's visible geometry. */ BatchType[BatchType["Primary"] = 0] = "Primary"; /** * This batch contains color volumes which are used to classify a model's visible geometry. * The graphics themselves are not rendered to the screen; instead they are rendered to the stencil buffer * to resymbolize the primary geometry. */ BatchType[BatchType["VolumeClassifier"] = 1] = "VolumeClassifier"; /** * This batch contains planar graphics which are used to classify a model's visible geometry. * The graphics themselves are not rendered to the screen; instead they are rendered to a texture buffer * to resymbolize the primary geometry. */ BatchType[BatchType["PlanarClassifier"] = 2] = "PlanarClassifier"; })(BatchType || (exports.BatchType = BatchType = {})); /** Defines a look-up table for [[Feature]]s within a batched [RenderGraphic]($frontend). Consecutive 32-bit * indices are assigned to each unique Feature. Primitives within the RenderGraphic can * use per-vertex indices to specify the distribution of Features within the primitive. The appearance of individual * features can be customized using [[FeatureOverrides]]. Typically a [Tile]($frontend) will contain a feature table * identifying the elements whose geometry appears within that tile. * @see [[FeatureOverrides]] for customizing the appearance of individual features. * @public */ class FeatureTable extends core_bentley_1.IndexMap { modelId; type; /** Construct an empty FeatureTable. */ constructor(maxFeatures, modelId = core_bentley_1.Id64.invalid, type = BatchType.Primary) { super((lhs, rhs) => lhs.compare(rhs), maxFeatures); this.modelId = modelId; this.type = type; } /** Returns the maximum number of [[Feature]]s this FeatureTable can contain. */ get maxFeatures() { return this._maximumSize; } /** Returns true if this table contains at least one [[Feature]] with a valid element and/or subcategory Id. */ get anyDefined() { return this.length > 1 || (1 === this.length && this._array[0].value.isDefined); } /** Returns true if this FeatureTable contains exactly one [[Feature]]. */ get isUniform() { return 1 === this.length; } /** If this FeatureTable contains exactly one [[Feature]], returns that Feature; otherwise returns undefined. */ get uniform() { return 1 === this.length ? this._array[0].value : undefined; } /** Returns true if this FeatureTable is associated with [[BatchType.VolumeClassifier]] geometry. */ get isVolumeClassifier() { return BatchType.VolumeClassifier === this.type; } /** Returns true if this FeatureTable is associated with [[BatchType.PlanarClassifier]] geometry. */ get isPlanarClassifier() { return BatchType.PlanarClassifier === this.type; } /** Returns the Feature corresponding to the specified index, or undefined if the index is not present. */ findFeature(index) { for (const entry of this._array) if (entry.index === index) return entry.value; return undefined; } /** Inserts the specified [[Feature]] at the specified index. This is really only useful when reconstructing a previously-create feature table * for which you know the index assigned to each feature. */ insertWithIndex(feature, index) { const bound = this.lowerBound(feature); (0, core_bentley_1.assert)(!bound.equal); (0, core_bentley_1.assert)(!this.isFull); const entry = new core_bentley_1.IndexedValue(feature, index); this._array.splice(bound.index, 0, entry); } /** Access the underlying array containing the table's current contents. */ getArray() { return this._array; } /** Convert this feature table to a representation that can be supplied to [RenderSystem.createBatch]($frontend). */ pack() { return PackedFeatureTable_1.PackedFeatureTable.pack(this); } } exports.FeatureTable = FeatureTable; //# sourceMappingURL=FeatureTable.js.map