Mercurial > gemma
view client/src/components/map/layers.js @ 4336:45307cf4931a
Review of fairway dimensions
In order to review fairway dimensions, the ids from the summary are used to retrieve
the according features from the geoserver. Then instances of the type Feature are
generated with the information given from the geoserver. These are then added
to the VectorSource layer and should be displayed.
Currently the display doesn't work.
author | Thomas Junk <thomas.junk@intevation.de> |
---|---|
date | Thu, 05 Sep 2019 15:52:43 +0200 |
parents | 18a34d9b289c |
children | e9d2573329da |
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 { styleFactory } 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, features)); } 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: "#FFFFFF", width: 5, lineDash: [7, 7] }) }), new Style({ stroke: new Stroke({ color: "#333333", width: 3, 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; } }); let layerConfigs = {}; export const unsetLayerConfigs = function() { layerConfigs = {}; }; export const layerFactory = function(mapId) { const styles = styleFactory(mapId); // Shared feature source for layers: // BOTTLENECKS, BOTTLENECKSTATUS and BOTTLENECKFAIRWAYAVAILABILITY // Reduces bottlenecks_geoserver requests and number of stored feature objects. const FDREVIEWLAYER = new VectorLayer({ id: "FDREVIEWLAYER", label: "Review", visible: true, source: new VectorSource(), style: styles.sections }); const bottlenecksSource = new VectorSource({ strategy: bboxStrategy }); bottlenecksSource.setLoader( buildVectorLoader( { featureTypes: ["bottlenecks_geoserver"], geometryName: "area" }, bottlenecksSource, 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 date = new Date(); data = await store.dispatch( "fairwayavailability/loadAvailableFairwayDepthLNWLForMap", { feature: f, from: date.toISOString().split("T")[0], to: date.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; } ) ); // either use existing config or create new one // important is only each map has its individual layer config // but we don't want to create new layer objects each time a store value // that is used here changes. const config = layerConfigs.hasOwnProperty(mapId) ? layerConfigs[mapId] : [ new TileLayer({ id: "OPENSTREETMAP", label: "Open Streetmap", visible: true, source: new OSM() }), new ImageLayer({ id: "INLANDECDIS", label: "Inland ECDIS chart Danube", visible: true, source: null }), 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({ strategy: bboxStrategy }); source.setLoader( buildVectorLoader( { geometryName: "area", featureTypes: ["fairway_dimensions"], filter: equalTo("level_of_service", 1) }, source, false ) ); 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({ strategy: bboxStrategy }); source.setLoader( buildVectorLoader( { geometryName: "area", featureTypes: ["fairway_dimensions"], filter: equalTo("level_of_service", 2) }, source, false ) ); 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({ strategy: bboxStrategy }); source.setLoader( buildVectorLoader( { geometryName: "area", featureTypes: ["fairway_dimensions"], filter: equalTo("level_of_service", 3) }, source, false ) ); 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() { return new VectorLayer({ id: "BOTTLENECKS", label: "Bottlenecks", visible: true, style: styles.bottleneck, source: bottlenecksSource }); })(), 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() { return new VectorLayer({ id: "BOTTLENECKSTATUS", label: "Critical Bottlenecks", forLegendStyle: { point: true, resolution: 16 }, visible: true, zIndex: 1, style: styles.bottleneckStatus, source: bottlenecksSource }); })(), (function() { return new VectorLayer({ id: "BOTTLENECKFAIRWAYAVAILABILITY", label: "Bottleneck Fairway Availability", forLegendStyle: { point: true, resolution: 16 }, visible: false, zIndex: 1, style: styles.bottleneckFairwayAvailability, source: bottlenecksSource }); })(), (function() { const source = new VectorSource({ strategy: bboxStrategy }); source.setLoader( buildVectorLoader( { featureTypes: [ "bottlenecks_geoserver", "gauges_geoserver", "stretches_geoserver", "sections_geoserver" ] }, source, true, // since we don't use bbox strategy, features will contain all features and we can use it // to find reference gauges for bottlenecks, yeah! async (f, store, features) => { // attach reference gauge to bottleneck if (f.getId().indexOf("bottlenecks") > -1) { f.set( "gauge_obj", features.find(feat => { return ( feat.getId().indexOf("gauges") > -1 && feat.get("objname") === f.get("gauge_objname") ); }) ); } // attach nsc data to gauge if (f.getId().indexOf("gauges") > -1) { store .dispatch( "gauges/getNashSutcliffeForISRS", f.get("isrs_code") ) .then(response => { f.set("nsc_data", response); }); } } ) ); return new VectorLayer({ id: "DATAAVAILABILITY", label: "Data Availability/Accuracy", forLegendStyle: { point: true, resolution: 16 }, visible: false, zIndex: 1, style: styles.dataAvailability, 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, FDREVIEWLAYER ]; layerConfigs[mapId] = config; return { get(id) { return config.find(l => l.get("id") === id); }, config }; };