@itwin/core-common
Version:
iTwin.js components common to frontend and backend
178 lines • 7.52 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 DisplayStyles
*/
import { Range1d } from "@itwin/core-geometry";
import { ThematicGradientSettings } from "./ThematicDisplay";
import { Gradient } from "./Gradient";
/** Describes how an [[AnalysisStyle]] deforms a [Polyface]($core-geometry) by applying translation to its vertices.
* @see [[AnalysisStyle.displacement]].
* @public
*/
export class AnalysisStyleDisplacement {
/** The name of the [AuxChannel]($core-geometry) supplying the displacements to be applied to the vertices. */
channelName;
/** A scale applied to the displacements to adjust the magnitude of the effect.
* Default value: 1.
*/
scale;
constructor(channelName, scale = 1) {
this.channelName = channelName;
this.scale = scale;
}
/** Create from JSON representation. */
static fromJSON(props) {
return new this(props.channelName, props.scale);
}
/** Convert to JSON representation. */
toJSON() {
const props = { channelName: this.channelName };
if (this.scale !== 1)
props.scale = this.scale;
return props;
}
/** Return true if `this` is equivalent to `other`. */
equals(other) {
return this.channelName === other.channelName && this.scale === other.scale;
}
}
/** Describes how an [[AnalysisStyle]] recolors [Polyface]($core-geometry) vertices by mapping values of type
* [AuxChannelDataType.Scalar]($core-geometry) or [AuxChannelDataType.Distance]($core-geometry) supplied
* by an [AuxChannel]($core-geometry) to colors supplied by a [[Gradient]] image.
* @see [[AnalysisStyle.thematic]].
* @public
*/
export class AnalysisStyleThematic {
/** The name of the [AuxChannel]($core-geometry) supplying the values from which the vertex colors are computed. */
channelName;
/** The minimum and maximum values that map to colors in the [[Gradient]] image. Vertices with values outside of
* this range are displayed with the gradient's margin color.
*/
range;
/** Settings used to produce the [[Gradient]] image. */
thematicSettings;
_gradient;
constructor(props) {
this.channelName = props.channelName;
this.range = Range1d.fromJSON(props.range);
this.thematicSettings = ThematicGradientSettings.fromJSON(props.thematicSettings);
}
/** Create from JSON representation. */
static fromJSON(props) {
return new this(props);
}
/** Convert to JSON representation. */
toJSON() {
const props = {
channelName: this.channelName,
range: this.range.toJSON(),
};
if (!this.thematicSettings.equals(ThematicGradientSettings.defaults))
props.thematicSettings = this.thematicSettings.toJSON();
return props;
}
/** The gradient computed from [[thematicSettings]]. */
get gradient() {
if (!this._gradient)
this._gradient = Gradient.Symb.createThematic(this.thematicSettings);
return this._gradient;
}
/** Return true if `this` is equivalent to `other`. */
equals(other) {
return this.channelName === other.channelName && this.range.isAlmostEqual(other.range) && this.thematicSettings.equals(other.thematicSettings);
}
}
function tryConvertLegacyProps(input) {
if (input.displacement || input.scalar)
return input;
const legacy = input;
if (undefined === legacy.displacementChannelName && undefined === legacy.scalarChannelName)
return input;
const output = {
normalChannelName: input.normalChannelName,
};
if (undefined !== legacy.displacementChannelName) {
output.displacement = {
channelName: legacy.displacementChannelName,
scale: legacy.displacementScale,
};
}
if (undefined !== legacy.scalarChannelName && undefined !== legacy.scalarRange) {
output.scalar = {
channelName: legacy.scalarChannelName,
range: legacy.scalarRange,
thematicSettings: legacy.scalarThematicSettings,
};
}
return output;
}
/** As part of a [[DisplayStyleSettings]], describes how to animate meshes in the view that have been augmented with
* [PolyfaceAuxData]($core-geometry). The style specifies which channels to use, and can deform the meshes by
* translating vertices and/or recolor vertices using [[ThematicDisplay]].
* @see [[DisplayStyleSettings.analysisStyle]] to define the analysis style for a [DisplayStyle]($backend).
* @see [[DisplayStyleSettings.analysisFraction]] to control playback of the animation.
* @public
*/
export class AnalysisStyle {
displacement;
thematic;
/** If defined, the name of the [AuxChannel]($core-geometry) from which to obtain normal vectors for the vertices. */
normalChannelName;
/** Create an analysis style from its JSON representation.
* @note AnalysisStyle is an immutable type - use [[clone]] to produce a modified copy.
*/
static fromJSON(props) {
if (!props)
return this.defaults;
props = tryConvertLegacyProps(props);
if (!props.displacement && !props.scalar && undefined === props.normalChannelName)
return this.defaults;
return new AnalysisStyle(props);
}
constructor(props) {
this.normalChannelName = props.normalChannelName;
if (props.displacement)
this.displacement = AnalysisStyleDisplacement.fromJSON(props.displacement);
if (props.scalar)
this.thematic = AnalysisStyleThematic.fromJSON(props.scalar);
}
/** Convert this style to its JSON representation. */
toJSON() {
const props = {};
if (this === AnalysisStyle.defaults)
return props;
if (this.displacement)
props.displacement = this.displacement.toJSON();
if (this.thematic)
props.scalar = this.thematic.toJSON();
if (undefined !== this.normalChannelName)
props.normalChannelName = this.normalChannelName;
return props;
}
/** Produce a copy of this style identical except for properties explicitly specified by `changedProps`. */
clone(changedProps) {
return AnalysisStyle.fromJSON({
...this.toJSON(),
...changedProps,
});
}
/** Return true if this style is equivalent to `other`. */
equals(other) {
if (this.normalChannelName !== other.normalChannelName)
return false;
if ((undefined === this.displacement) !== (undefined === other.displacement))
return false;
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
else if (this.displacement && !this.displacement.equals(other.displacement))
return false;
if ((undefined === this.thematic) !== (undefined === other.thematic))
return false;
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
return undefined === this.thematic || this.thematic.equals(other.thematic);
}
static defaults = new AnalysisStyle({});
}
//# sourceMappingURL=AnalysisStyle.js.map