From 17c25468c7b9d552a8c09ef5abdbbe734e1ca4f4 Mon Sep 17 00:00:00 2001 From: Adrien Berthet Date: Tue, 27 Feb 2018 13:06:39 +0100 Subject: [PATCH] refactor(core): Homogenize all providers as static There is no reason to keep an instance of each provider, and moving them to static like some other one (PointCloudProvider for example) do no harm, but homogenize all providers to one structure. Also note that there are two required functions in a provider: preprocessDataLayer and executeCommand, that are verified when adding a provider, in the scheduler. BREAKING CHANGE: KML_Provider and BuildingBox_Provider have been removed, as well as getPointOrder from WFS_Provider. --- .../Scheduler/Providers/3dTiles_Provider.js | 50 +- .../Providers/BuildingBox_Provider.js | 211 ------ src/Core/Scheduler/Providers/KML_Provider.js | 655 ------------------ src/Core/Scheduler/Providers/Provider.js | 16 - src/Core/Scheduler/Providers/TMS_Provider.js | 36 +- src/Core/Scheduler/Providers/TileProvider.js | 29 +- src/Core/Scheduler/Providers/WFS_Provider.js | 72 +- src/Core/Scheduler/Providers/WMS_Provider.js | 60 +- src/Core/Scheduler/Providers/WMTS_Provider.js | 68 +- src/Core/Scheduler/Scheduler.js | 25 +- test/scheduler_unit_test.js | 2 + 11 files changed, 151 insertions(+), 1073 deletions(-) delete mode 100644 src/Core/Scheduler/Providers/BuildingBox_Provider.js delete mode 100644 src/Core/Scheduler/Providers/KML_Provider.js delete mode 100644 src/Core/Scheduler/Providers/Provider.js diff --git a/src/Core/Scheduler/Providers/3dTiles_Provider.js b/src/Core/Scheduler/Providers/3dTiles_Provider.js index 15a35573f6..63ba4a5473 100644 --- a/src/Core/Scheduler/Providers/3dTiles_Provider.js +++ b/src/Core/Scheduler/Providers/3dTiles_Provider.js @@ -1,5 +1,4 @@ import * as THREE from 'three'; -import Provider from './Provider'; import B3dmLoader from '../../../Renderer/ThreeExtended/B3dmLoader'; import PntsLoader from '../../../Renderer/ThreeExtended/PntsLoader'; import Fetcher from './Fetcher'; @@ -10,7 +9,6 @@ import Capabilities from '../../System/Capabilities'; import PrecisionQualifier from '../../../Renderer/Shader/Chunk/PrecisionQualifier.glsl'; import { init3dTilesLayer } from '../../../Process/3dTilesProcessing'; - function $3dTilesIndex(tileset, baseURL) { let counter = 0; this.index = {}; @@ -63,19 +61,7 @@ function $3dTilesIndex(tileset, baseURL) { }; } -function $3dTiles_Provider() { - Provider.call(this); -} - -$3dTiles_Provider.prototype = Object.create(Provider.prototype); - -$3dTiles_Provider.prototype.constructor = $3dTiles_Provider; - -$3dTiles_Provider.prototype.removeLayer = function removeLayer() { - -}; - -$3dTiles_Provider.prototype.preprocessDataLayer = function preprocessDataLayer(layer, view, scheduler) { +function preprocessDataLayer(layer, view, scheduler) { layer.sseThreshold = layer.sseThreshold || 16; layer.cleanupDelay = layer.cleanupDelay || 1000; @@ -87,7 +73,7 @@ $3dTiles_Provider.prototype.preprocessDataLayer = function preprocessDataLayer(l layer.asset = tileset.asset; return init3dTilesLayer(view, scheduler, layer, tileset.root); }); -}; +} function getBox(volume, inverseTileTransform) { if (volume.region) { @@ -159,9 +145,11 @@ export function patchMaterialForLogDepthSupport(material) { }; } -$3dTiles_Provider.prototype.b3dmToMesh = function b3dmToMesh(data, layer, url) { - this._b3dmLoader = this._b3dmLoader || new B3dmLoader(); - return this._b3dmLoader.parse(data, layer.asset.gltfUpAxis, url, this._textDecoder).then((result) => { +let b3dmLoader; +let textDecoder; +function b3dmToMesh(data, layer, url) { + b3dmLoader = b3dmLoader || new B3dmLoader(); + return b3dmLoader.parse(data, layer.asset.gltfUpAxis, url, textDecoder).then((result) => { const init = function f_init(mesh) { mesh.frustumCulled = false; if (mesh.material) { @@ -189,13 +177,13 @@ $3dTiles_Provider.prototype.b3dmToMesh = function b3dmToMesh(data, layer, url) { const object3d = result.gltf.scene; return { batchTable, object3d }; }); -}; +} -$3dTiles_Provider.prototype.pntsParse = function pntsParse(data) { +function pntsParse(data) { return new Promise((resolve) => { - resolve({ object3d: PntsLoader.parse(data, this._textDecoder).point }); + resolve({ object3d: PntsLoader.parse(data, textDecoder).point }); }); -}; +} function configureTile(tile, layer, metadata, parent) { tile.frustumCulled = false; @@ -220,14 +208,13 @@ function configureTile(tile, layer, metadata, parent) { tile.updateMatrixWorld(); } -$3dTiles_Provider.prototype.executeCommand = function executeCommand(command) { +function executeCommand(command) { const layer = command.layer; const metadata = command.metadata; const tile = new THREE.Object3D(); configureTile(tile, layer, metadata, command.requester); const path = metadata.content ? metadata.content.url : undefined; - this._textDecoder = this._textDecoder || new TextDecoder('utf-8'); - const textDecoder = this._textDecoder; + textDecoder = textDecoder || new TextDecoder('utf-8'); const setLayer = (obj) => { obj.layers.set(layer.threejsLayer); @@ -236,8 +223,8 @@ $3dTiles_Provider.prototype.executeCommand = function executeCommand(command) { // Check if we have relative or absolute url (with tileset's lopocs for example) const url = path.startsWith('http') ? path : metadata.baseURL + path; const supportedFormats = { - b3dm: this.b3dmToMesh.bind(this), - pnts: this.pntsParse.bind(this), + b3dm: b3dmToMesh, + pnts: pntsParse, }; return Fetcher.arrayBuffer(url, layer.networkOptions).then((result) => { if (result !== undefined) { @@ -276,6 +263,9 @@ $3dTiles_Provider.prototype.executeCommand = function executeCommand(command) { resolve(tile); }); } -}; +} -export default $3dTiles_Provider; +export default { + preprocessDataLayer, + executeCommand, +}; diff --git a/src/Core/Scheduler/Providers/BuildingBox_Provider.js b/src/Core/Scheduler/Providers/BuildingBox_Provider.js deleted file mode 100644 index 0a887b517e..0000000000 --- a/src/Core/Scheduler/Providers/BuildingBox_Provider.js +++ /dev/null @@ -1,211 +0,0 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ - - -/** - * Generated On: 2015-10-5 - * Class: WMTS_Provider - * Description: Fournisseur de données à travers un flux WMTS - */ - - -// TODO , will use WFS_Provider -import * as THREE from 'three'; -import Earcut from 'earcut'; -import Provider from './Provider'; -import WFS_Provider from './WFS_Provider'; -import Coordinates, { C } from '../../Geographic/Coordinates'; - -function BuildingBox_Provider(options) { - // Constructor - - // Provider.call( this,new IoDriver_XBIL()); - // this.cache = CacheRessource(); - this.WFS_Provider = new WFS_Provider(options); - this.geometry = null; - this.geometryRoof = null; - this.pivot = null; - this.roadOn = true; - this.rtcOn = true; -} - -BuildingBox_Provider.prototype = Object.create(Provider.prototype); -BuildingBox_Provider.prototype.constructor = BuildingBox_Provider; - - -/** - * Return url wmts MNT - * @param {number} longitude - * @param {number} latitude - * @param {number} radius - * @returns {string} - */ -BuildingBox_Provider.prototype.url = function url(longitude, latitude, radius) { - // var key = "wmybzw30d6zg563hjlq8eeqb"; - // var key = coWMTS.zoom > 11 ? "va5orxd0pgzvq3jxutqfuy0b" : "wmybzw30d6zg563hjlq8eeqb"; // clef pro va5orxd0pgzvq3jxutqfuy0b - - var key = '72hpsel8j8nhb5qgdh07gcyp'; - - // var layer = "BDTOPO_BDD_WLD_WGS84G:bati_remarquable,BDTOPO_BDD_WLD_WGS84G:bati_indifferencie" - var serviceVersionRequestLayer = 'service=WFS&version=2.0.0&REQUEST=GetFeature&typeName=BDTOPO_BDD_WLD_WGS84G:bati_remarquable,BDTOPO_BDD_WLD_WGS84G:bati_indifferencie'; - - var bottomLeft = new THREE.Vector2(longitude - radius, latitude - radius); - var topRight = new THREE.Vector2(longitude + radius, latitude + radius); - - - var url = `http://wxs.ign.fr/${key}/geoportail/wfs?${serviceVersionRequestLayer - }&bbox=${bottomLeft.x},${bottomLeft.y},${topRight.x - },${topRight.y},epsg:4326&outputFormat=json`; - - return url; -}; - -BuildingBox_Provider.prototype.getData = function getData(bbox, altitude) { - return this.WFS_Provider.getData(bbox).then((data) => { - this.generateMesh(data, bbox, altitude); // console.log(data); - return this.geometry; - }); -}; - -BuildingBox_Provider.prototype.generateMesh = function generateMesh(elements, bbox, altitude) { - var roofGeometry = new THREE.Geometry(); // for the roof - var _geometry = new THREE.Geometry(); // for the walls - var geometry = new THREE.Geometry(); // for the roof - var suppHeight = 10; // So we don't cut the roof - var features = elements.features; - var altitude_ground = altitude - 1.5; // 35; // truck height - - for (const feature of features) { - const hauteur = (feature.properties.hauteur + suppHeight) || 0; - const z_min = altitude_ground; // features[r].properties.z_min; // altitude_ground // force altitude ground - const polygon = feature.geometry.coordinates[0][0]; - - const arrPoint2D = []; - if (polygon.length > 2) { - // VERTICES - for (let j = 0; j < polygon.length - 1; ++j) { - const pt2DTab = polygon[j]; // .split(' '); - const p1 = new THREE.Vector3(parseFloat(pt2DTab[0]), 0, parseFloat(pt2DTab[1])); - - const coordCarto1 = new Coordinates('EPSG:4326', p1.x, p1.z, z_min); - const coordCarto2 = new Coordinates('EPSG:4326', p1.x, p1.z, z_min + hauteur); // + Math.random(1000) ); - const pgeo1 = coordCarto1.as('EPSG:4978').xyz(); - const pgeo2 = coordCarto2.as('EPSG:4978').xyz(); - - const vector3_1 = new THREE.Vector3(pgeo1.x, pgeo1.y, pgeo1.z); // - x temporary, bug - const vector3_2 = new THREE.Vector3(pgeo2.x, pgeo2.y, pgeo2.z); - - - arrPoint2D.push(p1.z, p1.x); - _geometry.vertices.push(vector3_1, vector3_2); - } - - // FACES - // indice of the first point of the polygon 3D - for (let k = _geometry.vertices.length - ((polygon.length - 1) * 2); k < _geometry.vertices.length; k += 2) { - let l = k; // % (pts2DTab.length); - if (l > _geometry.vertices.length - 4) { - l = _geometry.vertices.length - ((polygon.length - 1) * 2); - } - _geometry.faces.push(new THREE.Face3(l, l + 1, l + 3)); - _geometry.faces.push(new THREE.Face3(l, l + 3, l + 2)); - } - - const ll = _geometry.vertices.length - ((polygon.length - 1) * 2); - _geometry.faces.push(new THREE.Face3(ll, ll + 1, _geometry.vertices.length - 1)); - _geometry.faces.push(new THREE.Face3(ll, _geometry.vertices.length - 1, _geometry.vertices.length - 2)); - } - - //* *************** ROOF **************************** - - var triangles = Earcut(arrPoint2D); - for (let w = 0; w < triangles.length; w += 3) { - const pt1 = new THREE.Vector2(arrPoint2D[triangles[w] * 2], arrPoint2D[triangles[w] * 2 + 1]); - const pt2 = new THREE.Vector2(arrPoint2D[triangles[w + 1] * 2], arrPoint2D[triangles[w + 1] * 2 + 1]); - const pt3 = new THREE.Vector2(arrPoint2D[triangles[w + 2] * 2], arrPoint2D[triangles[w + 2] * 2 + 1]); - const c1 = new C.EPSG_4326(pt1.x, pt1.y, z_min + hauteur); - const c2 = new C.EPSG_4326(pt2.x, pt2.y, z_min + hauteur); - const c3 = new C.EPSG_4326(pt3.x, pt3.y, z_min + hauteur); - - roofGeometry.vertices.push(c1.as('EPSG:4978').xyz()); - roofGeometry.vertices.push(c2.as('EPSG:4978').xyz()); - roofGeometry.vertices.push(c3.as('EPSG:4978').xyz()); - - var face = new THREE.Face3(geometry.vertices.length - 3, - geometry.vertices.length - 2, - geometry.vertices.length - 1); - geometry.faces.push(face); - } - } - - if (this.roadOn) { - this.addRoad(_geometry, bbox, altitude_ground); - } - - _geometry.computeFaceNormals(); // WARNING : VERY IMPORTANT WHILE WORKING WITH RAY CASTING ON CUSTOM MESH - geometry.computeFaceNormals(); - - /* - var matLambert = new THREE.MeshBasicMaterial({color: 0xffffff, transparent: true, opacity: 0.8}); - var _currentMeshForRoof = new THREE.Mesh(_geometry, matLambert);// //geometryClickToGo,mat); - gfxEngine().add3DScene(_currentMeshForRoof); - */ - - // Test if we return brute geometry or if we use local pivot (for useRTC) - var firstPos = new THREE.Vector3(); - if (this.rtcOn) { - firstPos = _geometry.vertices[0].clone(); - // create pivot from 1st pos vertex - for (const vertice of _geometry.vertices) { - vertice.sub(firstPos); - } - for (const vertice of geometry.vertices) { - vertice.sub(firstPos); - } - } - - this.geometry = _geometry; - this.pivot = firstPos; - this.geometryRoof = geometry; - - return { - geometry: _geometry, - pivot: firstPos, - geometryRoof: geometry, - }; -}; - - -BuildingBox_Provider.prototype.addRoad = function addRoad(geometry, bbox, altitude_road) { - // Version using SIMPLE PLANE ROAD for Click and Go - var ratio = 0.2; - var roadWidth = (bbox.east() - bbox.west()) * ratio; - var roadHeight = (bbox.north() - bbox.south()) * ratio; - var pos = new THREE.Vector3((bbox.south() + bbox.north()) / 2, - altitude_road, (bbox.west() + bbox.east()) / 2); // 48.8505774, altitude_sol, 2.3348124); - - var coordCarto1 = new Coordinates('EPSG:4326', pos.x - roadWidth, pos.z - roadHeight, altitude_road); - var coordCarto2 = new Coordinates('EPSG:4326', pos.x - roadWidth, pos.z + roadHeight, altitude_road); - var coordCarto3 = new Coordinates('EPSG:4326', pos.x + roadWidth, pos.z + roadHeight, altitude_road); - var coordCarto4 = new Coordinates('EPSG:4326', pos.x + roadWidth, pos.z - roadHeight, altitude_road); - - var pgeo1 = coordCarto1.as('EPSG:4978').xyz(); - var pgeo2 = coordCarto2.as('EPSG:4978').xyz(); - var pgeo3 = coordCarto3.as('EPSG:4978').xyz(); - var pgeo4 = coordCarto4.as('EPSG:4978').xyz(); - - geometry.vertices.push(new THREE.Vector3(pgeo1.x, pgeo1.y, pgeo1.z)); - geometry.vertices.push(new THREE.Vector3(pgeo2.x, pgeo2.y, pgeo2.z)); - geometry.vertices.push(new THREE.Vector3(pgeo3.x, pgeo3.y, pgeo3.z)); - geometry.vertices.push(new THREE.Vector3(pgeo4.x, pgeo4.y, pgeo4.z)); - - var len = geometry.vertices.length; - geometry.faces.push(new THREE.Face3(len - 4, len - 3, len - 2)); - geometry.faces.push(new THREE.Face3(len - 4, len - 2, len - 1)); -}; - - -export default BuildingBox_Provider; diff --git a/src/Core/Scheduler/Providers/KML_Provider.js b/src/Core/Scheduler/Providers/KML_Provider.js deleted file mode 100644 index a951ddbbb9..0000000000 --- a/src/Core/Scheduler/Providers/KML_Provider.js +++ /dev/null @@ -1,655 +0,0 @@ -import * as THREE from 'three'; -import Provider from './Provider'; -import Fetcher from './Fetcher'; -import KMZLoader from '../../../Renderer/ThreeExtended/KMZLoader'; - -function KML_Provider(ellipsoid) { - this.ellipsoid = ellipsoid; - this.kmzLoader = new KMZLoader(); - this.cache = new Map(); -} - -KML_Provider.prototype = Object.create(Provider.prototype); - -KML_Provider.prototype.constructor = KML_Provider; - - -const position = new THREE.Vector3(); -const axisX = new THREE.Vector3(1, 0, 0); -KML_Provider.prototype.loadKMZ = function loadKMZ(longitude, latitude) { - return this.getUrlCollada(longitude, latitude).then((result) => { - if (result === undefined) - { return undefined; } - - if (result.scene.children[0]) { - var child = result.scene.children[0]; - var coorCarto = result.coorCarto; - - this.ellipsoid.cartographicToCartesian(coorCarto, position); - coorCarto.altitude = 0; - var normal = this.ellipsoid.geodeticSurfaceNormalCartographic(coorCarto); - - var quaternion = new THREE.Quaternion(); - quaternion.setFromAxisAngle(axisX, Math.PI / 2); - - child.lookAt(position.add(normal)); - child.quaternion.multiply(quaternion); - child.position.copy(position); - - child.updateMatrix(); - child.visible = false; - - var changeMaterial = function changeMaterial(object3D) { - if (object3D.material instanceof THREE.MultiMaterial) { - object3D.material = new THREE.MeshBasicMaterial({ color: object3D.material.materials[0].color }); - } else if (object3D.material) - { object3D.material = new THREE.MeshBasicMaterial({ color: object3D.material.color }); } - }; - - - child.traverse(changeMaterial); - - return child; - } - return undefined; - }); -}; - -KML_Provider.prototype.parseKML = function parseKML(urlFile, longitude, latitude, networkOptions) { - var north = latitude; - var south = latitude; - var east = longitude; - var west = longitude; - var key = 'va5orxd0pgzvq3jxutqfuy0b'; - var url = `http://wxs.ign.fr/${key}/vecteurtuile3d/BATI3D/FXX/`; - return Fetcher.xml(urlFile, networkOptions).then((result) => { - var NetworkLink = []; - NetworkLink = result.getElementsByTagName('NetworkLink'); - - for (var i = 0; i < NetworkLink.length; i++) { - var coords = []; - coords[0] = NetworkLink[i].getElementsByTagName('north')[0].childNodes[0].nodeValue; - coords[1] = NetworkLink[i].getElementsByTagName('south')[0].childNodes[0].nodeValue; - coords[2] = NetworkLink[i].getElementsByTagName('east')[0].childNodes[0].nodeValue; - coords[3] = NetworkLink[i].getElementsByTagName('west')[0].childNodes[0].nodeValue; - - - if (north < coords[0] && south > coords[1] && east < coords[2] && west > coords[3]) { - var href = []; - href[i] = `${url}TREE/${NetworkLink[i].getElementsByTagName('href')[0].childNodes[0].nodeValue.replace('../', '')}`; - - if (href[i].toLowerCase().substr(-4) === '.kml') { - return this.parseKML(href[i], longitude, latitude); - } - // Next level : Get the next KMZ actual position's coords - else if (href[i].toLowerCase().substr(-4) === '.kmz') { - var url_kmz = url + NetworkLink[i].getElementsByTagName('href')[0].childNodes[0].nodeValue.replace('../../', ''); - // url_kmz = "http://localhost:8383/kmz/BT_000092.kmz"; - - var p = this.cache[url_kmz]; - if (!p) { - p = this.kmzLoader.load(url_kmz); - this.cache[url_kmz] = p; - } - return p; - } - } - } - }); -}; - - -KML_Provider.prototype.getUrlCollada = function getUrlCollada(longitude, latitude) { - return Fetcher.xml('http://wxs.ign.fr/va5orxd0pgzvq3jxutqfuy0b/vecteurtuile3d/BATI3D/BU.Building.kml').then(() => { - // get href's node value - // var kml_0 = result_0.getElementsByTagName("href"); - var url_href_1; - var key = 'va5orxd0pgzvq3jxutqfuy0b'; - - url_href_1 = `http://wxs.ign.fr/${key}/vecteurtuile3d/BATI3D/FXX/TREE/0/0_000_000.kml`; - - return this.parseKML(url_href_1, longitude, latitude); - }); -}; - -export default KML_Provider; -// If France -// if (url_href_1[i] === 'http://wxs.ign.fr/' + key + '/vecteurtuile3d/BATI3D/FXX/TREE/0/0_000_000.kml'){ -// //this.ParseKML(url_href_1[i]); -// //console.log("wesh"); -// Fetcher.xml(url_href_1[i]).then(function(result_1) -// { -// var kml_1 = []; -// kml_1 = result_1.getElementsByTagName("href"); -// //console.log(kml_1.length); -// -// for (j=0; j coords_3[k,2] && east < coords_3[k,3] && west > coords_3[k,4]){ -// -// Fetcher.xml(url_href_3[k]).then(function(result_3){ -// -// var kml_3 = []; -// kml_3 = result_3.getElementsByTagName("href"); -// -// for (l=0; l coords_4[l,2] && east < coords_4[l,3] && west > coords_4[l,4]){ -// -// Fetcher.xml(url_href_4[l]).then(function(result_4){ -// -// var kml_4 = []; -// kml_4 = result_4.getElementsByTagName("href"); -// -// //Get KMZ -// for (m=0; m coords_3[k,2] && east < coords_3[k,3] && west > coords_3[k,4]){ - Fetcher.xml(url_href_3[k]).then(function(result_3){ - - var kml_3 = []; - kml_3 = result_3.getElementsByTagName("href"); - - for (l=0; l coords_3[k,2] && east < coords_3[k,3] && west > coords_3[k,4]){ - Fetcher.xml(url_href_3[k]).then(function(result_3){ - - var kml_3 = []; - kml_3 = result_3.getElementsByTagName("href"); - - for (l=0; l coords_3[k,2] && east < coords_3[k,3] && west > coords_3[k,4]){ - Fetcher.xml(url_href_3[k]).then(function(result_3){ - - var kml_3 = []; - kml_3 = result_3.getElementsByTagName("href"); - - for (l=0; l coords_3[k,2] && east < coords_3[k,3] && west > coords_3[k,4]){ - Fetcher.xml(url_href_3[k]).then(function(result_3){ - - var kml_3 = []; - kml_3 = result_3.getElementsByTagName("href"); - - for (l=0; l coords_3[k,2] && east < coords_3[k,3] && west > coords_3[k,4]){ - Fetcher.xml(url_href_3[k]).then(function(result_3){ - - var kml_3 = []; - kml_3 = result_3.getElementsByTagName("href"); - - for (l=0; l { + return OGCWebServiceHelper.getColorTextureByUrl(urld, layer.networkOptions).then((texture) => { const result = {}; result.texture = texture; result.texture.coords = coordTMSParent || coordTMS; @@ -52,13 +49,13 @@ TMS_Provider.prototype.executeCommand = function executeCommand(command) { } return result; }); -}; +} -TMS_Provider.prototype.tileTextureCount = function tileTextureCount(tile, layer) { - return this.tileInsideLimit(tile, layer) ? 1 : 0; -}; +function tileTextureCount(tile, layer) { + return tileInsideLimit(tile, layer) ? 1 : 0; +} -TMS_Provider.prototype.tileInsideLimit = function tileInsideLimit(tile, layer, targetLevel) { +function tileInsideLimit(tile, layer, targetLevel) { // assume 1 TMS texture per tile (ie: tile geometry CRS is the same as layer's CRS) let tmsCoord = tile.getCoordsForLayer(layer)[0]; @@ -68,6 +65,11 @@ TMS_Provider.prototype.tileInsideLimit = function tileInsideLimit(tile, layer, t return layer.options.zoom.min <= tmsCoord.zoom && tmsCoord.zoom <= layer.options.zoom.max; -}; +} -export default TMS_Provider; +export default { + preprocessDataLayer, + executeCommand, + tileTextureCount, + tileInsideLimit, +}; diff --git a/src/Core/Scheduler/Providers/TileProvider.js b/src/Core/Scheduler/Providers/TileProvider.js index 706fddc234..3b186f7b32 100644 --- a/src/Core/Scheduler/Providers/TileProvider.js +++ b/src/Core/Scheduler/Providers/TileProvider.js @@ -4,22 +4,14 @@ * and open the template in the editor. */ import * as THREE from 'three'; -import Provider from './Provider'; import TileGeometry from '../../TileGeometry'; import TileMesh from '../../TileMesh'; import CancelledCommandException from '../CancelledCommandException'; import { requestNewTile } from '../../../Process/TiledNodeProcessing'; -function TileProvider() { - Provider.call(this, null); - this.cacheGeometry = new Map(); -} - -TileProvider.prototype = Object.create(Provider.prototype); +const cacheGeometry = new Map(); -TileProvider.prototype.constructor = TileProvider; - -TileProvider.prototype.preprocessDataLayer = function preprocessLayer(layer, view, scheduler) { +function preprocessDataLayer(layer, view, scheduler) { if (!layer.schemeTile) { throw new Error(`Cannot init tiled layer without schemeTile for layer ${layer.id}`); } @@ -39,9 +31,9 @@ TileProvider.prototype.preprocessDataLayer = function preprocessLayer(layer, vie level0.updateMatrixWorld(); } }); -}; +} -TileProvider.prototype.executeCommand = function executeCommand(command) { +function executeCommand(command) { const extent = command.extent; if (command.requester && !command.requester.material) { @@ -58,7 +50,7 @@ TileProvider.prototype.executeCommand = function executeCommand(command) { const segment = layer.segments || 16; const key = `${builder.type}_${layer.disableSkirt ? 0 : 1}_${segment}_${level}_${south}`; - let geometry = this.cacheGeometry.get(key); + let geometry = cacheGeometry.get(key); // build geometry if doesn't exist if (!geometry) { const paramsGeometry = { @@ -69,14 +61,14 @@ TileProvider.prototype.executeCommand = function executeCommand(command) { }; geometry = new TileGeometry(paramsGeometry, builder); - this.cacheGeometry.set(key, geometry); + cacheGeometry.set(key, geometry); geometry._count = 0; geometry.dispose = () => { geometry._count--; if (geometry._count == 0) { THREE.BufferGeometry.prototype.dispose.call(geometry); - this.cacheGeometry.delete(key); + cacheGeometry.delete(key); } }; } @@ -117,6 +109,9 @@ TileProvider.prototype.executeCommand = function executeCommand(command) { } return Promise.resolve(tile); -}; +} -export default TileProvider; +export default { + preprocessDataLayer, + executeCommand, +}; diff --git a/src/Core/Scheduler/Providers/WFS_Provider.js b/src/Core/Scheduler/Providers/WFS_Provider.js index 7293ca25da..c65574703a 100644 --- a/src/Core/Scheduler/Providers/WFS_Provider.js +++ b/src/Core/Scheduler/Providers/WFS_Provider.js @@ -5,21 +5,14 @@ */ import Extent from '../../Geographic/Extent'; -import Provider from './Provider'; import Fetcher from './Fetcher'; import CacheRessource from './CacheRessource'; import GeoJSON2Features from '../../../Renderer/ThreeExtended/GeoJSON2Features'; import Feature2Mesh from '../../../Renderer/ThreeExtended/Feature2Mesh'; -function WFS_Provider() { - this.cache = CacheRessource(); - this.pointOrder = new Map(); -} - -WFS_Provider.prototype = Object.create(Provider.prototype); -WFS_Provider.prototype.constructor = WFS_Provider; +const cache = CacheRessource(); -WFS_Provider.prototype.url = function url(bbox, layer) { +function url(bbox, layer) { const box = bbox.as(layer.projection); const w = box.west(); const s = box.south(); @@ -30,9 +23,9 @@ WFS_Provider.prototype.url = function url(bbox, layer) { const bboxInUnit = `${w},${s},${e},${n}`; return layer.customUrl.replace('%bbox', bboxInUnit); -}; +} -WFS_Provider.prototype.preprocessDataLayer = function preprocessDataLayer(layer) { +function preprocessDataLayer(layer) { if (!layer.typeName) { throw new Error('layer.typeName is required.'); } @@ -50,21 +43,21 @@ WFS_Provider.prototype.preprocessDataLayer = function preprocessDataLayer(layer) }&SRSNAME=${layer.crs }&outputFormat=${layer.format }&BBOX=%bbox,${layer.crs}`; -}; +} -WFS_Provider.prototype.tileInsideLimit = function tileInsideLimit(tile, layer) { +function tileInsideLimit(tile, layer) { return (layer.level === undefined || tile.level === layer.level) && layer.extent.intersectsExtent(tile.extent); -}; +} -WFS_Provider.prototype.executeCommand = function executeCommand(command) { +function executeCommand(command) { const layer = command.layer; const tile = command.requester; const destinationCrs = command.view.referenceCrs; // TODO : support xml, gml2 const supportedFormats = { - json: this.getFeatures.bind(this), - geojson: this.getFeatures.bind(this), + json: getFeatures, + geojson: getFeatures, }; const func = supportedFormats[layer.format]; @@ -73,7 +66,7 @@ WFS_Provider.prototype.executeCommand = function executeCommand(command) { } else { return Promise.reject(new Error(`Unsupported mimetype ${layer.format}`)); } -}; +} function assignLayer(object, layer) { if (object) { @@ -86,15 +79,15 @@ function assignLayer(object, layer) { } } -WFS_Provider.prototype.getFeatures = function getFeatures(crs, tile, layer) { +function getFeatures(crs, tile, layer) { if (!layer.tileInsideLimit(tile, layer) || tile.material === null) { return Promise.resolve(); } - const url = this.url(tile.extent.as(layer.crs), layer); + const urld = url(tile.extent.as(layer.crs), layer); const result = {}; - result.feature = this.cache.getRessource(url); + result.feature = cache.getRessource(url); if (result.feature !== undefined) { return Promise.resolve(result); @@ -102,36 +95,11 @@ WFS_Provider.prototype.getFeatures = function getFeatures(crs, tile, layer) { layer.convert = layer.convert ? layer.convert : Feature2Mesh.convert({}); - return Fetcher.json(url, layer.networkOptions).then(geojson => assignLayer(layer.convert(GeoJSON2Features.parse(crs, geojson, tile.extent, { filter: layer.filter })), layer)); -}; - -WFS_Provider.prototype.getPointOrder = function getPointOrder(crs) { - if (this.pointOrder[crs]) { - return this.pointOrder[crs]; - } + return Fetcher.json(urld, layer.networkOptions).then(geojson => assignLayer(layer.convert(GeoJSON2Features.parse(crs, geojson, tile.extent, { filter: layer.filter })), layer)); +} - var pointOrder = { lat: 0, long: 1 }; - - if (crs.type == 'EPSG' && crs.properties.code == '4326') { - pointOrder.long = 0; - pointOrder.lat = 1; - return pointOrder; - } else if (crs.type == 'name') { - if (crs.properties.name) { - var regExpEpsg = new RegExp(/^urn:[x-]?ogc:def:crs:EPSG:(\d*.?\d*)?:\d{4}/); - if (regExpEpsg.test(crs.properties.name)) { - return pointOrder; - } - else { - var regExpOgc = new RegExp(/^urn:[x-]?ogc:def:crs:OGC:(\d*.?\d*)?:(CRS)?(WSG)?\d{0,2}/); - if (regExpOgc.test(crs.properties.name)) { - pointOrder.long = 0; - pointOrder.lat = 1; - return pointOrder; - } - } - } - } +export default { + preprocessDataLayer, + executeCommand, + tileInsideLimit, }; - -export default WFS_Provider; diff --git a/src/Core/Scheduler/Providers/WMS_Provider.js b/src/Core/Scheduler/Providers/WMS_Provider.js index ffc731fd47..2391ba87cd 100644 --- a/src/Core/Scheduler/Providers/WMS_Provider.js +++ b/src/Core/Scheduler/Providers/WMS_Provider.js @@ -8,16 +8,7 @@ import * as THREE from 'three'; import Extent from '../../Geographic/Extent'; import OGCWebServiceHelper from './OGCWebServiceHelper'; -/** - * Return url wmts MNT - * @param {String} options.url: service base url - * @param {String} options.layer: requested data layer - * @param {String} options.format: image format (default: format/jpeg) - */ -function WMS_Provider() { -} - -WMS_Provider.prototype.url = function url(bbox, layer) { +function url(bbox, layer) { const box = bbox.as(layer.projection); const w = box.west(); const s = box.south(); @@ -29,13 +20,13 @@ WMS_Provider.prototype.url = function url(bbox, layer) { `${w},${s},${e},${n}`; return layer.customUrl.replace('%bbox', bboxInUnit); -}; +} -WMS_Provider.prototype.tileTextureCount = function tileTextureCount(tile, layer) { +function tileTextureCount(tile, layer) { return tile.extent.crs() == layer.projection ? 1 : tile.getCoordsForLayer(layer).length; -}; +} -WMS_Provider.prototype.preprocessDataLayer = function preprocessDataLayer(layer) { +function preprocessDataLayer(layer) { if (!layer.name) { throw new Error('layer.name is required.'); } @@ -86,16 +77,16 @@ WMS_Provider.prototype.preprocessDataLayer = function preprocessDataLayer(layer) `&${crsPropName}=${layer.projection }&WIDTH=${layer.width }&HEIGHT=${layer.width}`; -}; +} -WMS_Provider.prototype.tileInsideLimit = function tileInsideLimit(tile, layer) { +function tileInsideLimit(tile, layer) { return tile.level >= layer.options.zoom.min && tile.level <= layer.options.zoom.max && layer.extent.intersectsExtent(tile.extent); -}; +} -WMS_Provider.prototype.getColorTexture = function getColorTexture(tile, layer, targetLevel, tileCoords) { - if (!this.tileInsideLimit(tile, layer)) { +function getColorTexture(tile, layer, targetLevel, tileCoords) { + if (!tileInsideLimit(tile, layer)) { return Promise.reject(`Tile '${tile}' is outside layer bbox ${layer.extent}`); } if (tile.material === null) { @@ -119,11 +110,11 @@ WMS_Provider.prototype.getColorTexture = function getColorTexture(tile, layer, t } const coords = extent.as(layer.projection); - const url = this.url(coords, layer); + const urld = url(coords, layer); const pitch = tileCoords ? new THREE.Vector4(0, 0, 1, 1) : tile.extent.offsetToParent(extent); const result = { pitch }; - return OGCWebServiceHelper.getColorTextureByUrl(url, layer.networkOptions).then((texture) => { + return OGCWebServiceHelper.getColorTextureByUrl(urld, layer.networkOptions).then((texture) => { result.texture = texture; result.texture.extent = extent; if (layer.transparent) { @@ -139,17 +130,17 @@ WMS_Provider.prototype.getColorTexture = function getColorTexture(tile, layer, t } return result; }); -}; +} -WMS_Provider.prototype.executeCommand = function executeCommand(command) { +function executeCommand(command) { const tile = command.requester; const layer = command.layer; - const getTextureFunction = tile.extent.crs() == layer.projection ? this.getColorTexture : this.getColorTextures; + const getTextureFunction = tile.extent.crs() == layer.projection ? getColorTexture : getColorTextures; const supportedFormats = { - 'image/png': getTextureFunction.bind(this), - 'image/jpg': getTextureFunction.bind(this), - 'image/jpeg': getTextureFunction.bind(this), + 'image/png': getTextureFunction, + 'image/jpg': getTextureFunction, + 'image/jpeg': getTextureFunction, }; const func = supportedFormats[layer.format]; @@ -159,20 +150,25 @@ WMS_Provider.prototype.executeCommand = function executeCommand(command) { } else { return Promise.reject(new Error(`Unsupported mimetype ${layer.format}`)); } -}; +} // In the case where the tilematrixset of the tile don't correspond to the projection of the layer // when the projection of the layer corresponds to a tilematrixset inside the tile, like the PM -WMS_Provider.prototype.getColorTextures = function getColorTextures(tile, layer, targetLevel) { +function getColorTextures(tile, layer, targetLevel) { if (tile.material === null) { return Promise.resolve(); } const promises = []; for (const coord of tile.getCoordsForLayer(layer)) { - promises.push(this.getColorTexture(tile, layer, targetLevel, coord)); + promises.push(getColorTexture(tile, layer, targetLevel, coord)); } return Promise.all(promises); -}; +} -export default WMS_Provider; +export default { + preprocessDataLayer, + executeCommand, + tileTextureCount, + tileInsideLimit, +}; diff --git a/src/Core/Scheduler/Providers/WMTS_Provider.js b/src/Core/Scheduler/Providers/WMTS_Provider.js index b8c4dffdd1..285d2c649a 100644 --- a/src/Core/Scheduler/Providers/WMTS_Provider.js +++ b/src/Core/Scheduler/Providers/WMTS_Provider.js @@ -8,18 +8,17 @@ import * as THREE from 'three'; import OGCWebServiceHelper from './OGCWebServiceHelper'; import Extent from '../../Geographic/Extent'; -function WMTS_Provider() { -} +const coordTile = new Extent('WMTS:WGS84', 0, 0, 0); -WMTS_Provider.prototype.customUrl = function customUrl(layer, url, tilematrix, row, col) { +function customUrl(layer, url, tilematrix, row, col) { let urld = url.replace('%TILEMATRIX', tilematrix.toString()); urld = urld.replace('%ROW', row.toString()); urld = urld.replace('%COL', col.toString()); return urld; -}; +} -WMTS_Provider.prototype.preprocessDataLayer = function preprocessDataLayer(layer) { +function preprocessDataLayer(layer) { layer.fx = layer.fx || 0.0; layer.options = layer.options || {}; @@ -56,7 +55,7 @@ WMTS_Provider.prototype.preprocessDataLayer = function preprocessDataLayer(layer layer.customUrl = newBaseUrl; } layer.options.zoom = layer.options.zoom || { min: 2, max: 20 }; -}; +} /** * Return url wmts orthophoto @@ -64,9 +63,9 @@ WMTS_Provider.prototype.preprocessDataLayer = function preprocessDataLayer(layer * @param {Layer} layer * @returns {string} */ -WMTS_Provider.prototype.url = function url(coWMTS, layer) { - return this.customUrl(layer, layer.customUrl, coWMTS.zoom, coWMTS.row, coWMTS.col); -}; +function url(coWMTS, layer) { + return customUrl(layer, layer.customUrl, coWMTS.zoom, coWMTS.row, coWMTS.col); +} /** * return texture float alpha THREE.js of MNT @@ -75,7 +74,7 @@ WMTS_Provider.prototype.url = function url(coWMTS, layer) { * @param {number} targetZoom * @returns {Promise} */ -WMTS_Provider.prototype.getXbilTexture = function getXbilTexture(tile, layer, targetZoom) { +function getXbilTexture(tile, layer, targetZoom) { const pitch = new THREE.Vector4(0.0, 0.0, 1.0, 1.0); let coordWMTS = tile.getCoordsForLayer(layer)[0]; @@ -83,9 +82,9 @@ WMTS_Provider.prototype.getXbilTexture = function getXbilTexture(tile, layer, ta coordWMTS = OGCWebServiceHelper.WMTS_WGS84Parent(coordWMTS, targetZoom, pitch); } - const url = this.url(coordWMTS, layer); + const urld = url(coordWMTS, layer); - return OGCWebServiceHelper.getXBilTextureByUrl(url, layer.networkOptions).then((texture) => { + return OGCWebServiceHelper.getXBilTextureByUrl(urld, layer.networkOptions).then((texture) => { texture.coords = coordWMTS; return { texture, @@ -94,7 +93,7 @@ WMTS_Provider.prototype.getXbilTexture = function getXbilTexture(tile, layer, ta max: !texture.max ? 0 : texture.max, }; }); -}; +} /** * Return texture RGBA THREE.js of orthophoto @@ -103,9 +102,9 @@ WMTS_Provider.prototype.getXbilTexture = function getXbilTexture(tile, layer, ta * @param {Layer} layer * @returns {Promise} */ -WMTS_Provider.prototype.getColorTexture = function getColorTexture(coordWMTS, layer) { - const url = this.url(coordWMTS, layer); - return OGCWebServiceHelper.getColorTextureByUrl(url, layer.networkOptions).then((texture) => { +function getColorTexture(coordWMTS, layer) { + const urld = url(coordWMTS, layer); + return OGCWebServiceHelper.getColorTextureByUrl(urld, layer.networkOptions).then((texture) => { const result = {}; result.texture = texture; result.texture.coords = coordWMTS; @@ -116,17 +115,17 @@ WMTS_Provider.prototype.getColorTexture = function getColorTexture(coordWMTS, la return result; }); -}; +} -WMTS_Provider.prototype.executeCommand = function executeCommand(command) { +function executeCommand(command) { const layer = command.layer; const tile = command.requester; const supportedFormats = { - 'image/png': this.getColorTextures.bind(this), - 'image/jpg': this.getColorTextures.bind(this), - 'image/jpeg': this.getColorTextures.bind(this), - 'image/x-bil;bits=32': this.getXbilTexture.bind(this), + 'image/png': getColorTextures, + 'image/jpg': getColorTextures, + 'image/jpeg': getColorTextures, + 'image/x-bil;bits=32': getXbilTexture, }; const func = supportedFormats[layer.options.mimetype]; @@ -135,17 +134,15 @@ WMTS_Provider.prototype.executeCommand = function executeCommand(command) { } else { return Promise.reject(new Error(`Unsupported mimetype ${layer.options.mimetype}`)); } -}; +} -WMTS_Provider.prototype.tileTextureCount = function tileTextureCount(tile, layer) { +function tileTextureCount(tile, layer) { const tileMatrixSet = layer.options.tileMatrixSet; OGCWebServiceHelper.computeTileMatrixSetCoordinates(tile, tileMatrixSet); return tile.getCoordsForLayer(layer).length; -}; - +} -const coordTile = new Extent('WMTS:WGS84', 0, 0, 0); -WMTS_Provider.prototype.tileInsideLimit = function tileInsideLimit(tile, layer, targetLevel) { +function tileInsideLimit(tile, layer, targetLevel) { // This layer provides data starting at level = layer.options.zoom.min // (the zoom.max property is used when building the url to make // sure we don't use invalid levels) @@ -169,9 +166,9 @@ WMTS_Provider.prototype.tileInsideLimit = function tileInsideLimit(tile, layer, } } return true; -}; +} -WMTS_Provider.prototype.getColorTextures = function getColorTextures(tile, layer) { +function getColorTextures(tile, layer) { if (tile.material === null) { return Promise.resolve(); } @@ -179,10 +176,15 @@ WMTS_Provider.prototype.getColorTextures = function getColorTextures(tile, layer const bcoord = tile.getCoordsForLayer(layer); for (const coordWMTS of bcoord) { - promises.push(this.getColorTexture(coordWMTS, layer)); + promises.push(getColorTexture(coordWMTS, layer)); } return Promise.all(promises); -}; +} -export default WMTS_Provider; +export default { + preprocessDataLayer, + executeCommand, + tileTextureCount, + tileInsideLimit, +}; diff --git a/src/Core/Scheduler/Scheduler.js b/src/Core/Scheduler/Scheduler.js index 1432caef86..749b148d20 100644 --- a/src/Core/Scheduler/Scheduler.js +++ b/src/Core/Scheduler/Scheduler.js @@ -89,16 +89,15 @@ Scheduler.prototype.constructor = Scheduler; Scheduler.prototype.initDefaultProviders = function initDefaultProviders() { // Register all providers - var wmtsProvider = new WMTS_Provider(); - this.addProtocolProvider('wmts', wmtsProvider); - this.addProtocolProvider('wmtsc', wmtsProvider); - this.addProtocolProvider('tile', new TileProvider()); - this.addProtocolProvider('wms', new WMS_Provider()); - this.addProtocolProvider('3d-tiles', new $3dTiles_Provider()); - this.addProtocolProvider('tms', new TMS_Provider()); - this.addProtocolProvider('xyz', new TMS_Provider()); + this.addProtocolProvider('wmts', WMTS_Provider); + this.addProtocolProvider('wmtsc', WMTS_Provider); + this.addProtocolProvider('tile', TileProvider); + this.addProtocolProvider('wms', WMS_Provider); + this.addProtocolProvider('3d-tiles', $3dTiles_Provider); + this.addProtocolProvider('tms', TMS_Provider); + this.addProtocolProvider('xyz', TMS_Provider); this.addProtocolProvider('potreeconverter', PointCloudProvider); - this.addProtocolProvider('wfs', new WFS_Provider()); + this.addProtocolProvider('wfs', WFS_Provider); this.addProtocolProvider('rasterizer', Raster_Provider); this.addProtocolProvider('static', StaticProvider); }; @@ -162,8 +161,14 @@ Scheduler.prototype.execute = function execute(command) { return command.promise; }; - Scheduler.prototype.addProtocolProvider = function addProtocolProvider(protocol, provider) { + if (typeof (provider.executeCommand) !== 'function') { + throw new Error(`Can't add provider for ${protocol}: missing a executeCommand function.`); + } + if (typeof (provider.preprocessDataLayer) !== 'function') { + throw new Error(`Can't add provider for ${protocol}: missing a preprocessDataLayer function.`); + } + this.providers[protocol] = provider; }; diff --git a/test/scheduler_unit_test.js b/test/scheduler_unit_test.js index b567471c3c..1ab2f01aae 100644 --- a/test/scheduler_unit_test.js +++ b/test/scheduler_unit_test.js @@ -9,6 +9,8 @@ global.window = { }; scheduler.addProtocolProvider('test', { + preprocessDataLayer: () => { + }, executeCommand: (cmd) => { setTimeout(() => { cmd.done = true;