comparison client/src/map/Maplayer.vue @ 1140:2e06bc53b002

separating line/polygon/cut tools in UI Measurements can now be made while a bottleneck and sounding data is selected. The open layers interaction object(s) are now in the vuex store to disable them from other components (Morphtool.vue). Line and Polygon are now to separate buttons.
author Markus Kottlaender <markus@intevation.de>
date Mon, 12 Nov 2018 14:45:07 +0100
parents 2fda33d55d81
children 846e336d8ee5
comparison
equal deleted inserted replaced
1139:2fda33d55d81 1140:2e06bc53b002
42 import { HTTP } from "../application/lib/http"; 42 import { HTTP } from "../application/lib/http";
43 import { mapGetters, mapState } from "vuex"; 43 import { mapGetters, mapState } from "vuex";
44 import "ol/ol.css"; 44 import "ol/ol.css";
45 import { Map, View } from "ol"; 45 import { Map, View } from "ol";
46 import { WFS, GeoJSON } from "ol/format.js"; 46 import { WFS, GeoJSON } from "ol/format.js";
47 import LineString from "ol/geom/LineString.js";
48 import Draw from "ol/interaction/Draw.js";
49 import { Vector as VectorLayer } from "ol/layer.js";
50 import { Vector as VectorSource } from "ol/source.js";
51 import { getLength, getArea } from "ol/sphere.js";
52 import { Stroke, Style, Fill } from "ol/style.js"; 47 import { Stroke, Style, Fill } from "ol/style.js";
53
54 import { displayError } from "../application/lib/errors.js";
55 import { calculateFairwayCoordinates } from "../application/lib/geo.js";
56
57 const DEMODATA = 2.5;
58 48
59 /* for the sake of debugging */ 49 /* for the sake of debugging */
60 /* eslint-disable no-console */ 50 /* eslint-disable no-console */
61 export default { 51 export default {
62 name: "maplayer", 52 name: "maplayer",
63 props: ["lat", "long", "zoom", "split"], 53 props: ["lat", "long", "zoom", "split"],
64 data() { 54 data() {
65 return { 55 return {
66 projection: "EPSG:3857", 56 projection: "EPSG:3857"
67 interaction: null
68 }; 57 };
69 }, 58 },
70 computed: { 59 computed: {
71 ...mapGetters("map", ["getLayerByName"]), 60 ...mapGetters("map", ["getLayerByName"]),
72 ...mapState("map", ["layers", "openLayersMap", "drawMode"]), 61 ...mapState("map", ["layers", "openLayersMap", "drawMode"]),
77 mapsplit: this.split 66 mapsplit: this.split
78 }; 67 };
79 } 68 }
80 }, 69 },
81 methods: { 70 methods: {
82 removeCurrentInteraction() {
83 this.$store.commit("map/setCurrentMeasurement", null);
84 this.getLayerByName("Draw Tool").data.getSource().clear();
85 this.openLayersMap.removeInteraction(this.interaction);
86 this.interaction = null;
87 },
88 createInteraction(drawMode) {
89 const drawVectorSrc = this.getLayerByName("Draw Tool").data.getSource();
90 drawVectorSrc.clear();
91 var draw = new Draw({
92 source: drawVectorSrc,
93 type: drawMode,
94 maxPoints: drawMode === "LineString" ? 2 : 50
95 });
96 draw.on("drawstart", () => {
97 drawVectorSrc.clear();
98 this.$store.commit("map/setCurrentMeasurement", null);
99 // we are not setting an id here, to avoid the regular identify to
100 // pick it up
101 // event.feature.setId("drawn.1"); // unique id for new feature
102 });
103 draw.on("drawend", this.drawEnd);
104 return draw;
105 },
106 drawEnd(event) {
107 if (this.drawMode === "Polygon") {
108 const areaSize = getArea(event.feature.getGeometry());
109 // also place the a rounded areaSize in a property,
110 // so identify will show it
111 if (areaSize > 100000) {
112 this.$store.commit("map/setCurrentMeasurement", {
113 quantity: "Area",
114 unitSymbol: "km²",
115 // convert into 1 km² == 1000*1000 m² and round to 1000 m²
116 value: Math.round(areaSize / 1000) / 1000
117 });
118 } else {
119 this.$store.commit("map/setCurrentMeasurement", {
120 quantity: "Area",
121 unitSymbol: "m²",
122 value: Math.round(areaSize)
123 });
124 }
125 }
126 if (this.drawMode === "LineString") {
127 const length = getLength(event.feature.getGeometry());
128 this.$store.commit("map/setCurrentMeasurement", {
129 quantity: "Length",
130 unitSymbol: "m",
131 value: Math.round(length * 10) / 10
132 });
133 }
134
135 // if a survey has been selected, request a profile
136 // TODO an improvement could be to check if the line intersects
137 // with the bottleneck area's polygon before trying the server request
138 if (this.selectedSurvey) {
139 this.$store.commit("fairwayprofile/clearCurrentProfile");
140 console.log("requesting profile for", this.selectedSurvey);
141 const inputLineString = event.feature.getGeometry().clone();
142 inputLineString.transform("EPSG:3857", "EPSG:4326");
143 const [start, end] = inputLineString
144 .getCoordinates()
145 .map(coords => coords.map(coord => parseFloat(coord.toFixed(8))));
146 this.$store.commit("fairwayprofile/setStartPoint", start);
147 this.$store.commit("fairwayprofile/setEndPoint", end);
148 const profileLine = new LineString([start, end]);
149 this.$store
150 .dispatch("fairwayprofile/loadProfile", this.selectedSurvey)
151 .then(() => {
152 var vectorSource = this.getLayerByName(
153 "Fairway Dimensions"
154 ).data.getSource();
155 this.calculateIntersection(vectorSource, profileLine);
156 })
157 .then(() => {
158 this.$store.commit("application/showSplitscreen", true);
159 })
160 .catch(error => {
161 const { status, data } = error.response;
162 displayError({
163 title: "Backend Error",
164 message: `${status}: ${data.message || data}`
165 });
166 });
167 }
168 },
169 calculateIntersection(vectorSource, profileLine) {
170 const transformedLine = profileLine
171 .clone()
172 .transform("EPSG:4326", "EPSG:3857")
173 .getExtent();
174 const featureCallback = feature => {
175 // transform back to prepare for usage
176 var intersectingPolygon = feature
177 .getGeometry()
178 .clone()
179 .transform("EPSG:3857", "EPSG:4326");
180 const fairwayCoordinates = calculateFairwayCoordinates(
181 profileLine,
182 intersectingPolygon,
183 DEMODATA
184 );
185 this.$store.commit(
186 "fairwayprofile/setFairwayCoordinates",
187 fairwayCoordinates
188 );
189 };
190 vectorSource.forEachFeatureIntersectingExtent(
191 // need to use EPSG:3857 which is the proj of vectorSource
192 transformedLine,
193 featureCallback
194 );
195 },
196 activateInteraction() {
197 const interaction = this.createInteraction(this.drawMode);
198 this.interaction = interaction;
199 this.openLayersMap.addInteraction(interaction);
200 },
201 identify(coordinate, pixel) { 71 identify(coordinate, pixel) {
202 this.$store.commit("map/setIdentifiedFeatures", []); 72 this.$store.commit("map/setIdentifiedFeatures", []);
203 // checking our WFS layers 73 // checking our WFS layers
204 var features = this.openLayersMap.getFeaturesAtPixel(pixel); 74 var features = this.openLayersMap.getFeaturesAtPixel(pixel);
205 if (features) { 75 if (features) {
336 // reported that this was not feasable (back then). 206 // reported that this was not feasable (back then).
337 // console.log("onAfterPrint(", evt, ")"); 207 // console.log("onAfterPrint(", evt, ")");
338 } 208 }
339 }, 209 },
340 watch: { 210 watch: {
341 drawMode(newValue) {
342 if (this.interaction) {
343 this.removeCurrentInteraction();
344 }
345 if (newValue) {
346 this.activateInteraction();
347 }
348 },
349 split() { 211 split() {
350 const map = this.openLayersMap; 212 const map = this.openLayersMap;
351 this.$nextTick(() => { 213 this.$nextTick(() => {
352 map.updateSize(); 214 map.updateSize();
353 }); 215 });