Commit c798f80e authored by ncastejon's avatar ncastejon
Browse files

WIP big datasets

parent 28ccf9a3
......@@ -15177,7 +15177,6 @@
"version": "0.4.19",
"resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.19.tgz",
"integrity": "sha512-esZnJZJOiJR9wWKMyuvSE1y6Dq5LCuJanqhxslH2bxM6duahNZ+HMpCLhBQGZkbX6xRf8x1Y2eJlgt2q3qo49Q==",
"dev": true,
"requires": {
"sax": ">=0.6.0",
"xmlbuilder": "~9.0.1"
......@@ -15186,16 +15185,14 @@
"sax": {
"version": "1.2.4",
"resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz",
"integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==",
"dev": true
"integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw=="
}
}
},
"xmlbuilder": {
"version": "9.0.7",
"resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-9.0.7.tgz",
"integrity": "sha1-Ey7mPS7FVlxVfiD0wi35rKaGsQ0=",
"dev": true
"integrity": "sha1-Ey7mPS7FVlxVfiD0wi35rKaGsQ0="
},
"xmlhttprequest-ssl": {
"version": "1.5.5",
......
......@@ -41,7 +41,8 @@
"mapbox-gl": "^0.45.0",
"ng-inline-svg": "^8.0.1",
"ngx-infinite-scroll": "^6.0.1",
"rxjs": "^6.2.2",
"rxjs": "^6.2.0",
"xml2js": "^0.4.19",
"zone.js": "^0.8.26"
},
"devDependencies": {
......
......@@ -4,6 +4,7 @@ import { ErrorHandler, Injectable } from '@angular/core';
export class ErrorsHandler implements ErrorHandler {
handleError(error: Error) {
console.log(error);
return;
}
......
......@@ -18,6 +18,7 @@ export class HttpErrorResponseInterceptor implements HttpInterceptor {
}
},
(err) => {
console.log(err);
if (err instanceof HttpErrorResponse) {
switch (err.status) {
case 401:
......
......@@ -11,6 +11,7 @@ export class ErrorService {
) { }
handleError(err, opt): Error | HttpErrorResponse {
console.log(err);
let error = err;
if ((err instanceof HttpErrorResponse)) {
switch (err.status) {
......
......@@ -49,6 +49,7 @@ export class DatasetDetailComponent implements OnInit {
this.metadata = this._datasetDetailService.datasetMetadata;
},
(err) => {
console.log(err);
this._notificationService.notify(new Notification({
message: err.message,
type: 'error',
......
import { Component, OnInit, OnDestroy } from '@angular/core';
import * as mapboxgl from 'mapbox-gl';
import { Metadata, IMetadataLink } from '../../../models';
import { DatasetDetailService } from '../../../services';
import { DatasetDetailService, MapService } from '../../../services';
import { Subscription } from 'rxjs';
import { environment } from './../../../../../environments/environment';
import { Minimap } from './minimap-control';
import { NotificationService } from '../../../../core/services';
import { Notification } from '../../../../core/models';
import { errors } from '../../../../../i18n/error-messages/error-messages.fr';
import { HttpEvent, HttpEventType } from '@angular/common/http';
@Component({
selector: 'app-dataset-map',
......@@ -36,6 +37,9 @@ export class DatasetMapComponent implements OnInit, OnDestroy {
displayControls = false;
mapIsConstructed = false;
geojson: GeoJSON.FeatureCollection;
percentageLoading = 0;
// When the styles are changed, we don't want add new events each time
eventPopupAdded = false;
......@@ -44,6 +48,7 @@ export class DatasetMapComponent implements OnInit, OnDestroy {
constructor(
private _datasetDetailService: DatasetDetailService,
private _notificationService: NotificationService,
private _mapService: MapService,
) { }
ngOnInit() {
......@@ -102,6 +107,7 @@ export class DatasetMapComponent implements OnInit, OnDestroy {
// Create the map with the associated style Mapbox file
this.map = new mapboxgl.Map(options).on('error', (error) => {
console.log(error);
this._notificationService.notify(new Notification({
message: errors.geosource.mapError,
type: 'error',
......@@ -125,8 +131,13 @@ export class DatasetMapComponent implements OnInit, OnDestroy {
{
style: `assets/mapbox-gl-styles/${this.selectedBaseLayer.fileName}`,
classes: 'is-hidden-mobile',
<<<<<<< HEAD
}),
);
=======
}));
>>>>>>> WIP big datasets
}
});
......@@ -135,12 +146,79 @@ export class DatasetMapComponent implements OnInit, OnDestroy {
this.map.on('style.load', () => {
// Check if the metadata has WFS (vector) data format. If not we use WMS format
const uriWFS = this.metadata.link.find((e) => { return e.protocol === 'OGC:WFS'; });
if (uriWFS) {
this.addWFSLayer(uriWFS);
if (uriWFS && this._datasetDetailService.datasetDataNumber < 100000) {
// let loaded = 1;
// let size = 0;
const loadParts = Math.floor(this._datasetDetailService.datasetDataNumber / 5000);
const bounds = this.map.getBounds();
const bbox = '' + bounds.getSouthWest().lat + ',' + bounds.getSouthWest().lng
+ ',' + bounds.getNorthEast().lat + ',' + bounds.getNorthEast().lng;
this._mapService.getWFSFeatures(
uriWFS,
0,
1000, bbox).subscribe((geojson) => {
// switch (event.type) {
// case HttpEventType.Sent:
// console.log('Request sent!');
// break;
// case HttpEventType.ResponseHeader:
// console.log('Response header received!');
// break;
// case HttpEventType.DownloadProgress:
// const kbLoaded = Math.round(event.loaded / 1024);
// this.percentageLoading = Math.round(100 * event.loaded / event.total);
// console.log(`Download in progress! ${kbLoaded}Kb loaded`);
// break;
// case HttpEventType.Response:
// console.log(event);
// this.geojson = event.body;
// this.addWFSLayer(event.body);
// console.log('😺 Done!', event.body);
// }
this.addWFSLayer(geojson);
});
// for (let i = 1; i <= loadParts; i += 1) {
// this._mapService.getWFSFeatures(uriWFS, size, 5000).subscribe((geojson) => {
// this.geojson.features = this.geojson.features.concat(geojson.features);
// const source = this.map.getSource('wfs-clustered-points') as mapboxgl.GeoJSONSource;
// source.setData(this.geojson);
// loaded += 1;
// console.log(i);
// console.log(loadParts);
// this.percentageLoading = Math.floor(loaded * 5000 / this._datasetDetailService.datasetDataNumber * 100);
// if (i === loadParts) {
// this.percentageLoading = 100;
// }
// });
// size = size + 5000;
// }
} else {
const uriWMS = this.metadata.link.find((e) => { return e.protocol === 'OGC:WMS'; });
this.addWMSLayer(uriWMS);
}
this.map.on('zoomend', () => {
const bounds = this.map.getBounds();
const bbox = '' + bounds.getSouthWest().lat + ',' + bounds.getSouthWest().lng
+ ',' + bounds.getNorthEast().lat + ',' + bounds.getNorthEast().lng;
this._mapService.getWFSFeatures(uriWFS, 0, 1000, bbox).subscribe((geojson) => {
const source = this.map.getSource('wfs-clustered-points') as mapboxgl.GeoJSONSource;
source.setData(geojson);
});
});
this.map.on('move', () => {
const bounds = this.map.getBounds();
const bbox = '' + bounds.getSouthWest().lat + ',' + bounds.getSouthWest().lng
+ ',' + bounds.getNorthEast().lat + ',' + bounds.getNorthEast().lng;
this._mapService.getWFSFeatures(uriWFS, 0, 1000, bbox).subscribe((geojson) => {
const source = this.map.getSource('wfs-clustered-points') as mapboxgl.GeoJSONSource;
source.setData(geojson);
});
});
});
}
}
......@@ -173,12 +251,10 @@ export class DatasetMapComponent implements OnInit, OnDestroy {
// - add the source (url where to fetch the data)
// - create layers from the source
// - if the features are 'Point', create clustering layers
addWFSLayer(uriWFS: IMetadataLink) {
addWFSLayer(geojson: GeoJSON.FeatureCollection) {
this.map.addSource('wfs-clustered-points', {
type: 'geojson',
data: uriWFS.url + '?SERVICE=WFS&VERSION=2.0.0' +
'&outputformat=GEOJSON&maxfeatures=1000&request=GetFeature&typename=' +
uriWFS.name + '&srsname=EPSG:4326&' + ',EPSG:4326',
data: geojson,
cluster: true,
clusterMaxZoom: 13, // Max zoom to cluster points on
clusterRadius: 45, // Radius of each cluster when clustering points (defaults to 50)
......@@ -186,9 +262,7 @@ export class DatasetMapComponent implements OnInit, OnDestroy {
this.map.addSource('wfs-polygon', {
type: 'geojson',
data: uriWFS.url + '?SERVICE=WFS&VERSION=2.0.0' +
'&outputformat=GEOJSON&maxfeatures=1000&request=GetFeature&typename=' +
uriWFS.name + '&srsname=EPSG:4326&' + ',EPSG:4326',
data: geojson,
});
// Add the layers for 'Point' features (clustered and unclustered layers)
......@@ -259,6 +333,7 @@ export class DatasetMapComponent implements OnInit, OnDestroy {
'text-halo-width': 2,
},
});
});
// For 'Polygon' feature, one layer is enough (no cluster)
......@@ -347,6 +422,18 @@ export class DatasetMapComponent implements OnInit, OnDestroy {
source: 'WMS',
paint: {},
});
this.map.on('click', (e) => {
console.log(e);
const features = this.map.queryRenderedFeatures(e.point);
console.log(features);
const bounds = this.map.getBounds();
const bbox = '' + bounds.getSouthWest().lat + ',' + bounds.getSouthWest().lng
+ ',' + bounds.getNorthEast().lat + ',' + bounds.getNorthEast().lng;
const result = this._mapService.getFeatureInfo(uriWMS.name, bbox, e.point.x, e.point.y).subscribe((result) => {
console.log(result);
});
});
}
switch3DLayer() {
......@@ -394,8 +481,6 @@ export class DatasetMapComponent implements OnInit, OnDestroy {
// Display inside the popup the key-value properties of the feature
createPopupContent(e: any) {
const features = this.map.queryRenderedFeatures(e.point);
const coordinates = e.features[0].geometry.coordinates.slice();
let content = '<h4>Informations</h4>';
for (const property in e.features[0].properties) {
......
import { DatasetResearchService } from './dataset-research.service';
import { DatasetDetailService } from './dataset-detail.service';
import { ElasticsearchService } from './elasticsearch.service';
import { MapService } from './map.service';
export { DatasetResearchService, DatasetDetailService, ElasticsearchService };
export { DatasetResearchService, DatasetDetailService, ElasticsearchService, MapService };
// tslint:disable-next-line:variable-name
export const GeosourceServices = [
DatasetResearchService,
DatasetDetailService,
ElasticsearchService,
MapService,
];
import { Injectable } from '@angular/core';
import { Observable } from 'rxjs';
import { HttpClient, HttpRequest } from '@angular/common/http';
import { IMetadataLink } from '../models';
import { LngLatBounds } from 'mapbox-gl';
import { map } from 'rxjs/operators';
@Injectable()
export class MapService {
constructor(
private _http: HttpClient,
) { }
getWFSFeatures(uriWFS: IMetadataLink, startindex: number, count: number, bbox: string) {
let url = uriWFS.url + '?SERVICE=WFS&VERSION=2.0.0' +
'&outputformat=GEOJSON&maxfeatures=100000&request=GetFeature&typename=' +
uriWFS.name + '&srsname=EPSG:4326&' + ',EPSG:4326&startindex=' + startindex + '&count=' + count;
if (bbox) {
url = url + '&bbox=' + bbox;
}
return this._http.get<GeoJSON.FeatureCollection>(url);
}
getFeatureInfo(layer, bbox, x, y) {
const url = 'https://download.data.grandlyon.com/wms/grandlyon?request=GetFeatureInfo' +
'&service=WMS' +
'&version=1.1.1' +
'&layers=' + layer +
'&srs=EPSG:3857' +
'&width=780' +
'&height=330' +
'&bbox=' + bbox +
'&query_layers=' + layer +
'&info_format=text/plain' +
'&feature_count=1' +
'&x=' + x +
'&y=' + y;
return this._http.get(url).pipe(
map((xml) => {
// const parseString = require('xml2js').parseString;
// return parseString(xml, (err, result) => {
// return result;
// });
}));
}
}
......@@ -17,18 +17,10 @@ body {
line-height: 1.375rem;
}
.site{
.site {
height: 100%;
display: flex;
flex-direction: column;
}
.site-content {
flex: 1 0 auto;
}
.site-header, .site-footer {
flex-shrink: 0;
display: grid;
grid-template-rows: auto 1fr auto
}
h1, h2, h3, h4, h5, h6, .h1, .h2, .h3, .h4, .h5, .h6 .card-header-title, .navbar {
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment