Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature zoom if not in extent based on feature geometry. #198

Merged
merged 14 commits into from
Oct 16, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions demo/src/app/geo/search/search.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@ import {
IgoFeatureModule,
IgoOverlayModule,
provideIChercheSearchSource,
provideDataSourceSearchSource
provideDataSourceSearchSource,
provideNominatimSearchSource
} from '@igo2/geo';

import { AppSearchComponent } from './search.component';
Expand All @@ -42,6 +43,7 @@ import { AppSearchRoutingModule } from './search-routing.module';
exports: [AppSearchComponent],
providers: [
provideIChercheSearchSource(),
provideDataSourceSearchSource()]
provideDataSourceSearchSource(),
provideNominatimSearchSource()]
})
export class AppSearchModule {}
2 changes: 2 additions & 0 deletions demo/src/environments/environment.prod.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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: {
Expand Down
4 changes: 3 additions & 1 deletion demo/src/environments/environment.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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: {
Expand Down
5 changes: 3 additions & 2 deletions projects/context/src/lib/sidenav/sidenav.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -71,8 +71,9 @@
mat-icon-button
panelRightButton
class="igo-icon-button"
*ngIf="media !== 'mobile'">
<mat-icon>open_in_new</mat-icon>
(click)="zoomToFeatureExtent()"
*ngIf="feature.geometry">
<mat-icon>zoom_in</mat-icon>
</button>

<igo-feature-details
Expand Down
23 changes: 22 additions & 1 deletion projects/context/src/lib/sidenav/sidenav.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,27 @@ import { Component, Input } from '@angular/core';

import { Media } from '@igo2/core';
import { FlexibleState } from '@igo2/common';
import { Feature } from '@igo2/geo';
import { Feature, IgoMap } from '@igo2/geo';
import { Tool } from '../tool/shared/tool.interface';
import { ToolService } from '../tool/shared/tool.service';

import olFormatGeoJSON from 'ol/format/GeoJSON';

@Component({
selector: 'igo-sidenav',
templateUrl: './sidenav.component.html',
styleUrls: ['./sidenav.component.scss']
})
export class SidenavComponent {
private format = new olFormatGeoJSON();
@Input()
get map(): IgoMap {
return this._map;
}
set map(value: IgoMap) {
this._map = value;
}
private _map: IgoMap;
@Input()
get opened(): boolean {
return this._opened;
Expand Down Expand Up @@ -52,6 +63,16 @@ export class SidenavComponent {

constructor(public toolService: ToolService) {}

zoomToFeatureExtent() {
if (this.feature.geometry) {
const olFeature = this.format.readFeature(this.feature, {
dataProjection: this.feature.projection,
featureProjection: this.map.projection
});
this.map.zoomToFeature(olFeature);
}
}

toggleTopPanel() {
if (this.topPanelState === 'initial') {
this.topPanelState = 'expanded';
Expand Down
1 change: 1 addition & 0 deletions projects/geo/src/lib/feature/shared/feature.interface.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ export interface Feature {
title: string;
format?: FeatureFormat;
title_html?: string;
zoomMaxOnSelect?: number;
icon?: string;

projection?: string;
Expand Down
30 changes: 26 additions & 4 deletions projects/geo/src/lib/overlay/shared/overlay.directive.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,13 +48,13 @@ export class OverlayDirective implements OnInit, OnDestroy {

const extent = olextent.createEmpty();

let featureExtent, geometry;
let featureExtent, geometry, featureFlatCoordinates, featureZoomLevelTrigger;
features.forEach((feature: Feature) => {
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)) {
Expand All @@ -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();
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand All @@ -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 {
Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -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
Expand All @@ -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,
Expand All @@ -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
Expand All @@ -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,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand All @@ -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 {
Expand All @@ -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 {
Expand Down Expand Up @@ -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,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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 {
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ export interface SearchSourceOptions {
enabled?: boolean;
type?: string;
distance?: number;
zoomMaxOnSelect?: number;
}

export interface SearchSourcesOptions {
Expand Down