Created
February 23, 2015 21:36
-
-
Save mojodna/9a4e28ec70e685066c03 to your computer and use it in GitHub Desktop.
Calculate zoom / bounds for target image size
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
"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