| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336 |
- import Color from "../Core/Color.js";
- import defined from "../Core/defined.js";
- import srgbToLinear from "../Core/srgbToLinear.js";
-
- /**
- * This class implements an I3S symbology for I3S Layers.
- * <p>
- * Do not construct this directly, instead access symbology through {@link I3SLayer}.
- * </p>
- * @alias I3SSymbology
- * @internalConstructor
- */
- function I3SSymbology(layer) {
- this._layer = layer;
- this._defaultSymbology = undefined;
- this._valueFields = [];
- this._uniqueValueHash = undefined;
- this._classBreaksHash = undefined;
-
- this._parseLayerSymbology();
- }
-
- Object.defineProperties(I3SSymbology.prototype, {
- /**
- * Gets the default symbology data.
- * @memberof I3SSymbology.prototype
- * @type {object}
- * @readonly
- */
- defaultSymbology: {
- get: function () {
- return this._defaultSymbology;
- },
- },
- });
-
- function convertColor(color, transparency) {
- // color is represented as a three or four-element array, values range from 0 through 255.
- // transparency value has to lie between 100 (full transparency) and 0 (full opacity).
- const convertedColor = [];
- for (let i = 0; i < color.length; i++) {
- const floatColor = Color.byteToFloat(color[i]);
- if (i < 3) {
- convertedColor.push(srgbToLinear(floatColor));
- } else {
- convertedColor.push(floatColor);
- }
- }
- if (convertedColor.length === 3) {
- if (defined(transparency)) {
- convertedColor.push(1.0 - transparency / 100.0);
- } else {
- convertedColor.push(1.0);
- }
- }
- return convertedColor;
- }
-
- function parseSymbol(symbol, isColorCaptured) {
- const symbology = {
- edges: undefined,
- material: undefined,
- };
- if (defined(symbol) && defined(symbol.symbolLayers)) {
- for (let i = 0; i < symbol.symbolLayers.length; i++) {
- const symbolLayer = symbol.symbolLayers[i];
- if (symbolLayer.type === "Fill") {
- const edges = symbolLayer.edges;
- const outline = symbolLayer.outline;
- if (defined(edges)) {
- symbology.edges = {};
- if (defined(edges.color)) {
- symbology.edges.color = convertColor(
- edges.color,
- edges.transparency,
- );
- }
- } else if (defined(outline)) {
- symbology.edges = {};
- if (defined(outline.color)) {
- symbology.edges.color = convertColor(
- outline.color,
- outline.transparency,
- );
- }
- }
-
- if (!isColorCaptured) {
- const material = symbolLayer.material;
- if (defined(material)) {
- symbology.material = {
- colorMixMode: material.colorMixMode,
- };
- if (defined(material.color)) {
- symbology.material.color = convertColor(
- material.color,
- material.transparency,
- );
- }
- }
- }
- break;
- }
- }
- }
- return symbology;
- }
-
- function buildUniqueValueHash(renderer, isColorCaptured) {
- if (defined(renderer.uniqueValueGroups)) {
- const valueHash = {};
- for (
- let groupIndex = 0;
- groupIndex < renderer.uniqueValueGroups.length;
- groupIndex++
- ) {
- const classes = renderer.uniqueValueGroups[groupIndex].classes;
- if (defined(classes)) {
- for (let classIndex = 0; classIndex < classes.length; classIndex++) {
- const classSymbology = parseSymbol(
- classes[classIndex].symbol,
- isColorCaptured,
- );
- const values = classes[classIndex].values;
- for (let valueIndex = 0; valueIndex < values.length; valueIndex++) {
- const fieldValues = values[valueIndex];
- let hash = valueHash;
- for (
- let fieldIndex = 0;
- fieldIndex < fieldValues.length;
- fieldIndex++
- ) {
- const fieldValue = fieldValues[fieldIndex];
- if (fieldIndex === fieldValues.length - 1) {
- hash[fieldValue] = classSymbology;
- } else {
- if (!defined(hash[fieldValue])) {
- hash[fieldValue] = {};
- }
- hash = hash[fieldValue];
- }
- }
- }
- }
- }
- }
- return valueHash;
- }
- if (defined(renderer.uniqueValueInfos)) {
- const valueHash = {};
- for (
- let infoIndex = 0;
- infoIndex < renderer.uniqueValueInfos.length;
- infoIndex++
- ) {
- const info = renderer.uniqueValueInfos[infoIndex];
- valueHash[info.value] = parseSymbol(info.symbol, isColorCaptured);
- }
- return valueHash;
- }
- return undefined;
- }
-
- function buildClassBreaksHash(renderer, isColorCaptured) {
- if (defined(renderer.classBreakInfos)) {
- const classBreakInfos = [...renderer.classBreakInfos];
- classBreakInfos.sort(function (a, b) {
- const aMax = a.classMaxValue ?? a.classMinValue;
- const bMax = b.classMaxValue ?? b.classMinValue;
- return aMax - bMax;
- });
- const valueHash = {
- ranges: [],
- symbols: [],
- };
-
- if (defined(renderer.minValue)) {
- valueHash.ranges.push(renderer.minValue);
- valueHash.symbols.push(undefined);
- }
- for (let infoIndex = 0; infoIndex < classBreakInfos.length; infoIndex++) {
- const info = classBreakInfos[infoIndex];
- if (defined(info.classMinValue)) {
- if (
- valueHash.ranges.length === 0 ||
- info.classMinValue > valueHash.ranges[valueHash.ranges.length - 1]
- ) {
- valueHash.ranges.push(info.classMinValue);
- valueHash.symbols.push(undefined);
- }
- }
- if (defined(info.classMaxValue)) {
- if (
- valueHash.ranges.length === 0 ||
- info.classMaxValue > valueHash.ranges[valueHash.ranges.length - 1]
- ) {
- valueHash.ranges.push(info.classMaxValue);
- valueHash.symbols.push(parseSymbol(info.symbol, isColorCaptured));
- }
- }
- }
- valueHash.symbols.push(undefined);
-
- return valueHash;
- }
- return undefined;
- }
-
- /**
- * @private
- */
- I3SSymbology.prototype._parseLayerSymbology = function () {
- const drawingInfo = this._layer.data.drawingInfo;
- if (defined(drawingInfo) && defined(drawingInfo.renderer)) {
- const cachedDrawingInfo = this._layer.data.cachedDrawingInfo;
- const isColorCaptured =
- defined(cachedDrawingInfo) && cachedDrawingInfo.color === true;
- const renderer = drawingInfo.renderer;
- if (renderer.type === "simple") {
- this._defaultSymbology = parseSymbol(renderer.symbol, isColorCaptured);
- } else if (renderer.type === "uniqueValue") {
- this._defaultSymbology = parseSymbol(
- renderer.defaultSymbol,
- isColorCaptured,
- );
- this._valueFields.push(renderer.field1);
- if (defined(renderer.field2)) {
- this._valueFields.push(renderer.field2);
- }
- if (defined(renderer.field3)) {
- this._valueFields.push(renderer.field3);
- }
- this._uniqueValueHash = buildUniqueValueHash(renderer, isColorCaptured);
- } else if (renderer.type === "classBreaks") {
- this._defaultSymbology = parseSymbol(
- renderer.defaultSymbol,
- isColorCaptured,
- );
- this._valueFields.push(renderer.field);
- this._classBreaksHash = buildClassBreaksHash(renderer, isColorCaptured);
- }
- }
- };
-
- function findHashForUniqueValues(hash, values, hashLevel, valueIndex) {
- const levelValues = values[hashLevel];
- if (valueIndex < levelValues.length) {
- const hashValue = levelValues[valueIndex];
- const innerHash = hash[hashValue];
- if (defined(innerHash) && ++hashLevel < values.length) {
- return findHashForUniqueValues(innerHash, values, hashLevel, valueIndex);
- }
- return innerHash;
- }
- return undefined;
- }
-
- function bisect(array, value) {
- let low = 0;
- let high = array.length;
- if (low < high) {
- do {
- const mid = (low + high) >>> 1;
- if (array[mid] < value) {
- low = mid + 1;
- } else {
- high = mid;
- }
- } while (low < high);
- }
- return low;
- }
-
- function findHashForClassBreaks(hash, values, valueIndex) {
- const value = values[valueIndex];
- const range = bisect(hash.ranges, value);
- return hash.symbols[range];
- }
-
- /**
- * @private
- */
- I3SSymbology.prototype._getSymbology = async function (node) {
- const symbology = {
- default: this._defaultSymbology,
- };
-
- if (this._valueFields.length > 0) {
- const promises = [];
- for (let i = 0; i < this._valueFields.length; i++) {
- promises.push(node.loadField(this._valueFields[i]));
- }
- await Promise.all(promises);
-
- const fieldsValues = [];
- for (let i = 0; i < this._valueFields.length; i++) {
- fieldsValues.push(node.fields[this._valueFields[i]].values);
- }
-
- let featureHashFn;
- if (defined(this._uniqueValueHash)) {
- featureHashFn = (featureIndex) =>
- findHashForUniqueValues(
- this._uniqueValueHash,
- fieldsValues,
- 0,
- featureIndex,
- );
- } else if (defined(this._classBreaksHash)) {
- featureHashFn = (featureIndex) =>
- findHashForClassBreaks(
- this._classBreaksHash,
- fieldsValues[0],
- featureIndex,
- );
- }
-
- if (defined(featureHashFn)) {
- const firstFieldValues = fieldsValues[0];
- for (
- let featureIndex = 0;
- featureIndex < firstFieldValues.length;
- featureIndex++
- ) {
- const featureSymbology = featureHashFn(featureIndex);
- if (defined(featureSymbology)) {
- symbology[featureIndex] = featureSymbology;
- }
- }
- }
- }
-
- return symbology;
- };
-
- export default I3SSymbology;
|