changeset 3951:e467159d04cc

Merged changes from v3.1.1
author Sascha Wilde <wilde@intevation.de>
date Mon, 15 Jul 2019 17:09:01 +0200
parents 5020128dc5a0 (diff) 2db4b8693408 (current diff)
children 858b1bf1d21b
files pkg/imports/sr.go
diffstat 11 files changed, 223 insertions(+), 291 deletions(-) [+]
line wrap: on
line diff
--- a/.hgtags	Mon Jul 15 16:58:13 2019 +0200
+++ b/.hgtags	Mon Jul 15 17:09:01 2019 +0200
@@ -9,3 +9,5 @@
 d4a5d11e23a043026a747c626d133b45047d17df v3
 ad93adaeb68827534b1b3dd96c50096b3fa9a24c v3.1-preview20190626
 b166cb97b98a40f33e977c96e65e79bf22e92fca v3.1
+b166cb97b98a40f33e977c96e65e79bf22e92fca v3.1
+d78af8354b95cea86744459f350edb16662dadd0 v3.1
--- a/client/src/components/fairway/AvailableFairwayDepth.vue	Mon Jul 15 16:58:13 2019 +0200
+++ b/client/src/components/fairway/AvailableFairwayDepth.vue	Mon Jul 15 17:09:01 2019 +0200
@@ -75,8 +75,7 @@
 import debounce from "debounce";
 import { mapState } from "vuex";
 import filters from "@/lib/filters.js";
-import svg2pdf from "svg2pdf.js";
-import { pdfgen, templateLoader } from "@/lib/mixins";
+import { diagram, pdfgen, templateLoader } from "@/lib/mixins";
 import { HTTP } from "@/lib/http";
 import { displayError } from "@/lib/errors";
 import { FREQUENCIES } from "@/store/fairwayavailability";
@@ -85,7 +84,7 @@
 const hoursInDays = x => x / 24;
 
 export default {
-  mixins: [pdfgen, templateLoader],
+  mixins: [diagram, pdfgen, templateLoader],
   components: {
     DiagramLegend: () => import("@/components/DiagramLegend")
   },
@@ -217,19 +216,6 @@
     }
   },
   methods: {
-    getDimensions({ svgHeight, svgWidth, main, nav }) {
-      const mainMargin = main || { top: 0, right: 20, bottom: 50, left: 20 };
-      const navMargin = nav || {
-        top: svgHeight - mainMargin.top - 65,
-        right: 20,
-        bottom: 30,
-        left: 80
-      };
-      const width = Number(svgWidth) - mainMargin.left - mainMargin.right;
-      const mainHeight = Number(svgHeight) - mainMargin.top - mainMargin.bottom;
-      const navHeight = Number(svgHeight) - navMargin.top - navMargin.bottom;
-      return { width, mainHeight, navHeight, mainMargin, navMargin };
-    },
     applyChange() {
       if (this.form.template.hasOwnProperty("properties")) {
         this.templateData = this.defaultTemplate;
@@ -264,36 +250,6 @@
       });
       this.pdf.doc.save(`Available Fairway Depth: ${this.featureName}`);
     },
