Add Geo.multiplier value to expand or compress WebGL coordinate space relative to Pseudo-Mercator metres

pull/1/head
Robin Hawkes 2017-06-03 18:52:19 +01:00
rodzic e2e9ad367b
commit a7d5865028
2 zmienionych plików z 32 dodań i 28 usunięć

Wyświetl plik

@ -11,6 +11,20 @@ Geo.MAX_LATITUDE = 85.0511287798;
Geo.ECC = 0.081819191; Geo.ECC = 0.081819191;
Geo.ECC2 = 0.081819191 * 0.081819191; Geo.ECC2 = 0.081819191 * 0.081819191;
// Multiplier is used to expand or compress the WebGL coordinate space relative
// to the EPSG:3857 / Pseudo-Mercator coordinate space (metres).
//
// This is useful for keeping coordinate calculations to smaller numbers and
// helps increase accuracy of things like the z-buffer, object intersection,
// and camera near and far clipping.
//
// A multiplier of 1 would mean a 1:1 mapping between WebGL and EPSG:3857
// coordinates (1 EPSG:3857 metre === 1 WebGL unit)
//
// A multiplier of 0.1 would mean a 1:0.1 mapping between WebGL and EPSG:3857
// coordinates (1 EPSG:3857 metre === 0.1 WebGL units)
Geo.multiplier = 0.1;
Geo.project = function(latlon) { Geo.project = function(latlon) {
var d = Math.PI / 180; var d = Math.PI / 180;
var max = Geo.MAX_LATITUDE; var max = Geo.MAX_LATITUDE;
@ -38,6 +52,9 @@ Geo.latLonToPoint = function(latlon) {
var projected = Geo.project(latlon); var projected = Geo.project(latlon);
projected.y *= -1; projected.y *= -1;
projected.x *= Geo.multiplier;
projected.y *= Geo.multiplier;
return projected; return projected;
}; };
@ -45,6 +62,10 @@ Geo.latLonToPoint = function(latlon) {
// This just reverses the Y axis to match WebGL // This just reverses the Y axis to match WebGL
Geo.pointToLatLon = function(point) { Geo.pointToLatLon = function(point) {
var _point = Point(point.x, point.y * -1); var _point = Point(point.x, point.y * -1);
_point.x /= Geo.multiplier;
_point.y /= Geo.multiplier;
return Geo.unproject(_point); return Geo.unproject(_point);
}; };
@ -114,36 +135,21 @@ Geo.metresToWorld = function(metres, pointScale) {
// //
// Latitude scale is chosen because it fluctuates more than longitude // Latitude scale is chosen because it fluctuates more than longitude
var projectedMetres = Geo.metresToProjected(metres, pointScale); var projectedMetres = Geo.metresToProjected(metres, pointScale);
return projectedMetres * Geo.multiplier;
var scale = Geo.scale();
// Scale projected metres
var scaledMetres = (scale * projectedMetres);
return scaledMetres;
}; };
// Convert world (WebGL) units to a value in real metres // Convert world (WebGL) units to a value in real metres
Geo.worldToMetres = function(worldUnits, pointScale) { Geo.worldToMetres = function(worldUnits, pointScale) {
var scale = Geo.scale(); var projectedUnits = worldUnits;
var projectedUnits = worldUnits / scale;
var realMetres = Geo.projectedToMetres(projectedUnits, pointScale); var realMetres = Geo.projectedToMetres(projectedUnits, pointScale);
return realMetres; return realMetres / Geo.multiplier;
}; };
// If zoom is provided, returns the map width in pixels for a given zoom // Returns the world width in pixels for a given zoom, assuming tile dimensions
// Else, provides fixed scale value // of 256x256 pixels
Geo.scale = function(zoom) { Geo.scale = function(zoom) {
// If zoom is provided then return scale based on map tile zoom return 256 * Math.pow(2, zoom);
if (zoom >= 0) {
return 256 * Math.pow(2, zoom);
// Else, return fixed scale value to expand projected coordinates from
// their 0 to 1 range into something more practical
} else {
return 1;
}
}; };
// Returns zoom level for a given scale value // Returns zoom level for a given scale value
@ -193,7 +199,7 @@ Geo.distance = function(latlon1, latlon2, accurate) {
}; };
Geo.bounds = (function() { Geo.bounds = (function() {
var d = Geo.R * Math.PI; var d = Geo.R * Math.PI * Geo.multiplier;
return [[-d, -d], [d, d]]; return [[-d, -d], [d, d]];
})(); })();

Wyświetl plik

@ -108,14 +108,12 @@ describe('Geo', () => {
}); });
describe('#scale', () => { describe('#scale', () => {
it('defaults to 1', () => { it('returns scale for given zoom level', () => {
var scale = Geo.scale();
expect(scale).to.equal(1);
});
it('uses the zoom level if provided', () => {
var scale = Geo.scale(1); var scale = Geo.scale(1);
expect(scale).to.equal(512); expect(scale).to.equal(512);
scale = Geo.scale(2);
expect(scale).to.equal(1024);
}); });
}); });