/usr/lib/nodejs/sphericalmercator.js is in node-sphericalmercator 1.0.1-2.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 | var SphericalMercator = (function(){
// Closures including constants and other precalculated values.
var cache = {},
EPSLN = 1.0e-10,
D2R = Math.PI / 180,
R2D = 180 / Math.PI,
// 900913 properties.
A = 6378137,
MAXEXTENT = 20037508.34;
// SphericalMercator constructor: precaches calculations
// for fast tile lookups.
function SphericalMercator(options) {
options = options || {};
this.size = options.size || 256;
if (!cache[this.size]) {
var size = this.size;
var c = cache[this.size] = {};
c.Bc = [];
c.Cc = [];
c.zc = [];
c.Ac = [];
for (var d = 0; d < 30; d++) {
c.Bc.push(size / 360);
c.Cc.push(size / (2 * Math.PI));
c.zc.push(size / 2);
c.Ac.push(size);
size *= 2;
}
}
this.Bc = cache[this.size].Bc;
this.Cc = cache[this.size].Cc;
this.zc = cache[this.size].zc;
this.Ac = cache[this.size].Ac;
};
// Convert lon lat to screen pixel value
//
// - `ll` {Array} `[lon, lat]` array of geographic coordinates.
// - `zoom` {Number} zoom level.
SphericalMercator.prototype.px = function(ll, zoom) {
var d = this.zc[zoom];
var f = Math.min(Math.max(Math.sin(D2R * ll[1]), -0.9999), 0.9999);
var x = Math.round(d + ll[0] * this.Bc[zoom]);
var y = Math.round(d + 0.5 * Math.log((1 + f) / (1 - f)) * (-this.Cc[zoom]));
(x > this.Ac[zoom]) && (x = this.Ac[zoom]);
(y > this.Ac[zoom]) && (y = this.Ac[zoom]);
//(x < 0) && (x = 0);
//(y < 0) && (y = 0);
return [x, y];
};
// Convert screen pixel value to lon lat
//
// - `px` {Array} `[x, y]` array of geographic coordinates.
// - `zoom` {Number} zoom level.
SphericalMercator.prototype.ll = function(px, zoom) {
var g = (px[1] - this.zc[zoom]) / (-this.Cc[zoom]);
var lon = (px[0] - this.zc[zoom]) / this.Bc[zoom];
var lat = R2D * (2 * Math.atan(Math.exp(g)) - 0.5 * Math.PI);
return [lon, lat];
};
// Convert tile xyz value to bbox of the form `[w, s, e, n]`
//
// - `x` {Number} x (longitude) number.
// - `y` {Number} y (latitude) number.
// - `zoom` {Number} zoom.
// - `tms_style` {Boolean} whether to compute using tms-style.
// - `srs` {String} projection for resulting bbox (WGS84|900913).
// - `return` {Array} bbox array of values in form `[w, s, e, n]`.
SphericalMercator.prototype.bbox = function(x, y, zoom, tms_style, srs) {
// Convert xyz into bbox with srs WGS84
if (tms_style) {
y = (Math.pow(2, zoom) - 1) - y;
}
// Use +y to make sure it's a number to avoid inadvertent concatenation.
var ll = [x * this.size, (+y + 1) * this.size]; // lower left
// Use +x to make sure it's a number to avoid inadvertent concatenation.
var ur = [(+x + 1) * this.size, y * this.size]; // upper right
var bbox = this.ll(ll, zoom).concat(this.ll(ur, zoom));
// If web mercator requested reproject to 900913.
if (srs === '900913') {
return this.convert(bbox, '900913');
} else {
return bbox;
}
};
// Convert bbox to xyx bounds
//
// - `bbox` {Number} bbox in the form `[w, s, e, n]`.
// - `zoom` {Number} zoom.
// - `tms_style` {Boolean} whether to compute using tms-style.
// - `srs` {String} projection of input bbox (WGS84|900913).
// - `@return` {Object} XYZ bounds containing minX, maxX, minY, maxY properties.
SphericalMercator.prototype.xyz = function(bbox, zoom, tms_style, srs) {
// If web mercator provided reproject to WGS84.
if (srs === '900913') {
bbox = this.convert(bbox, 'WGS84');
}
var ll = [bbox[0], bbox[1]]; // lower left
var ur = [bbox[2], bbox[3]]; // upper right
var px_ll = this.px(ll, zoom);
var px_ur = this.px(ur, zoom);
// Y = 0 for XYZ is the top hence minY uses px_ur[1].
var bounds = {
minX: Math.floor(px_ll[0] / this.size),
minY: Math.floor(px_ur[1] / this.size),
maxX: Math.floor((px_ur[0] - 1) / this.size),
maxY: Math.floor((px_ll[1] - 1) / this.size)
};
if (tms_style) {
var tms = {
minY: (Math.pow(2, zoom) - 1) - bounds.maxY,
maxY: (Math.pow(2, zoom) - 1) - bounds.minY
};
bounds.minY = tms.minY;
bounds.maxY = tms.maxY;
}
return bounds;
};
// Convert projection of given bbox.
//
// - `bbox` {Number} bbox in the form `[w, s, e, n]`.
// - `to` {String} projection of output bbox (WGS84|900913). Input bbox
// assumed to be the "other" projection.
// - `@return` {Object} bbox with reprojected coordinates.
SphericalMercator.prototype.convert = function(bbox, to) {
if (to === '900913') {
return this.forward(bbox.slice(0, 2)).concat(this.forward(bbox.slice(2,4)));
} else {
return this.inverse(bbox.slice(0, 2)).concat(this.inverse(bbox.slice(2,4)));
}
};
// Convert lon/lat values to 900913 x/y.
SphericalMercator.prototype.forward = function(ll) {
var xy = [
A * ll[0] * D2R,
A * Math.log(Math.tan((Math.PI*0.25) + (0.5 * ll[1] * D2R)))
];
// if xy value is beyond maxextent (e.g. poles), return maxextent.
(xy[0] > MAXEXTENT) && (xy[0] = MAXEXTENT);
(xy[0] < -MAXEXTENT) && (xy[0] = -MAXEXTENT);
(xy[1] > MAXEXTENT) && (xy[1] = MAXEXTENT);
(xy[1] < -MAXEXTENT) && (xy[1] = -MAXEXTENT);
return xy;
};
// Convert 900913 x/y values to lon/lat.
SphericalMercator.prototype.inverse = function(xy) {
return [
(xy[0] * R2D / A),
((Math.PI*0.5) - 2.0 * Math.atan(Math.exp(-xy[1] / A))) * R2D
];
};
return SphericalMercator;
})();
if (typeof module !== 'undefined' && typeof exports !== 'undefined') {
module.exports = exports = SphericalMercator;
}
|