-    addDiagram(position, offset, width, height) {
-      let x = offset.x,
-        y = offset.y;
-      const svgWidth = this.millimeter2pixels(width, 80);
-      const svgHeight = this.millimeter2pixels(height, 80);
-      // draw the diagram in a separated html element to get the full size
-      const offScreen = document.querySelector("#offScreen");
-      offScreen.style.width = `${svgWidth}px`;
-      offScreen.style.height = `${svgHeight}px`;
-      this.renderTo({
-        element: offScreen,
-        dimensions: this.getDimensions({
-          svgWidth: svgWidth,
-          svgHeight: svgHeight
-        })
-      });
-      var svg = offScreen.querySelector("svg");
-      if (["topright", "bottomright"].indexOf(position) !== -1) {
-        x = this.pdf.width - offset.x - width;
-      }
-      if (["bottomright", "bottomleft"].indexOf(position) !== -1) {
-        y = this.pdf.height - offset.y - height;
-      }
-      svg2pdf(svg, this.pdf.doc, {
-        xOffset: x,
-        yOffset: y,
-        scale: 0.354
-      });
-      offScreen.removeChild(svg);
-    },
     addDiagramLegend(position, offset, color) {
       let x = offset.x,
         y = offset.y;
@@ -341,13 +297,26 @@
     close() {
       this.$store.commit("application/paneSetup", "DEFAULT");
     },
+    getPrintLayout(svgHeight) {
+      return {
+        main: { top: 0, right: 20, bottom: 50, left: 20 },
+        nav: {
+          top: svgHeight - 65,
+          right: 20,
+          bottom: 30,
+          left: 80
+        }
+      };
+    },
     drawDiagram() {
       const elem = document.querySelector("#" + this.containerId);
       const svgWidth = elem != null ? elem.clientWidth : 0;
       const svgHeight = elem != null ? elem.clientHeight : 0;
+      const layout = this.getPrintLayout(svgHeight);
       const dimensions = this.getDimensions({
         svgHeight,
-        svgWidth
+        svgWidth,
+        ...layout
       });
       d3.select(".diagram-container svg").remove();
       this.renderTo({ element: ".diagram-container", dimensions });
--- a/client/src/components/fairway/AvailableFairwayDepthLNWL.vue	Mon Jul 15 16:58:13 2019 +0200
+++ b/client/src/components/fairway/AvailableFairwayDepthLNWL.vue	Mon Jul 15 17:09:01 2019 +0200
@@ -74,15 +74,14 @@
 import app from "@/main";
 import debounce from "debounce";
 import { mapState } from "vuex";
-import svg2pdf from "svg2pdf.js";
 import filters from "@/lib/filters.js";
-import { pdfgen, templateLoader } from "@/lib/mixins";
+import { diagram, pdfgen, templateLoader } from "@/lib/mixins";
 import { HTTP } from "@/lib/http";
 import { displayError } from "@/lib/errors";
 import { defaultDiagramTemplate } from "@/lib/DefaultDiagramTemplate";
 
 export default {
-  mixins: [pdfgen, templateLoader],
+  mixins: [diagram, pdfgen, templateLoader],
   components: {
     DiagramLegend: () => import("@/components/DiagramLegend")
   },
@@ -249,36 +248,6 @@
       });
       this.pdf.doc.save(`Available Fairway Depth LNWL: ${this.featureName}`);
     },
