Mercurial > gemma
comparison client/src/map/Maplayer.vue @ 1063:7ec2133c6404
client: add area measurement. simpify code
* Add a third draw mode which can only be activated when no
morphology is selected and we are already in LineString mode.
It adds an area calculation. Because the Polygon drawMode ends
on a double click, there needs to be an extra callback for this to
run identify so that the area calculation is shown all times.
* Add Bernhard as author to some files and also simplify copyright
note.
* Remove DRAWMODES in the code to simplify as this is just one
indirection used once in stores/application.js.
* Use mapState instead mapGetters to get the drawMode at all places
to save some code lines.
author | Bernhard Reiter <bernhard@intevation.de> |
---|---|
date | Thu, 25 Oct 2018 23:16:53 +0200 |
parents | d3bdad8ed8d3 |
children | 907321455f39 3f14b73414e2 |
comparison
equal
deleted
inserted
replaced
1062:d3bdad8ed8d3 | 1063:7ec2133c6404 |
---|---|
47 import LineString from "ol/geom/LineString.js"; | 47 import LineString from "ol/geom/LineString.js"; |
48 import Point from "ol/geom/Point.js"; | 48 import Point from "ol/geom/Point.js"; |
49 import Draw from "ol/interaction/Draw.js"; | 49 import Draw from "ol/interaction/Draw.js"; |
50 import { Vector as VectorLayer } from "ol/layer.js"; | 50 import { Vector as VectorLayer } from "ol/layer.js"; |
51 import { Vector as VectorSource } from "ol/source.js"; | 51 import { Vector as VectorSource } from "ol/source.js"; |
52 import { getLength } from "ol/sphere.js"; | 52 import { getLength, getArea } from "ol/sphere.js"; |
53 import { Icon, Stroke, Style, Fill } from "ol/style.js"; | 53 import { Icon, Stroke, Style, Fill } from "ol/style.js"; |
54 | 54 |
55 import { displayError } from "../application/lib/errors.js"; | 55 import { displayError } from "../application/lib/errors.js"; |
56 import { calculateFairwayCoordinates } from "../application/lib/geo.js"; | 56 import { calculateFairwayCoordinates } from "../application/lib/geo.js"; |
57 | 57 |
103 width: 2 | 103 width: 2 |
104 }) | 104 }) |
105 }) | 105 }) |
106 ]; | 106 ]; |
107 | 107 |
108 geometry.forEachSegment(function(start, end) { | 108 if (geometry.getType() === "LineString") { |
109 var dx = end[0] - start[0]; | 109 geometry.forEachSegment(function(start, end) { |
110 var dy = end[1] - start[1]; | 110 var dx = end[0] - start[0]; |
111 var rotation = Math.atan2(dy, dx); | 111 var dy = end[1] - start[1]; |
112 // arrows | 112 var rotation = Math.atan2(dy, dx); |
113 styles.push( | 113 // arrows |
114 new Style({ | 114 styles.push( |
115 geometry: new Point(end), | 115 new Style({ |
116 image: new Icon({ | 116 geometry: new Point(end), |
117 // we need to make sure the image is loaded by Vue Loader | 117 image: new Icon({ |
118 src: require("../application/assets/linestring_arrow.png"), | 118 // we need to make sure the image is loaded by Vue Loader |
119 // fiddling with the anchor's y value does not help to | 119 src: require("../application/assets/linestring_arrow.png"), |
120 // position the image more centered on the line ending, as the | 120 // fiddling with the anchor's y value does not help to |
121 // default line style seems to be slightly uncentered in the | 121 // position the image more centered on the line ending, as the |
122 // anti-aliasing, but the image is not placed with subpixel | 122 // default line style seems to be slightly uncentered in the |
123 // precision | 123 // anti-aliasing, but the image is not placed with subpixel |
124 anchor: [0.75, 0.5], | 124 // precision |
125 rotateWithView: true, | 125 anchor: [0.75, 0.5], |
126 rotation: -rotation | 126 rotateWithView: true, |
127 rotation: -rotation | |
128 }) | |
127 }) | 129 }) |
128 }) | 130 ); |
129 ); | 131 }); |
130 }); | 132 } |
131 | |
132 return styles; | 133 return styles; |
133 }, | 134 }, |
134 createVectorLayer() { | 135 createVectorLayer() { |
135 this.vectorLayer = new VectorLayer({ | 136 this.vectorLayer = new VectorLayer({ |
136 source: this.vectorSource, | 137 source: this.vectorSource, |
139 }, | 140 }, |
140 removeCurrentInteraction() { | 141 removeCurrentInteraction() { |
141 this.openLayersMap.removeInteraction(this.interaction); | 142 this.openLayersMap.removeInteraction(this.interaction); |
142 this.interaction = null; | 143 this.interaction = null; |
143 }, | 144 }, |
144 createInteraction() { | 145 createInteraction(drawMode) { |
145 this.vectorSource.clear(); | 146 this.vectorSource.clear(); |
146 var draw = new Draw({ | 147 var draw = new Draw({ |
147 source: this.vectorSource, | 148 source: this.vectorSource, |
148 type: this.drawMode, | 149 type: drawMode, |
149 maxPoints: 2 | 150 maxPoints: drawMode === "LineString" ? 2 : 50 |
150 }); | 151 }); |
151 draw.on("drawstart", event => { | 152 draw.on("drawstart", event => { |
152 this.vectorSource.clear(); | 153 this.vectorSource.clear(); |
153 this.$store.commit("identifystore/setCurrentMeasurement", null); | 154 this.$store.commit("identifystore/setCurrentMeasurement", null); |
154 event.feature.setId("drawn.1"); // unique id for new feature | 155 event.feature.setId("drawn.1"); // unique id for new feature |
155 }); | 156 }); |
156 draw.on("drawend", this.drawEnd); | 157 draw.on("drawend", this.drawEnd); |
157 return draw; | 158 return draw; |
158 }, | 159 }, |
159 drawEnd(event) { | 160 drawEnd(event) { |
160 const length = getLength(event.feature.getGeometry()); | 161 if (this.drawMode === "Polygon") { |
161 this.$store.commit("identifystore/setCurrentMeasurement", length); | 162 const areaSize = getArea(event.feature.getGeometry()); |
162 // also place the a rounded length in a property, so identify can show it | 163 // also place the a rounded areaSize in a property, |
163 event.feature.set("length (m)", Math.round(length * 10) / 10); | 164 // so identify will show it |
165 event.feature.set("area (kmĀ²)", Math.round(areaSize) / 1000); | |
166 } | |
167 if (this.drawMode === "LineString") { | |
168 const length = getLength(event.feature.getGeometry()); | |
169 this.$store.commit("identifystore/setCurrentMeasurement", length); | |
170 // also place the a rounded length in a property, | |
171 // so identify will show it | |
172 event.feature.set("length (m)", Math.round(length * 10) / 10); | |
173 } | |
164 | 174 |
165 // if a survey has been selected, request a profile | 175 // if a survey has been selected, request a profile |
166 // TODO an improvement could be to check if the line intersects | 176 // TODO an improvement could be to check if the line intersects |
167 // with the bottleneck area's polygon before trying the server request | 177 // with the bottleneck area's polygon before trying the server request |
168 if (this.selectedMorph) { | 178 if (this.selectedMorph) { |
227 this.interaction = interaction; | 237 this.interaction = interaction; |
228 this.openLayersMap.addInteraction(interaction); | 238 this.openLayersMap.addInteraction(interaction); |
229 }, | 239 }, |
230 activateIdentifyMode() { | 240 activateIdentifyMode() { |
231 this.openLayersMap.on("singleclick", event => { | 241 this.openLayersMap.on("singleclick", event => { |
232 // console.log("single click on map:", event); | 242 this.identify(event.coordinate, event.pixel); |
243 }); | |
244 this.openLayersMap.on("dblclick", event => { | |
233 this.identify(event.coordinate, event.pixel); | 245 this.identify(event.coordinate, event.pixel); |
234 }); | 246 }); |
235 }, | 247 }, |
236 identify(coordinate, pixel) { | 248 identify(coordinate, pixel) { |
237 this.$store.commit("identifystore/setIdentifiedFeatures", []); | 249 this.$store.commit("identifystore/setIdentifiedFeatures", []); |
360 // reported that this was not feasable (back then). | 372 // reported that this was not feasable (back then). |
361 // console.log("onAfterPrint(", evt, ")"); | 373 // console.log("onAfterPrint(", evt, ")"); |
362 } | 374 } |
363 }, | 375 }, |
364 watch: { | 376 watch: { |
365 drawMode() { | 377 drawMode(newValue) { |
366 if (this.interaction) { | 378 if (this.interaction) { |
367 this.removeCurrentInteraction(); | 379 this.removeCurrentInteraction(); |
368 } else { | 380 } |
381 if (newValue) { | |
369 this.activateInteraction(); | 382 this.activateInteraction(); |
370 } | 383 } |
371 }, | 384 }, |
372 split() { | 385 split() { |
373 const map = this.openLayersMap; | 386 const map = this.openLayersMap; |