From 8729b4f292a4f86fa8f73b34ab0ef3574e887028 Mon Sep 17 00:00:00 2001 From: "arnaud.morvan@camptocamp.com" Date: Mon, 25 Nov 2024 15:19:22 +0100 Subject: [PATCH] Filter Mapillary images by organzation_id --- src/options.js | 1 + src/streetview/MapillaryGraphQueryCreator.js | 61 ++++++++++++++++++++ src/streetview/MapillaryService.js | 46 +++++++++++++-- src/streetview/component.js | 2 + 4 files changed, 105 insertions(+), 5 deletions(-) create mode 100644 src/streetview/MapillaryGraphQueryCreator.js diff --git a/src/options.js b/src/options.js index 7a678e4ef89a..729eab04035f 100644 --- a/src/options.js +++ b/src/options.js @@ -357,6 +357,7 @@ export function buildStyle(styleDescriptor) { * @property {string} viewer The viewer to use (google or mapillary) * @property {string} key ClientId for Mapillary * @property {number} [bufferSize] Buffer size in pixels for Mapillary bbox + * @property {string} [organizationId] The id of the Mapillary organization to get images from. */ /** diff --git a/src/streetview/MapillaryGraphQueryCreator.js b/src/streetview/MapillaryGraphQueryCreator.js new file mode 100644 index 000000000000..869e61153358 --- /dev/null +++ b/src/streetview/MapillaryGraphQueryCreator.js @@ -0,0 +1,61 @@ +/** + * Mapillary GraphQueryCreator which allow filtering by organisation_id. + */ +export default class MapillaryGraphQueryCreator { + /** + * @param {string} organizationId The id of the organization to get images from. + */ + constructor(organizationId) { + this.organizationId = organizationId; + + this.imagesPath = 'images'; + this.sequencePath = 'image_ids'; + this._imageTilesPath = 'tiles'; + + this.coreFields = ['computed_geometry', 'geometry', 'sequence']; + this.idFields = ['id']; + this.spatialFields = [ + 'altitude', + 'atomic_scale', + 'camera_parameters', + 'camera_type', + 'captured_at', + 'compass_angle', + 'computed_altitude', + 'computed_compass_angle', + 'computed_rotation', + 'creator', + 'exif_orientation', + 'height', + 'merge_cc', + 'mesh', + 'organization', + 'quality_score', + 'sfm_cluster', + 'thumb_1024_url', + 'thumb_2048_url', + 'width', + ]; + this.imageTileFields = ['url', 'z', 'x', 'y']; + } + + images(imageIds, fields) { + return `image_ids=${imageIds.join(',')}&fields=${fields.join(',')}`; + } + + imagesS2(cellId, fields) { + return `organization_id=${this.organizationId}&s2=${cellId}&fields=${fields.join(',')}`; + } + + imageTiles(z, fields) { + return `z=${z}&fields=${fields.join(',')}`; + } + + imageTilesPath(imageId) { + return `${imageId}/${this._imageTilesPath}`; + } + + sequence(sequenceId) { + return `sequence_id=${sequenceId}`; + } +} diff --git a/src/streetview/MapillaryService.js b/src/streetview/MapillaryService.js index 6e0931367fa1..c925ce7e2b39 100644 --- a/src/streetview/MapillaryService.js +++ b/src/streetview/MapillaryService.js @@ -19,6 +19,7 @@ // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. import {StreetviewService} from './Service'; +import MapillaryGraphQueryCreator from './MapillaryGraphQueryCreator'; import {buffer} from 'ol/extent'; const MLY_METADATA_ENDPOINT = 'https://graph.mapillary.com'; @@ -34,8 +35,9 @@ export default class MapillaryService extends StreetviewService { * @param {(newCoordinates: import('ol/coordinate').Coordinate | null) => void} handlePanoramaPositionChange Position change handler. * @param {string} accessToken The key to access the mapillary api. * @param {number} bufferSize The size to add to the bbox buffer. + * @param {string} organizationId The id of the organization to get images from. */ - constructor($scope, $timeout, $http, map, handlePanoramaPositionChange, accessToken, bufferSize) { + constructor($scope, $timeout, $http, map, handlePanoramaPositionChange, accessToken, bufferSize, organizationId) { super($scope, map, handlePanoramaPositionChange); /** @@ -65,14 +67,21 @@ export default class MapillaryService extends StreetviewService { */ this.bufferSizePx_ = bufferSize || 10; + /** + * The organization to get images from (filter images by organisation_id). + * + * @private + */ + this.organizationId = organizationId; + /** * Container of the mapillary viewer. */ this.mapillaryElement = document.getElementById('mly'); this.mapillaryElement.hidden = true; import(/* webpackChunkName: "mapillary" */ 'mapillary-js').then((Mapillary) => { - this.Mapillary = Mapillary; - this.mly = new Mapillary.Viewer({ + + const viewerOptions = { accessToken: this.accessToken_, container: 'mly', component: { @@ -81,7 +90,25 @@ export default class MapillaryService extends StreetviewService { visible: false, }, }, - }); + } + + if (this.organizationId) { + const queryCreator = new MapillaryGraphQueryCreator(this.organizationId); + + const dataProvider = new Mapillary.GraphDataProvider( + { + accessToken: this.accessToken_ + }, + undefined, + undefined, + queryCreator + ); + viewerOptions.dataProvider = dataProvider; + } + + this.Mapillary = Mapillary; + this.mly = new Mapillary.Viewer(viewerOptions); + window.addEventListener('resize', () => { this.resize(); }); @@ -167,7 +194,16 @@ export default class MapillaryService extends StreetviewService { */ searchImage_(bbox) { const baseUrl = `${MLY_METADATA_ENDPOINT}/images`; - const path = `${baseUrl}?access_token=${this.accessToken_}&fields=id&bbox=${bbox}&limit=1`; + const params = new URLSearchParams([ + ['access_token', this.accessToken_], + ['fields', 'id'], + ['bbox', bbox], + ['limit', '1'], + ]) + if (this.organizationId) { + params.append('organization_id', this.organizationId) + } + const path = `${baseUrl}?${params.toString()}` return this.$http_.get(path).then( /** * @param {any} response object. diff --git a/src/streetview/component.js b/src/streetview/component.js index 70f30d153654..acc8dfd3a7c8 100644 --- a/src/streetview/component.js +++ b/src/streetview/component.js @@ -317,6 +317,7 @@ class StreetviewController { } const accessToken = this.options.key; const bufferSize = this.options.bufferSize; + const organizationId = this.options.organizationId; //wait for the mly div to be there before making the service which needs it this.timeout_(() => { const mapillaryService = new MapillaryService( @@ -327,6 +328,7 @@ class StreetviewController { this.handlePanoramaPositionChange_, accessToken, bufferSize, + organizationId, ); this.scope_.$watch( () => this.panelWidth,