From 73da36e9752a6cd2d4367b08feb88743f8063991 Mon Sep 17 00:00:00 2001 From: "arnaud.morvan@camptocamp.com" Date: Mon, 25 Nov 2024 15:19:22 +0100 Subject: [PATCH 1/3] 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 b02af3be2afd..06af144559a0 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, From e4f36d78c5183345913f09fc7a84106de66e6f25 Mon Sep 17 00:00:00 2001 From: "geo-ghci-int[bot]" <146321879+geo-ghci-int[bot]@users.noreply.github.com> Date: Mon, 25 Nov 2024 14:28:27 +0000 Subject: [PATCH 2/3] Apply pre-commit fix From the artifact of the previous workflow run --- src/streetview/MapillaryGraphQueryCreator.js | 98 ++++++++++---------- src/streetview/MapillaryService.js | 40 ++++---- 2 files changed, 73 insertions(+), 65 deletions(-) diff --git a/src/streetview/MapillaryGraphQueryCreator.js b/src/streetview/MapillaryGraphQueryCreator.js index 869e61153358..ab08aeac0f36 100644 --- a/src/streetview/MapillaryGraphQueryCreator.js +++ b/src/streetview/MapillaryGraphQueryCreator.js @@ -2,60 +2,60 @@ * 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; + /** + * @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.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']; - } + 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(',')}`; - } + images(imageIds, fields) { + return `image_ids=${imageIds.join(',')}&fields=${fields.join(',')}`; + } - imagesS2(cellId, fields) { - return `organization_id=${this.organizationId}&s2=${cellId}&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(',')}`; - } + imageTiles(z, fields) { + return `z=${z}&fields=${fields.join(',')}`; + } - imageTilesPath(imageId) { - return `${imageId}/${this._imageTilesPath}`; - } + imageTilesPath(imageId) { + return `${imageId}/${this._imageTilesPath}`; + } - sequence(sequenceId) { - return `sequence_id=${sequenceId}`; - } + sequence(sequenceId) { + return `sequence_id=${sequenceId}`; + } } diff --git a/src/streetview/MapillaryService.js b/src/streetview/MapillaryService.js index 06af144559a0..9a48198c708d 100644 --- a/src/streetview/MapillaryService.js +++ b/src/streetview/MapillaryService.js @@ -37,7 +37,16 @@ export default class MapillaryService extends StreetviewService { * @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, organizationId) { + constructor( + $scope, + $timeout, + $http, + map, + handlePanoramaPositionChange, + accessToken, + bufferSize, + organizationId, + ) { super($scope, map, handlePanoramaPositionChange); /** @@ -80,7 +89,6 @@ export default class MapillaryService extends StreetviewService { this.mapillaryElement = document.getElementById('mly'); this.mapillaryElement.hidden = true; import(/* webpackChunkName: "mapillary" */ 'mapillary-js').then((Mapillary) => { - const viewerOptions = { accessToken: this.accessToken_, container: 'mly', @@ -90,18 +98,18 @@ 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 + { + accessToken: this.accessToken_, + }, + undefined, + undefined, + queryCreator, ); viewerOptions.dataProvider = dataProvider; } @@ -195,15 +203,15 @@ export default class MapillaryService extends StreetviewService { searchImage_(bbox) { const baseUrl = `${MLY_METADATA_ENDPOINT}/images`; const params = new URLSearchParams([ - ['access_token', this.accessToken_], - ['fields', 'id'], - ['bbox', bbox], - ['limit', '1'], - ]) + ['access_token', this.accessToken_], + ['fields', 'id'], + ['bbox', bbox], + ['limit', '1'], + ]); if (this.organizationId) { - params.append('organization_id', this.organizationId) + params.append('organization_id', this.organizationId); } - const path = `${baseUrl}?${params.toString()}` + const path = `${baseUrl}?${params.toString()}`; return this.$http_.get(path).then( /** * @param {any} response object. From 8b2a15d48a4ee1cd2b51fd6b877ab3c97028914d Mon Sep 17 00:00:00 2001 From: "arnaud.morvan@camptocamp.com" Date: Wed, 27 Nov 2024 10:08:11 +0100 Subject: [PATCH 3/3] Make organizationId optional in MapillaryService --- src/streetview/MapillaryService.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/streetview/MapillaryService.js b/src/streetview/MapillaryService.js index 9a48198c708d..f8b769bbb97b 100644 --- a/src/streetview/MapillaryService.js +++ b/src/streetview/MapillaryService.js @@ -35,7 +35,7 @@ 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. + * @param {string} [organizationId] The id of the organization to get images from. */ constructor( $scope,