itowns
Version:
A JS/WebGL framework for 3D geospatial data visualization
288 lines (237 loc) • 9.36 kB
JavaScript
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
var _interopRequireWildcard = require("@babel/runtime/helpers/interopRequireWildcard");
Object.defineProperty(exports, "__esModule", {
value: true
});
exports["default"] = void 0;
var THREE = _interopRequireWildcard(require("three"));
var _LayerUpdateState = _interopRequireDefault(require("../Layer/LayerUpdateState"));
var _ObjectRemovalHelper = _interopRequireDefault(require("./ObjectRemovalHelper"));
var _handlerNodeError = _interopRequireDefault(require("./handlerNodeError"));
var _Coordinates = _interopRequireDefault(require("../Core/Geographic/Coordinates"));
var _Extent = _interopRequireDefault(require("../Core/Geographic/Extent"));
var _extent = new _Extent["default"]('EPSG:4326', 0, 0, 0, 0);
var coord = new _Coordinates["default"]('EPSG:4326', 0, 0, 0);
var vector = new THREE.Vector3();
var tmp = new THREE.Vector3();
function applyOffset(obj, offset, quaternion) {
var offsetAltitude = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : 0;
if (obj.geometry) {
if (obj.geometry.isBufferGeometry) {
var count = obj.geometry.attributes.position.count * 3;
for (var i = 0; i < count; i += 3) {
vector.fromArray(obj.geometry.attributes.position.array, i);
vector.add(offset).applyQuaternion(quaternion);
vector.z -= offsetAltitude;
vector.toArray(obj.geometry.attributes.position.array, i);
}
obj.geometry.attributes.position.needsUpdate = true;
} else {
var _iteratorNormalCompletion = true;
var _didIteratorError = false;
var _iteratorError = undefined;
try {
for (var _iterator = obj.geometry.vertices[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
var v = _step.value;
v.add(offset).applyQuaternion(quaternion);
v.z -= offsetAltitude;
}
} catch (err) {
_didIteratorError = true;
_iteratorError = err;
} finally {
try {
if (!_iteratorNormalCompletion && _iterator["return"] != null) {
_iterator["return"]();
}
} finally {
if (_didIteratorError) {
throw _iteratorError;
}
}
}
obj.geometry.verticesNeedUpdate = true;
}
}
obj.children.forEach(function (c) {
return applyOffset(c, offset, quaternion, offsetAltitude);
});
}
function assignLayer(object, layer) {
if (object) {
object.layer = layer;
if (object.material) {
object.material.transparent = layer.opacity < 1.0;
object.material.opacity = layer.opacity;
object.material.wireframe = layer.wireframe;
if (layer.size) {
object.material.size = layer.size;
}
if (layer.linewidth) {
object.material.linewidth = layer.linewidth;
}
}
object.layers.set(layer.threejsLayer);
var _iteratorNormalCompletion2 = true;
var _didIteratorError2 = false;
var _iteratorError2 = undefined;
try {
for (var _iterator2 = object.children[Symbol.iterator](), _step2; !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true) {
var c = _step2.value;
assignLayer(c, layer);
}
} catch (err) {
_didIteratorError2 = true;
_iteratorError2 = err;
} finally {
try {
if (!_iteratorNormalCompletion2 && _iterator2["return"] != null) {
_iterator2["return"]();
}
} finally {
if (_didIteratorError2) {
throw _iteratorError2;
}
}
}
return object;
}
}
function extentInsideSource(extent, source) {
return !source.extentInsideLimit(extent) || source.parsedData && !source.parsedData.extent.isPointInside(extent.center(coord));
}
var quaternion = new THREE.Quaternion();
var _default = {
update: function update(context, layer, node) {
if (!node.parent && node.children.length) {
// if node has been removed dispose three.js resource
_ObjectRemovalHelper["default"].removeChildrenAndCleanupRecursively(layer, node);
return;
}
if (!node.visible) {
return;
}
if (node.layerUpdateState[layer.id] === undefined) {
node.layerUpdateState[layer.id] = new _LayerUpdateState["default"]();
}
if (!node.layerUpdateState[layer.id].canTryUpdate()) {
return;
}
var features = node.children.filter(function (n) {
return n.layer == layer;
});
if (features.length > 0) {
return features;
}
var extentsDestination = node.getExtentsByProjection(layer.source.projection) || [node.extent];
extentsDestination.forEach(function (e) {
e.zoom = node.level;
});
var extentsSource = [];
var _iteratorNormalCompletion3 = true;
var _didIteratorError3 = false;
var _iteratorError3 = undefined;
try {
for (var _iterator3 = extentsDestination[Symbol.iterator](), _step3; !(_iteratorNormalCompletion3 = (_step3 = _iterator3.next()).done); _iteratorNormalCompletion3 = true) {
var extentDest = _step3.value;
var ext = layer.source.projection == extentDest.crs ? extentDest : extentDest.as(layer.source.projection);
ext.zoom = extentDest.zoom;
if (extentInsideSource(ext, layer.source)) {
node.layerUpdateState[layer.id].noMoreUpdatePossible();
return;
}
extentsSource.push(extentDest);
}
} catch (err) {
_didIteratorError3 = true;
_iteratorError3 = err;
} finally {
try {
if (!_iteratorNormalCompletion3 && _iterator3["return"] != null) {
_iterator3["return"]();
}
} finally {
if (_didIteratorError3) {
throw _iteratorError3;
}
}
}
node.layerUpdateState[layer.id].newTry();
var command = {
layer: layer,
extentsSource: extentsSource,
view: context.view,
threejsLayer: layer.threejsLayer,
requester: node
};
return context.scheduler.execute(command).then(function (result) {
// if request return empty json, WFSProvider.getFeatures return undefined
result = result[0];
if (result) {
// special case for FileSource, as it is not tiled and we need
// to attach it to the correct node
if (layer.source && layer.source.isFileSource) {
var _iteratorNormalCompletion4 = true;
var _didIteratorError4 = false;
var _iteratorError4 = undefined;
try {
for (var _iterator4 = extentsSource[Symbol.iterator](), _step4; !(_iteratorNormalCompletion4 = (_step4 = _iterator4.next()).done); _iteratorNormalCompletion4 = true) {
var extentSrc = _step4.value;
var ext = extentSrc.crs == layer.source.projection ? extentSrc : extentSrc.as(layer.source.projection, _extent);
ext.zoom = extentSrc.zoom;
if (extentInsideSource(ext, layer.source)) {
node.layerUpdateState[layer.id].noMoreUpdatePossible();
return;
}
}
} catch (err) {
_didIteratorError4 = true;
_iteratorError4 = err;
} finally {
try {
if (!_iteratorNormalCompletion4 && _iterator4["return"] != null) {
_iterator4["return"]();
}
} finally {
if (_didIteratorError4) {
throw _iteratorError4;
}
}
}
}
var isApplied = !result.layer;
result.minAltitude = isNaN(result.minAltitude) ? 0 : result.minAltitude;
assignLayer(result, layer); // call onMeshCreated callback if needed
if (layer.onMeshCreated) {
layer.onMeshCreated(result);
}
node.layerUpdateState[layer.id].success();
if (!node.parent) {
_ObjectRemovalHelper["default"].removeChildrenAndCleanupRecursively(layer, result);
return;
} // We don't use node.matrixWorld here, because feature coordinates are
// expressed in crs coordinates (which may be different than world coordinates,
// if node's layer is attached to an Object with a non-identity transformation)
if (isApplied) {
// NOTE: now data source provider use cache on Mesh
// TODO move transform in feature2Mesh
node.extent.center(coord).as(context.view.referenceCrs, coord).toVector3(tmp).negate();
quaternion.setFromRotationMatrix(node.matrixWorld).inverse(); // const quaternion = new THREE.Quaternion().setFromUnitVectors(new THREE.Vector3(0, 0, 1), node.extent.center().geodesicNormal).inverse();
applyOffset(result, tmp, quaternion, result.minAltitude);
}
if (result.minAltitude) {
result.position.z = result.minAltitude;
}
result.layer = layer;
node.add(result);
node.updateMatrixWorld();
} else {
node.layerUpdateState[layer.id].failure(1, true);
}
}, function (err) {
return (0, _handlerNodeError["default"])(err, node, layer, node.level, context.view);
});
}
};
exports["default"] = _default;
;