Skip to content

Commit

Permalink
Merge pull request #153 from tschaub/proj
Browse files Browse the repository at this point in the history
Move mercator transforms to Projection.js.
  • Loading branch information
tschaub committed Jan 17, 2012
2 parents 188be77 + 9a6827f commit 974ed29
Show file tree
Hide file tree
Showing 8 changed files with 96 additions and 131 deletions.
8 changes: 0 additions & 8 deletions examples/web-mercator.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,6 @@
// make map available for easy debugging
var map;

// if your application transforms coordinates to and from EPSG:102113 then
// you must uncomment the lines below

// OpenLayers.Projection.addTransform("EPSG:4326", "EPSG:102113",
// OpenLayers.Layer.SphericalMercator.projectForward);
// OpenLayers.Projection.addTransform("EPSG:102113", "EPSG:4326",
// OpenLayers.Layer.SphericalMercator.projectInverse);

function init() {

var options = {
Expand Down
1 change: 0 additions & 1 deletion lib/OpenLayers/Layer/Bing.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@

/**
* @requires OpenLayers/Layer/XYZ.js
* @requires OpenLayers/Layer/SphericalMercator.js
*/

/**
Expand Down
1 change: 0 additions & 1 deletion lib/OpenLayers/Layer/OSM.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@

/**
* @requires OpenLayers/Layer/XYZ.js
* @requires OpenLayers/Layer/SphericalMercator.js
*/

/**
Expand Down
103 changes: 16 additions & 87 deletions lib/OpenLayers/Layer/SphericalMercator.js
Original file line number Diff line number Diff line change
Expand Up @@ -114,14 +114,14 @@ OpenLayers.Layer.SphericalMercator = {
* Returns:
* {<OpenLayers.LonLat>} The coordinates transformed to Mercator.
*/
forwardMercator: function(lon, lat) {
var x = lon * 20037508.34 / 180;
var y = Math.log(Math.tan((90 + lat) * Math.PI / 360)) / (Math.PI / 180);

y = y * 20037508.34 / 180;

return new OpenLayers.LonLat(x, y);
},
forwardMercator: (function() {
var gg = new OpenLayers.Projection("EPSG:4326");
var sm = new OpenLayers.Projection("EPSG:900913");
return function(lon, lat) {
var point = OpenLayers.Projection.transform({x: lon, y: lat}, gg, sm);
return new OpenLayers.LonLat(point.x, point.y);
};
})(),

/**
* APIMethod: inverseMercator
Expand All @@ -134,84 +134,13 @@ OpenLayers.Layer.SphericalMercator = {
* Returns:
* {<OpenLayers.LonLat>} The coordinates transformed to EPSG:4326.
*/
inverseMercator: function(x, y) {

var lon = (x / 20037508.34) * 180;
var lat = (y / 20037508.34) * 180;

lat = 180/Math.PI * (2 * Math.atan(Math.exp(lat * Math.PI / 180)) - Math.PI / 2);

return new OpenLayers.LonLat(lon, lat);
},

/**
* Method: projectForward
* Given an object with x and y properties in EPSG:4326, modify the x,y
* properties on the object to be the Spherical Mercator projected
* coordinates.
*
* Parameters:
* point - {Object} An object with x and y properties.
*
* Returns:
* {Object} The point, with the x and y properties transformed to spherical
* mercator.
*/
projectForward: function(point) {
var lonlat = OpenLayers.Layer.SphericalMercator.forwardMercator(point.x, point.y);
point.x = lonlat.lon;
point.y = lonlat.lat;
return point;
},

/**
* Method: projectInverse
* Given an object with x and y properties in Spherical Mercator, modify
* the x,y properties on the object to be the unprojected coordinates.
*
* Parameters:
* point - {Object} An object with x and y properties.
*
* Returns:
* {Object} The point, with the x and y properties transformed from
* spherical mercator to unprojected coordinates..
*/
projectInverse: function(point) {
var lonlat = OpenLayers.Layer.SphericalMercator.inverseMercator(point.x, point.y);
point.x = lonlat.lon;
point.y = lonlat.lat;
return point;
}
inverseMercator: (function() {
var gg = new OpenLayers.Projection("EPSG:4326");
var sm = new OpenLayers.Projection("EPSG:900913");
return function(x, y) {
var point = OpenLayers.Projection.transform({x: x, y: y}, sm, gg);
return new OpenLayers.LonLat(point.x, point.y);
};
})()

};

/**
* Note: Transforms for web mercator <-> EPSG:4326
* OpenLayers recognizes EPSG:3857, EPSG:900913, EPSG:102113 and EPSG:102100.
* OpenLayers originally started referring to EPSG:900913 as web mercator.
* The EPSG has declared EPSG:3857 to be web mercator.
* ArcGIS 10 recognizes the EPSG:3857, EPSG:102113, and EPSG:102100 as
* equivalent. See http://blogs.esri.com/Dev/blogs/arcgisserver/archive/2009/11/20/ArcGIS-Online-moving-to-Google-_2F00_-Bing-tiling-scheme_3A00_-What-does-this-mean-for-you_3F00_.aspx#12084
*/
(function() {

// list of equivalent codes for web mercator
var codes = ["EPSG:900913", "EPSG:3857", "EPSG:102113", "EPSG:102100"];

var add = OpenLayers.Projection.addTransform;
var merc = OpenLayers.Layer.SphericalMercator;
var same = OpenLayers.Projection.nullTransform;

var i, len, code, other, j;
for (i=0, len=codes.length; i<len; ++i) {
code = codes[i];
add("EPSG:4326", code, merc.projectForward);
add(code, "EPSG:4326", merc.projectInverse);
for (j=i+1; j<len; ++j) {
other = codes[j];
add(code, other, same);
add(other, code, same);
}
}

})();
79 changes: 67 additions & 12 deletions lib/OpenLayers/Projection.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,21 @@
*/

/**
* Class: OpenLayers.Projection
* Class for coordinate transforms between coordinate systems.
* Depends on the proj4js library. If proj4js is not available,
* then this is just an empty stub.
* Namespace: OpenLayers.Projection
* Methods for coordinate transforms between coordinate systems. By default,
* OpenLayers ships with the ability to transform coordinates between
* geographic (EPSG:4326) and web or spherical mercator (EPSG:900913 et al.)
* coordinate reference systems. See the <transform> method for details
* on usage.
*
* Additional transforms may be added by using the <proj4js at http://proj4js.org/>
* library. If the proj4js library is included, the <transform> method
* will work between any two coordinate reference systems with proj4js
* definitions.
*
* If the proj4js library is not included, or if you wish to allow transforms
* between arbitrary coordinate reference systems, use the <addTransform>
* method to register a custom transform method.
*/
OpenLayers.Projection = OpenLayers.Class({

Expand Down Expand Up @@ -195,10 +206,14 @@ OpenLayers.Projection.transform = function(point, source, dest) {
}
if (source.proj && dest.proj) {
point = Proj4js.transform(source.proj, dest.proj, point);
} else if (OpenLayers.Projection.transforms[source.getCode()] &&
OpenLayers.Projection.transforms[source.getCode()][dest.getCode()]) {
OpenLayers.Projection.transforms[source.getCode()][dest.getCode()](point);
}
} else {
var sourceCode = source.getCode();
var destCode = dest.getCode();
var transforms = OpenLayers.Projection.transforms;
if (transforms[sourceCode] && transforms[sourceCode][destCode]) {
transforms[sourceCode][destCode](point);
}
}
}
return point;
};
Expand All @@ -209,10 +224,6 @@ OpenLayers.Projection.transform = function(point, source, dest) {
* proj4js is not available:
*
* (code)
* OpenLayers.Projection.addTransform("EPSG:4326", "EPSG:3857",
* OpenLayers.Layer.SphericalMercator.projectForward);
* OpenLayers.Projection.addTransform("EPSG:3857", "EPSG:3857",
* OpenLayers.Layer.SphericalMercator.projectInverse);
* OpenLayers.Projection.addTransform("EPSG:3857", "EPSG:900913",
* OpenLayers.Projection.nullTransform);
* OpenLayers.Projection.addTransform("EPSG:900913", "EPSG:3857",
Expand All @@ -222,3 +233,47 @@ OpenLayers.Projection.transform = function(point, source, dest) {
OpenLayers.Projection.nullTransform = function(point) {
return point;
};

/**
* Note: Transforms for web mercator <-> EPSG:4326
* OpenLayers recognizes EPSG:3857, EPSG:900913, EPSG:102113 and EPSG:102100.
* OpenLayers originally started referring to EPSG:900913 as web mercator.
* The EPSG has declared EPSG:3857 to be web mercator.
* ArcGIS 10 recognizes the EPSG:3857, EPSG:102113, and EPSG:102100 as
* equivalent. See http://blogs.esri.com/Dev/blogs/arcgisserver/archive/2009/11/20/ArcGIS-Online-moving-to-Google-_2F00_-Bing-tiling-scheme_3A00_-What-does-this-mean-for-you_3F00_.aspx#12084
*/
(function() {

var pole = 20037508.34;

function inverseMercator(xy) {
xy.x = 180 * xy.x / pole;
xy.y = 180 / Math.PI * (2 * Math.atan(Math.exp((xy.y / pole) * Math.PI)) - Math.PI / 2);
return xy;
}

function forwardMercator(xy) {
xy.x = xy.x * pole / 180;
xy.y = Math.log(Math.tan((90 + xy.y) * Math.PI / 360)) / Math.PI * pole;
return xy;
}

// list of equivalent codes for web mercator
var codes = ["EPSG:900913", "EPSG:3857", "EPSG:102113", "EPSG:102100"];

var add = OpenLayers.Projection.addTransform;
var same = OpenLayers.Projection.nullTransform;

var i, len, code, other, j;
for (i=0, len=codes.length; i<len; ++i) {
code = codes[i];
add("EPSG:4326", code, forwardMercator);
add(code, "EPSG:4326", inverseMercator);
for (j=i+1; j<len; ++j) {
other = codes[j];
add(code, other, same);
add(other, code, same);
}
}

})();
6 changes: 6 additions & 0 deletions notes/2.12.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,12 @@ Without the WKT format included (by default), the `OpenLayers.Geometry::toString

`Layer.OSM` is now defined in its own script file, namely `OpenLayers/Layer/OSM.js`. So people using `Layer.OSM` should now include `OpenLayers/Layer/OSM.js`, as opposed to `OpenLayers/Layer/XYZ.js`, in their OpenLayers builds. (See https://github.com/openlayers/openlayers/issues/138)

## Projection & SphericalMercator

In previous releases, coordinate transforms between EPSG:4326 and EPSG:900913 were defined in the SphericalMercator.js script. In 2.12, these default transforms are included in the Projection.js script. The Projection.js script is included as a dependency in builds with any layer types, so no special build configuration is necessary to get the web mercator transforms.

If you were previously using the `OpenLayers.Layer.SphericalMercator.forwardMercator` or `inverseMercator` methods, you may have to explicitly include the SphericalMercator.js script in your build. The Google layer is the only layer that depends on the SphericalMercator mixin. If you are not using the Google layer but want to use the SphericalMercator methods listed above, you have to explicitly include the SphericalMercator.js script in your build.

## QueryStringFilter

`OpenLayers.Protocol.HTTP` no longer requires `OpenLayers.Format.QueryStringFilter`. It you need this, make sure it is included in your build config file.
Expand Down
6 changes: 1 addition & 5 deletions tests/Layer/Google/v3.html
Original file line number Diff line number Diff line change
Expand Up @@ -65,11 +65,7 @@
// works correctly both ways.
var gLatLng = new google.maps.LatLng(50,100);
// v3 uses sphericalMercator by default
var correspondingOLLonLat = new OpenLayers.LonLat(100,50).transform(
new OpenLayers.Projection("EPSG:4326"),
map.getProjectionObject()
);

var correspondingOLLonLat = layer.forwardMercator(100, 50);

olLonLat = layer.getOLLonLatFromMapObjectLonLat(gLatLng);
t.ok(olLonLat.equals(correspondingOLLonLat), "Translation from GLatLng to OpenLayers.LonLat works");
Expand Down
23 changes: 6 additions & 17 deletions tests/Layer/SphericalMercator.html
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,8 @@
t.eq(sw.lon, -180, "Southwest lon correct");
t.eq(ne.lon, 180, "Northeast lon correct");

t.eq(sw.lat, -85.051128779807, "Southwest lat correct");
t.eq(ne.lat, 85.051128779807, "Northeast lat correct");
t.eq(sw.lat.toFixed(10), "-85.0511287798", "Southwest lat correct");
t.eq(ne.lat.toFixed(10), "85.0511287798", "Northeast lat correct");
}

function strToFixed(str, dig) {
Expand All @@ -51,22 +51,11 @@
});
}

function test_SphericalMercator_projectForward(t) {
t.plan(1);
var point = new OpenLayers.Geometry.Point(10, 20);
OpenLayers.Layer.SphericalMercator.projectForward(point);

t.eq(strToFixed(point.toString()),
strToFixed("POINT(1113194.9077777779 2273030.9266712805)"),
"point transforms from EPSG:4326 to Spherical Mercator");
}

function test_SphericalMercator_to4326(t) {
t.plan(1);
var point = new OpenLayers.Geometry.Point(1113195, 2273031);
var point = new OpenLayers.Geometry.Point(1113195, 2273031);
point.transform("EPSG:900913", "EPSG:4326");

OpenLayers.Layer.SphericalMercator.projectInverse(point);

t.eq(strToFixed(point.toString()),
strToFixed("POINT(10.000000828446318 20.000000618997227)"),
"point transforms from Spherical Mercator to EPSG:4326");
Expand All @@ -82,9 +71,9 @@
var smerc = OpenLayers.Projection.transforms["EPSG:900913"];
t.ok(smerc instanceof Object, "EPSG:900913 exists in table");

t.ok(wgs84["EPSG:900913"] === OpenLayers.Layer.SphericalMercator.projectForward,
t.ok(typeof(wgs84["EPSG:900913"]) === "function",
"from EPSG:4326 to EPSG:900913 correctly defined");
t.ok(smerc["EPSG:4326"] === OpenLayers.Layer.SphericalMercator.projectInverse,
t.ok(typeof(smerc["EPSG:4326"]) === "function",
"from EPSG:900913 to EPSG:4326 correctly defined");
}

Expand Down

0 comments on commit 974ed29

Please sign in to comment.