From a170e3fdf6c4dbe1c54a9e7f80a9c87b2b178060 Mon Sep 17 00:00:00 2001 From: crschmidt Date: Fri, 14 Dec 2007 20:45:42 +0000 Subject: [PATCH] Add support for transformation functions without using proj4js, and make the SphericalMercator mixin register two transformations to/from EPSG:900913, EPSG:4326. Thanks to Tim for the feedback and review. (Closes #1210) This allows us to transform points to/from SphericalMercator without proj4js support -- and if other projects need similar functionality, they can write their own custom transformation functions rather than modifying proj4js to support some custom projection. git-svn-id: http://svn.openlayers.org/trunk/openlayers@5410 dc9f47b5-9b13-0410-9fdd-eb0c1a62fdaf --- apidoc_config/Menu.txt | 2 + doc_config/Menu.txt | 2 + lib/OpenLayers.js | 4 +- lib/OpenLayers/Layer/SphericalMercator.js | 50 +++++++++++++++++++ lib/OpenLayers/Projection.js | 61 ++++++++++++++++++++--- tests/Layer/test_SphericalMercator.html | 51 +++++++++++++++++-- 6 files changed, 158 insertions(+), 12 deletions(-) diff --git a/apidoc_config/Menu.txt b/apidoc_config/Menu.txt index 5695a2a992..f0a42af4f2 100644 --- a/apidoc_config/Menu.txt +++ b/apidoc_config/Menu.txt @@ -168,6 +168,8 @@ Group: OpenLayers { File: Box (no auto-title, OpenLayers/Marker/Box.js) } # Group: Marker + File: Projection (no auto-title, OpenLayers/Projection.js) + Group: Popup { File: Popup (OpenLayers/Popup.js) diff --git a/doc_config/Menu.txt b/doc_config/Menu.txt index 8325473734..9493377953 100644 --- a/doc_config/Menu.txt +++ b/doc_config/Menu.txt @@ -168,6 +168,8 @@ Group: OpenLayers { File: Box (no auto-title, OpenLayers/Marker/Box.js) } # Group: Marker + File: Projection (no auto-title, OpenLayers/Projection.js) + Group: Popup { File: Popup (OpenLayers/Popup.js) diff --git a/lib/OpenLayers.js b/lib/OpenLayers.js index 62e153d8c8..91714594dd 100644 --- a/lib/OpenLayers.js +++ b/lib/OpenLayers.js @@ -78,6 +78,7 @@ "Rico/Color.js", "OpenLayers/Ajax.js", "OpenLayers/Events.js", + "OpenLayers/Projection.js", "OpenLayers/Map.js", "OpenLayers/Layer.js", "OpenLayers/Icon.js", @@ -175,8 +176,7 @@ "OpenLayers/Layer/WFS.js", "OpenLayers/Control/MouseToolbar.js", "OpenLayers/Control/NavToolbar.js", - "OpenLayers/Control/EditingToolbar.js", - "OpenLayers/Projection.js" + "OpenLayers/Control/EditingToolbar.js" ); // etc. diff --git a/lib/OpenLayers/Layer/SphericalMercator.js b/lib/OpenLayers/Layer/SphericalMercator.js index 66c031d72e..fff5a372c1 100644 --- a/lib/OpenLayers/Layer/SphericalMercator.js +++ b/lib/OpenLayers/Layer/SphericalMercator.js @@ -1,4 +1,5 @@ /** @requires OpenLayers/Layer.js + * @requires OpenLayers/Projection.js * * Class: OpenLayers.Layer.SphericalMercator * A mixin for layers that wraps up the pieces neccesary to have a coordinate @@ -101,6 +102,55 @@ OpenLayers.Layer.SphericalMercator = { 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: projectForward + * 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; } }; + +/** + * Note: Two transforms declared + * Transforms from EPSG:4326 to EPSG:900913 and from EPSG:900913 to EPSG:4326 + * are set by this class. + */ +OpenLayers.Projection.addTransform("EPSG:4326", "EPSG:900913", + OpenLayers.Layer.SphericalMercator.projectForward); +OpenLayers.Projection.addTransform("EPSG:900913", "EPSG:4326", + OpenLayers.Layer.SphericalMercator.projectInverse); diff --git a/lib/OpenLayers/Projection.js b/lib/OpenLayers/Projection.js index 53cbae45b8..2923c18e1b 100644 --- a/lib/OpenLayers/Projection.js +++ b/lib/OpenLayers/Projection.js @@ -6,7 +6,7 @@ * @requires OpenLayers/Util.js * * Class: OpenLayers.Projection - * Class for coordinate transformations between coordinate systems. + * Class for coordinate transforms between coordinate systems. * Depends on the proj4js library. If proj4js is not available, * then this is just an empty stub. */ @@ -101,22 +101,69 @@ OpenLayers.Projection = OpenLayers.Class({ CLASS_NAME: "OpenLayers.Projection" }); +/** + * Property: transforms + * Transforms is an object, with from properties, each of which may + * have a to property. This allows you to define projections without + * requiring support for proj4js to be included. + * + * This object has keys which correspond to a 'source' projection object. The + * keys should be strings, corresponding to the projection.getCode() value. + * Each source projection object should have a set of destination projection + * keys included in the object. + * + * Each value in the destination object should be a transformation function, + * where the function is expected to be passed an object with a .x and a .y + * property. The function should return the object, with the .x and .y + * transformed according to the transformation function. + * + * Note - Properties on this object should not be set directly. To add a + * transform method to this object, use the method. For an + * example of usage, see the OpenLayers.Layer.SphericalMercator file. + */ +OpenLayers.Projection.transforms = {}; + +/** + * APIMethod: addTransform + * Set a custom transform method between two projections. Use this method in + * cases where the proj4js lib is not available or where custom projections + * need to be handled. + * + * Parameters: + * from - {String} The code for the source projection + * to - {String} the code for the destination projection + * method - {Function} A function that takes a point as an argument and + * transforms that point from the source to the destination projection + * in place. The original point should be modified. + */ +OpenLayers.Projection.addTransform = function(from, to, method) { + if(!OpenLayers.Projection.transforms[from]) { + OpenLayers.Projection.transforms[from] = {}; + } + OpenLayers.Projection.transforms[from][to] = method; +}; + /** * APIMethod: transform - * Read data from a string, and return an object whose type depends on the - * subclass. + * Transform a point coordinate from one projection to another. Note that + * the input point is transformed in place. * * Parameters: - * point - {object} input horizontal coodinate - * sourceProj - {OpenLayers.Projection} source map coordinate system - * destProj - {OpenLayers.Projection} destination map coordinate system + * point - {{OpenLayers.Geometry.Point> | Object} An object with x and y + * properties representing coordinates in those dimensions. + * sourceProj - {OpenLayers.Projection} Source map coordinate system + * destProj - {OpenLayers.Projection} Destination map coordinate system * * Returns: - * point - {object} trasnformed coordinate + * point - {object} A transformed coordinate. The original point is modified. */ OpenLayers.Projection.transform = function(point, source, dest) { if (source.proj && dest.proj) { point = Proj4js.transform(source.proj, dest.proj, point); + } else if (source && dest && + OpenLayers.Projection.transforms[source.getCode()] && + OpenLayers.Projection.transforms[source.getCode()][dest.getCode()]) { + OpenLayers.Projection.transforms[source.getCode()][dest.getCode()](point); } return point; }; diff --git a/tests/Layer/test_SphericalMercator.html b/tests/Layer/test_SphericalMercator.html index bd77422ca9..68f0254b97 100644 --- a/tests/Layer/test_SphericalMercator.html +++ b/tests/Layer/test_SphericalMercator.html @@ -1,9 +1,8 @@ -