Mercurial > gemma
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 }); |