From cb77a935c1deb4a9f76d696e14d6473789d65dbe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pierre-=C3=89tienne=20Lord?= <7397743+pelord@users.noreply.github.com> Date: Tue, 16 Oct 2018 13:41:57 -0400 Subject: [PATCH] fix(ogc-filter): Fix for Angular 6 and adjustements for minilib (#186) * refactor(map) a more customizable way to add overlay * feat(wkt service) refactor and adding ways to return wkt objects * fix(ogc-fillter interface and class) refactor interfaces and operators * refactor(ogc-filter) bing map to ogcfilter. * (feat) feature color used as a extent (0000 vs gray) and autorefresh * fix(download-service) with right properties * feat(ogc-filter) Autorefresh toggle feature extent and bind map * refactor(wfs) interface for outputFormatDownload * ui(ogc-filter) updating demo with proper params. * fix(ogc-filter) Moving to angular 6 and selectionChange on select * i18n(ogc-filter) translation for feature extent. * feat(ogc-filter-form) AutoRefresh on change, feature extent overlay * refactor(*) sourcefields * refactor(wms-datasource)managing sourcefield for wms * refactor(ogc-filter) isOgcFilterable/filtersAreEditable enabled/editable * fix(wfs) not using filters when filters are disabled. * refactor(ogc-filter) ogcFilters: {enabled: true,editable: true,...} * fix(wfs) default value for ogcfilters * ui(ogc-filter) cleaner example * ui(ogc-filter) refresh button removed due to autorefresh on change. * feat(ogc-filter) refactor and defining a cleaner way for refresh events * refactor(*)move wfs-service usage from ogc-filter.service to datasources * fix(wkt-service) Wrong regex. Was excluding some SNRC * feat(datasource) providing data wfs-service to datasources * fix(download-service) Adjustement on interface and services params. * feat(wms wfs) wfs for wms source and common interfaces on wms and wfs * fix(filterable-datasource) Let filterable layer apply active filters. * refactor(ogc-fliter) adjustements for wms with linked wfs * fix(ogc-filter) active filter geometry footprint on init * refactor(ogc-filter) various interfaces * fix(ogc-filter) fixing wrong conflict resolution. * fic(ogc-filter-button) Fix button integration * fix(ogc-filter-button) fix button integration into layer-list * fix(ogc-filter-button) download button shown. * ui(ogc-filter) hide spatial extent button if no geometry active. * fix(ogc-filter-button) fix button integration into layer-list * Update layer.component.ts * Update ogc-filter.component.ts * lint code * Update map.ts * remove inused import * fix position buttons layer --- demo/src/app/geo/layer/layer.component.html | 1 + demo/src/app/geo/layer/layer.component.ts | 39 ++++ demo/src/app/geo/layer/layer.module.ts | 2 + .../geo/ogc-filter/ogc-filter.component.html | 2 +- .../geo/ogc-filter/ogc-filter.component.ts | 92 +++++++- .../core/src/lib/request/error.interceptor.ts | 1 + .../shared/datasource.service.spec.ts | 2 +- .../datasource/shared/datasource.service.ts | 19 +- .../shared/datasources/data.service.ts | 3 + .../datasources/datasource.interface.ts | 9 + .../shared/datasources/datasource.ts | 5 +- .../datasource/shared/datasources/index.ts | 2 + .../datasources/wfs-datasource.interface.ts | 13 +- .../shared/datasources/wfs-datasource.ts | 116 +++++----- .../shared/{ => datasources}/wfs.service.ts | 115 +++++++--- .../datasources/wms-datasource.interface.ts | 6 +- .../shared/datasources/wms-datasource.ts | 81 ++++++- .../geo/src/lib/datasource/shared/index.ts | 1 - .../lib/download/shared/download.interface.ts | 3 +- .../lib/download/shared/download.service.ts | 24 +- .../ogc-filter-button.component.html | 11 +- .../ogc-filter-button.component.ts | 11 +- .../ogc-filter-form.component.html | 44 ++-- .../ogc-filter-form.component.ts | 169 ++++++++++---- .../ogc-filterable-form.component.html | 2 +- .../ogc-filterable-form.component.ts | 25 +++ .../ogc-filterable-item.component.html | 28 ++- .../ogc-filterable-item.component.ts | 150 ++++++++++--- .../ogc-filterable-list.component.html | 2 +- .../ogc-filterable-list.component.ts | 10 + .../shared/filterable-datasource.pipe.ts | 4 +- .../lib/filter/shared/ogc-filter.interface.ts | 10 +- .../lib/filter/shared/ogc-filter.service.ts | 209 +++--------------- .../geo/src/lib/filter/shared/ogc-filter.ts | 58 ++--- .../layer-item/layer-item.component.html | 6 +- projects/geo/src/lib/map/shared/map.ts | 58 +++-- .../geo/src/lib/wkt/shared/wkt.service.ts | 84 +++++-- projects/geo/src/locale/en.geo.json | 4 +- projects/geo/src/locale/fr.geo.json | 4 +- 39 files changed, 929 insertions(+), 496 deletions(-) create mode 100644 projects/geo/src/lib/datasource/shared/datasources/data.service.ts rename projects/geo/src/lib/datasource/shared/{ => datasources}/wfs.service.ts (68%) diff --git a/demo/src/app/geo/layer/layer.component.html b/demo/src/app/geo/layer/layer.component.html index 17fdad185e..89e9d7cb80 100644 --- a/demo/src/app/geo/layer/layer.component.html +++ b/demo/src/app/geo/layer/layer.component.html @@ -20,6 +20,7 @@ floatLabel="never"> + diff --git a/demo/src/app/geo/layer/layer.component.ts b/demo/src/app/geo/layer/layer.component.ts index a55b9c4db6..64e6880bf8 100644 --- a/demo/src/app/geo/layer/layer.component.ts +++ b/demo/src/app/geo/layer/layer.component.ts @@ -7,6 +7,8 @@ import { LayerService, WMSDataSourceOptions, LayerOptions, + WFSDataSourceOptions, + OgcFilterableDataSourceOptions, MetadataLayerOptions } from '@igo2/geo'; @@ -47,6 +49,43 @@ export class AppLayerComponent { ); }); + interface WFSoptions + extends WFSDataSourceOptions, + OgcFilterableDataSourceOptions {} + + const wfsDatasource: WFSoptions = { + type: 'wfs', + url: 'https://geoegl.msp.gouv.qc.ca/igo2/api/ws/igo_gouvouvert.fcgi', + params: { + featureTypes: 'vg_observation_v_autre_wmst', + fieldNameGeometry: 'geometry', + maxFeatures: 10000, + version: '2.0.0', + outputFormat: 'geojson_utf8', + outputFormatDownload: 'shp' + }, + ogcFilters: { + enabled: true, + editable: true, + filters: { + operator: 'PropertyIsEqualTo', + propertyName: 'code_municipalite', + expression: '10043' + } + } + }; + + this.dataSourceService + .createAsyncDataSource(wfsDatasource) + .subscribe(dataSource => { + const layer: LayerOptions = { + title: 'WFS ', + visible: true, + source: dataSource + }; + this.map.addLayer(this.layerService.createLayer(layer)); + }); + this.layerService .createAsyncLayer({ sourceOptions: { diff --git a/demo/src/app/geo/layer/layer.module.ts b/demo/src/app/geo/layer/layer.module.ts index 37948595a7..67ca3b7872 100644 --- a/demo/src/app/geo/layer/layer.module.ts +++ b/demo/src/app/geo/layer/layer.module.ts @@ -9,6 +9,7 @@ import { IgoPanelModule } from '@igo2/common'; import { IgoMapModule, IgoLayerModule, + IgoFilterModule, IgoMetadataModule, IgoDownloadModule } from '@igo2/geo'; @@ -26,6 +27,7 @@ import { AppLayerRoutingModule } from './layer-routing.module'; IgoPanelModule, IgoMapModule, IgoLayerModule, + IgoFilterModule, IgoMetadataModule, IgoDownloadModule ], diff --git a/demo/src/app/geo/ogc-filter/ogc-filter.component.html b/demo/src/app/geo/ogc-filter/ogc-filter.component.html index 041ec3e49e..0fca5c743c 100644 --- a/demo/src/app/geo/ogc-filter/ogc-filter.component.html +++ b/demo/src/app/geo/ogc-filter/ogc-filter.component.html @@ -14,7 +14,7 @@ - + diff --git a/demo/src/app/geo/ogc-filter/ogc-filter.component.ts b/demo/src/app/geo/ogc-filter/ogc-filter.component.ts index 520d4109f4..3f721ffd6e 100644 --- a/demo/src/app/geo/ogc-filter/ogc-filter.component.ts +++ b/demo/src/app/geo/ogc-filter/ogc-filter.component.ts @@ -5,8 +5,11 @@ import { IgoMap, DataSourceService, LayerService, + WMSDataSourceOptions, WFSDataSourceOptions, - OgcFilterableDataSourceOptions + WFSDataSourceOptionsParams, + OgcFilterableDataSourceOptions, + AnyBaseOgcFilterOptions } from '@igo2/geo'; @Component({ @@ -58,15 +61,43 @@ export class AppOgcFilterComponent { fieldNameGeometry: 'geometry', maxFeatures: 10000, version: '2.0.0', - outputFormat: 'geojson' + outputFormat: 'geojson', + outputFormatDownload: 'SHP' // based on service capabilities }, - isOgcFilterable: true, + sourceFields: [ + { name: 'code_municipalite', alias: '# de la municipalitée' }, + { name: 'date_observation' }, + { name: 'urgence', values: ['immédiate', 'inconnue'] } + ], ogcFilters: { - filtersAreEditable: true, + enabled: true, + editable: true, filters: { - operator: 'PropertyIsEqualTo', - propertyName: 'code_municipalite', - expression: '10043' + logical: 'Or', + filters: [ + { + operator: 'PropertyIsEqualTo', + propertyName: 'code_municipalite', + expression: '10043' + }, + { + operator: 'Intersects', + geometryName: 'the_geom', + wkt_geometry: `MULTIPOLYGON((( + -8379441.158019895 5844447.897707146, + -8379441.158019895 5936172.331649357, + -8134842.66750733 5936172.331649357, + -8134842.66750733 5844447.897707146, + -8379441.158019895 5844447.897707146 + ), ( + -8015003 5942074, + -8015003 5780349, + -7792364 5780349, + -7792364 5942074, + -8015003 5942074 + )))` + } + ] as AnyBaseOgcFilterOptions[] } } }; @@ -81,5 +112,52 @@ export class AppOgcFilterComponent { }) ); }); + + interface WMSoptions + extends WMSDataSourceOptions, + OgcFilterableDataSourceOptions {} + + const datasourceWms: WMSoptions = { + type: 'wms', + url: '/geoserver/wms', + urlWfs: '/geoserver/wfs', + params: { + layers: 'water_areas', + version: '1.3.0' + }, + ogcFilters: { + enabled: true, + editable: true, + filters: { + operator: 'PropertyIsEqualTo', + propertyName: 'waterway', + expression: 'riverbank' + } + }, + sourceFields: [ + { name: 'waterway', alias: 'Chemin d eau' }, + { name: 'osm_id' }, + { name: 'landuse', values: ['yes', 'no'] } + ], + paramsWFS: { + featureTypes: 'water_areas', + fieldNameGeometry: 'the_geom', + maxFeatures: 10000, + version: '1.1.0', + outputFormat: 'application/json', + outputFormatDownload: 'application/vnd.google-earth.kml+xml' + } as WFSDataSourceOptionsParams + }; + + this.dataSourceService + .createAsyncDataSource(datasourceWms) + .subscribe(dataSource => { + this.map.addLayer( + this.layerService.createLayer({ + title: 'Geoserver water_areas', + source: dataSource + }) + ); + }); } } diff --git a/projects/core/src/lib/request/error.interceptor.ts b/projects/core/src/lib/request/error.interceptor.ts index 5273de4fd5..1d2f8052b4 100644 --- a/projects/core/src/lib/request/error.interceptor.ts +++ b/projects/core/src/lib/request/error.interceptor.ts @@ -71,6 +71,7 @@ export class ErrorInterceptor implements HttpInterceptor { const translate = this.injector.get(LanguageService).translate; const message = translate.instant('igo.core.errors.uncaught.message'); const title = translate.instant('igo.core.errors.uncaught.title'); + this.httpError.error.caught = true; this.messageService.error(message, title); } } diff --git a/projects/geo/src/lib/datasource/shared/datasource.service.spec.ts b/projects/geo/src/lib/datasource/shared/datasource.service.spec.ts index dba7d44746..fbf7d91dec 100644 --- a/projects/geo/src/lib/datasource/shared/datasource.service.spec.ts +++ b/projects/geo/src/lib/datasource/shared/datasource.service.spec.ts @@ -3,7 +3,7 @@ import { HttpClientModule } from '@angular/common/http'; import { CapabilitiesService } from './capabilities.service'; import { DataSourceService } from './datasource.service'; -import { WFSService } from './wfs.service'; +import { WFSService } from './datasources/wfs.service'; describe('DataSourceService', () => { beforeEach(() => { diff --git a/projects/geo/src/lib/datasource/shared/datasource.service.ts b/projects/geo/src/lib/datasource/shared/datasource.service.ts index 583206fda5..06dfbbc5ec 100644 --- a/projects/geo/src/lib/datasource/shared/datasource.service.ts +++ b/projects/geo/src/lib/datasource/shared/datasource.service.ts @@ -14,6 +14,7 @@ import { XYZDataSourceOptions, WFSDataSource, WFSDataSourceOptions, + WFSService, WMTSDataSource, WMTSDataSourceOptions, WMSDataSource, @@ -33,7 +34,10 @@ import { export class DataSourceService { public datasources$ = new BehaviorSubject([]); - constructor(private capabilitiesService: CapabilitiesService) {} + constructor( + private capabilitiesService: CapabilitiesService, + private wfsDataSourceService: WFSService + ) {} createAsyncDataSource(context: AnyDataSourceOptions): Observable { if (!context.type) { @@ -104,7 +108,9 @@ export class DataSourceService { private createWFSDataSource( context: WFSDataSourceOptions ): Observable { - return new Observable(d => d.next(new WFSDataSource(context))); + return new Observable(d => + d.next(new WFSDataSource(context, this.wfsDataSourceService)) + ); } private createWMSDataSource( @@ -114,11 +120,16 @@ export class DataSourceService { return this.capabilitiesService .getWMSOptions(context) .pipe( - map((options: WMSDataSourceOptions) => new WMSDataSource(options)) + map( + (options: WMSDataSourceOptions) => + new WMSDataSource(options, this.wfsDataSourceService) + ) ); } - return new Observable(d => d.next(new WMSDataSource(context))); + return new Observable(d => + d.next(new WMSDataSource(context, this.wfsDataSourceService)) + ); } private createWMTSDataSource( diff --git a/projects/geo/src/lib/datasource/shared/datasources/data.service.ts b/projects/geo/src/lib/datasource/shared/datasources/data.service.ts new file mode 100644 index 0000000000..b43685c234 --- /dev/null +++ b/projects/geo/src/lib/datasource/shared/datasources/data.service.ts @@ -0,0 +1,3 @@ +export abstract class DataService { + abstract getData(): string; +} diff --git a/projects/geo/src/lib/datasource/shared/datasources/datasource.interface.ts b/projects/geo/src/lib/datasource/shared/datasources/datasource.interface.ts index 76a6f32295..287f413f9c 100644 --- a/projects/geo/src/lib/datasource/shared/datasources/datasource.interface.ts +++ b/projects/geo/src/lib/datasource/shared/datasources/datasource.interface.ts @@ -1,6 +1,7 @@ import olSource from 'ol/source/Source'; import { DataSource } from './datasource'; +import { DownloadOptions } from '../../../download/shared/download.interface'; export interface DataSourceOptions { type?: @@ -21,6 +22,8 @@ export interface DataSourceOptions { // view?: ol.olx.layer.ImageOptions; // displayField?: string; ol?: olSource; + sourceFields?: SourceFieldsOptionsParams[]; + download?: DownloadOptions; } export interface DataSourceLegendOptions { @@ -31,3 +34,9 @@ export interface DataSourceLegendOptions { style?: { [key: string]: string | number }; title?: string; } + +export interface SourceFieldsOptionsParams { + name: any; + alias?: any; + values?: any; +} diff --git a/projects/geo/src/lib/datasource/shared/datasources/datasource.ts b/projects/geo/src/lib/datasource/shared/datasources/datasource.ts index 6011c00b20..7d5fe75ad8 100644 --- a/projects/geo/src/lib/datasource/shared/datasources/datasource.ts +++ b/projects/geo/src/lib/datasource/shared/datasources/datasource.ts @@ -5,14 +5,15 @@ import { DataSourceLegendOptions } from './datasource.interface'; -// import { DataService } from './data.service'; +import { DataService } from './data.service'; export abstract class DataSource { public id: string; public ol: olSource; constructor( - public options: DataSourceOptions = {} // protected dataSourceService?: DataService + public options: DataSourceOptions = {}, + protected dataService?: DataService ) { this.options = options; this.id = this.generateId(); diff --git a/projects/geo/src/lib/datasource/shared/datasources/index.ts b/projects/geo/src/lib/datasource/shared/datasources/index.ts index 39cecd1518..d6d293f1db 100644 --- a/projects/geo/src/lib/datasource/shared/datasources/index.ts +++ b/projects/geo/src/lib/datasource/shared/datasources/index.ts @@ -1,3 +1,4 @@ +export * from './data.service'; export * from './datasource'; export * from './datasource.interface'; export * from './feature-datasource'; @@ -8,6 +9,7 @@ export * from './xyz-datasource'; export * from './xyz-datasource.interface'; export * from './wfs-datasource'; export * from './wfs-datasource.interface'; +export * from './wfs.service'; export * from './wms-datasource'; export * from './wms-datasource.interface'; export * from './wmts-datasource'; diff --git a/projects/geo/src/lib/datasource/shared/datasources/wfs-datasource.interface.ts b/projects/geo/src/lib/datasource/shared/datasources/wfs-datasource.interface.ts index 87513a1142..53b05024d5 100644 --- a/projects/geo/src/lib/datasource/shared/datasources/wfs-datasource.interface.ts +++ b/projects/geo/src/lib/datasource/shared/datasources/wfs-datasource.interface.ts @@ -5,7 +5,9 @@ export interface WFSDataSourceOptions extends DataSourceOptions, FeatureDataSourceOptions { // type?: 'wfs'; - params: WFSDataSourceOptionsParams; + params: WFSDataSourceOptionsParams; // Used by user + paramsWFS?: WFSDataSourceOptionsParams; // Used by code + urlWfs?: string; // Used by code } export interface WFSDataSourceOptionsParams { @@ -13,7 +15,14 @@ export interface WFSDataSourceOptionsParams { featureTypes: string; fieldNameGeometry: string; maxFeatures?: Number; - outputFormat?: string; + outputFormat: string; + outputFormatDownload?: string; srsname?: string; xmlFilter?: string; + wfsCapabilities?: WFSCapabilitiesParams; +} + +export interface WFSCapabilitiesParams { + xmlBody?: string; + GetPropertyValue?: boolean; } diff --git a/projects/geo/src/lib/datasource/shared/datasources/wfs-datasource.ts b/projects/geo/src/lib/datasource/shared/datasources/wfs-datasource.ts index 9aefece8d9..78ba9bc18a 100644 --- a/projects/geo/src/lib/datasource/shared/datasources/wfs-datasource.ts +++ b/projects/geo/src/lib/datasource/shared/datasources/wfs-datasource.ts @@ -6,17 +6,23 @@ import { uuid } from '@igo2/utils'; import { DataSource } from './datasource'; import { WFSDataSourceOptions } from './wfs-datasource.interface'; +import { WFSService } from './wfs.service'; import { OgcFilterWriter } from '../../../filter/shared/ogc-filter'; +import { OgcFilterableDataSourceOptions } from '../../../filter/shared/ogc-filter.interface'; export class WFSDataSource extends DataSource { public ol: olSourceVector; public ogcFilterWriter: OgcFilterWriter; - constructor(public options: WFSDataSourceOptions) { + constructor( + public options: WFSDataSourceOptions, + protected wfsService: WFSService + ) { super(options); - this.options = this.checkWfsOptions(options); + this.options = this.wfsService.checkWfsOptions(options); this.ogcFilterWriter = new OgcFilterWriter(); + this.wfsService.getSourceFieldsFromWFS(this.options); } protected generateId() { @@ -24,7 +30,28 @@ export class WFSDataSource extends DataSource { } protected createOlSource(): olSourceVector { - const wfsOptions = this.options; + // reassignation of params to paramsWFS and url to urlWFS to have a common interface with wms-wfs datasources + this.options.paramsWFS = this.options.params; + this.options.urlWfs = this.options.url; + // default wfs version + this.options.paramsWFS.version = this.options.paramsWFS.version + ? this.options.paramsWFS.version + : '2.0.0'; + const ogcFiltersDefaultValue = true; // default values for wfs. + (this.options as OgcFilterableDataSourceOptions).ogcFilters = + (this.options as OgcFilterableDataSourceOptions).ogcFilters === undefined + ? {} + : (this.options as OgcFilterableDataSourceOptions).ogcFilters; + (this.options as OgcFilterableDataSourceOptions).ogcFilters.enabled = + (this.options as OgcFilterableDataSourceOptions).ogcFilters.enabled === + undefined + ? ogcFiltersDefaultValue + : (this.options as OgcFilterableDataSourceOptions).ogcFilters.enabled; + (this.options as OgcFilterableDataSourceOptions).ogcFilters.editable = + (this.options as OgcFilterableDataSourceOptions).ogcFilters.editable === + undefined + ? ogcFiltersDefaultValue + : (this.options as OgcFilterableDataSourceOptions).ogcFilters.editable; return new olSourceVector({ format: this.getFormatFromOptions(), @@ -32,51 +59,56 @@ export class WFSDataSource extends DataSource { url: (extent, resolution, proj) => { const baseWfsQuery = 'service=WFS&request=GetFeature'; // Mandatory - const url = wfsOptions.url; + const url = this.options.urlWfs; // Optional - const outputFormat = wfsOptions.params.outputFormat - ? 'outputFormat=' + wfsOptions.params.outputFormat + const outputFormat = this.options.paramsWFS.outputFormat + ? 'outputFormat=' + this.options.paramsWFS.outputFormat : ''; - const wfsVersion = wfsOptions.params.version - ? 'version=' + wfsOptions.params.version + const wfsVersion = this.options.paramsWFS.version + ? 'version=' + this.options.paramsWFS.version : 'version=' + '2.0.0'; let paramTypename = 'typename'; let paramMaxFeatures = 'maxFeatures'; if ( - wfsOptions.params.version === '2.0.0' || - !wfsOptions.params.version + this.options.paramsWFS.version === '2.0.0' || + !this.options.paramsWFS.version ) { paramTypename = 'typenames'; paramMaxFeatures = 'count'; } const featureTypes = - paramTypename + '=' + wfsOptions.params.featureTypes; + paramTypename + '=' + this.options.paramsWFS.featureTypes; - const maxFeatures = wfsOptions.params.maxFeatures - ? paramMaxFeatures + '=' + wfsOptions.params.maxFeatures + const maxFeatures = this.options.paramsWFS.maxFeatures + ? paramMaxFeatures + '=' + this.options.paramsWFS.maxFeatures : paramMaxFeatures + '=5000'; - const srsname = wfsOptions.params.srsname - ? 'srsname=' + wfsOptions.params.srsname + const srsname = this.options.paramsWFS.srsname + ? 'srsname=' + this.options.paramsWFS.srsname : 'srsname=' + proj.getCode(); - wfsOptions.params.xmlFilter = this.ogcFilterWriter.buildFilter( - (wfsOptions as any).ogcFilters.filters, - extent, - proj, - wfsOptions.params.fieldNameGeometry - ); + if ( + (this.options as OgcFilterableDataSourceOptions).ogcFilters && + (this.options as OgcFilterableDataSourceOptions).ogcFilters.enabled + ) { + this.options.paramsWFS.xmlFilter = this.ogcFilterWriter.buildFilter( + (this.options as OgcFilterableDataSourceOptions).ogcFilters.filters, + extent, + proj, + this.options.paramsWFS.fieldNameGeometry + ); + } let baseUrl = `${url}?${baseWfsQuery}&${wfsVersion}&${featureTypes}&`; baseUrl += `${outputFormat}&${srsname}&${maxFeatures}`; const patternFilter = /filter=.*/gi; - if (patternFilter.test(wfsOptions.params.xmlFilter)) { - baseUrl += `&${wfsOptions.params.xmlFilter}`; + if (patternFilter.test(this.options.paramsWFS.xmlFilter)) { + baseUrl += `&${this.options.paramsWFS.xmlFilter}`; } - this.options['download'] = Object.assign({}, this.options['download'], { + this.options.download = Object.assign({}, this.options.download, { dynamicUrl: baseUrl }); @@ -89,7 +121,7 @@ export class WFSDataSource extends DataSource { private getFormatFromOptions() { let olFormatCls; - const outputFormat = this.options.params.outputFormat.toLowerCase(); + const outputFormat = this.options.paramsWFS.outputFormat.toLowerCase(); const patternGml3 = new RegExp('.*?gml.*?'); const patternGeojson = new RegExp('.*?json.*?'); @@ -102,38 +134,4 @@ export class WFSDataSource extends DataSource { return new olFormatCls(); } - - private checkWfsOptions( - wfsDataSourceOptions: WFSDataSourceOptions - ): WFSDataSourceOptions { - const mandatoryParamMissing: any[] = []; - - if (!wfsDataSourceOptions.url) { - mandatoryParamMissing.push('url'); - } - ['featureTypes', 'fieldNameGeometry', 'outputFormat'].forEach(element => { - if (wfsDataSourceOptions.params[element] === undefined) { - mandatoryParamMissing.push(element); - } - }); - - if (mandatoryParamMissing.length > 0) { - throw new Error( - `A mandatory parameter is missing - for your WFS datasource source. - (Mandatory parameter(s) missing :` + mandatoryParamMissing - ); - } - - // Look at https://github.com/openlayers/openlayers/pull/6400 - const patternGml = new RegExp('.*?gml.*?'); - - if (patternGml.test(wfsDataSourceOptions.params.outputFormat)) { - wfsDataSourceOptions.params.version = '1.1.0'; - } - - return Object.assign({}, wfsDataSourceOptions, { - wfsCapabilities: { xml: '', GetPropertyValue: false } - }); - } } diff --git a/projects/geo/src/lib/datasource/shared/wfs.service.ts b/projects/geo/src/lib/datasource/shared/datasources/wfs.service.ts similarity index 68% rename from projects/geo/src/lib/datasource/shared/wfs.service.ts rename to projects/geo/src/lib/datasource/shared/datasources/wfs.service.ts index 786386172c..02dbbfed7a 100644 --- a/projects/geo/src/lib/datasource/shared/wfs.service.ts +++ b/projects/geo/src/lib/datasource/shared/datasources/wfs.service.ts @@ -5,13 +5,74 @@ import { Observable } from 'rxjs'; import olFeature from 'ol/Feature'; import * as olformat from 'ol/format'; -import { WFSDataSourceOptions } from './datasources/wfs-datasource.interface'; +import { WFSDataSourceOptions } from './wfs-datasource.interface'; +import { DataService } from './data.service'; @Injectable({ providedIn: 'root' }) -export class WFSService { - constructor(private http: HttpClient) {} +export class WFSService extends DataService { + constructor(private http: HttpClient) { + super(); + } + + getData() { + console.log('This is defining a data service.'); + return 'This is defining a data service.'; + } + + public getSourceFieldsFromWFS(datasource) { + if ( + datasource.sourceFields === undefined || + Object.keys(datasource.sourceFields).length === 0 + ) { + datasource.sourceFields = []; + this.wfsGetCapabilities(datasource).subscribe(wfsCapabilities => { + datasource.paramsWFS.wfsCapabilities = { + xmlBody: wfsCapabilities.body, + GetPropertyValue: /GetPropertyValue/gi.test(wfsCapabilities.body) + ? true + : false + }; + + this.defineFieldAndValuefromWFS(datasource).subscribe(sourceFields => { + datasource.sourceFields = sourceFields; + }); + }); + } else { + datasource.sourceFields.forEach(sourcefield => { + if (sourcefield.alias === undefined) { + sourcefield.alias = sourcefield.name; // to allow only a list of sourcefield with names + } + }); + + datasource.sourceFields + .filter( + field => field.values === undefined || field.values.length === 0 + ) + .forEach(f => { + this.getValueFromWfsGetPropertyValues( + datasource, + f.name, + 200, + 0, + 0 + ).subscribe(rep => (f.values = rep)); + }); + } + } + + public checkWfsOptions(wfsDataSourceOptions) { + // Look at https://github.com/openlayers/openlayers/pull/6400 + const patternGml = new RegExp(/.*?gml.*?/gi); + + if (patternGml.test(wfsDataSourceOptions.paramsWFS.outputFormat)) { + wfsDataSourceOptions.paramsWFS.version = '1.1.0'; + } + return Object.assign({}, wfsDataSourceOptions, { + wfsCapabilities: { xmlBody: '', GetPropertyValue: false } + }); + } public buildBaseWfsUrl( wfsDataSourceOptions: WFSDataSourceOptions, @@ -19,20 +80,20 @@ export class WFSService { ): string { let paramTypename = 'typename'; if ( - wfsDataSourceOptions.params.version === '2.0.0' || - !wfsDataSourceOptions.params.version + wfsDataSourceOptions.paramsWFS.version === '2.0.0' || + !wfsDataSourceOptions.paramsWFS.version ) { paramTypename = 'typenames'; } const baseWfsQuery = 'service=wfs&request=' + wfsQuery; const wfs_typeName = - paramTypename + '=' + wfsDataSourceOptions.params.featureTypes; - const wfsVersion = wfsDataSourceOptions.params.version - ? 'version=' + wfsDataSourceOptions.params.version + paramTypename + '=' + wfsDataSourceOptions.paramsWFS.featureTypes; + const wfsVersion = wfsDataSourceOptions.paramsWFS.version + ? 'version=' + wfsDataSourceOptions.paramsWFS.version : 'version=' + '2.0.0'; return `${ - wfsDataSourceOptions.url + wfsDataSourceOptions.urlWfs }?${baseWfsQuery}&${wfsVersion}&${wfs_typeName}`; } @@ -43,18 +104,18 @@ export class WFSService { propertyname = '' ): Observable { const base_url = this.buildBaseWfsUrl(wfsDataSourceOptions, 'GetFeature'); - const outputFormat = wfsDataSourceOptions.params.outputFormat - ? 'outputFormat=' + wfsDataSourceOptions.params.outputFormat + const outputFormat = wfsDataSourceOptions.paramsWFS.outputFormat + ? 'outputFormat=' + wfsDataSourceOptions.paramsWFS.outputFormat : ''; - const srsname = wfsDataSourceOptions.params.srsname - ? 'srsname=' + wfsDataSourceOptions.params.srsname + const srsname = wfsDataSourceOptions.paramsWFS.srsname + ? 'srsname=' + wfsDataSourceOptions.paramsWFS.srsname : 'srsname=EPSG:' + epsgCode; const wfspropertyname = propertyname === '' ? propertyname : '&propertyname=' + propertyname; let paramMaxFeatures = 'maxFeatures'; if ( - wfsDataSourceOptions.params.version === '2.0.0' || - !wfsDataSourceOptions.params.version + wfsDataSourceOptions.paramsWFS.version === '2.0.0' || + !wfsDataSourceOptions.paramsWFS.version ) { paramMaxFeatures = 'count'; } @@ -63,18 +124,18 @@ export class WFSService { if (nb !== 5000) { maxFeatures = paramMaxFeatures + '=' + nb; } else { - maxFeatures = wfsDataSourceOptions.params.maxFeatures - ? paramMaxFeatures + '=' + wfsDataSourceOptions.params.maxFeatures + maxFeatures = wfsDataSourceOptions.paramsWFS.maxFeatures + ? paramMaxFeatures + '=' + wfsDataSourceOptions.paramsWFS.maxFeatures : paramMaxFeatures + '=' + nb; } - const url = `${base_url}&${outputFormat}&${srsname}&${maxFeatures}${wfspropertyname}`; + const urlWfs = `${base_url}&${outputFormat}&${srsname}&${maxFeatures}${wfspropertyname}`; const patternGml = new RegExp('.*?gml.*?'); if ( - patternGml.test(wfsDataSourceOptions.params.outputFormat.toLowerCase()) + patternGml.test(wfsDataSourceOptions.paramsWFS.outputFormat.toLowerCase()) ) { - return this.http.get(url, { responseType: 'text' }); + return this.http.get(urlWfs, { responseType: 'text' }); } else { - return this.http.get(url); + return this.http.get(urlWfs); } } @@ -148,7 +209,7 @@ export class WFSService { const wfsVersion = options.version ? 'version=' + options.version : 'version=' + '2.0.0'; - const wfs_gc_url = `${options.url}?${baseWfsQuery}&${wfsVersion}`; + const wfs_gc_url = `${options.urlWfs}?${baseWfsQuery}&${wfsVersion}`; return this.http.get(wfs_gc_url, { observe: 'response', responseType: 'text' @@ -165,13 +226,13 @@ export class WFSService { let fieldListWoGeomStr; let olFormats; const patternGml3 = /gml/gi; - if (wfsDataSourceOptions.params.outputFormat.match(patternGml3)) { + if (wfsDataSourceOptions.paramsWFS.outputFormat.match(patternGml3)) { olFormats = olformat.WFS; } else { olFormats = olformat.GeoJSON; } - if (wfsDataSourceOptions['wfsCapabilities']['GetPropertyValue']) { + if (wfsDataSourceOptions.paramsWFS.wfsCapabilities.GetPropertyValue) { this.wfsGetFeature(wfsDataSourceOptions, 1).subscribe(oneFeature => { const features = new olFormats().readFeatures(oneFeature); fieldList = features[0].getKeys(); @@ -194,7 +255,6 @@ export class WFSService { sourceFields.push({ name: element, alias: element, - type: fieldType, values: valueList }); d.next(sourceFields); @@ -238,12 +298,11 @@ export class WFSService { const baseWfsQuery = 'service=wfs&request=GetPropertyValue&count=' + maxFeatures; const wfs_typeName = - 'typenames=' + wfsDataSourceOptions.params.featureTypes; + 'typenames=' + wfsDataSourceOptions.paramsWFS.featureTypes; const wfsValueReference = 'valueReference=' + field; const wfsVersion = 'version=' + '2.0.0'; - // tslint:disable-next-line:max-line-length const gfv_url = `${ - wfsDataSourceOptions.url + wfsDataSourceOptions.urlWfs }?${baseWfsQuery}&${wfsVersion}&${wfs_typeName}&${wfsValueReference}`; return this.http.get(gfv_url, { responseType: 'text' }); } diff --git a/projects/geo/src/lib/datasource/shared/datasources/wms-datasource.interface.ts b/projects/geo/src/lib/datasource/shared/datasources/wms-datasource.interface.ts index 6fa98b20d8..7f6678045d 100644 --- a/projects/geo/src/lib/datasource/shared/datasources/wms-datasource.interface.ts +++ b/projects/geo/src/lib/datasource/shared/datasources/wms-datasource.interface.ts @@ -1,13 +1,13 @@ import olSourceImageWMS from 'ol/source/ImageWMS'; import { DataSourceOptions } from './datasource.interface'; -import { WFSDataSourceOptions } from './wfs-datasource.interface'; +import { WFSDataSourceOptionsParams } from './wfs-datasource.interface'; export interface WMSDataSourceOptions extends DataSourceOptions { // type?: 'wms'; optionsFromCapabilities?: boolean; - wfsSource?: WFSDataSourceOptions; - + paramsWFS?: WFSDataSourceOptionsParams; // for wms linked with wfs + urlWfs?: string; // if url for linked wfs differ from the url for wms. url: string; params: WMSDataSourceOptionsParams; projection?: string; diff --git a/projects/geo/src/lib/datasource/shared/datasources/wms-datasource.ts b/projects/geo/src/lib/datasource/shared/datasources/wms-datasource.ts index f002565d9f..3f01380759 100644 --- a/projects/geo/src/lib/datasource/shared/datasources/wms-datasource.ts +++ b/projects/geo/src/lib/datasource/shared/datasources/wms-datasource.ts @@ -4,9 +4,15 @@ import olSourceImageWMS from 'ol/source/ImageWMS'; import { DataSource } from './datasource'; import { DataSourceLegendOptions } from './datasource.interface'; import { WMSDataSourceOptions } from './wms-datasource.interface'; +import { WFSService } from './wfs.service'; +import { WFSDataSourceOptions } from './wfs-datasource.interface'; + +import { OgcFilterWriter } from '../../../filter/shared/ogc-filter'; +import { OgcFilterableDataSourceOptions } from '../../../filter/shared/ogc-filter.interface'; export class WMSDataSource extends DataSource { public ol: olSourceImageWMS; + public ogcFilterWriter: OgcFilterWriter; private queryInfoFormat: string; @@ -26,9 +32,11 @@ export class WMSDataSource extends DataSource { : 'newtab'; } - constructor(public options: WMSDataSourceOptions) { + constructor( + public options: WMSDataSourceOptions, + protected wfsService: WFSService + ) { super(options); - // Important: To use wms versions smaller than 1.3.0, SRS // needs to be supplied in the source "params" @@ -38,14 +46,81 @@ export class WMSDataSource extends DataSource { if (sourceParams && sourceParams.version) { sourceParams.VERSION = sourceParams.version; } + if (options.refreshIntervalSec && options.refreshIntervalSec > 0) { setInterval(() => { - this.ol.updateParams({'igoRefresh': Math.random()}); + this.ol.updateParams({ igoRefresh: Math.random() }); }, options.refreshIntervalSec * 1000); // Convert seconds to MS } + + // #### START if paramsWFS + if (options.paramsWFS) { + const wfsCheckup = this.wfsService.checkWfsOptions(options); + options.paramsWFS.version = wfsCheckup.paramsWFS.version; + options.paramsWFS.wfsCapabilities = wfsCheckup.params.wfsCapabilities; + + this.wfsService.getSourceFieldsFromWFS(options); + + this.options.download = Object.assign({}, this.options.download, { + dynamicUrl: this.buildDynamicDownloadUrlFromParamsWFS(this.options) + }); + } // #### END if paramsWFS + this.ogcFilterWriter = new OgcFilterWriter(); + if (!options.sourceFields || options.sourceFields.length === 0) { + options.sourceFields = []; + } + } + + private buildDynamicDownloadUrlFromParamsWFS(asWFSDataSourceOptions) { + const outputFormat = + asWFSDataSourceOptions.paramsWFS.outputFormat !== undefined + ? 'outputFormat=' + asWFSDataSourceOptions.paramsWFS.outputFormat + : ''; + + let paramMaxFeatures = 'maxFeatures'; + if ( + asWFSDataSourceOptions.paramsWFS.version === '2.0.0' || + !asWFSDataSourceOptions.paramsWFS.version + ) { + paramMaxFeatures = 'count'; + } + const maxFeatures = asWFSDataSourceOptions.paramsWFS.maxFeatures + ? paramMaxFeatures + '=' + asWFSDataSourceOptions.paramsWFS.maxFeatures + : paramMaxFeatures + '=5000'; + const srsname = asWFSDataSourceOptions.paramsWFS.srsname + ? 'srsname=' + asWFSDataSourceOptions.paramsWFS.srsname + : 'srsname=EPSG:3857'; + const baseWfsQuery = this.wfsService.buildBaseWfsUrl( + asWFSDataSourceOptions, + 'GetFeature' + ); + return `${baseWfsQuery}&${outputFormat}&${srsname}&${maxFeatures}`; } protected createOlSource(): olSourceImageWMS { + if (this.options.paramsWFS) { + this.options.urlWfs = this.options.urlWfs + ? this.options.urlWfs + : this.options.url; + this.options.paramsWFS.version = this.options.paramsWFS.version + ? this.options.paramsWFS.version + : '2.0.0'; + } + const ogcFiltersDefaultValue = false; // default values for wms. + (this.options as OgcFilterableDataSourceOptions).ogcFilters = + (this.options as OgcFilterableDataSourceOptions).ogcFilters === undefined + ? {} + : (this.options as OgcFilterableDataSourceOptions).ogcFilters; + (this.options as OgcFilterableDataSourceOptions).ogcFilters.enabled = + (this.options as OgcFilterableDataSourceOptions).ogcFilters.enabled === + undefined + ? ogcFiltersDefaultValue + : (this.options as OgcFilterableDataSourceOptions).ogcFilters.enabled; + (this.options as OgcFilterableDataSourceOptions).ogcFilters.editable = + (this.options as OgcFilterableDataSourceOptions).ogcFilters.editable === + undefined + ? ogcFiltersDefaultValue + : (this.options as OgcFilterableDataSourceOptions).ogcFilters.editable; return new olSourceImageWMS(this.options); } diff --git a/projects/geo/src/lib/datasource/shared/index.ts b/projects/geo/src/lib/datasource/shared/index.ts index 006a0e4986..42bec971ed 100644 --- a/projects/geo/src/lib/datasource/shared/index.ts +++ b/projects/geo/src/lib/datasource/shared/index.ts @@ -1,4 +1,3 @@ export * from './datasources'; export * from './datasource.service'; -export * from './wfs.service'; export * from './capabilities.service'; diff --git a/projects/geo/src/lib/download/shared/download.interface.ts b/projects/geo/src/lib/download/shared/download.interface.ts index c8a4d2f7b2..4731d982b8 100644 --- a/projects/geo/src/lib/download/shared/download.interface.ts +++ b/projects/geo/src/lib/download/shared/download.interface.ts @@ -2,9 +2,10 @@ import { DataSourceOptions } from '../../datasource/shared/datasources/datasourc export interface DownloadOptions { url: string; + dynamicUrl?: string; extern?: boolean; } -export interface DownloadDataSourceOptions extends DataSourceOptions { +export interface DownloadDataSourceOptions { download?: DownloadOptions; } diff --git a/projects/geo/src/lib/download/shared/download.service.ts b/projects/geo/src/lib/download/shared/download.service.ts index 010e65265c..6f18fc4409 100644 --- a/projects/geo/src/lib/download/shared/download.service.ts +++ b/projects/geo/src/lib/download/shared/download.service.ts @@ -7,7 +7,7 @@ import { MessageService, LanguageService } from '@igo2/core'; import { Layer } from '../../layer/shared'; import { OgcFilterWriter } from '../../filter/shared'; -import { DownloadDataSourceOptions } from './download.interface'; +import { DataSourceOptions } from '../../datasource/shared/datasources/datasource.interface'; @Injectable({ providedIn: 'root' @@ -30,28 +30,28 @@ export class DownloadService { title ); - const DSOptions: DownloadDataSourceOptions = layer.dataSource.options; + const DSOptions: DataSourceOptions = layer.dataSource.options; if (Object.keys(DSOptions.download).length > 0) { if ( - DSOptions.download['dynamicUrl'] && + DSOptions.download.dynamicUrl && DSOptions.download.url === undefined ) { let wfsOptions; if ( - layer.dataSource.options['wfsSource'] && - Object.keys(layer.dataSource.options['wfsSource']).length > 0 + layer.dataSource.options['paramsWFS'] && + Object.keys(layer.dataSource.options['paramsWFS']).length > 0 ) { - wfsOptions = layer.dataSource.options['wfsSource']; + wfsOptions = layer.dataSource.options['paramsWFS']; } else { - wfsOptions = layer.dataSource.options; + wfsOptions = layer.dataSource.options['params']; } const outputFormatDownload = - wfsOptions['outputFormatDownload'] === undefined - ? 'outputformat=' + wfsOptions['outputFormat'] - : 'outputformat=' + wfsOptions['outputFormatDownload']; + wfsOptions.outputFormatDownload === undefined + ? 'outputformat=' + wfsOptions.outputFormat + : 'outputformat=' + wfsOptions.outputFormatDownload; - const baseurl = DSOptions.download['dynamicUrl'] + const baseurl = DSOptions.download.dynamicUrl .replace(/&?outputformat=[^&]*/gi, '') .replace(/&?filter=[^&]*/gi, '') .replace(/&?bbox=[^&]*/gi, ''); @@ -60,7 +60,7 @@ export class DownloadService { layer.dataSource.options['ogcFilters']['filters'], layer.map.getExtent(), new olProjection({ code: layer.map.projection }), - wfsOptions['fieldNameGeometry'] + wfsOptions.fieldNameGeometry ); window.open( `${baseurl}&${rebuildFilter}&${outputFormatDownload}`, diff --git a/projects/geo/src/lib/filter/ogc-filter-button/ogc-filter-button.component.html b/projects/geo/src/lib/filter/ogc-filter-button/ogc-filter-button.component.html index b522fd2737..ae91a7b4cb 100644 --- a/projects/geo/src/lib/filter/ogc-filter-button/ogc-filter-button.component.html +++ b/projects/geo/src/lib/filter/ogc-filter-button/ogc-filter-button.component.html @@ -1,5 +1,5 @@ - -
+
diff --git a/projects/geo/src/lib/filter/ogc-filter-button/ogc-filter-button.component.ts b/projects/geo/src/lib/filter/ogc-filter-button/ogc-filter-button.component.ts index 090a2e0f5a..8ac9db15ac 100644 --- a/projects/geo/src/lib/filter/ogc-filter-button/ogc-filter-button.component.ts +++ b/projects/geo/src/lib/filter/ogc-filter-button/ogc-filter-button.component.ts @@ -1,7 +1,7 @@ import { Component, Input, ChangeDetectionStrategy } from '@angular/core'; import { Layer } from '../../layer/shared/layers/layer'; - +import { IgoMap } from '../../map'; import { OgcFilterableDataSourceOptions } from '../shared/ogc-filter.interface'; @Component({ @@ -20,6 +20,15 @@ export class OgcFilterButtonComponent { } private _layer: Layer; + @Input() + get map(): IgoMap { + return this._map; + } + set map(value: IgoMap) { + this._map = value; + } + private _map: IgoMap; + @Input() get color() { return this._color; diff --git a/projects/geo/src/lib/filter/ogc-filter-form/ogc-filter-form.component.html b/projects/geo/src/lib/filter/ogc-filter-form/ogc-filter-form.component.html index 59dddf185a..eb88b1da7a 100644 --- a/projects/geo/src/lib/filter/ogc-filter-form/ogc-filter-form.component.html +++ b/projects/geo/src/lib/filter/ogc-filter-form/ogc-filter-form.component.html @@ -1,7 +1,7 @@
- {{'igo.geo.operators.And' | translate}} {{'igo.geo.operators.Or' | translate}} @@ -18,7 +18,7 @@ -
- - {{operator.value.alias}} + + {{('igo.geo.operators.'+ operator.key) | translate}}
@@ -40,8 +40,8 @@ - + {{ value }} @@ -59,8 +59,8 @@ - + {{ value }} @@ -81,8 +81,8 @@ - + {{ value }} @@ -99,8 +99,8 @@ - + {{ value }} @@ -111,8 +111,8 @@ - + {{ value }} @@ -130,8 +130,8 @@ - + {{ value }} @@ -143,8 +143,8 @@ - + {{ value }} @@ -164,13 +164,13 @@
- - {{operator.value.alias}} + + {{('igo.geo.operators.'+ operator.key) | translate}}
- {{igoSpatialSelector.alias}} + {{('igo.geo.spatialSelector.'+ igoSpatialSelector.type) | translate}}
@@ -185,7 +185,7 @@ - - + + + - +
diff --git a/projects/geo/src/lib/map/shared/map.ts b/projects/geo/src/lib/map/shared/map.ts index cbd583677c..3b0ac12727 100644 --- a/projects/geo/src/lib/map/shared/map.ts +++ b/projects/geo/src/lib/map/shared/map.ts @@ -115,25 +115,7 @@ export class IgoMap { this.overlayMarkerStyle = this.setOverlayMarkerStyle(); this.overlayDataSource = new FeatureDataSource(); - - const stroke = new olstyle.Stroke({ - color: [0, 161, 222, 1], - width: 2 - }); - - const fill = new olstyle.Fill({ - color: [0, 161, 222, 0.15] - }); - - this.overlayStyle = new olstyle.Style({ - stroke: stroke, - fill: fill, - image: new olstyle.Circle({ - radius: 5, - stroke: stroke, - fill: fill - }) - }); + this.overlayStyle = this.setOverlayDataSourceStyle(); const layer = new VectorLayer({ title: 'Overlay', @@ -352,6 +334,12 @@ export class IgoMap { this.overlayDataSource.ol.addFeature(feature); } + getOverlayByID(id): olFeature { + if (this.overlayDataSource.ol.getFeatureById(id)) { + return this.overlayDataSource.ol.getFeatureById(id); + } + return; + } removeOverlayByID(id) { if (this.overlayDataSource.ol.getFeatureById(id)) { @@ -455,6 +443,38 @@ export class IgoMap { return listLegend; } + setOverlayDataSourceStyle( + strokeRGBA: [number, number, number, number] = [0, 161, 222, 1], + strokeWidth: number = 2, + fillRGBA: [number, number, number, number] = [0, 161, 222, 0.15], + text? + ): olstyle.Style { + const stroke = new olstyle.Stroke({ + color: strokeRGBA, + width: strokeWidth + }); + + const fill = new olstyle.Fill({ + color: fillRGBA + }); + + return new olstyle.Style({ + stroke: stroke, + fill: fill, + image: new olstyle.Circle({ + radius: 5, + stroke: stroke, + fill: fill + }), + text: new olstyle.Text({ + font: '12px Calibri,sans-serif', + text: text, + fill: new olstyle.Fill({ color: '#000' }), + stroke: new olstyle.Stroke({ color: '#fff', width: 3 }) + }) + }); + } + setOverlayMarkerStyle(color = 'blue', text?): olstyle.Style { let iconColor; switch (color) { diff --git a/projects/geo/src/lib/wkt/shared/wkt.service.ts b/projects/geo/src/lib/wkt/shared/wkt.service.ts index b04423f78b..2d1985a61a 100644 --- a/projects/geo/src/lib/wkt/shared/wkt.service.ts +++ b/projects/geo/src/lib/wkt/shared/wkt.service.ts @@ -2,25 +2,44 @@ import { Injectable } from '@angular/core'; import * as olproj from 'ol/proj'; import olWKT from 'ol/format/WKT'; -import olPolygon from 'ol/geom/Polygon'; - -import { MapService } from '../../map/shared/map.service'; @Injectable({ providedIn: 'root' }) export class WktService { - constructor(private mapService: MapService) {} - - public mapExtentToWKT(epsgTO = this.mapService.getMap().projection) { - let extent = olproj.transformExtent( - this.mapService.getMap().getExtent(), - this.mapService.getMap().projection, - epsgTO - ); - extent = this.roundCoordinateArray(extent, epsgTO, 0); - const wkt = new olWKT().writeGeometry(olPolygon.fromExtent(extent)); - return wkt; + constructor() {} + + public wktToFeature(wkt, wktProj, featureProj = 'EPSG:3857') { + return new olWKT().readFeature(wkt, { + dataProjection: wktProj, + featureProjection: featureProj + }); + } + public extentToWkt(epsgTO, extent, extentProj) { + let currentExtent = olproj.transformExtent(extent, extentProj, epsgTO); + currentExtent = this.roundCoordinateArray(currentExtent, epsgTO, 0); + const wktPoly = `POLYGON(( + ${extent[0]} ${extent[1]}, + ${extent[0]} ${extent[3]}, + ${extent[2]} ${extent[3]}, + ${extent[2]} ${extent[1]}, + ${extent[0]} ${extent[1]}))`; + const wktLine = `LINESTRING( + ${extent[0]} ${extent[1]}, + ${extent[0]} ${extent[3]}, + ${extent[2]} ${extent[3]}, + ${extent[2]} ${extent[1]}, + ${extent[0]} ${extent[1]})`; + const wktMultiPoints = `MULTIPOINT( + ${extent[0]} ${extent[1]}, + ${extent[0]} ${extent[3]}, + ${extent[2]} ${extent[3]}, + ${extent[2]} ${extent[1]})`; + return { + wktPoly: wktPoly, + wktLine: wktLine, + wktMultiPoints: wktMultiPoints + }; } private roundCoordinateArray(coordinateArray, projection, decimal = 0) { @@ -28,7 +47,7 @@ export class WktService { const units = lproj.getUnits(); const olUnits = ['ft', 'm', 'us-ft']; if (olUnits.indexOf(units) !== -1) { - coordinateArray = this.roundArray(coordinateArray); + coordinateArray = this.roundArray(coordinateArray, decimal); } return coordinateArray; } @@ -42,7 +61,7 @@ export class WktService { return array; } - public snrcWKT(snrc, epsgTO = 'EPSG:3857') { + public snrcToWkt(snrc, epsgTO = 'EPSG:3857') { snrc = snrc.toLowerCase(); let wktPoly; const ew = { @@ -81,8 +100,8 @@ export class WktService { ['05', '06', '07', '08'], ['04', '03', '02', '01'] ]; - const checkSNRC50k = /\d{2,3}[a-l][0,1][0-9]/gi; - const checkSNRC250k = /\d{2,3}[a-l]/gi; + const checkSNRC50k = /\d{2,3}[a-p][0,1][0-9]/gi; + const checkSNRC250k = /\d{2,3}[a-p]/gi; const checkSNRC1m = /\d{2,3}/gi; let snrc1m = false; @@ -106,8 +125,8 @@ export class WktService { } else if (snrc250k) { snrc += '01'; } - if (/\d{2,3}[a-l][0,1][0-9]/gi.test(snrc)) { - const regex_1m = /(?=[a-l])/gi; + if (/\d{2,3}[a-p][0,1][0-9]/gi.test(snrc)) { + const regex_1m = /(?=[a-p])/gi; const ar1m = snrc.split(regex_1m); const part1m = ar1m[0]; const part250k = ar1m[1][0]; @@ -214,8 +233,31 @@ export class WktService { coord.ul.join(' ') ].join(',') + '))'; + const wktLine = + 'LINESTRING(' + + [ + coord.ul.join(' '), + coord['ur'].join(' '), + coord['lr'].join(' '), + coord['ll'].join(' '), + coord.ul.join(' ') + ].join(',') + + ')'; - return wktPoly; + const wktMultiPoints = + 'MULTIPOINT(' + + [ + coord.ul.join(' '), + coord['ur'].join(' '), + coord['lr'].join(' '), + coord['ll'].join(' ') + ].join(',') + + ')'; + return { + wktPoly: wktPoly, + wktLine: wktLine, + wktMultiPoints: wktMultiPoints + }; } } } diff --git a/projects/geo/src/locale/en.geo.json b/projects/geo/src/locale/en.geo.json index aea0c94997..fbddb857b1 100644 --- a/projects/geo/src/locale/en.geo.json +++ b/projects/geo/src/locale/en.geo.json @@ -58,7 +58,9 @@ "Update this datasource with the active filter(s). To enable this button, the layer must be visible (or in the defined scale ranges) or you must modify the current filter.", "layerFiltered": "This layer is currently filtered", "layerFilterable": "This layer is filterable", - "filterBy": "Filter by" + "filterBy": "Filter by", + "showFeatureExtent": "Show feature used as spatial extent", + "hideFeatureExtent": "Hide feature used as spatial extent " }, "spatialSelector": { "fixedExtent": "Fixed extent", diff --git a/projects/geo/src/locale/fr.geo.json b/projects/geo/src/locale/fr.geo.json index e01a0012ab..6a023a6b4a 100644 --- a/projects/geo/src/locale/fr.geo.json +++ b/projects/geo/src/locale/fr.geo.json @@ -58,7 +58,9 @@ "Mettre à jour la source de donnée avec les filtres actifs de la liste. Pour activer ce boutton, la couche doit etre visible (et dans les échelles permises) ou veillez modifier le présent filtre.", "layerFiltered": "Cette couche d'information est présentement filtrée.", "layerFilterable": "Cette couche d'information est filtrable", - "filterBy": "Filtrer par" + "filterBy": "Filtrer par", + "showFeatureExtent": "Montrer l'empreinte des étendues", + "hideFeatureExtent": "Cacher l'empreinte des étendues" }, "spatialSelector": { "fixedExtent": "Étendue fixe",