qwc2
Version:
QGIS Web Client
243 lines (238 loc) • 12.4 kB
JavaScript
function _slicedToArray(r, e) { return _arrayWithHoles(r) || _iterableToArrayLimit(r, e) || _unsupportedIterableToArray(r, e) || _nonIterableRest(); }
function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
function _iterableToArrayLimit(r, l) { var t = null == r ? null : "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (null != t) { var e, n, i, u, a = [], f = !0, o = !1; try { if (i = (t = t.call(r)).next, 0 === l) { if (Object(t) !== t) return; f = !1; } else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0); } catch (r) { o = !0, n = r; } finally { try { if (!f && null != t["return"] && (u = t["return"](), Object(u) !== u)) return; } finally { if (o) throw n; } } return a; } }
function _arrayWithHoles(r) { if (Array.isArray(r)) return r; }
function _toConsumableArray(r) { return _arrayWithoutHoles(r) || _iterableToArray(r) || _unsupportedIterableToArray(r) || _nonIterableSpread(); }
function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }
function _iterableToArray(r) { if ("undefined" != typeof Symbol && null != r[Symbol.iterator] || null != r["@@iterator"]) return Array.from(r); }
function _arrayWithoutHoles(r) { if (Array.isArray(r)) return _arrayLikeToArray(r); }
function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }
/**
* Copyright 2025 Sourcepole AG
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree.
*/
import { Parser as ExprParser } from 'expr-eval';
import isEmpty from "lodash.isempty";
import parseCssColor from 'parse-css-color';
import { Float32BufferAttribute, Group, Vector3 } from "three";
import MiscUtils from '../../../utils/MiscUtils';
import { createLabelObject, TileMeshHelper } from "./MiscUtils3D";
var styleExpressionParser = new ExprParser();
styleExpressionParser.functions.color = function (name) {
var alpha = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 1;
var color = parseCssColor(name);
return [].concat(_toConsumableArray(color.values.map(function (c) {
return c / 255;
})), [alpha]);
};
styleExpressionParser.functions.rgb = function (r, g, b) {
return [r / 255, g / 255, g / 255, 1];
};
styleExpressionParser.functions.rgba = function (r, g, b, a) {
return [r / 255, g / 255, g / 255, a];
};
styleExpressionParser.functions.hsl = function (h, s, l) {
return [].concat(_toConsumableArray(MiscUtils.hslToRgb(h, s, l)), [1]);
};
styleExpressionParser.functions.hsla = function (h, s, l, a) {
return [].concat(_toConsumableArray(MiscUtils.hslToRgb(h, s, l)), [a]);
};
function featureColor(objectId, featureProperties, context) {
var _context$featureStyle, _context$featureStyle2;
if (((_context$featureStyle = (_context$featureStyle2 = context.featureStyles) === null || _context$featureStyle2 === void 0 || (_context$featureStyle2 = _context$featureStyle2[objectId]) === null || _context$featureStyle2 === void 0 ? void 0 : _context$featureStyle2.color) !== null && _context$featureStyle !== void 0 ? _context$featureStyle : null) !== null) {
var color = parseCssColor(context.featureStyles[objectId].color);
return [].concat(_toConsumableArray(color.values.map(function (c) {
return c / 255;
})), [color.alpha]);
} else if (context.colorExpressions.length) {
try {
for (var i = 0; i < context.colorExpressions.length; ++i) {
var condition = context.colorExpressions[i][0].evaluate(featureProperties);
if (condition) {
return context.colorExpressions[i][1].evaluate(featureProperties);
}
}
} catch (e) {
/* eslint-disable-next-line */
console.warn("Failed to parse color expression: " + String(e));
}
return null;
} else if (featureProperties[context.colorAttr]) {
var _featureProperties$co;
var _color = featureProperties[context.colorAttr];
var alpha = context.alphaAttr ? (_featureProperties$co = featureProperties[context.alphaAttr]) !== null && _featureProperties$co !== void 0 ? _featureProperties$co : 255 : 255;
var r = (_color >> 16 & 0xff) / 255;
var g = (_color >> 8 & 0xff) / 255;
var b = (_color & 0xff) / 255;
return [r, g, b, alpha / 255];
} else {
return null;
}
}
function featureLabel(objectId, featureProperties, context) {
var _context$featureStyle3, _context$featureStyle4;
if (((_context$featureStyle3 = (_context$featureStyle4 = context.featureStyles) === null || _context$featureStyle4 === void 0 || (_context$featureStyle4 = _context$featureStyle4[objectId]) === null || _context$featureStyle4 === void 0 ? void 0 : _context$featureStyle4.label) !== null && _context$featureStyle3 !== void 0 ? _context$featureStyle3 : null) !== null) {
var _context$featureStyle5;
return {
text: context.featureStyles[objectId].label,
offset: (_context$featureStyle5 = context.featureStyles[objectId].labelOffset) !== null && _context$featureStyle5 !== void 0 ? _context$featureStyle5 : 80
};
} else if (context.labelAttr) {
return featureProperties[context.labelAttr];
} else {
return null;
}
}
var Tiles3DStyle = {
applyTileStyle: function applyTileStyle(group, config, sceneContext) {
var _config$idAttr, _config$tilesetStyle, _config$tilesetStyle2;
var featureColorCache = {};
var featureLabelCache = {};
var labels = {};
var idAttr = (_config$idAttr = config.idAttr) !== null && _config$idAttr !== void 0 ? _config$idAttr : "id";
var context = {
colorExpressions: [],
featureStyles: (_config$tilesetStyle = config.tilesetStyle) === null || _config$tilesetStyle === void 0 ? void 0 : _config$tilesetStyle.featureStyles,
colorAttr: config.colorAttr,
alphaAttr: config.alphaAttr,
labelAttr: config.labelAttr
};
var baseColor = [1, 1, 1, 1];
var customBaseColor = false;
if (config.baseColor) {
var color = parseCssColor(config.baseColor);
baseColor = [].concat(_toConsumableArray(color.values.map(function (x) {
return x / 255;
})), [color.alpha]);
customBaseColor = true;
}
var colorRules = (_config$tilesetStyle2 = config.tilesetStyle) === null || _config$tilesetStyle2 === void 0 ? void 0 : _config$tilesetStyle2.color;
var parseExpr = function parseExpr(expr) {
var cleanExpr = expr.replace(/\$\{(\w+)\}/g, '$1').replaceAll('===', '==').replaceAll('!==', '==').replaceAll('||', 'or').replaceAll('&&', 'and');
return styleExpressionParser.parse(cleanExpr);
};
if (colorRules !== null && colorRules !== void 0 && colorRules.conditions) {
colorRules === null || colorRules === void 0 || colorRules.conditions.forEach(function (cond) {
context.colorExpressions.push([parseExpr(cond[0]), parseExpr(cond[1])]);
});
} else if (typeof colorRules === "string") {
context.colorExpressions.push([parseExpr("true"), parseExpr(colorRules)]);
}
group.traverse(function (c) {
if (c.geometry) {
var helper = new TileMeshHelper(c);
var featureIdAttr = helper.getFeatureIdAttr();
if (!featureIdAttr) {
return;
}
var posAttr = c.geometry.getAttribute('position');
var rgbaColors = [];
var rgbColors = [];
var haveColor = customBaseColor;
var haveAlpha = baseColor[3] < 1;
for (var idx = 0; idx < featureIdAttr.count; ++idx) {
var featureId = featureIdAttr.getX(idx);
var featureProperties = helper.getFeatureProperties(featureId);
var objectId = String(featureProperties[idAttr]);
// Handle color
var _color2 = featureColorCache[featureId];
if (_color2 === undefined) {
_color2 = featureColorCache[featureId] = featureColor(objectId, featureProperties, context);
}
if (_color2) {
haveColor = true;
haveAlpha |= _color2[3] < 1;
rgbaColors.push.apply(rgbaColors, _toConsumableArray(_color2));
rgbColors.push.apply(rgbColors, _toConsumableArray(_color2.slice(0, 3)));
} else {
rgbaColors.push.apply(rgbaColors, _toConsumableArray(baseColor));
rgbColors.push.apply(rgbColors, _toConsumableArray(baseColor.slice(0, 3)));
}
// Handle label
var label = featureLabelCache[featureId];
if (label === undefined) {
label = featureLabelCache[featureId] = featureLabel(objectId, featureProperties, context);
}
if (label) {
var pos = posAttr.array.slice(3 * idx, 3 * idx + 3);
var entry = labels[featureId];
if (!entry) {
entry = labels[featureId] = {
label: label.text,
labelOffset: label.offset,
pos: pos,
ymax: pos[1],
count: 1,
matrix: c.matrixWorld
};
} else {
entry.pos[0] += pos[0];
entry.pos[1] += pos[1];
entry.pos[2] += pos[2];
entry.ymax = Math.max(entry.ymax, pos[1]);
++entry.count;
}
}
}
// NOTE: Also update color buffers if they were previously colored
if (haveColor || group.userData.haveColor) {
if (haveAlpha) {
c.geometry.setAttribute('color', new Float32BufferAttribute(rgbaColors, 4));
} else {
// Discard alpha
var count = rgbaColors.length / 4;
var bufAttr = new Float32BufferAttribute(count * 3, 3);
for (var i = 0, j = 0; i < count; ++i) {
bufAttr.array[j++] = rgbaColors[4 * i];
bufAttr.array[j++] = rgbaColors[4 * i + 1];
bufAttr.array[j++] = rgbaColors[4 * i + 2];
}
c.geometry.setAttribute('color', bufAttr);
}
c.material.vertexColors = true;
c.material.transparent = haveAlpha;
group.userData.haveColor = haveColor;
}
}
});
// Clear previous labels
if (group.userData.labelGroup) {
group.remove(group.children.find(function (child) {
return child.uuid === group.userData.labelGroup;
}));
// Explicitly remove label DOM elements
Object.values(group.userData.tileLabels).forEach(function (entry) {
entry.labelObject.element.parentNode.removeChild(entry.labelObject.element);
});
delete group.userData.tileLabels;
delete group.userData.labelGroup;
}
// Add new labels
if (!isEmpty(labels)) {
var tileLabels = {};
var labelObjects = new Group();
Object.entries(labels).forEach(function (_ref) {
var _ref2 = _slicedToArray(_ref, 2),
featureId = _ref2[0],
entry = _ref2[1];
var pos = new Vector3(entry.pos[0] / entry.count, entry.pos[1] / entry.count, entry.pos[2] / entry.count).applyMatrix4(entry.matrix);
var maxpos = new Vector3(entry.pos[0] / entry.count, entry.ymax, entry.pos[2] / entry.count).applyMatrix4(entry.matrix);
tileLabels[featureId] = {
pos: pos,
label: entry.label,
labelOffset: entry.labelOffset
};
tileLabels[featureId].labelObject = createLabelObject(entry.label, pos, sceneContext, 0, entry.labelOffset + (maxpos.y - pos.y));
labelObjects.add(tileLabels[featureId].labelObject);
});
group.userData.tileLabels = tileLabels;
group.userData.labelGroup = labelObjects.uuid;
group.add(labelObjects);
}
}
};
export default Tiles3DStyle;