diff --git a/demo/src/app/geo/search/search.module.ts b/demo/src/app/geo/search/search.module.ts index b27b5e7b4f..dd24df7949 100644 --- a/demo/src/app/geo/search/search.module.ts +++ b/demo/src/app/geo/search/search.module.ts @@ -17,7 +17,8 @@ import { IgoFeatureModule, IgoOverlayModule, provideIChercheSearchSource, - provideDataSourceSearchSource + provideDataSourceSearchSource, + provideNominatimSearchSource } from '@igo2/geo'; import { AppSearchComponent } from './search.component'; @@ -42,6 +43,7 @@ import { AppSearchRoutingModule } from './search-routing.module'; exports: [AppSearchComponent], providers: [ provideIChercheSearchSource(), - provideDataSourceSearchSource()] + provideDataSourceSearchSource(), + provideNominatimSearchSource()] }) export class AppSearchModule {} diff --git a/demo/src/environments/environment.prod.ts b/demo/src/environments/environment.prod.ts index f1ebdb36e1..c1851206a5 100644 --- a/demo/src/environments/environment.prod.ts +++ b/demo/src/environments/environment.prod.ts @@ -29,11 +29,13 @@ export const environment: Environment = { reseautq: { searchUrl: 'https://ws.mapserver.transports.gouv.qc.ca/swtq', locateUrl: 'https://ws.mapserver.transports.gouv.qc.ca/swtq', + zoomMaxOnSelect: 8, enabled: true }, icherche: { searchUrl: 'https://geoegl.msp.gouv.qc.ca/icherche/geocode', locateUrl: 'https://geoegl.msp.gouv.qc.ca/icherche/xy', + zoomMaxOnSelect: 10, enabled: true }, datasource: { diff --git a/demo/src/environments/environment.ts b/demo/src/environments/environment.ts index 816b9b2561..57d1fc21de 100644 --- a/demo/src/environments/environment.ts +++ b/demo/src/environments/environment.ts @@ -30,18 +30,20 @@ export const environment: Environment = { }, searchSources: { nominatim: { - enabled: false + enabled: true }, reseautq: { searchUrl: 'https://ws.mapserver.transports.gouv.qc.ca/swtq', locateUrl: 'https://ws.mapserver.transports.gouv.qc.ca/swtq', limit: 5, locateLimit: 15, + zoomMaxOnSelect: 8, enabled: false }, icherche: { searchUrl: 'https://geoegl.msp.gouv.qc.ca/icherche/geocode', locateUrl: 'https://geoegl.msp.gouv.qc.ca/icherche/xy', + zoomMaxOnSelect: 10, enabled: true }, datasource: { diff --git a/projects/context/src/lib/sidenav/sidenav.component.html b/projects/context/src/lib/sidenav/sidenav.component.html index 810ca22075..9bf2ac039d 100644 --- a/projects/context/src/lib/sidenav/sidenav.component.html +++ b/projects/context/src/lib/sidenav/sidenav.component.html @@ -71,8 +71,9 @@ mat-icon-button panelRightButton class="igo-icon-button" - *ngIf="media !== 'mobile'"> - open_in_new + (click)="zoomToFeatureExtent()" + *ngIf="feature.geometry"> + zoom_in { const olFeature = this.format.readFeature(feature, { dataProjection: feature.projection, featureProjection: this.map.projection }); - + featureZoomLevelTrigger = feature.zoomMaxOnSelect; geometry = olFeature.getGeometry(); featureExtent = this.getFeatureExtent(feature); if (olextent.isEmpty(featureExtent)) { @@ -64,23 +64,45 @@ export class OverlayDirective implements OnInit, OnDestroy { } olextent.extend(extent, featureExtent); + if (geometry !== null) { + featureFlatCoordinates = geometry.simplify(100).getFlatCoordinates(); + } this.map.addOverlay(olFeature); }, this); + const mapExtent = this.map.getExtent(); + const mapExtentHeight = olextent.getHeight(mapExtent); + const mapExtentWithInnerBuffer = olextent.buffer(mapExtent, mapExtentHeight * 0.05 * -1); if (features[0].sourceType === SourceFeatureType.Click) { - if (olextent.intersects(featureExtent, this.map.getExtent())) { + if (olextent.intersects(featureExtent, mapExtentWithInnerBuffer)) { action = OverlayAction.None; } else { action = OverlayAction.Move; } } + // Enabling a configurable parameter to overide the default behavior + if (featureZoomLevelTrigger && this.map.getZoom() < featureZoomLevelTrigger) { + action = OverlayAction.Zoom; + } + + let cntOverlapExtent = 0; + if (featureFlatCoordinates) { + for (let i = 0; i < featureFlatCoordinates.length; i += 2) { + if (olextent.containsCoordinate(mapExtentWithInnerBuffer, + [featureFlatCoordinates[i], featureFlatCoordinates[i + 1]])) { + cntOverlapExtent += 1; + } + } + } if (!olextent.isEmpty(featureExtent)) { if (action === OverlayAction.Zoom) { this.map.zoomToExtent(extent); } else if (action === OverlayAction.Move) { this.map.moveToExtent(extent); } else if (action === OverlayAction.ZoomIfOutMapExtent) { - if (!olextent.intersects(featureExtent, this.map.getExtent())) { + if (cntOverlapExtent === 0) { this.map.zoomToExtent(extent); + } else if (cntOverlapExtent / (featureFlatCoordinates.length / 2) <= 0.05) { + this.map.zoomOut(); } } } diff --git a/projects/geo/src/lib/search/search-sources/icherche-search-source.ts b/projects/geo/src/lib/search/search-sources/icherche-search-source.ts index 6e31f8930c..f453fa3b63 100644 --- a/projects/geo/src/lib/search/search-sources/icherche-search-source.ts +++ b/projects/geo/src/lib/search/search-sources/icherche-search-source.ts @@ -28,6 +28,7 @@ export class IChercheSearchSource extends SearchSource { private searchUrl = 'https://geoegl.msp.gouv.qc.ca/icherche/geocode'; private locateUrl = 'https://geoegl.msp.gouv.qc.ca/icherche/xy'; + private zoomMaxOnSelect; private options: SearchSourceOptions; constructor(private http: HttpClient, private config: ConfigService) { @@ -36,6 +37,7 @@ export class IChercheSearchSource extends SearchSource { this.options = this.config.getConfig('searchSources.icherche') || {}; this.searchUrl = this.options.searchUrl || this.searchUrl; this.locateUrl = this.options.locateUrl || this.locateUrl; + this.zoomMaxOnSelect = this.options.zoomMaxOnSelect || this.zoomMaxOnSelect; } getName(): string { @@ -71,11 +73,11 @@ export class IChercheSearchSource extends SearchSource { } private extractSearchData(response): Feature[] { - return response.features.map(this.formatSearchResult); + return response.features.map(res => this.formatSearchResult(res, this.zoomMaxOnSelect)); } private extractLocateData(response): Feature[] { - return response.features.map(this.formatLocateResult); + return response.features.map(res => this.formatLocateResult(res, this.zoomMaxOnSelect)); } private getSearchParams(term: string): HttpParams { @@ -116,7 +118,7 @@ export class IChercheSearchSource extends SearchSource { }); } - private formatSearchResult(result: any): Feature { + private formatSearchResult(result: any, zoomMaxOnSelect: number): Feature { const properties = Object.assign( { type: result.doc_type @@ -134,6 +136,7 @@ export class IChercheSearchSource extends SearchSource { source: IChercheSearchSource._name, sourceType: SourceFeatureType.Search, order: 1, + zoomMaxOnSelect: zoomMaxOnSelect, type: FeatureType.Feature, format: FeatureFormat.GeoJSON, title: result.properties.recherche, @@ -146,7 +149,7 @@ export class IChercheSearchSource extends SearchSource { }; } - private formatLocateResult(result: any): Feature { + private formatLocateResult(result: any, zoomMaxOnSelect: number): Feature { const properties = Object.assign( { type: result.properties.doc_type @@ -159,6 +162,7 @@ export class IChercheSearchSource extends SearchSource { source: IChercheSearchSource._name, sourceType: SourceFeatureType.LocateXY, order: 1, + zoomMaxOnSelect: zoomMaxOnSelect, type: FeatureType.Feature, format: FeatureFormat.GeoJSON, title: result.properties.nom, diff --git a/projects/geo/src/lib/search/search-sources/nominatim-search-source.ts b/projects/geo/src/lib/search/search-sources/nominatim-search-source.ts index 7457e9d1ac..45c67f9ee2 100644 --- a/projects/geo/src/lib/search/search-sources/nominatim-search-source.ts +++ b/projects/geo/src/lib/search/search-sources/nominatim-search-source.ts @@ -28,6 +28,7 @@ export class NominatimSearchSource extends SearchSource { private searchUrl = 'https://nominatim.openstreetmap.org/search'; private locateUrl = 'https://nominatim.openstreetmap.org/reverse'; + private zoomMaxOnSelect; private options: SearchSourceOptions; constructor(private http: HttpClient, private config: ConfigService) { @@ -36,6 +37,7 @@ export class NominatimSearchSource extends SearchSource { this.options = this.config.getConfig('searchSources.nominatim') || {}; this.searchUrl = this.options.searchUrl || this.searchUrl; this.locateUrl = this.options.locateUrl || this.locateUrl; + this.zoomMaxOnSelect = this.options.zoomMaxOnSelect || this.zoomMaxOnSelect; } getName(): string { @@ -61,7 +63,7 @@ export class NominatimSearchSource extends SearchSource { if (response[0] && response[0].error) { return []; } - return response.map(res => this.formatResult(res, resultType)); + return response.map(res => this.formatResult(res, resultType, this.zoomMaxOnSelect)); } private getSearchParams(term: string): HttpParams { @@ -91,12 +93,13 @@ export class NominatimSearchSource extends SearchSource { }); } - private formatResult(result: any, resultType): Feature { + private formatResult(result: any, resultType, zoomMaxOnSelect: number): Feature { return { id: result.place_id, source: NominatimSearchSource._name, sourceType: resultType, order: 0, + zoomMaxOnSelect: zoomMaxOnSelect, type: FeatureType.Feature, format: FeatureFormat.GeoJSON, title: result.display_name, diff --git a/projects/geo/src/lib/search/search-sources/reseau-transport-quebec-search-source.ts b/projects/geo/src/lib/search/search-sources/reseau-transport-quebec-search-source.ts index 25aac4ec61..843aad4d79 100644 --- a/projects/geo/src/lib/search/search-sources/reseau-transport-quebec-search-source.ts +++ b/projects/geo/src/lib/search/search-sources/reseau-transport-quebec-search-source.ts @@ -27,6 +27,7 @@ export class ReseauTransportsQuebecSearchSource extends SearchSource { private searchUrl = 'https://ws.mapserver.transports.gouv.qc.ca/swtq'; private locateUrl = 'https://ws.mapserver.transports.gouv.qc.ca/swtq'; + private zoomMaxOnSelect; private searchlimit = 5; private locatelimit = this.searchlimit * 2; private options: SearchSourceOptions; @@ -39,6 +40,7 @@ export class ReseauTransportsQuebecSearchSource extends SearchSource { this.locateUrl = this.options.locateUrl || this.locateUrl; this.searchlimit = this.options.limit || this.searchlimit; this.locatelimit = this.options.locateLimit || this.locatelimit; + this.zoomMaxOnSelect = this.options.zoomMaxOnSelect || this.zoomMaxOnSelect; } getName(): string { @@ -162,10 +164,11 @@ export class ReseauTransportsQuebecSearchSource extends SearchSource { } private extractSearchData(response): Feature[] { - return response.features.map(this.formatSearchResult); + // return response.features.map(this.formatSearchResult); + return response.features.map(res => this.formatSearchResult(res, this.zoomMaxOnSelect)); } - private formatSearchResult(result: any): Feature { + private formatSearchResult(result: any, zoomMaxOnSelect: number): Feature { const properties = Object.assign( { type: result.type @@ -200,6 +203,7 @@ export class ReseauTransportsQuebecSearchSource extends SearchSource { source: ReseauTransportsQuebecSearchSource._name, sourceType: SourceFeatureType.Search, order: 1, + zoomMaxOnSelect: zoomMaxOnSelect, type: FeatureType.Feature, format: FeatureFormat.GeoJSON, title: properties.title, diff --git a/projects/geo/src/lib/search/search-sources/search-source.interface.ts b/projects/geo/src/lib/search/search-sources/search-source.interface.ts index 248417b232..3dec35f422 100644 --- a/projects/geo/src/lib/search/search-sources/search-source.interface.ts +++ b/projects/geo/src/lib/search/search-sources/search-source.interface.ts @@ -6,6 +6,7 @@ export interface SearchSourceOptions { enabled?: boolean; type?: string; distance?: number; + zoomMaxOnSelect?: number; } export interface SearchSourcesOptions {