Mercurial > gemma
view client/src/components/map/layers.js @ 3353:b01bf2399c20
client: available fairway depth vs lnwl: fetching data for diagrams on map
Data gets stored in the client for 15 mins. Diagrams are still drawn with static data for demo purpose.
author | Markus Kottlaender <markus@intevation.de> |
---|---|
date | Tue, 21 May 2019 14:42:08 +0200 |
parents | 59db0b5921c5 |
children | e56b280582ae |
line wrap: on
line source
import TileWMS from "ol/source/TileWMS"; import { Tile as TileLayer, Vector as VectorLayer, Image as ImageLayer } from "ol/layer"; import { Icon, Stroke, Style } from "ol/style"; import VectorSource from "ol/source/Vector"; import { ImageWMS as ImageSource } from "ol/source"; import Point from "ol/geom/Point"; import { bbox as bboxStrategy } from "ol/loadingstrategy"; import { WFS, GeoJSON } from "ol/format"; import OSM from "ol/source/OSM"; import { equalTo } from "ol/format/filter"; import { HTTP } from "@/lib/http"; import styles from "./styles"; import store from "@/store/index"; const buildVectorLoader = ( featureRequestOptions, vectorSource, bboxStrategyDisabled, featurePostProcessor ) => { // build a function to be used for VectorSource.setLoader() // make use of WFS().writeGetFeature to build the request // and use our HTTP library to actually do it // NOTE: the geometryName has to be given in featureRequestOptions if // bboxStrategy (default) is used featureRequestOptions.featureNS = "gemma"; featureRequestOptions.featurePrefix = "gemma"; featureRequestOptions.outputFormat = "application/json"; return (extent, resolution, projection) => { if (!bboxStrategyDisabled) { featureRequestOptions.bbox = extent; } featureRequestOptions.srsName = projection.getCode(); HTTP.post( "/internal/wfs", new XMLSerializer().serializeToString( new WFS().writeGetFeature(featureRequestOptions) ), { headers: { "X-Gemma-Auth": localStorage.getItem("token"), "Content-type": "text/xml; charset=UTF-8" } } ) .then(response => { const features = new GeoJSON().readFeatures( JSON.stringify(response.data) ); if (featurePostProcessor) { features.map(f => featurePostProcessor(f, store)); } vectorSource.addFeatures(features); }) .catch(() => { vectorSource.removeLoadedExtent(extent); }); }; }; // SHARED LAYERS: // DRAW- and CUTLAYER are shared across maps. E.g. you want to see the cross cut // arrow on both maps when comparing surveys. So we don't need to initialize a // new VectorLayer object for each map. Instead we use these two constants so // that all maps use the same object. const DRAWLAYER = new VectorLayer({ id: "DRAWTOOL", label: "Draw Tool", visible: true, source: new VectorSource({ wrapX: false }), style: function(feature) { // adapted from OpenLayer's LineString Arrow Example var geometry = feature.getGeometry(); var styles = [ // linestring new Style({ stroke: new Stroke({ color: "#369aca", width: 2 }) }) ]; if (geometry.getType() === "LineString") { geometry.forEachSegment(function(start, end) { var dx = end[0] - start[0]; var dy = end[1] - start[1]; var rotation = Math.atan2(dy, dx); // arrows styles.push( new Style({ geometry: new Point(end), image: new Icon({ // we need to make sure the image is loaded by Vue Loader src: require("@/assets/linestring_arrow.png"), // fiddling with the anchor's y value does not help to // position the image more centered on the line ending, as the // default line style seems to be slightly uncentered in the // anti-aliasing, but the image is not placed with subpixel // precision anchor: [0.75, 0.5], rotateWithView: true, rotation: -rotation }) }) ); }); } return styles; } }); const CUTLAYER = new VectorLayer({ id: "CUTTOOL", label: "Cut Tool", visible: true, source: new VectorSource({ wrapX: false }), style: function(feature) { // adapted from OpenLayer's LineString Arrow Example var geometry = feature.getGeometry(); var styles = [ // linestring new Style({ stroke: new Stroke({ color: "#333333", width: 2, lineDash: [7, 7] }) }) ]; if (geometry.getType() === "LineString") { geometry.forEachSegment(function(start, end) { var dx = end[0] - start[0]; var dy = end[1] - start[1]; var rotation = Math.atan2(dy, dx); // arrows styles.push( new Style({ geometry: new Point(end), image: new Icon({ // we need to make sure the image is loaded by Vue Loader src: require("@/assets/linestring_arrow_grey.png"), // fiddling with the anchor's y value does not help to // position the image more centered on the line ending, as the // default line style seems to be slightly uncentered in the // anti-aliasing, but the image is not placed with subpixel // precision anchor: [0.75, 0.5], rotateWithView: true, rotation: -rotation }) }) ); }); } return styles; } }); export default function() { return { get(id) { return this.config.find(l => l.get("id") === id); }, config: [ new TileLayer({ id: "OPENSTREETMAP", label: "Open Streetmap", visible: true, source: new OSM() }), new ImageLayer({ id: "INLANDECDIS", label: "Inland ECDIS chart Danube", visible: true, source: new ImageSource({ preload: 1, url: "https://service.d4d-portal.info/wms/", crossOrigin: "anonymous", params: { LAYERS: "d4d", VERSION: "1.1.1", TILED: true } }) }), new ImageLayer({ id: "WATERWAYAREA", label: "Waterway Area", maxResolution: 100, minResolution: 0, source: new ImageSource({ url: window.location.origin + "/api/internal/wms", params: { LAYERS: "waterway_area", VERSION: "1.1.1", TILED: true }, imageLoadFunction: function(tile, src) { HTTP.get(src, { headers: { "X-Gemma-Auth": localStorage.getItem("token") }, responseType: "blob" }).then(response => { tile.getImage().src = URL.createObjectURL(response.data); }); } // TODO tile.setState(TileState.ERROR); }) }), (function() { const source = new VectorSource({ strategy: bboxStrategy }); source.setLoader( buildVectorLoader( { featureTypes: ["stretches_geoserver"], geometryName: "area" }, source, true, (f, store) => { if (f.getId() === store.state.imports.selectedStretchId) { f.set("highlighted", true); } return f; } ) ); return new VectorLayer({ id: "STRETCHES", label: "Stretches", visible: false, style: styles.stretches, source }); })(), (function() { const source = new VectorSource({ strategy: bboxStrategy }); source.setLoader( buildVectorLoader( { featureTypes: ["sections_geoserver"], geometryName: "area" }, source, true, (f, store) => { if (f.getId() === store.state.imports.selectedSectionId) { f.set("highlighted", true); } return f; } ) ); return new VectorLayer({ id: "SECTIONS", label: "Sections", visible: false, style: styles.sections, source }); })(), (function() { const source = new VectorSource(); source.setLoader( buildVectorLoader( { featureTypes: ["fairway_dimensions"], filter: equalTo("level_of_service", 1) }, source, true ) ); return new VectorLayer({ id: "FAIRWAYDIMENSIONSLOS1", label: "LOS 1 Fairway Dimensions", visible: false, style: styles.fwd1, maxResolution: 80, minResolution: 0, source }); })(), (function() { const source = new VectorSource(); source.setLoader( buildVectorLoader( { featureTypes: ["fairway_dimensions"], filter: equalTo("level_of_service", 2) }, source, true ) ); return new VectorLayer({ id: "FAIRWAYDIMENSIONSLOS2", label: "LOS 2 Fairway Dimensions", visible: false, style: styles.fwd2, maxResolution: 80, minResolution: 0, source }); })(), (function() { const source = new VectorSource(); source.setLoader( buildVectorLoader( { featureTypes: ["fairway_dimensions"], filter: equalTo("level_of_service", 3) }, source, true ) ); return new VectorLayer({ id: "FAIRWAYDIMENSIONSLOS3", label: "LOS 3 Fairway Dimensions", visible: true, style: styles.fwd3, maxResolution: 80, minResolution: 0, source }); })(), new ImageLayer({ id: "WATERWAYAXIS", label: "Waterway Axis", source: new ImageSource({ url: window.location.origin + "/api/internal/wms", params: { LAYERS: "waterway_axis", VERSION: "1.1.1", TILED: true }, imageLoadFunction: function(tile, src) { HTTP.get(src, { headers: { "X-Gemma-Auth": localStorage.getItem("token") }, responseType: "blob" }).then(response => { tile.getImage().src = URL.createObjectURL(response.data); }); } // TODO tile.setState(TileState.ERROR); }) }), (function() { const source = new VectorSource({ strategy: bboxStrategy }); source.setLoader( buildVectorLoader( { featureTypes: ["waterway_profiles"], geometryName: "geom" }, source ) ); return new VectorLayer({ id: "WATERWAYPROFILES", label: "Waterway Profiles", visible: true, style: new Style({ stroke: new Stroke({ color: "rgba(0, 0, 255, .5)", lineDash: [5, 5], width: 2 }) }), maxResolution: 2.5, minResolution: 0, source }); })(), (function() { const source = new VectorSource({ strategy: bboxStrategy }); source.setLoader( buildVectorLoader( { featureTypes: ["bottlenecks_geoserver"], geometryName: "area" }, source ) ); return new VectorLayer({ id: "BOTTLENECKS", label: "Bottlenecks", visible: true, style: styles.bottleneck, source }); })(), new TileLayer({ id: "BOTTLENECKISOLINE", label: "Bottleneck isolines", visible: false, source: new TileWMS({ preload: 0, projection: "EPSG:3857", url: window.location.origin + "/api/internal/wms", params: { LAYERS: "sounding_results_contour_lines_geoserver", VERSION: "1.1.1", TILED: true }, tileLoadFunction: function(tile, src) { // console.log("calling for", tile, src); HTTP.get(src, { headers: { "X-Gemma-Auth": localStorage.getItem("token") }, responseType: "blob" }).then(response => { tile.getImage().src = URL.createObjectURL(response.data); }); } // TODO tile.setState(TileState.ERROR); }) }), new TileLayer({ id: "DIFFERENCES", label: "Bottleneck Differences", visible: false, source: new TileWMS({ preload: 0, projection: "EPSG:3857", url: window.location.origin + "/api/internal/wms", params: { LAYERS: "sounding_differences", VERSION: "1.1.1", TILED: true }, tileLoadFunction: function(tile, src) { // console.log("calling for", tile, src); HTTP.get(src, { headers: { "X-Gemma-Auth": localStorage.getItem("token") }, responseType: "blob" }).then(response => { tile.getImage().src = URL.createObjectURL(response.data); }); } // TODO tile.setState(TileState.ERROR); }) }), (function() { const source = new VectorSource({ strategy: bboxStrategy }); source.setLoader( buildVectorLoader( { featureTypes: ["bottlenecks_geoserver"], geometryName: "area" }, source ) ); return new VectorLayer({ id: "BOTTLENECKSTATUS", label: "Critical Bottlenecks", forLegendStyle: { point: true, resolution: 16 }, visible: true, zIndex: 1, style: styles.bottleneckStatus, source }); })(), (function() { const source = new VectorSource({ strategy: bboxStrategy }); source.setLoader( buildVectorLoader( { featureTypes: ["bottlenecks_geoserver"], geometryName: "area" }, source, false, async (f, store) => { if (f.get("fa_critical")) { // look for fairway availability data in store. If present and // not older than 15 min use it or fetch new data and store it. let data = store.getters[ "fairwayavailability/fwLNWLOverviewData" ](f); if ( data && new Date().getTime() - data.createdAt.getTime() < 900000 ) { f.set("fa_data", data.data); } else { let from = new Date(); from.setDate(from.getDate() - 30); let to = new Date(); data = await store.dispatch( "fairwayavailability/loadAvailableFairwayDepthLNWL", { feature: f, from: from.toISOString().split("T")[0], to: to.toISOString().split("T")[0], frequency: "monthly", LOS: 3 } ); if (data) { store.commit("fairwayavailability/addFwLNWLOverviewData", { feature: f, data, createdAt: new Date() }); f.set("fa_data", data); } } } return f; } ) ); return new VectorLayer({ id: "BOTTLENECKFAIRWAYAVAILABILITY", label: "Bottlenecks Fairway Availability", forLegendStyle: { point: true, resolution: 16 }, visible: false, zIndex: 1, style: styles.bottleneckFairwayAvailability, source }); })(), new ImageLayer({ id: "DISTANCEMARKS", label: "Distance Marks", maxResolution: 10, minResolution: 0, source: new ImageSource({ url: window.location.origin + "/api/internal/wms", params: { LAYERS: "distance_marks_ashore_geoserver", VERSION: "1.1.1", TILED: true }, imageLoadFunction: function(tile, src) { HTTP.get(src, { headers: { "X-Gemma-Auth": localStorage.getItem("token") }, responseType: "blob" }).then(response => { tile.getImage().src = URL.createObjectURL(response.data); }); } // TODO tile.setState(TileState.ERROR); }) }), new ImageLayer({ id: "DISTANCEMARKSAXIS", label: "Distance Marks, Axis", source: new ImageSource({ url: window.location.origin + "/api/internal/wms", params: { LAYERS: "distance_marks_geoserver", VERSION: "1.1.1", TILED: true }, imageLoadFunction: function(tile, src) { HTTP.get(src, { headers: { "X-Gemma-Auth": localStorage.getItem("token") }, responseType: "blob" }).then(response => { tile.getImage().src = URL.createObjectURL(response.data); }); } // TODO tile.setState(TileState.ERROR); }) }), (function() { const source = new VectorSource({ strategy: bboxStrategy }); source.setLoader( buildVectorLoader( { featureTypes: ["gauges_geoserver"], geometryName: "geom" }, source ) ); return new VectorLayer({ id: "GAUGES", label: "Gauges", forLegendStyle: { point: true, resolution: 8 }, visible: true, style: styles.gauge, maxResolution: 100, minResolution: 0, source }); })(), DRAWLAYER, CUTLAYER ] }; }