Mercurial > gemma
changeset 1897:c78efb1ddb02 dev-pdf-generation
client: pdf-gen: improve scalebar to show nice values
* Add an algorithm to shorten the scale bar to show nice value for the
four parts.
* Remove or disable some debugging console.log() output.
* Disable print of "Scale 1:x" as this would still show fine grained
numbers.
author | Bernhard Reiter <bernhard@intevation.de> |
---|---|
date | Fri, 18 Jan 2019 12:26:08 +0100 |
parents | 3ed036adc80f |
children | 7247ac316cb7 |
files | client/src/components/Pdftool.vue |
diffstat | 1 files changed, 75 insertions(+), 12 deletions(-) [+] |
line wrap: on
line diff
--- a/client/src/components/Pdftool.vue Thu Jan 17 21:48:11 2019 +0100 +++ b/client/src/components/Pdftool.vue Fri Jan 18 12:26:08 2019 +0100 @@ -128,7 +128,6 @@ } // FUTURE: consider margins - console.log(width, height); // dots per mm = dots per inch / (25.4 mm/inch) var pixelsPerMapMillimeter = this.form.resolution / 25.4; @@ -173,7 +172,13 @@ let metersPerPixel = // average meters (reality) per pixel (map) getPointResolution(proj, view.getResolution(), view.getCenter()) * proj.getMetersPerUnit(); - console.log("metersPerPixel = ", metersPerPixel); + // DEBUG console.log("metersPerPixel = ", metersPerPixel); + + let scaleNominator = Math.round( + // the x in 1:x map scale + 1000 * pixelsPerMapMillimeter * metersPerPixel + ); + console.log("scaleNominator = ", scaleNominator); var data = canvas.toDataURL("image/jpeg"); pdf.addImage(data, "JPEG", 0, 0, width, height); @@ -188,9 +193,10 @@ pdf, width - scalebarSize * 5, height - scalebarSize / 2, - scalebarSize, - scalebarSize * pixelsPerMapMillimeter * metersPerPixel + scalebarSize * 4, + scaleNominator ); + /* self.addText( pdf, width - scalebarSize * 5, @@ -198,9 +204,9 @@ 10, "black", 50, - "Scale 1:" + - Math.round(1000 * pixelsPerMapMillimeter * metersPerPixel) + "Scale 1:" + scaleNominator ); + */ //self.addText(pdf, 150, 20, 10, "black", 70, "some text"); self.addNorthArrow(pdf, 15, 8, northarrowSize); pdf.save("map.pdf"); @@ -241,8 +247,64 @@ doc.setFillColor(255, 255, 255); doc.roundedRect(x, y, w, h, 3, 3, "FD"); }, - addScalebar(doc, x, y, size, realLength) { - // realLength as number in meters (reality) + addScalebar(doc, x, y, maxWidth, scaleNominator) { + // maxWidth in mm + // scaleNominator is the x in 1:x of the map scale + + // reduce width until we'll find a nice number for printing + // strategy: + // 1. check which unit prefix we shall use to get [10:10000[ + // 2. using a mapping for the leading digit to get [1:10[ + // 3. select a smaller number which is nicely dividable + // 4. scale up again to get length in paper mm and to be shown + + // from https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/log10#Polyfill + let log10 = + Math.log10 || // more precise, but unsupported by IE + function(x) { + return Math.log(x) * Math.LOG10E; + }; + + let maxLength = maxWidth * scaleNominator; + + let unit = "mm"; + let unitConversionFactor = 0; + if (maxLength > 10e7) { + // >10 km + unit = "km"; + unitConversionFactor = 10e6; + } else if (maxLength > 10e4) { + // >10m + unit = "m"; + unitConversionFactor = 10e3; + } + + maxLength /= unitConversionFactor; + + // DEBUG console.log(maxLength, unit); + let unroundedLength = maxLength; + let numberOfDigits = Math.floor(log10(unroundedLength)); + let factor = Math.pow(10, numberOfDigits); + let mapped = unroundedLength / factor; + // DEBUG console.log(mapped); + + var length = Math.floor(maxLength); // just to have an upper limit + + // manually only use numbers that are very nice to devide by 4 + // note that this is taken into account for rounding later + if (mapped > 8) { + length = 8 * factor; + } else if (mapped > 4) { + length = 4 * factor; + } else if (mapped > 2) { + length = 2 * factor; + } else { + length = factor; + } + + let size = (length * unitConversionFactor) / scaleNominator / 4; + // DEBUG console.log(length, size); + doc.setDrawColor(0, 0, 0); doc.setFillColor(0, 0, 0); doc.rect(x, y, size, 1, "FD"); @@ -254,13 +316,14 @@ doc.rect(x + size * 2, y, size * 2, 1, "FD"); doc.setFontSize(5); doc.text(x, y + 3, "0"); - doc.text(x + size, y + 3, Math.round(realLength).toString()); - doc.text(x + size * 2, y + 3, Math.round(realLength * 2).toString()); + // /4 and could give 2.5. We still round, because of floating point arith doc.text( - x + size * 4, + x + size, y + 3, - Math.round(realLength * 4).toString() + " m" + (Math.round((length * 10) / 4) / 10).toString() ); + doc.text(x + size * 2, y + 3, Math.round(length / 2).toString()); + doc.text(x + size * 4, y + 3, Math.round(length).toString() + " " + unit); }, addNorthArrow(doc, x1, y1, size) {