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

feat(datasource): add layer source connection to CARTO and ArcGIS Rest services #174

Merged
merged 2 commits into from
Aug 21, 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
121 changes: 119 additions & 2 deletions projects/geo/src/lib/datasource/shared/capabilities.service.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,21 @@
import { Injectable } from '@angular/core';
import { HttpClient, HttpParams } from '@angular/common/http';
import { Observable } from 'rxjs';
import { Observable, forkJoin } from 'rxjs';
import { map } from 'rxjs/operators';

import { WMSCapabilities, WMTSCapabilities } from 'ol/format';
import olSourceWMTS from 'ol/source/WMTS';
import olAttribution from 'ol/control/Attribution';

import { ObjectUtils } from '@igo2/utils';
import { EsriStyleGenerator } from '../utils/esri-style-generator';

import { WMTSDataSourceOptions, WMSDataSourceOptions } from './datasources';
import {
WMTSDataSourceOptions,
WMSDataSourceOptions,
ArcGISRestDataSourceOptions,
TileArcGISRestDataSourceOptions
} from './datasources';

@Injectable({
providedIn: 'root'
Expand Down Expand Up @@ -50,6 +57,35 @@ export class CapabilitiesService {
return options;
}

getArcgisOptions(
baseOptions: ArcGISRestDataSourceOptions
): Observable<ArcGISRestDataSourceOptions> {
const baseUrl = baseOptions.url + '/' + baseOptions.layer + '?f=json';

return this.http
.get(baseUrl)
.pipe(
map((arcgisOptions: any) =>
this.parseArcgisOptions(baseOptions, arcgisOptions)
)
);
}

getTileArcgisOptions(
baseOptions: TileArcGISRestDataSourceOptions
): Observable<TileArcGISRestDataSourceOptions> {
const baseUrl = baseOptions.url + '/' + baseOptions.layer + '?f=json';
const legendUrl = baseOptions.url + '/legend?f=json';
const tileArcgisOptions = this.http.get(baseUrl);
const legendInfo = this.http.get(legendUrl);

return forkJoin([tileArcgisOptions, legendInfo]).pipe(
map((res: any) =>
this.parseTileArcgisOptions(baseOptions, res[0], res[1])
)
);
}

getCapabilities(
service: 'wms' | 'wmts',
baseUrl: string,
Expand Down Expand Up @@ -133,6 +169,87 @@ export class CapabilitiesService {
return Object.assign(options, baseOptions);
}

private parseArcgisOptions(
baseOptions: ArcGISRestDataSourceOptions,
arcgisOptions: any
): ArcGISRestDataSourceOptions {
const styleGenerator = new EsriStyleGenerator();
const units = arcgisOptions.units === 'esriMeters' ? 'm' : 'degrees';
const style = styleGenerator.generateStyle(arcgisOptions, units);
const attributions = new olAttribution({
html: arcgisOptions.copyrightText
});
let timeExtent, timeFilter;
if (arcgisOptions.timeInfo) {
const time = arcgisOptions.timeInfo.timeExtent;
timeExtent = time[0] + ',' + time[1];
const min = new Date();
min.setTime(time[0]);
const max = new Date();
max.setTime(time[1]);
timeFilter = {
min: min.toUTCString(),
max: max.toUTCString(),
range: true,
type: 'datetime',
style: 'calendar'
};
}
const params = Object.assign(
{},
{
style: style,
timeFilter: timeFilter,
timeExtent: timeExtent,
attributions: attributions
}
);
const options = ObjectUtils.removeUndefined({
params: params
});
return ObjectUtils.mergeDeep(options, baseOptions);
}

private parseTileArcgisOptions(
baseOptions: TileArcGISRestDataSourceOptions,
tileArcgisOptions: any,
legendInfo: any
): TileArcGISRestDataSourceOptions {
const attributions = new olAttribution({
html: tileArcgisOptions.copyrightText
});
let timeExtent, timeFilter;
if (tileArcgisOptions.timeInfo) {
const time = tileArcgisOptions.timeInfo.timeExtent;
timeExtent = time[0] + ',' + time[1];
const min = new Date();
min.setTime(time[0]);
const max = new Date();
max.setTime(time[1]);
timeFilter = {
min: min.toUTCString(),
max: max.toUTCString(),
range: true,
type: 'datetime',
style: 'calendar'
};
}
const params = Object.assign(
{},
{
layers: 'show:' + baseOptions.layer,
time: timeExtent
}
);
const options = ObjectUtils.removeUndefined({
params: params,
legendInfo: legendInfo,
timeFilter: timeFilter,
attributions: attributions
});
return ObjectUtils.mergeDeep(options, baseOptions);
}

private findDataSourceInCapabilities(layerArray, name): any {
if (Array.isArray(layerArray)) {
let layer;
Expand Down
53 changes: 53 additions & 0 deletions projects/geo/src/lib/datasource/shared/datasource.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,12 @@ import {
WMTSDataSourceOptions,
WMSDataSource,
WMSDataSourceOptions,
CartoDataSource,
CartoDataSourceOptions,
ArcGISRestDataSource,
ArcGISRestDataSourceOptions,
TileArcGISRestDataSource,
TileArcGISRestDataSourceOptions,
AnyDataSourceOptions
} from './datasources';

Expand Down Expand Up @@ -54,6 +60,21 @@ export class DataSourceService {
case 'xyz':
dataSource = this.createXYZDataSource(context as XYZDataSourceOptions);
break;
case 'carto':
dataSource = this.createCartoDataSource(
context as CartoDataSourceOptions
);
break;
case 'arcgisrest':
dataSource = this.createArcGISRestDataSource(
context as ArcGISRestDataSourceOptions
);
break;
case 'tilearcgisrest':
dataSource = this.createTileArcGISRestDataSource(
context as TileArcGISRestDataSourceOptions
);
break;
default:
break;
}
Expand Down Expand Up @@ -114,4 +135,36 @@ export class DataSourceService {
): Observable<XYZDataSource> {
return new Observable(d => d.next(new XYZDataSource(context)));
}

private createCartoDataSource(
context: CartoDataSourceOptions
): Observable<CartoDataSource> {
return new Observable(d => d.next(new CartoDataSource(context)));
}

private createArcGISRestDataSource(
context: ArcGISRestDataSourceOptions
): Observable<ArcGISRestDataSource> {
return this.capabilitiesService
.getArcgisOptions(context)
.pipe(
map(
(options: ArcGISRestDataSourceOptions) =>
new ArcGISRestDataSource(options)
)
);
}

private createTileArcGISRestDataSource(
context: TileArcGISRestDataSourceOptions
): Observable<TileArcGISRestDataSource> {
return this.capabilitiesService
.getTileArcgisOptions(context)
.pipe(
map(
(options: TileArcGISRestDataSourceOptions) =>
new TileArcGISRestDataSource(options)
)
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@ import { WMSDataSourceOptions } from './wms-datasource.interface';
import { WMTSDataSourceOptions } from './wmts-datasource.interface';
import { WFSDataSourceOptions } from './wfs-datasource.interface';
import { FeatureDataSourceOptions } from './feature-datasource.interface';
import { CartoDataSourceOptions } from './carto-datasource.interface';
import { ArcGISRestDataSourceOptions } from './arcgisrest-datasource.interface';
import { TileArcGISRestDataSourceOptions } from './tilearcgisrest-datasource.interface';

export type AnyDataSourceOptions =
| DataSourceOptions
Expand All @@ -13,4 +16,7 @@ export type AnyDataSourceOptions =
| WFSDataSourceOptions
| XYZDataSourceOptions
| WMTSDataSourceOptions
| WMSDataSourceOptions;
| WMSDataSourceOptions
| CartoDataSourceOptions
| ArcGISRestDataSourceOptions
| TileArcGISRestDataSourceOptions;
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@ import { WMSDataSource } from './wms-datasource';
import { WMTSDataSource } from './wmts-datasource';
import { WFSDataSource } from './wfs-datasource';
import { FeatureDataSource } from './feature-datasource';
import { CartoDataSource } from './carto-datasource';
import { ArcGISRestDataSource } from './arcgisrest-datasource';
import { TileArcGISRestDataSource } from './tilearcgisrest-datasource';

export type AnyDataSource =
| DataSource
Expand All @@ -13,4 +16,7 @@ export type AnyDataSource =
| WFSDataSource
| XYZDataSource
| WMTSDataSource
| WMSDataSource;
| WMSDataSource
| CartoDataSource
| ArcGISRestDataSource
| TileArcGISRestDataSource;
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import olAttribution from 'ol/control/Attribution';

import { DataSourceOptions } from './datasource.interface';
import { FeatureDataSourceOptions } from './feature-datasource.interface';

export interface ArcGISRestDataSourceOptions
extends DataSourceOptions,
FeatureDataSourceOptions {
// type?: 'arcgisrest';
layer: string;
params?: ArcGISRestDataSourceOptionsParams;
}

export interface ArcGISRestDataSourceOptionsParams {
legendInfo?: any;
style?: any;
timefilter?: any;
timeExtent?: string;
attributions?: olAttribution;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import olSourceVector from 'ol/source/Vector';
import olFormatEsriJSON from 'ol/format/EsriJSON';
import * as olloadingstrategy from 'ol/loadingstrategy';

import { uuid } from '@igo2/utils';

import { DataSource } from './datasource';
import { ArcGISRestDataSourceOptions } from './arcgisrest-datasource.interface';

export class ArcGISRestDataSource extends DataSource {
public ol: olSourceVector;
public options: ArcGISRestDataSourceOptions;

protected createOlSource(): olSourceVector {
const esrijsonFormat = new olFormatEsriJSON();
return new olSourceVector({
attributions: this.options.params.attributions,
overlaps: false,
format: esrijsonFormat,
url: function(extent, resolution, proj) {
const baseUrl = this.options.url + '/' + this.options.layer + '/query/';
const geometry = encodeURIComponent(
'{"xmin":' +
extent[0] +
',"ymin":' +
extent[1] +
',"xmax":' +
extent[2] +
',"ymax":' +
extent[3] +
',"spatialReference":{"wkid":102100}}'
);
const params = [
'f=json',
`geometry=${geometry}`,
'geometryType=esriGeometryEnvelope',
'inSR=102100',
'spatialRel=esriSpatialRelIntersects',
'outFields=*',
'returnGeometry=true',
'outSR=102100'
];
if (this.options.params.timeFilter) {
let time = `time=${this.options.params.timeExtent}`;
params.push(time);
}
return `${baseUrl}?${params.join('&')}`;
}.bind(this),
strategy: olloadingstrategy.bbox
});
}

protected generateId() {
return uuid();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import olSourceCarto from 'ol/source/CartoDB';

import { DataSourceOptions } from './datasource.interface';

export interface CartoDataSourceOptions extends DataSourceOptions {
// type?: 'carto';
params?: any;
queryPrecision?: string;

crossOrigin?: string;
projection?: string;
config?: any;
map?: string;
account?: string;

ol?: olSourceCarto;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import olSourceCarto from 'ol/source/CartoDB';

import { uuid } from '@igo2/utils';
import { DataSource } from './datasource';
import { DataSourceLegendOptions } from './datasource.interface';
import { CartoDataSourceOptions } from './carto-datasource.interface';

export class CartoDataSource extends DataSource {
public ol: olSourceCarto;
public options: CartoDataSourceOptions;

get params(): any {
return this.options.params as any;
}

get queryTitle(): string {
return (this.options as any).queryTitle
? (this.options as any).queryTitle
: 'title';
}

get queryHtmlTarget(): string {
return (this.options as any).queryHtmlTarget
? (this.options as any).queryHtmlTarget
: 'newtab';
}

protected createOlSource(): olSourceCarto {
return new olSourceCarto(this.options);
}

protected generateId() {
return uuid();
}
}
Loading