-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathgmaps_mercator.js
141 lines (119 loc) · 4.38 KB
/
gmaps_mercator.js
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
function Point(x, y) {
this.x = x;
this.y = y;
}
/** return a copy of this point with coordinates as int */
Point.prototype.floor = function() {
return new Point(this.x>>0, this.y>>0);
}
function LatLng(lat, lng) {
this.lat = lat;
this.lng = lng;
}
LatLng.prototype.clone = function() {
return new LatLng(this.lat, this.lng);
}
var TILE_SIZE = 256;
MercatorProjection.prototype.TILE_SIZE = TILE_SIZE;
function bound(value, opt_min, opt_max) {
if (opt_min != null) value = Math.max(value, opt_min);
if (opt_max != null) value = Math.min(value, opt_max);
return value;
}
function degreesToRadians(deg) {
return deg * (Math.PI / 180);
}
function radiansToDegrees(rad) {
return rad / (Math.PI / 180);
}
function MercatorProjection() {
this.pixelOrigin_ = new Point(TILE_SIZE / 2,
TILE_SIZE / 2);
this.pixelsPerLonDegree_ = TILE_SIZE / 360;
this.pixelsPerLonRadian_ = TILE_SIZE / (2 * Math.PI);
}
MercatorProjection.prototype.fromLatLngToPixel = function(latLng, zoom) {
var p = this.fromLatLngToPoint(latLng);
return this.toPixelCoordinate(p, zoom);
};
MercatorProjection.prototype.fromLatLngToPoint = function(latLng,
opt_point) {
var me = this;
var point = opt_point || new Point(0, 0);
var origin = me.pixelOrigin_;
point.x = origin.x + latLng.lng * me.pixelsPerLonDegree_;
// NOTE(appleton): Truncating to 0.9999 effectively limits latitude to
// 89.189. This is about a third of a tile past the edge of the world
// tile.
var siny = bound(Math.sin(degreesToRadians(latLng.lat)), -0.9999,
0.9999);
point.y = origin.y + 0.5 * Math.log((1 + siny) / (1 - siny)) *
-me.pixelsPerLonRadian_;
return point;
};
MercatorProjection.prototype.fromPointToLatLng = function(point) {
var me = this;
var origin = me.pixelOrigin_;
var lng = (point.x - origin.x) / me.pixelsPerLonDegree_;
var latRadians = (point.y - origin.y) / -me.pixelsPerLonRadian_;
var lat = radiansToDegrees(2 * Math.atan(Math.exp(latRadians)) -
Math.PI / 2);
return new LatLng(lat, lng);
};
MercatorProjection.prototype.tileBBox = function(x, y, zoom) {
var numTiles = 1 << zoom;
var inc = TILE_SIZE/numTiles;
var px = x*TILE_SIZE/numTiles;
var py = y*TILE_SIZE/numTiles;
return [
this.fromPointToLatLng(new Point(px, py + inc)),
this.fromPointToLatLng(new Point(px + inc, py))
];
};
MercatorProjection.prototype.tilePoint = function(x, y, zoom) {
var numTiles = 1 << zoom;
var px = x*TILE_SIZE;
var py = y*TILE_SIZE;
return [px, py];
}
MercatorProjection.prototype.toPixelCoordinate = function(worldCoordinate, zoom) {
var numTiles = 1 << zoom;
return new Point(
worldCoordinate.x * numTiles,
worldCoordinate.y * numTiles);
}
MercatorProjection.prototype.latLngToTilePoint = function(latLng, x, y, zoom) {
var numTiles = 1 << zoom;
var projection = this;
var worldCoordinate = projection.fromLatLngToPoint(latLng);
var pixelCoordinate = new Point(
worldCoordinate.x * numTiles,
worldCoordinate.y * numTiles);
var tp = this.tilePoint(x, y, zoom);
return new Point(
Math.floor(pixelCoordinate.x - tp[0]),
Math.floor(pixelCoordinate.y - tp[1]));
}
MercatorProjection.prototype.pixelToTile = function(pixelCoordinate) {
return new Point(
Math.floor(pixelCoordinate.x / TILE_SIZE),
Math.floor(pixelCoordinate.y / TILE_SIZE));
};
MercatorProjection.prototype.pointToTile = function(point, zoom) {
var numTiles = 1 << zoom;
var pixelCoordinate = new Point(
point.x * numTiles,
point.y * numTiles);
return this.pixelToTile(pixelCoordinate);
};
MercatorProjection.prototype.latLngToTile = function(latLng, zoom) {
var numTiles = 1 << zoom;
var projection = this;
var worldCoordinate = projection.fromLatLngToPoint(latLng);
var pixelCoordinate = new Point(
worldCoordinate.x * numTiles,
worldCoordinate.y * numTiles);
return new Point(
Math.floor(pixelCoordinate.x / TILE_SIZE),
Math.floor(pixelCoordinate.y / TILE_SIZE));
}