-    addDiagram(position, offset, width, height) {
-      let x = offset.x,
-        y = offset.y;
-      const svgWidth = this.millimeter2pixels(width, 80);
-      const svgHeight = this.millimeter2pixels(height, 80);
-      // draw the diagram in a separated html element to get the full size
-      const offScreen = document.querySelector("#offScreen");
-      offScreen.style.width = `${svgWidth}px`;
-      offScreen.style.height = `${svgHeight}px`;
-      this.renderTo({
-        element: offScreen,
-        dimensions: this.getDimensions({
-          svgWidth: svgWidth,
-          svgHeight: svgHeight
-        })
-      });
-      var svg = offScreen.querySelector("svg");
-      if (["topright", "bottomright"].indexOf(position) !== -1) {
-        x = this.pdf.width - offset.x - width;
-      }
-      if (["bottomright", "bottomleft"].indexOf(position) !== -1) {
-        y = this.pdf.height - offset.y - height;
-      }
-      svg2pdf(svg, this.pdf.doc, {
-        xOffset: x,
-        yOffset: y,
-        scale: 0.354
-      });
-      offScreen.removeChild(svg);
-    },
     addDiagramLegend(position, offset, color) {
       let x = offset.x,
         y = offset.y;
@@ -317,26 +286,26 @@
     close() {
       this.$store.commit("application/paneSetup", "DEFAULT");
     },
-    getDimensions({ svgHeight, svgWidth }) {
-      const mainMargin = { top: 0, right: 20, bottom: 50, left: 20 };
-      const navMargin = {
-        top: svgHeight - mainMargin.top - 65,
-        right: 20,
-        bottom: 30,
-        left: 80
+    getPrintLayout(svgHeight) {
+      return {
+        main: { top: 0, right: 20, bottom: 50, left: 20 },
+        nav: {
+          top: svgHeight - 65,
+          right: 20,
+          bottom: 30,
+          left: 80
+        }
       };
-      const width = Number(svgWidth) - mainMargin.left - mainMargin.right;
-      const mainHeight = Number(svgHeight) - mainMargin.top - mainMargin.bottom;
-      const navHeight = Number(svgHeight) - navMargin.top - navMargin.bottom;
-      return { width, mainHeight, navHeight, mainMargin, navMargin };
     },
     drawDiagram() {
       const elem = document.querySelector("#" + this.containerId);
       const svgWidth = elem != null ? elem.clientWidth : 0;
       const svgHeight = elem != null ? elem.clientHeight : 0;
+      const layout = this.getPrintLayout(svgHeight);
       const dimensions = this.getDimensions({
         svgHeight,
-        svgWidth
+        svgWidth,
+        ...layout
       });
       d3.select(".diagram-container svg").remove();
       this.renderTo({ element: ".diagram-container", dimensions });
--- a/client/src/components/fairway/Fairwayprofile.vue	Mon Jul 15 16:58:13 2019 +0200
+++ b/client/src/components/fairway/Fairwayprofile.vue	Mon Jul 15 17:09:01 2019 +0200
@@ -149,8 +149,7 @@
 import * as d3 from "d3";
 import { mapState, mapGetters } from "vuex";
 import debounce from "debounce";
-import svg2pdf from "svg2pdf.js";
-import { pdfgen, templateLoader } from "@/lib/mixins";
+import { diagram, pdfgen, templateLoader } from "@/lib/mixins";
 import { HTTP } from "@/lib/http";
 import { displayError } from "@/lib/errors";
 import { defaultDiagramTemplate } from "@/lib/DefaultDiagramTemplate";
@@ -159,7 +158,7 @@
 const WATER_COLOR = "#005DFF";
 
 export default {
-  mixins: [pdfgen, templateLoader],
+  mixins: [diagram, pdfgen, templateLoader],
   name: "fairwayprofile",
   components: {
     DiagramLegend: () => import("@/components/DiagramLegend")
@@ -169,12 +168,6 @@
       resizeListenerFunction: null,
       width: null,
       height: null,
-      margin: {
-        top: 20,
-        right: 80,
-        bottom: 60,
-        left: 80
-      },
       form: {
         template: null
       },
@@ -339,43 +332,7 @@
         this.title.replace(/\s/g, "_").replace(/[():,]/g, "") + ".pdf"
       );
     },
-    addDiagram(position, offset, width, height) {
-      let x = offset.x,
-        y = offset.y;
-      const resolution = this.templateData.properties.resolution || 80;
-      const svgWidth = this.millimeter2pixels(width, resolution);
-      const svgHeight = this.millimeter2pixels(height, resolution);
-      const offScreen = document.querySelector("#offScreen");
-      offScreen.style.width = `${svgWidth}px`;
-      offScreen.style.height = `${svgHeight}px`;
-      this.renderTo({
-        element: offScreen,
-        dimensions: {
-          svgWidth: svgWidth - this.margin.right - this.margin.left,
-          svgHeight: svgHeight - this.margin.top - this.margin.bottom
-        }
-      });
-      var svg = offScreen.querySelector("svg");
-      // use default width,height if they are missing in the template definition
-      if (!width) {
-        width = this.templateData.properties.paperSize === "a3" ? 380 : 290;
-      }
-      if (!height) {
-        height = this.templateData.properties.paperSize === "a3" ? 130 : 100;
-      }
-      if (["topright", "bottomright"].indexOf(position) !== -1) {
-        x = this.pdf.width - offset.x - width;
-      }
-      if (["bottomright", "bottomleft"].indexOf(position) !== -1) {
-        y = this.pdf.height - offset.y - height;
-      }
-      svg2pdf(svg, this.pdf.doc, {
-        xOffset: x,
-        yOffset: y,
-        scale: 0.353
-      });
-      offScreen.removeChild(svg);
-    },
+
     // Diagram legend
     addDiagramLegend(position, offset, color) {
       let x = offset.x,
@@ -424,31 +381,44 @@
       this.pdf.doc.circle(x, y + 25, 2, "FD");
       this.pdf.doc.text(x + 3, y + 26, "Sediment (Compare)");
     },
+    getPrintLayout() {
+      return {
+        main: {
+          top: 20,
+          right: 80,
+          bottom: 60,
+          left: 80
+        }
+      };
+    },
     drawDiagram() {
       d3.select(".diagram-container svg").remove();
       this.scaleFairwayProfile();
       if (!this.height || !this.width) return; // do not try to render when height and width are unknown
+      const layout = this.getPrintLayout(this.height);
       this.renderTo({
         element: ".diagram-container",
-        dimensions: {
-          svgWidth: this.width - this.margin.right - this.margin.left,
-          svgHeight: this.height - this.margin.top - this.margin.bottom
-        }
+        dimensions: this.getDimensions({
+          svgWidth: this.width,
+          svgHeight: this.height,
+          ...layout
+        })
       });
     },
     renderTo({ element, dimensions }) {
       let svg = d3.select(element).append("svg");
       svg.attr("width", "100%");
       svg.attr("height", "100%");
-      const width = dimensions.svgWidth;
-      const height = dimensions.svgHeight;
+      const width = dimensions.width;
+      const height = dimensions.mainHeight;
       const currentData = this.currentData;
       const additionalData = this.additionalData;
-      const { xScale, yScaleRight, graph } = this.generateScalesAndGraph(
+      const { xScale, yScaleRight, graph } = this.generateScalesAndGraph({
         svg,
         height,
-        width
-      );
+        width,
+        dimensions
+      });
       this.drawWaterlevel({ graph, xScale, yScaleRight, height });
       this.drawLabels({ graph, dimensions });
       if (currentData) {
@@ -525,8 +495,8 @@
       graph
         .append("text")
         .attr("transform", ["rotate(-90)"])
-        .attr("y", dimensions.svgWidth + 45)
-        .attr("x", -dimensions.svgHeight / 2)
+        .attr("y", dimensions.width + 45)
+        .attr("x", -dimensions.mainHeight / 2)
         .attr("fill", "black")
         .style("text-anchor", "middle")
         .text("Depth [m]");
@@ -534,7 +504,7 @@
         .append("text")
         .attr("transform", ["rotate(-90)"])
         .attr("y", -50)
-        .attr("x", -dimensions.svgHeight / 2)
+        .attr("x", -dimensions.mainHeight / 2)
         .attr("fill", "black")
         .style("text-anchor", "middle")
         .text("Waterlevel [m]");
@@ -547,15 +517,15 @@
         .style("text-anchor", "middle")
         .attr("transform", [
           "translate(" +
-            dimensions.svgWidth / 2 +
+            dimensions.width / 2 +
             "," +
-            dimensions.svgHeight +
+            dimensions.mainHeight +
             ")",
           "rotate(0)"
         ])
         .text("Width [m]");
     },
-    generateScalesAndGraph(svg, height, width) {
+    generateScalesAndGraph({ svg, height, width, dimensions }) {
       let xScale = d3
         .scaleLinear()
         .domain([0, this.totalLength])
@@ -590,7 +560,11 @@
         .append("g")
         .attr(
           "transform",
-          "translate(" + this.margin.left + "," + this.margin.top + ")"
+          "translate(" +
+            dimensions.mainMargin.left +
+            "," +
+            dimensions.mainMargin.top +
+            ")"
         );
       graph
         .append("g")
--- a/client/src/components/gauge/HydrologicalConditions.vue	Mon Jul 15 16:58:13 2019 +0200
+++ b/client/src/components/gauge/HydrologicalConditions.vue	Mon Jul 15 17:09:01 2019 +0200
@@ -104,14 +104,13 @@
 import * as d3 from "d3";
 import debounce from "debounce";
 import { startOfYear, endOfYear } from "date-fns";
-import svg2pdf from "svg2pdf.js";
-import { pdfgen, templateLoader } from "@/lib/mixins";
+import { diagram, pdfgen, templateLoader } from "@/lib/mixins";
 import { HTTP } from "@/lib/http";
 import { displayError } from "@/lib/errors";
 import { defaultDiagramTemplate } from "@/lib/DefaultDiagramTemplate";
 
 export default {
-  mixins: [pdfgen, templateLoader],
+  mixins: [diagram, pdfgen, templateLoader],
   components: {
     DiagramLegend: () => import("@/components/DiagramLegend")
   },
@@ -214,36 +213,6 @@
           " Hydrological-condition Diagram.pdf"
       );
     },
-    addDiagram(position, offset, width, height) {
-      let x = offset.x,
-        y = offset.y;
-      const svgWidth = this.millimeter2pixels(width, 80);
-      const svgHeight = this.millimeter2pixels(height, 80);
-      // draw the diagram in a separated html element to get the full size
-      const offScreen = document.querySelector("#offScreen");
-      offScreen.style.width = `${svgWidth}px`;
-      offScreen.style.height = `${svgHeight}px`;
-      this.renderTo({
-        element: offScreen,
-        dimensions: this.getDimensions({
-          svgWidth: svgWidth,
-          svgHeight: svgHeight
-        })
-      });
-      var svg = offScreen.querySelector("svg");
-      if (["topright", "bottomright"].indexOf(position) !== -1) {
-        x = this.pdf.width - offset.x - width;
-      }
-      if (["bottomright", "bottomleft"].indexOf(position) !== -1) {
-        y = this.pdf.height - offset.y - height;
-      }
-      svg2pdf(svg, this.pdf.doc, {
-        xOffset: x,
-        yOffset: y,
-        scale: 0.353
-      });
-      offScreen.removeChild(svg);
-    },
     applyChange() {
       if (this.form.template.hasOwnProperty("properties")) {
         this.templateData = this.defaultTemplate;
@@ -305,6 +274,17 @@
       this.pdf.doc.circle(x, y + 20, 2, "FD");
       this.pdf.doc.text(x + 3, y + 21, "Long-term Amplitude");
     },
+    getPrintLayout(svgHeight) {
+      return {
+        main: { top: 20, right: 50, bottom: 110, left: 80 },
+        nav: {
+          top: svgHeight - 85,
+          right: 20,
+          bottom: 30,
+          left: 80
+        }
+      };
+    },
     drawDiagram() {
       // remove old diagram
       d3.select("#" + this.containerId + " svg").remove();
@@ -313,11 +293,13 @@
         return;
       const svgWidth = el.clientWidth;
       const svgHeight = el.clientHeight;
+      const layout = this.getPrintLayout(svgHeight);
       this.renderTo({
         element: `#${this.containerId}`,
         dimensions: this.getDimensions({
           svgWidth: svgWidth,
-          svgHeight: svgHeight
+          svgHeight: svgHeight,
+          ...layout
         })
       });
     },
@@ -531,20 +513,6 @@
         .attr("fill", "666")
         .style("font-size", "0.8em");
     },
-    getDimensions({ svgWidth, svgHeight }) {
-      const mainMargin = { top: 20, right: 50, bottom: 110, left: 80 };
-      const navMargin = {
-        top: svgHeight - mainMargin.top - 65,
-        right: 20,
-        bottom: 30,
-        left: 80
-      };
-      const width = +svgWidth - mainMargin.left - mainMargin.right;
-      const mainHeight = +svgHeight - mainMargin.top - mainMargin.bottom;
-      const navHeight = +svgHeight - navMargin.top - navMargin.bottom;
-
-      return { width, mainHeight, navHeight, mainMargin, navMargin };
-    },
     getExtent(refWaterLevels) {
       const waterlevelValues = [];
       this.longtermWaterlevels.forEach(wl => {
--- a/client/src/components/gauge/Waterlevel.vue	Mon Jul 15 16:58:13 2019 +0200
+++ b/client/src/components/gauge/Waterlevel.vue	Mon Jul 15 17:09:01 2019 +0200
@@ -80,10 +80,6 @@
         </div>
       </div>
     </div>
-    <div
-      id="pdfContainer"
-      style="position: absolute; z-index: -1; top: -9999px; width: 387mm; height: 100mm;"
-    ></div>
   </div>
 </template>
 
@@ -109,9 +105,8 @@
 import { lineChunked } from "d3-line-chunked";
 import { endOfDay } from "date-fns";
 import debounce from "debounce";
-import svg2pdf from "svg2pdf.js";
 import { saveAs } from "file-saver";
-import { pdfgen, templateLoader } from "@/lib/mixins";
+import { diagram, pdfgen, templateLoader } from "@/lib/mixins";
 import { HTTP } from "@/lib/http";
 import { displayError } from "@/lib/errors";
 import { defaultDiagramTemplate } from "@/lib/DefaultDiagramTemplate";
@@ -121,7 +116,7 @@
 const d3 = Object.assign(d3Base, { lineChunked });
 
 export default {
-  mixins: [pdfgen, templateLoader],
+  mixins: [diagram, pdfgen, templateLoader],
   components: {
     DiagramLegend: () => import("@/components/DiagramLegend")
   },
@@ -250,42 +245,6 @@
           });
       }
     },
-    addDiagram(position, offset, width, height) {
-      let x = offset.x,
-        y = offset.y;
-      const svgWidth = this.millimeter2pixels(
-        width,
-        this.templateData.properties.resolution || 80
-      );
-      const svgHeight = this.millimeter2pixels(
-        height,
-        this.templateData.properties.resolution || 80
-      );
-      // draw the diagram in a separated html element to get the full size
-      const offScreen = document.querySelector("#offScreen");
-      offScreen.style.width = `${svgWidth}px`;
-      offScreen.style.height = `${svgHeight}px`;
-      this.renderTo({
-        element: offScreen,
-        dimensions: this.getDimensions({
-          svgWidth: svgWidth,
-          svgHeight: svgHeight
-        })
-      });
-      var svg = offScreen.querySelector("svg");
-      if (["topright", "bottomright"].indexOf(position) !== -1) {
-        x = this.pdf.width - offset.x - width;
-      }
-      if (["bottomright", "bottomleft"].indexOf(position) !== -1) {
-        y = this.pdf.height - offset.y - height;
-      }
-      svg2pdf(svg, this.pdf.doc, {
-        xOffset: x,
-        yOffset: y,
-        scale: 0.353
-      });
-      offScreen.removeChild(svg);
-    },
     // Diagram legend
     addDiagramLegend(position, offset, color) {
       let x = offset.x;
@@ -316,15 +275,31 @@
       this.pdf.doc.circle(x, y + 5, 0.6, "FD");
       this.pdf.doc.text(x + 3, y + 6, "Prediction");
     },
+    getPrintLayout(svgHeight) {
+      return {
+        main: { top: 20, right: 50, bottom: 110, left: 80 },
+        nav: {
+          top: svgHeight - 85,
+          right: 20,
+          bottom: 30,
+          left: 80
+        }
+      };
+    },
     drawDiagram() {
       // remove old diagram and exit if necessary data is missing
       d3.select("#" + this.containerId + " svg").remove();
-      if (!this.selectedGauge || !this.waterlevels.length) return;
+      const elem = document.querySelector("#" + this.containerId);
+      const svgWidth = elem.clientWidth;
+      const svgHeight = elem.clientHeight;
+      const layout = this.getPrintLayout(svgHeight);
+      if (!this.selectedGauge || !this.waterlevels.length || !elem) return;
       this.renderTo({
         element: `#${this.containerId}`,
         dimensions: this.getDimensions({
-          svgWidth: document.querySelector("#" + this.containerId).clientWidth,
-          svgHeight: document.querySelector("#" + this.containerId).clientHeight
+          svgWidth: svgWidth,
+          svgHeight: svgHeight,
+          ...layout
         })
       });
     },
@@ -578,20 +553,6 @@
         .attr("fill", "666")
         .style("font-size", "0.8em");
     },
-    getDimensions({ svgWidth, svgHeight }) {
-      const mainMargin = { top: 20, right: 50, bottom: 110, left: 80 };
-      const navMargin = {
-        top: svgHeight - mainMargin.top - 65,
-        right: 20,
-        bottom: 30,
-        left: 80
-      };
-      const width = +svgWidth - mainMargin.left - mainMargin.right;
-      const mainHeight = +svgHeight - mainMargin.top - mainMargin.bottom;
-      const navHeight = +svgHeight - navMargin.top - navMargin.bottom;
-
-      return { width, mainHeight, navHeight, mainMargin, navMargin };
-    },
     getExtent(refWaterLevels) {
       return {
         // set min/max values for the date axis
--- a/client/src/components/importconfiguration/types/Soundingresults.vue	Mon Jul 15 16:58:13 2019 +0200
+++ b/client/src/components/importconfiguration/types/Soundingresults.vue	Mon Jul 15 17:09:01 2019 +0200
@@ -106,6 +106,21 @@
             </small>
           </span>
         </div>
+        <div class="ml-3 text-left d-flex flex-column">
+          <div class="text-left">
+            <small class="text-muted">
+              <translate>Negate Z values in XYZ files</translate>
+            </small>
+          </div>
+          <div class="ml-4 mt-2 text-left">
+            <input
+              id="negatez"
+              type="checkbox"
+              class="form-check-input"
+              v-model="negateZ"
+            />
+          </div>
+        </div>
       </div>
     </div>
     <div class="mt-2">
@@ -219,7 +234,8 @@
       disableUpload: false,
       token: null,
       messages: [],
-      eMailNotification: false
+      eMailNotification: false,
+      negateZ: false
     };
   },
   methods: {
@@ -280,6 +296,7 @@
             const { bottleneck, date, epsg } = response.data.meta;
             const depthReference = response.data.meta["depth-reference"];
             const singlebeam = response.data.meta["single-beam"];
+            this.negateZ = response.data.meta["negate-z"];
             this.bottleneck = this.bottlenecks.find(
               bn => bn.properties.objnam === bottleneck
             );
@@ -318,7 +335,7 @@
           "single-beam",
           this.beamType === this.$options.BEAMTYPES.SINGLEBEAM
         );
-
+      formData.append("negate-z", this.negateZ == true);
       HTTP.post("/imports/sr", formData, {
         headers: {
           "X-Gemma-Auth": localStorage.getItem("token"),
@@ -432,7 +449,8 @@
               date: this.importDate,
               "single-beam":
                 this.beamType === this.$options.BEAMTYPES.SINGLEBEAM,
-              epsg: Number(this.projection)
+              epsg: Number(this.projection),
+              "negate-z": this.negateZ == true
             })
           )
         );
--- a/client/src/lib/mixins.js	Mon Jul 15 16:58:13 2019 +0200
+++ b/client/src/lib/mixins.js	Mon Jul 15 17:09:01 2019 +0200
@@ -14,6 +14,7 @@
  * * Bernhard Reiter <bernhard.reiter@intevation.de>
  */
 import jsPDF from "jspdf-yworks";
+import svg2pdf from "svg2pdf.js";
 import locale2 from "locale2";
 import { mapState } from "vuex";
 import { HTTP } from "@/lib/http";
@@ -37,12 +38,13 @@
 
 export const diagram = {
   methods: {
-    getDimensions({ main, nav }) {
-      //dimensions and margins
-      const elem = document.querySelector("#" + this.containerId);
-      const svgWidth = elem != null ? elem.clientWidth : 0;
-      const svgHeight = elem != null ? elem.clientHeight : 0;
-      const mainMargin = main || { top: 20, right: 20, bottom: 110, left: 80 };
+    getDimensions({ svgWidth, svgHeight, main, nav }) {
+      const mainMargin = main || {
+        top: 20,
+        right: 80,
+        bottom: 60,
+        left: 80
+      };
       const navMargin = nav || {
         top: svgHeight - mainMargin.top - 65,
         right: 20,
@@ -132,6 +134,38 @@
     ...mapState("user", ["user"])
   },
   methods: {
+    addDiagram(position, offset, width, height) {
+      let x = offset.x,
+        y = offset.y;
+      const svgWidth = this.millimeter2pixels(width, 80);
+      const svgHeight = this.millimeter2pixels(height, 80);
+      // draw the diagram in a separated html element to get the full size
+      const offScreen = document.querySelector("#offScreen");
+      offScreen.style.width = `${svgWidth}px`;
+      offScreen.style.height = `${svgHeight}px`;
+      const layout = this.getPrintLayout(svgHeight);
+      this.renderTo({
+        element: offScreen,
+        dimensions: this.getDimensions({
+          svgWidth: svgWidth,
+          svgHeight: svgHeight,
+          ...layout
+        })
+      });
+      var svg = offScreen.querySelector("svg");
+      if (["topright", "bottomright"].indexOf(position) !== -1) {
+        x = this.pdf.width - offset.x - width;
+      }
+      if (["bottomright", "bottomleft"].indexOf(position) !== -1) {
+        y = this.pdf.height - offset.y - height;
+      }
+      svg2pdf(svg, this.pdf.doc, {
+        xOffset: x,
+        yOffset: y,
+        scale: 0.354
+      });
+      offScreen.removeChild(svg);
+    },
     getPaperDimensions(format) {
       const dims = {
         A3: {
@@ -197,8 +231,11 @@
               this.addDiagram(
                 e.position,
                 e.offset || defaultOffset,
-                e.width || 200,
-                e.height || 100
+                // use default width,height if they are missing in template definition
+                e.width ||
+                  (this.templateData.properties.paperSize === "a3" ? 318 : 230),
+                e.height ||
+                  (this.templateData.properties.paperSize === "a3" ? 104 : 110)
               );
               break;
             }
--- a/pkg/controllers/srimports.go	Mon Jul 15 16:58:13 2019 +0200
+++ b/pkg/controllers/srimports.go	Mon Jul 15 17:09:01 2019 +0200
@@ -97,6 +97,19 @@
 		sr.Bottleneck = &v
 	}
 
+	if v := req.FormValue("negate-z"); v != "" {
+		var negateZ bool
+		switch strings.ToLower(v) {
+		case "true", "1":
+			negateZ = true
+		case "false", "0":
+			negateZ = false
+		default:
+			return fmt.Errorf("Unknown negate-z '%s'", v)
+		}
+		sr.NegateZ = &negateZ
+	}
+
 	if v := req.FormValue("single-beam"); v != "" {
 		var singleBeam bool
 		switch strings.ToLower(v) {
--- a/pkg/imports/sr.go	Mon Jul 15 16:58:13 2019 +0200
+++ b/pkg/imports/sr.go	Mon Jul 15 17:09:01 2019 +0200
@@ -60,6 +60,9 @@
 	DepthReference *string `json:"depth-reference,omitempty"`
 	// SingleBeam indicates that the sounding is a single beam scan.
 	SingleBeam *bool `json:"single-beam,omitempty"`
+	// NegateZ indicated that the Z values of thy XYZ input should be
+	// multiplied by -1.
+	NegateZ *bool `json:"negate-z,omitempty"`
 }
 
 const (
@@ -206,10 +209,14 @@
 `
 )
 
-func (sr *SoundingResult) isSingleBeam() bool {
+func (sr *SoundingResult) singleBeam() bool {
 	return sr.SingleBeam != nil && *sr.SingleBeam
 }
 
+func (sr *SoundingResult) negateZ() bool {
+	return sr.NegateZ != nil && *sr.NegateZ
+}
+
 // Do executes the actual sounding result import.
 func (sr *SoundingResult) Do(
 	ctx context.Context,
@@ -249,6 +256,12 @@
 
 	var xform vertexTransform
 
+	if sr.negateZ() {
+		xform = negateZTransform
+	} else {
+		xform = identityTransform
+	}
+
 	if m.DepthReference == "ZPG" {
 		feedback.Info("Found ZPG as reference system -> translating Z values to LDC")
 		var ldc float64
@@ -270,9 +283,11 @@
 
 		// LDC is cm. The data is in m.
 		ldc /= 100
-		xform = func(v octree.Vertex) octree.Vertex {
-			return octree.Vertex{X: v.X, Y: v.Y, Z: v.Z + ldc}
-		}
+		xform = chainTransforms(
+			xform,
+			func(v octree.Vertex) octree.Vertex {
+				return octree.Vertex{X: v.X, Y: v.Y, Z: v.Z + ldc}
+			})
 		m.DepthReference = depthReference
 	}
 
@@ -319,7 +334,7 @@
 
 	var summary interface{}
 
-	if sr.isSingleBeam() {
+	if sr.singleBeam() {
 		summary, err = sr.processScan(
 			ctx,
 			tx,
@@ -655,7 +670,8 @@
 	return sr.Bottleneck != nil &&
 		sr.Date != nil &&
 		sr.DepthReference != nil &&
-		sr.SingleBeam != nil
+		sr.SingleBeam != nil &&
+		sr.NegateZ != nil
 }
 
 func (sr *SoundingResult) loadMeta(f *zip.File) (*models.SoundingResultMeta, error) {
@@ -671,6 +687,8 @@
 			Bottleneck:     *sr.Bottleneck,
 			EPSG:           epsg,
 			DepthReference: *sr.DepthReference,
+			SingleBeam:     sr.singleBeam(),
+			NegateZ:        sr.negateZ(),
 		}, nil
 	}
 	r, err := f.Open()
@@ -699,18 +717,29 @@
 	if sr.SingleBeam != nil {
 		m.SingleBeam = *sr.SingleBeam
 	}
+	if sr.NegateZ != nil {
+		m.NegateZ = *sr.NegateZ
+	}
 
 	return &m, nil
 }
 
 type vertexTransform func(octree.Vertex) octree.Vertex
 
+func identityTransform(v octree.Vertex) octree.Vertex { return v }
+
+func negateZTransform(v octree.Vertex) octree.Vertex {
+	return octree.Vertex{X: v.X, Y: v.Y, Z: -v.Z}
+}
+
+func chainTransforms(a, b vertexTransform) vertexTransform {
+	return func(v octree.Vertex) octree.Vertex { return b(a(v)) }
+}
+
 func loadXYZReader(r io.Reader, feedback Feedback, xform vertexTransform) (octree.MultiPointZ, error) {
 	mpz := make(octree.MultiPointZ, 0, 250000)
 	s := bufio.NewScanner(r)
 
-	var hasNegZ bool
-
 	warnLimiter := misc.WarningLimiter{Log: feedback.Warn, MaxWarnings: 100}
 	warn := warnLimiter.Warn
 	defer warnLimiter.Close()
@@ -743,16 +772,7 @@
 			warn("format error in line %d: %v", line, err)
 			continue
 		}
-		if p.Z < 0 {
-			p.Z = -p.Z
-			if !hasNegZ {
-				hasNegZ = true
-				warn("Negative Z value found: Using -Z")
-			}
-		}
-		if xform != nil {
-			p = xform(p)
-		}
+		p = xform(p)
 		mpz = append(mpz, p)
 	}
 
--- a/pkg/models/sr.go	Mon Jul 15 16:58:13 2019 +0200
+++ b/pkg/models/sr.go	Mon Jul 15 17:09:01 2019 +0200
@@ -32,6 +32,7 @@
 		EPSG           uint   `json:"epsg"`
 		DepthReference string `json:"depth-reference"`
 		SingleBeam     bool   `json:"single-beam"`
+		NegateZ        bool   `json:"negate-z,omitempty"`
 	}
 )