From 88e8dc37351ac95a98d7e3328dfbcd870654d8cc Mon Sep 17 00:00:00 2001 From: "dereck.lynch" Date: Fri, 28 Jun 2019 09:58:14 -0400 Subject: [PATCH 1/2] feat(datasource,layer,style): add Cluster datasource and configurable style for it --- demo/src/contexts/context3.json | 11 ++++ .../datasource/shared/datasource.service.ts | 15 ++++- .../datasources/any-datasource.interface.ts | 5 +- .../shared/datasources/any-datasource.ts | 4 +- .../cluster-datasource.interface.ts | 11 ++++ .../shared/datasources/cluster-datasource.ts | 21 +++++++ .../datasources/datasource.interface.ts | 3 +- .../datasource/shared/datasources/index.ts | 2 + .../geo/src/lib/layer/shared/clusterParam.ts | 5 ++ .../geo/src/lib/layer/shared/layer.service.ts | 12 +++- .../shared/layers/vector-layer.interface.ts | 14 +++-- .../lib/layer/shared/layers/vector-layer.ts | 7 +-- .../geo/src/lib/layer/shared/style.service.ts | 61 +++++++++++++++++++ 13 files changed, 155 insertions(+), 16 deletions(-) create mode 100644 packages/geo/src/lib/datasource/shared/datasources/cluster-datasource.interface.ts create mode 100644 packages/geo/src/lib/datasource/shared/datasources/cluster-datasource.ts create mode 100644 packages/geo/src/lib/layer/shared/clusterParam.ts diff --git a/demo/src/contexts/context3.json b/demo/src/contexts/context3.json index 8ee206233b..c34c38a5fc 100644 --- a/demo/src/contexts/context3.json +++ b/demo/src/contexts/context3.json @@ -48,6 +48,17 @@ ] } } + }, + { + "title": "cluster", + "clusterParam": { + "clusterRange": [8, 16] + }, + "sourceOptions": { + "type": "cluster", + "url": "http://10.202.76.35/fichier/bureaux_locaux3857.geojson", + "distance": 70 + } } ] } diff --git a/packages/geo/src/lib/datasource/shared/datasource.service.ts b/packages/geo/src/lib/datasource/shared/datasource.service.ts index 48ecc2466e..adcc85885c 100644 --- a/packages/geo/src/lib/datasource/shared/datasource.service.ts +++ b/packages/geo/src/lib/datasource/shared/datasource.service.ts @@ -25,7 +25,9 @@ import { TileArcGISRestDataSource, TileArcGISRestDataSourceOptions, WebSocketDataSource, - AnyDataSourceOptions + AnyDataSourceOptions, + ClusterDataSource, + ClusterDataSourceOptions } from './datasources'; @Injectable({ @@ -88,6 +90,11 @@ export class DataSourceService { context as TileArcGISRestDataSourceOptions ); break; + case 'cluster': + dataSource = this.createClusterDataSource( + context as ClusterDataSourceOptions + ); + break; default: console.error(context); throw new Error('Invalid datasource type'); @@ -201,4 +208,10 @@ export class DataSourceService { ) ); } + + private createClusterDataSource( + context: ClusterDataSourceOptions + ): Observable { + return new Observable(d => d.next(new ClusterDataSource(context))); + } } diff --git a/packages/geo/src/lib/datasource/shared/datasources/any-datasource.interface.ts b/packages/geo/src/lib/datasource/shared/datasources/any-datasource.interface.ts index 9ce7f08ffc..3aad5153a9 100644 --- a/packages/geo/src/lib/datasource/shared/datasources/any-datasource.interface.ts +++ b/packages/geo/src/lib/datasource/shared/datasources/any-datasource.interface.ts @@ -8,6 +8,7 @@ import { FeatureDataSourceOptions } from './feature-datasource.interface'; import { CartoDataSourceOptions } from './carto-datasource.interface'; import { ArcGISRestDataSourceOptions } from './arcgisrest-datasource.interface'; import { TileArcGISRestDataSourceOptions } from './tilearcgisrest-datasource.interface'; +import { ClusterDataSourceOptions } from './cluster-datasource.interface'; export type AnyDataSourceOptions = | DataSourceOptions @@ -19,4 +20,6 @@ export type AnyDataSourceOptions = | WMSDataSourceOptions | CartoDataSourceOptions | ArcGISRestDataSourceOptions - | TileArcGISRestDataSourceOptions; + | TileArcGISRestDataSourceOptions + | ClusterDataSourceOptions; + diff --git a/packages/geo/src/lib/datasource/shared/datasources/any-datasource.ts b/packages/geo/src/lib/datasource/shared/datasources/any-datasource.ts index cc3408c8bd..d06f1d61bf 100644 --- a/packages/geo/src/lib/datasource/shared/datasources/any-datasource.ts +++ b/packages/geo/src/lib/datasource/shared/datasources/any-datasource.ts @@ -9,6 +9,7 @@ import { CartoDataSource } from './carto-datasource'; import { ArcGISRestDataSource } from './arcgisrest-datasource'; import { TileArcGISRestDataSource } from './tilearcgisrest-datasource'; import { WebSocketDataSource } from './websocket-datasource'; +import { ClusterDataSource } from './cluster-datasource'; export type AnyDataSource = | DataSource @@ -21,4 +22,5 @@ export type AnyDataSource = | CartoDataSource | ArcGISRestDataSource | TileArcGISRestDataSource - | WebSocketDataSource; + | WebSocketDataSource + | ClusterDataSource; diff --git a/packages/geo/src/lib/datasource/shared/datasources/cluster-datasource.interface.ts b/packages/geo/src/lib/datasource/shared/datasources/cluster-datasource.interface.ts new file mode 100644 index 0000000000..180147b9a3 --- /dev/null +++ b/packages/geo/src/lib/datasource/shared/datasources/cluster-datasource.interface.ts @@ -0,0 +1,11 @@ +import olSourceVector from 'ol/source/Vector'; + +import { FeatureDataSource } from './feature-datasource'; +import { FeatureDataSourceOptions } from './feature-datasource.interface'; + +export interface ClusterDataSourceOptions extends FeatureDataSourceOptions { + // type?: 'cluster'; + distance?: number; + source?: FeatureDataSource; + ol?: olSourceVector; +} diff --git a/packages/geo/src/lib/datasource/shared/datasources/cluster-datasource.ts b/packages/geo/src/lib/datasource/shared/datasources/cluster-datasource.ts new file mode 100644 index 0000000000..4f3a0925b1 --- /dev/null +++ b/packages/geo/src/lib/datasource/shared/datasources/cluster-datasource.ts @@ -0,0 +1,21 @@ +import olSourceCluster from 'ol/source/Cluster'; + +import { uuid } from '@igo2/utils'; + +import { FeatureDataSource } from './feature-datasource'; +import { ClusterDataSourceOptions } from './cluster-datasource.interface'; + +export class ClusterDataSource extends FeatureDataSource { + public options: ClusterDataSourceOptions; + public ol: olSourceCluster; + + protected createOlSource(): olSourceCluster { + this.options.format = this.getSourceFormatFromOptions(this.options); + this.options.source = super.createOlSource(); + return new olSourceCluster(this.options); + } + + protected generateId() { + return uuid(); + } +} diff --git a/packages/geo/src/lib/datasource/shared/datasources/datasource.interface.ts b/packages/geo/src/lib/datasource/shared/datasources/datasource.interface.ts index 7bafbcd495..d63aa98901 100644 --- a/packages/geo/src/lib/datasource/shared/datasources/datasource.interface.ts +++ b/packages/geo/src/lib/datasource/shared/datasources/datasource.interface.ts @@ -14,7 +14,8 @@ export interface DataSourceOptions { | 'carto' | 'arcgisrest' | 'tilearcgisrest' - | 'websocket'; + | 'websocket' + | 'cluster'; legend?: DataSourceLegendOptions; optionsFromCapabilities?: boolean; // title: string; diff --git a/packages/geo/src/lib/datasource/shared/datasources/index.ts b/packages/geo/src/lib/datasource/shared/datasources/index.ts index 85855213ab..3ad5efe149 100644 --- a/packages/geo/src/lib/datasource/shared/datasources/index.ts +++ b/packages/geo/src/lib/datasource/shared/datasources/index.ts @@ -22,5 +22,7 @@ export * from './tilearcgisrest-datasource'; export * from './tilearcgisrest-datasource.interface'; export * from './websocket-datasource'; export * from './websocket-datasource.interface'; +export * from './cluster-datasource'; +export * from './cluster-datasource.interface'; export * from './any-datasource'; export * from './any-datasource.interface'; diff --git a/packages/geo/src/lib/layer/shared/clusterParam.ts b/packages/geo/src/lib/layer/shared/clusterParam.ts new file mode 100644 index 0000000000..989a69f6ef --- /dev/null +++ b/packages/geo/src/lib/layer/shared/clusterParam.ts @@ -0,0 +1,5 @@ +export interface ClusterParam { + clusterRange?: Array; // utiliser lorsqu'on veux une symbologie active pour une source cluster. + clusterIcon?: string; + clusterScale?: number; +} diff --git a/packages/geo/src/lib/layer/shared/layer.service.ts b/packages/geo/src/lib/layer/shared/layer.service.ts index b45d362f9f..0b25b84eec 100644 --- a/packages/geo/src/lib/layer/shared/layer.service.ts +++ b/packages/geo/src/lib/layer/shared/layer.service.ts @@ -15,7 +15,8 @@ import { CartoDataSource, ArcGISRestDataSource, TileArcGISRestDataSource, - WebSocketDataSource + WebSocketDataSource, + ClusterDataSource } from '../../datasource'; import { DataSourceService } from '../../datasource/shared/datasource.service'; @@ -77,6 +78,7 @@ export class LayerService { case WFSDataSource: case ArcGISRestDataSource: case WebSocketDataSource: + case ClusterDataSource: layer = this.createVectorLayer(layerOptions as VectorLayerOptions); break; case WMSDataSource: @@ -127,6 +129,14 @@ export class LayerService { style = source.options.params.style; } + if (layerOptions.source instanceof ClusterDataSource) { + const serviceStyle = this.styleService; + layerOptions.style = function(feature) { + return serviceStyle.createClusterStyle(feature, layerOptions.clusterParam); + }; + return new VectorLayer(layerOptions); + } + const layerOptionsOl = Object.assign({}, layerOptions, { style }); diff --git a/packages/geo/src/lib/layer/shared/layers/vector-layer.interface.ts b/packages/geo/src/lib/layer/shared/layers/vector-layer.interface.ts index 3157b1a049..f8288e59a1 100644 --- a/packages/geo/src/lib/layer/shared/layers/vector-layer.interface.ts +++ b/packages/geo/src/lib/layer/shared/layers/vector-layer.interface.ts @@ -8,28 +8,30 @@ import { FeatureDataSource } from '../../../datasource/shared/datasources/featur import { WFSDataSource } from '../../../datasource/shared/datasources/wfs-datasource'; import { ArcGISRestDataSource } from '../../../datasource/shared/datasources/arcgisrest-datasource'; import { WebSocketDataSource } from '../../../datasource/shared/datasources/websocket-datasource'; +import { ClusterDataSource } from '../../../datasource/shared/datasources/cluster-datasource'; import { FeatureDataSourceOptions } from '../../../datasource/shared/datasources/feature-datasource.interface'; import { WFSDataSourceOptions } from '../../../datasource/shared/datasources/wfs-datasource.interface'; import { ArcGISRestDataSourceOptions } from '../../../datasource/shared/datasources/arcgisrest-datasource.interface'; import { WebSocketDataSourceOptions } from '../../../datasource/shared/datasources/websocket-datasource.interface'; +import { ClusterDataSourceOptions } from '../../../datasource/shared/datasources/cluster-datasource.interface'; + +import { ClusterParam } from '../clusterParam'; export interface VectorLayerOptions extends LayerOptions { - source?: - | FeatureDataSource - | WFSDataSource - | ArcGISRestDataSource - | WebSocketDataSource; + source?: FeatureDataSource | WFSDataSource | ArcGISRestDataSource | WebSocketDataSource | ClusterDataSource; sourceOptions?: | FeatureDataSourceOptions | WFSDataSourceOptions | ArcGISRestDataSourceOptions - | WebSocketDataSourceOptions; + | WebSocketDataSourceOptions + | ClusterDataSourceOptions; style?: { [key: string]: any } | olStyle | olStyle[]; browsable?: boolean; exportable?: boolean; ol?: olLayerVector; animation?: VectorAnimation; + clusterParam?: ClusterParam; } export interface VectorAnimation { diff --git a/packages/geo/src/lib/layer/shared/layers/vector-layer.ts b/packages/geo/src/lib/layer/shared/layers/vector-layer.ts index dbeecf2cb1..597c69aac7 100644 --- a/packages/geo/src/lib/layer/shared/layers/vector-layer.ts +++ b/packages/geo/src/lib/layer/shared/layers/vector-layer.ts @@ -8,16 +8,13 @@ import { FeatureDataSource } from '../../../datasource/shared/datasources/featur import { WFSDataSource } from '../../../datasource/shared/datasources/wfs-datasource'; import { ArcGISRestDataSource } from '../../../datasource/shared/datasources/arcgisrest-datasource'; import { WebSocketDataSource } from '../../../datasource/shared/datasources/websocket-datasource'; +import { ClusterDataSource } from '../../../datasource/shared/datasources/cluster-datasource'; import { Layer } from './layer'; import { VectorLayerOptions } from './vector-layer.interface'; export class VectorLayer extends Layer { - public dataSource: - | FeatureDataSource - | WFSDataSource - | ArcGISRestDataSource - | WebSocketDataSource; + public dataSource: FeatureDataSource | WFSDataSource | ArcGISRestDataSource | WebSocketDataSource | ClusterDataSource; public options: VectorLayerOptions; public ol: olLayerVector; diff --git a/packages/geo/src/lib/layer/shared/style.service.ts b/packages/geo/src/lib/layer/shared/style.service.ts index 56c7c4a307..52dce1d71e 100644 --- a/packages/geo/src/lib/layer/shared/style.service.ts +++ b/packages/geo/src/lib/layer/shared/style.service.ts @@ -2,6 +2,8 @@ import { Injectable } from '@angular/core'; import * as olstyle from 'ol/style'; +import { ClusterParam } from './clusterParam'; + @Injectable({ providedIn: 'root' }) @@ -50,4 +52,63 @@ export class StyleService { return olCls; } + + createClusterStyle(feature, clusterParam: ClusterParam) { + let style; + const range = clusterParam.clusterRange; + const icon = clusterParam.clusterIcon; + const scale = clusterParam.clusterScale; + const size = feature.get('features').length; + let color; + if (size !== 1) { + if (range) { + if (size >= range[1]) { + color = 'red'; + } else if (size < range[1] && size >= range[0]) { + color = 'orange'; + } else if (size < range[0]) { + color = 'green'; + } + } + style = [new olstyle.Style({ + image: new olstyle.Circle({ + radius: 2 * size + 3.4, + stroke: new olstyle.Stroke({ + color: 'black' + }), + fill: new olstyle.Fill({ + color: range ? color : 'blue' + }) + }), + text: new olstyle.Text({ + text: size.toString(), + fill: new olstyle.Fill({ + color: '#fff' + }) + }) + })]; + } else { + if (icon) { + style = [new olstyle.Style({ + image: new olstyle.Icon({ + src: icon, + scale: scale + }) + })]; + } else { + style = [new olstyle.Style({ + image: new olstyle.Circle({ + radius: 2 * size + 3.4, + stroke: new olstyle.Stroke({ + color: 'black' + }), + fill: new olstyle.Fill({ + color: 'blue' + }) + }) + })]; + } + } + return style; + } } From 8c123e981b9993867c8a2bc2bfcb7c05bc18cee3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Barbeau?= Date: Wed, 24 Jul 2019 12:29:07 -0400 Subject: [PATCH 2/2] Delete context3.json --- demo/src/contexts/context3.json | 64 --------------------------------- 1 file changed, 64 deletions(-) delete mode 100644 demo/src/contexts/context3.json diff --git a/demo/src/contexts/context3.json b/demo/src/contexts/context3.json deleted file mode 100644 index c34c38a5fc..0000000000 --- a/demo/src/contexts/context3.json +++ /dev/null @@ -1,64 +0,0 @@ -{ - "uri": "context3", - "title": "CARTO examples", - "map": { - "view": { - "projection": "EPSG:3857", - "center": [-73, 48], - "zoom": 5, - "geolocate": true - } - }, - "layers": [ - { - "title": "OSM", - "sourceOptions": { - "type": "osm" - } - }, - { - "title": "California Protected Areas", - "sourceOptions": { - "type": "carto", - "account": "common-data", - "mapId": "dbd9d89a-bf8a-11e5-b333-0e98b61680bf", - "queryFormat": "geojson" - } - }, - { - "title": "Tornado", - "sourceOptions": { - "type": "carto", - "account": "common-data", - "queryFormat": "geojson", - "queryPrecision": "5000", - "crossOrigin": "Anonymous", - "config": { - "version": "1.3.0", - "layers": [ - { - "type": "cartodb", - "options": { - "cartocss_version": "2.3.0", - "cartocss": - "#layer { line-width: 3; line-color: ramp([yr], (#5F4690, #1D6996, #38A6A5, #0F8554, #73AF48, #EDAD08, #E17C05, #CC503E, #94346E, #6F4070, #666666), (\"2004\", \"2008\", \"2011\", \"1998\", \"2003\", \"1999\", \"1992\", \"2010\", \"2005\", \"1995\"), \"=\"); }", - "sql": "select * from tornado" - } - } - ] - } - } - }, - { - "title": "cluster", - "clusterParam": { - "clusterRange": [8, 16] - }, - "sourceOptions": { - "type": "cluster", - "url": "http://10.202.76.35/fichier/bureaux_locaux3857.geojson", - "distance": 70 - } - } - ] -}