Mercurial > gemma
view client/src/map/Maplayer.vue @ 734:1581ba78a360
client: prepare for fairway intersection for profile
* Add calculation of features which intersect the extend of the profileLine
as preparation for the more expensive detailed intersect operation.
author | Bernhard Reiter <bernhard@intevation.de> |
---|---|
date | Mon, 24 Sep 2018 09:56:51 +0200 |
parents | e57955c1996f |
children | d7530644dde3 |
line wrap: on
line source
<template> <div id="map" :class="mapStyle"></div> </template> <style lang="scss"> .mapsplit { height: 50vh; } .mapfull { height: 100vh; } </style> <script> import { HTTP } from "../application/lib/http"; import { mapGetters } from "vuex"; import "ol/ol.css"; // openlayers imports, sorted by module name import { Map, View } from "ol"; import Feature from "ol/Feature"; // import { bbox as bboxFilter } from "ol/format/filter.js"; import { WFS, GeoJSON } from "ol/format.js"; import GeometryType from "ol/geom/GeometryType.js"; import LineString from "ol/geom/LineString.js"; import Draw from "ol/interaction/Draw.js"; import { Vector as VectorLayer } from "ol/layer.js"; import { Vector as VectorSource } from "ol/source.js"; export default { name: "maplayer", props: ["drawMode", "lat", "long", "zoom", "split"], data() { return { projection: "EPSG:3857", openLayersMap: null, interaction: null, vectorLayer: null, vectorSource: null }; }, computed: { ...mapGetters("mapstore", ["layers"]), mapStyle() { return { mapfull: !this.split, mapsplit: this.split }; }, layerData() { const l = this.layers.map(x => { return x.data; }); return [...l, this.vectorLayer]; } }, methods: { createVectorSource() { this.vectorSource = new VectorSource({ wrapX: false }); }, createVectorLayer() { this.vectorLayer = new VectorLayer({ source: this.vectorSource }); }, removeCurrentInteraction() { this.openLayersMap.removeInteraction(this.interaction); this.interaction = null; }, createInteraction() { var that = this; this.vectorSource.clear(); // start empty var draw = new Draw({ source: this.vectorSource, type: this.drawMode }); draw.on("drawstart", function(event) { console.log(event); that.vectorSource.clear(); // remove old features when draw starts }); draw.on("drawend", this.drawEnd); return draw; }, drawEnd(event) { console.log(event); var inputLineString = event.feature.getGeometry().clone(); if (inputLineString.getType() == GeometryType.LINE_STRING) { // prepare to send the first line seqment to the server as GeoJSON inputLineString.transform("EPSG:3857", "EPSG:4326"); var coords = inputLineString.getCoordinates(); if (coords.length >= 2) { var profileLine = new LineString([coords[0], coords[1]]); var feature = new Feature({ geometry: profileLine, // FIXME: hardcoded bottleneck and survey date bottleneck: "AT_Bottleneck_44", date: "2017-11-20" }); var gStr = new GeoJSON({ geometryName: "geometry" }).writeFeature( feature ); console.log("Ready to start profile view with: ", feature, gStr); // FIXME: assuming that we have the fairway dimensions loaded var vectorSource = this.getLayerByName( "Fairway Dimensions" ).data.getSource(); console.log(vectorSource); var diagStack = []; vectorSource.forEachFeatureIntersectingExtent( // need to use EPSG:3857 which is the proj of vectorSource profileLine .clone() .transform("EPSG:4326", "EPSG:3857") .getExtent(), feature => { // transform back to prepare for usage var g = feature .getGeometry() .clone() .transform("EPSG:3857", "EPSG:4326"); // console.log("intersecting:", g); this.addToFairwayRectangle(profileLine, g, diagStack); } ); } } }, addToFairwayRectangle(profileLine, fairwayGeometry, diagStack) { // both geometries have to be in EPSG:4326 console.log( "addToFairwayRectangle(", profileLine, fairwayGeometry, diagStack, ")" ); }, activateInteraction() { const interaction = this.createInteraction(this.drawMode); this.interaction = interaction; this.openLayersMap.addInteraction(interaction); }, buildVectorLoader(featureRequestOptions, endpoint, vectorSource) { // 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: a) the geometryName has to be given in featureRequestOptions, // because we want to load depending on the bbox // b) the VectorSource has to have the option strategy: bbox featureRequestOptions["outputFormat"] = "application/json"; var loader = function(extent, resolution, projection) { featureRequestOptions["bbox"] = extent; featureRequestOptions["srsName"] = projection.getCode(); var featureRequest = new WFS().writeGetFeature(featureRequestOptions); // DEBUG console.log(featureRequest); HTTP.post( endpoint, new XMLSerializer().serializeToString(featureRequest), { headers: { "X-Gemma-Auth": localStorage.getItem("token"), "Content-type": "text/xml; charset=UTF-8" } } ) .then(response => { var features = new GeoJSON().readFeatures( JSON.stringify(response.data) ); vectorSource.addFeatures(features); console.log( "loaded", features.length, featureRequestOptions.featureTypes, "features" ); // DEBUG console.log("loaded ", features, "for", vectorSource); // eslint-disable-next-line }) .catch(() => { vectorSource.removeLoadedExtent(extent); }); }; return loader; }, getLayerByName(name) { for (let layer of this.layers) { if (layer.name === name) { return layer; } } } }, watch: { drawMode() { if (this.interaction) { this.removeCurrentInteraction(); } else { this.activateInteraction(); } }, split() { const map = this.openLayersMap; this.$nextTick(() => { map.updateSize(); }); } }, mounted() { this.createVectorSource(); this.createVectorLayer(); this.openLayersMap = new Map({ layers: this.layerData, target: "map", controls: [], view: new View({ center: [this.long, this.lat], zoom: this.zoom, projection: this.projection }) }); // TODO make display of layers more dynamic, e.g. from a list // loading the full WFS layer, by not setting the loader function // and without bboxStrategy var featureRequest2 = new WFS().writeGetFeature({ srsName: "EPSG:3857", featureNS: "gemma", featurePrefix: "gemma", featureTypes: ["fairway_dimensions"], outputFormat: "application/json" }); // NOTE: loading the full fairway_dimensions makes sure // that all are available for the intersection with the profile HTTP.post( "/internal/wfs", new XMLSerializer().serializeToString(featureRequest2), { headers: { "X-Gemma-Auth": localStorage.getItem("token"), "Content-type": "text/xml; charset=UTF-8" } } ).then(response => { var features = new GeoJSON().readFeatures(JSON.stringify(response.data)); var vectorSrc = this.getLayerByName( "Fairway Dimensions" ).data.getSource(); vectorSrc.addFeatures(features); // would scale to the extend of all resulting features // this.openLayersMap.getView().fit(vectorSrc.getExtent()); }); // load following layers with bboxStrategy (using our request builder) var layer = null; layer = this.getLayerByName("Waterway Area"); layer.data.getSource().setLoader( this.buildVectorLoader( { featurePrefix: "ws-wamos", featureTypes: ["ienc_wtware"], geometryName: "geom" }, "/external/d4d", layer.data.getSource() ) ); layer = this.getLayerByName("Waterway Axis"); layer.data.getSource().setLoader( this.buildVectorLoader( { featurePrefix: "ws-wamos", featureTypes: ["ienc_wtwaxs"], geometryName: "geom" }, "/external/d4d", layer.data.getSource() ) ); layer = this.getLayerByName("Distance marks"); layer.data.getSource().setLoader( this.buildVectorLoader( { featurePrefix: "ws-wamos", featureTypes: ["ienc_dismar"], geometryName: "geom" //, /* restrict loading approximately to extend of danube in Austria */ // filter: bboxFilter("geom", [13.3, 48.0, 17.1, 48.6], "EPSG:4326") }, "/external/d4d", layer.data.getSource() ) ); layer.data.setVisible(layer.isVisible); layer = this.getLayerByName("Distance marks, Axis"); layer.data.getSource().setLoader( this.buildVectorLoader( { featureNS: "gemma", featurePrefix: "gemma", featureTypes: ["distance_marks_geoserver"], geometryName: "geom" }, "/internal/wfs", layer.data.getSource() ) ); } }; </script>