Skip to content

Instantly share code, notes, and snippets.

@mojodna

mojodna/print.js

Created Feb 23, 2015
Embed
What would you like to do?
Calculate zoom / bounds for target image size
"use strict";
var assert = require("assert");
var merc = new (require("sphericalmercator"))();
var BASE_PPI = 72, // native ppi
BASE_ZOOM = 22; // sufficiently large zoom level to use pixels at
var getView = function(options) {
var size = options.size;
if (options.units === "in") {
size = options.size.map(function(x) {
return x * options.ppi;
});
}
if (!(options.bbox || (options.center && options.zoom))) {
throw new Error("An extent or a center + zoom is required");
}
if (options.center && options.zoom) {
var px = merc.px(options.center, options.zoom),
bbox = [px[0] - (size[0] / 2),
px[1] - (size[1] / 2),
px[0] + (size[0] / 2),
px[1] + (size[1] / 2)],
scale = options.ppi / BASE_PPI;
bbox = merc.ll(bbox.slice(0, 2), options.zoom).concat(merc.ll(bbox.slice(2, 4), options.zoom))
.map(function(x) {
return +x.toFixed(8);
});
// flip y coordinates (origin is top-left)
bbox = [bbox[0], bbox[3], bbox[2], bbox[1]];
return {
extents: [bbox],
ppi: options.ppi,
scale: scale,
size: size,
zoom: options.zoom
};
}
if (options.bbox[0] > options.bbox[2]) {
// split the extent into 2 pieces
var left = [options.bbox[0], options.bbox[1], 180, options.bbox[3]],
right = [-180, options.bbox[1], options.bbox[2], options.bbox[3]],
leftWidth = (left[2] - left[0]) / ((left[2] - left[0]) + (right[2] - right[0])) * size[0],
rightWidth = (right[2] - right[0]) / ((left[2] - left[0]) + (right[2] - right[0])) * size[0],
leftView = getView({
bbox: left,
size: [leftWidth, size[1]],
units: options.units,
ppi: options.ppi
}),
rightView = getView({
bbox: right,
size: [rightWidth, size[1]],
units: options.units,
ppi: options.ppi
});
assert.equal(leftView.scale, rightView.scale, "left and right scales should match.");
assert.equal(leftView.zoom, rightView.zoom, "left and right zooms should match.");
return {
extents: [left, right],
ppi: options.ppi,
scale: leftView.scale,
size: size,
zoom: leftView.zoom
};
}
var px = merc.px(options.bbox.slice(0, 2), BASE_ZOOM).concat(merc.px(options.bbox.slice(2, 4), BASE_ZOOM)),
scale = options.ppi / BASE_PPI,
// determine zoom level according to the requested bounding box
zx = (px[2] - px[0]) / (size[0] / scale),
zy = (px[1] - px[3]) / (size[1] / scale), // origin is top-left
zoom = BASE_ZOOM - (Math.log(Math.min(zx, zy)) / Math.log(2)); // constrain to the largest dimension
// return the original size; so, depending on the rendering implementation
// the extent will either be ignored or the image will be scaled
return {
extents: [options.bbox],
ppi: options.ppi,
scale: scale,
size: size,
zoom: zoom
};
};
module.exports.getView = getView;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.