diff --git a/build.py b/build.py
index cf7ff7a6b7..b24075599f 100755
--- a/build.py
+++ b/build.py
@@ -128,10 +128,6 @@ SRC = [path
if path.endswith('.js')
if path not in SHADER_SRC]
-PROJ4JS = 'build/proj4js/lib/proj4js-combined.js'
-PROJ4JS_ZIP = 'build/proj4js-1.1.0.zip'
-PROJ4JS_ZIP_MD5 = '17caad64cf6ebc6e6fe62f292b134897'
-
def report_sizes(t):
stringio = StringIO()
@@ -348,7 +344,7 @@ def examples_star_combined_js(name, match):
return Target(name, action=action, dependencies=dependencies)
-@target('serve', PROJ4JS, 'examples')
+@target('serve', 'examples')
def serve(t):
t.run('node', 'tasks/serve.js')
@@ -671,24 +667,7 @@ def check_examples(t):
t.run('%(PHANTOMJS)s', 'bin/check-example.js', example)
-@target(PROJ4JS, PROJ4JS_ZIP)
-def proj4js(t):
- from zipfile import ZipFile
- zf = ZipFile(PROJ4JS_ZIP)
- contents = zf.open('proj4js/lib/proj4js-combined.js').read()
- with open(t.name, 'wb') as f:
- f.write(contents)
-
-
-@target(PROJ4JS_ZIP, clean=False)
-def proj4js_zip(t):
- t.info('downloading %r', t.name)
- t.download('http://download.osgeo.org/proj4js/' +
- os.path.basename(t.name), md5=PROJ4JS_ZIP_MD5)
- t.info('downloaded %r', t.name)
-
-
-@target('test', PROJ4JS, phony=True)
+@target('test', phony=True)
def test(t):
t.run('node', 'tasks/test.js')
diff --git a/examples/wms-custom-proj.html b/examples/wms-custom-proj.html
index 12a1dec0f1..45fe8f8fec 100644
--- a/examples/wms-custom-proj.html
+++ b/examples/wms-custom-proj.html
@@ -8,7 +8,7 @@
-
Tiled WMS with Proj4js projection example
+ Tiled WMS with custom projection example
@@ -31,21 +31,18 @@
-
Tiled WMS with Proj4js projection example
+
Tiled WMS with custom projection example
Example of two tiled WMS layers (Pixelmap 1:1'000'000 and national parks) using the projection EPSG:21781.
-
wms, tile, tilelayer, proj4js, projection
+
wms, tile, tilelayer, projection
-
-
-
diff --git a/examples/wms-custom-proj.js b/examples/wms-custom-proj.js
index 39ba860d2b..e3b5f2920b 100644
--- a/examples/wms-custom-proj.js
+++ b/examples/wms-custom-proj.js
@@ -5,13 +5,41 @@ goog.require('ol.control');
goog.require('ol.control.ScaleLine');
goog.require('ol.layer.Tile');
goog.require('ol.proj');
+goog.require('ol.proj.Projection');
goog.require('ol.source.TileWMS');
-var projection = ol.proj.configureProj4jsProjection({
+
+// By default OpenLayers does not know about the EPSG:21781 (Swiss) projection.
+// So we create a projection instance for EPSG:21781 and pass it to
+// ol.proj.addProjection to make it available to the library.
+
+var projection = new ol.proj.Projection({
code: 'EPSG:21781',
- extent: [485869.5728, 76443.1884, 837076.5648, 299941.7864]
+ // The extent is used to determine zoom level 0. Recommended values for a
+ // projection's validity extent can be found at http://epsg.io/.
+ extent: [485869.5728, 76443.1884, 837076.5648, 299941.7864],
+ units: 'm'
});
+ol.proj.addProjection(projection);
+
+// We also declare EPSG:21781/EPSG:4326 transform functions. These functions
+// are necessary for the ScaleLine control and when calling ol.proj.transform
+// for setting the view's initial center (see below).
+
+ol.proj.addCoordinateTransforms('EPSG:4326', projection,
+ function(coordinate) {
+ return [
+ WGStoCHy(coordinate[1], coordinate[0]),
+ WGStoCHx(coordinate[1], coordinate[0])
+ ];
+ },
+ function(coordinate) {
+ return [
+ CHtoWGSlng(coordinate[0], coordinate[1]),
+ CHtoWGSlat(coordinate[0], coordinate[1])
+ ];
+ });
var extent = [420000, 30000, 900000, 350000];
var layers = [
@@ -61,8 +89,160 @@ var map = new ol.Map({
target: 'map',
view: new ol.View({
projection: projection,
- center: [660000, 190000],
+ center: ol.proj.transform([8.23, 46.86], 'EPSG:4326', 'EPSG:21781'),
extent: extent,
zoom: 2
})
});
+
+
+
+/*
+ * Swiss projection transform functions downloaded from
+ * http://www.swisstopo.admin.ch/internet/swisstopo/en/home/products/software/products/skripts.html
+ */
+
+// Convert WGS lat/long (° dec) to CH y
+function WGStoCHy(lat, lng) {
+
+ // Converts degrees dec to sex
+ lat = DECtoSEX(lat);
+ lng = DECtoSEX(lng);
+
+ // Converts degrees to seconds (sex)
+ lat = DEGtoSEC(lat);
+ lng = DEGtoSEC(lng);
+
+ // Axiliary values (% Bern)
+ var lat_aux = (lat - 169028.66) / 10000;
+ var lng_aux = (lng - 26782.5) / 10000;
+
+ // Process Y
+ var y = 600072.37 +
+ 211455.93 * lng_aux -
+ 10938.51 * lng_aux * lat_aux -
+ 0.36 * lng_aux * Math.pow(lat_aux, 2) -
+ 44.54 * Math.pow(lng_aux, 3);
+
+ return y;
+}
+
+// Convert WGS lat/long (° dec) to CH x
+function WGStoCHx(lat, lng) {
+
+ // Converts degrees dec to sex
+ lat = DECtoSEX(lat);
+ lng = DECtoSEX(lng);
+
+ // Converts degrees to seconds (sex)
+ lat = DEGtoSEC(lat);
+ lng = DEGtoSEC(lng);
+
+ // Axiliary values (% Bern)
+ var lat_aux = (lat - 169028.66) / 10000;
+ var lng_aux = (lng - 26782.5) / 10000;
+
+ // Process X
+ var x = 200147.07 +
+ 308807.95 * lat_aux +
+ 3745.25 * Math.pow(lng_aux, 2) +
+ 76.63 * Math.pow(lat_aux, 2) -
+ 194.56 * Math.pow(lng_aux, 2) * lat_aux +
+ 119.79 * Math.pow(lat_aux, 3);
+
+ return x;
+
+}
+
+
+// Convert CH y/x to WGS lat
+function CHtoWGSlat(y, x) {
+
+ // Converts militar to civil and to unit = 1000km
+ // Axiliary values (% Bern)
+ var y_aux = (y - 600000) / 1000000;
+ var x_aux = (x - 200000) / 1000000;
+
+ // Process lat
+ var lat = 16.9023892 +
+ 3.238272 * x_aux -
+ 0.270978 * Math.pow(y_aux, 2) -
+ 0.002528 * Math.pow(x_aux, 2) -
+ 0.0447 * Math.pow(y_aux, 2) * x_aux -
+ 0.0140 * Math.pow(x_aux, 3);
+
+ // Unit 10000" to 1 " and converts seconds to degrees (dec)
+ lat = lat * 100 / 36;
+
+ return lat;
+
+}
+
+// Convert CH y/x to WGS long
+function CHtoWGSlng(y, x) {
+
+ // Converts militar to civil and to unit = 1000km
+ // Axiliary values (% Bern)
+ var y_aux = (y - 600000) / 1000000;
+ var x_aux = (x - 200000) / 1000000;
+
+ // Process long
+ var lng = 2.6779094 +
+ 4.728982 * y_aux +
+ 0.791484 * y_aux * x_aux +
+ 0.1306 * y_aux * Math.pow(x_aux, 2) -
+ 0.0436 * Math.pow(y_aux, 3);
+
+ // Unit 10000" to 1 " and converts seconds to degrees (dec)
+ lng = lng * 100 / 36;
+
+ return lng;
+
+}
+
+
+// Convert SEX DMS angle to DEC
+function SEXtoDEC(angle) {
+
+ // Extract DMS
+ var deg = parseInt(angle, 10);
+ var min = parseInt((angle - deg) * 100, 10);
+ var sec = (((angle - deg) * 100) - min) * 100;
+
+ // Result in degrees sex (dd.mmss)
+ return deg + (sec / 60 + min) / 60;
+
+}
+
+// Convert DEC angle to SEX DMS
+function DECtoSEX(angle) {
+
+ // Extract DMS
+ var deg = parseInt(angle, 10);
+ var min = parseInt((angle - deg) * 60, 10);
+ var sec = (((angle - deg) * 60) - min) * 60;
+
+ // Result in degrees sex (dd.mmss)
+ return deg + min / 100 + sec / 10000;
+
+}
+
+// Convert Degrees angle to seconds
+function DEGtoSEC(angle) {
+
+ // Extract DMS
+ var deg = parseInt(angle, 10);
+ var min = parseInt((angle - deg) * 100, 10);
+ var sec = (((angle - deg) * 100) - min) * 100;
+
+ // Avoid rounding problems with seconds=0
+ var parts = String(angle).split('.');
+ if (parts.length == 2 && parts[1].length == 2) {
+ min = Number(parts[1]);
+ sec = 0;
+ }
+
+ // Result in degrees sex (dd.mmss)
+ return sec + min * 60 + deg * 3600;
+
+}
diff --git a/examples/wms-image-custom-proj.html b/examples/wms-image-custom-proj.html
index e8c7230996..bbdd94039e 100644
--- a/examples/wms-image-custom-proj.html
+++ b/examples/wms-image-custom-proj.html
@@ -8,7 +8,7 @@
- Single image WMS with custom projection example
+ Single image WMS with Proj4js projection example
@@ -31,13 +31,13 @@
-
Single image WMS with custom projection example
+
Single image WMS with Proj4js projection example
Example of two single image WMS layers.
-
wms, single image, projection
+
wms, single image, proj4js, projection
@@ -45,8 +45,8 @@
-
-
+
+
diff --git a/examples/wms-image-custom-proj.js b/examples/wms-image-custom-proj.js
index d7f0b45f0b..05292d72ae 100644
--- a/examples/wms-image-custom-proj.js
+++ b/examples/wms-image-custom-proj.js
@@ -1,15 +1,21 @@
goog.require('ol.Attribution');
goog.require('ol.Map');
goog.require('ol.View');
+goog.require('ol.control');
+goog.require('ol.control.ScaleLine');
goog.require('ol.layer.Image');
goog.require('ol.proj');
goog.require('ol.source.ImageWMS');
-var projection = ol.proj.configureProj4jsProjection({
- code: 'EPSG:21781',
- extent: [485869.5728, 76443.1884, 837076.5648, 299941.7864]
-});
+// Transparent Proj4js support: ol.proj.get() creates and returns a projection
+// known to Proj4js if it is unknown to OpenLayers, and registers functions to
+// transform between all registered projections.
+// EPSG:21781 is known to Proj4js because its definition was loaded in the html.
+var projection = ol.proj.get('EPSG:21781');
+// The extent is used to determine zoom level 0. Recommended values for a
+// projection's validity extent can be found at http://epsg.io/.
+projection.setExtent([485869.5728, 76443.1884, 837076.5648, 299941.7864]);
var extent = [420000, 30000, 900000, 350000];
var layers = [
@@ -49,12 +55,15 @@ var layers = [
];
var map = new ol.Map({
+ controls: ol.control.defaults().extend([
+ new ol.control.ScaleLine()
+ ]),
layers: layers,
renderer: exampleNS.getRendererFromQueryString(),
target: 'map',
view: new ol.View({
projection: projection,
- center: [660000, 190000],
+ center: ol.proj.transform([8.23, 46.86], 'EPSG:4326', 'EPSG:21781'),
extent: extent,
zoom: 2
})
diff --git a/externs/olx.js b/externs/olx.js
index 4dc7e75a87..59f641f951 100644
--- a/externs/olx.js
+++ b/externs/olx.js
@@ -274,37 +274,6 @@ olx.OverlayOptions.prototype.stopEvent;
olx.OverlayOptions.prototype.insertFirst;
-/**
- * Object literal with config options for the Proj4js projection.
- * @typedef {{code: string,
- * extent: (ol.Extent|undefined),
- * global: (boolean|undefined)}}
- * @api
- */
-olx.Proj4jsProjectionOptions;
-
-
-/**
- * The SRS identifier code, e.g. `EPSG:31256`.
- * @type {string}
- */
-olx.Proj4jsProjectionOptions.prototype.code;
-
-
-/**
- * The validity extent for the SRS.
- * @type {ol.Extent|undefined}
- */
-olx.Proj4jsProjectionOptions.prototype.extent;
-
-
-/**
- * Whether the projection is valid for the whole globe. Default is `false`.
- * @type {boolean|undefined}
- */
-olx.Proj4jsProjectionOptions.prototype.global;
-
-
/**
* Object literal with config options for the projection.
* @typedef {{code: string,
diff --git a/externs/proj4js.js b/externs/proj4js.js
index d91a06b561..aca6cfd8e2 100644
--- a/externs/proj4js.js
+++ b/externs/proj4js.js
@@ -1,92 +1,22 @@
/**
* @externs
- * @see http://trac.osgeo.org/proj4js/
+ * @see http://proj4js.org/
*/
/**
- * @type {Object}
+ * @param {...*} var_args
+ * @return {undefined|Array.|Object.<{
+ * forward: function(Array.): Array.,
+ * inverse: function(Array.): Array.}>}
*/
-var Proj4js = {};
+var proj4 = function(var_args) {};
/**
- * @type {Object.}
+ * @param {string} name
+ * @param {(string|Object)=} opt_def
+ * @return {undefined|Object.>}
*/
-Proj4js.defs;
-
-
-/**
- * @type {function(string)}
- */
-Proj4js.reportError;
-
-
-
-/**
- * @constructor
- * @param {number} x
- * @param {number} y
- */
-Proj4js.Point = function(x, y) {};
-
-
-/**
- * @type {number}
- */
-Proj4js.Point.prototype.x;
-
-
-/**
- * @type {number}
- */
-Proj4js.Point.prototype.y;
-
-
-
-/**
- * @constructor
- * @param {string} srsCode
- * @param {Function=} opt_callback
- */
-Proj4js.Proj = function(srsCode, opt_callback) {};
-
-
-/**
- * @type {string}
- */
-Proj4js.Proj.prototype.axis;
-
-
-/**
- * @type {string}
- */
-Proj4js.Proj.prototype.title;
-
-
-/**
- * @type {string}
- */
-Proj4js.Proj.prototype.units;
-
-
-/**
- * @type {string}
- */
-Proj4js.Proj.prototype.srsCode;
-
-
-/**
- * @type {number}
- */
-Proj4js.Proj.prototype.to_meter;
-
-
-/**
- * @nosideeffects
- * @param {Proj4js.Proj} source
- * @param {Proj4js.Proj} dest
- * @param {Proj4js.Point|{x:number, y:number}} point
- * @return {Proj4js.Point}
- */
-Proj4js.transform = function(source, dest, point) {return null;};
+proj4.defs = function(name, opt_def) {};
diff --git a/package.json b/package.json
index 6f5a267482..dbf6d6f482 100644
--- a/package.json
+++ b/package.json
@@ -31,6 +31,7 @@
"mocha-phantomjs": "~3.5.0",
"nomnom": "~1.6.2",
"phantomjs": "~1.9.7-5",
+ "proj4": "~2.2.1",
"sinon": "~1.10.2",
"temp": "~0.7.0",
"walk": "~2.3.3"
diff --git a/src/ol/proj/proj.js b/src/ol/proj/proj.js
index 421874a57f..bbf004ad04 100644
--- a/src/ol/proj/proj.js
+++ b/src/ol/proj/proj.js
@@ -14,14 +14,6 @@ goog.require('ol.extent');
goog.require('ol.sphere.NORMAL');
-/**
- * Have Proj4js.
- * @const
- * @type {boolean}
- */
-ol.HAVE_PROJ4JS = ol.ENABLE_PROJ4JS && typeof Proj4js == 'object';
-
-
/**
* A projection as {@link ol.proj.Projection}, SRS identifier string or
* undefined.
@@ -62,12 +54,13 @@ ol.proj.METERS_PER_UNIT[ol.proj.Units.METERS] = 1;
* Class 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:3857)
- * coordinate reference systems.
+ * coordinate reference systems. Any transform functions can be added with
+ * {@link ol.proj.addCoordinateTransforms}.
*
- * Additional transforms may be added by using the
- * {@link http://proj4js.org/|proj4js} library. If the proj4js library is
- * included, the method will work between any two coordinate
- * reference systems with proj4js definitions.
+ * Additional transforms may be added by using the {@link http://proj4js.org/}
+ * library. If the proj4js library is loaded, transforms will work between any
+ * coordinate reference systems with proj4js definitions. These definitions can
+ * be obtained from {@link http://epsg.io/}.
*
* @constructor
* @param {olx.ProjectionOptions} options Projection options.
@@ -136,19 +129,6 @@ ol.proj.Projection.prototype.getExtent = function() {
};
-/**
- * Get the resolution of the point in degrees. For projections with degrees as
- * the unit this will simply return the provided resolution. For other
- * projections the point resolution is estimated by transforming the center
- * pixel to EPSG:4326, measuring its width and height on the normal sphere,
- * and taking the average of the width and height.
- * @param {number} resolution Resolution.
- * @param {ol.Coordinate} point Point.
- * @return {number} Point resolution.
- */
-ol.proj.Projection.prototype.getPointResolution = goog.abstractMethod;
-
-
/**
* Get the units of this projection.
* @return {ol.proj.Units} Units.
@@ -209,80 +189,42 @@ ol.proj.Projection.prototype.setDefaultTileGrid = function(tileGrid) {
};
-
/**
- * @constructor
- * @extends {ol.proj.Projection}
- * @param {Proj4js.Proj} proj4jsProj Proj4js projection.
- * @param {olx.Proj4jsProjectionOptions} options Proj4js projection options.
- * @private
- * @struct
+ * Set the validity extent for this projection.
+ * @param {ol.Extent} extent Extent.
+ * @api
*/
-ol.Proj4jsProjection_ = function(proj4jsProj, options) {
-
- var units = /** @type {ol.proj.Units} */ (proj4jsProj.units);
-
- var config = /** @type {olx.ProjectionOptions} */ ({
- units: units,
- axisOrientation: proj4jsProj.axis
- });
- goog.object.extend(config, options);
-
- goog.base(this, config);
-
- /**
- * @private
- * @type {Proj4js.Proj}
- */
- this.proj4jsProj_ = proj4jsProj;
-
- /**
- * @private
- * @type {?ol.TransformFunction}
- */
- this.toEPSG4326_ = null;
-
-};
-goog.inherits(ol.Proj4jsProjection_, ol.proj.Projection);
-
-
-/**
- * @inheritDoc
- */
-ol.Proj4jsProjection_.prototype.getMetersPerUnit = function() {
- var metersPerUnit = this.proj4jsProj_.to_meter;
- if (!goog.isDef(metersPerUnit)) {
- metersPerUnit = ol.proj.METERS_PER_UNIT[this.units_];
- }
- return metersPerUnit;
+ol.proj.Projection.prototype.setExtent = function(extent) {
+ this.extent_ = extent;
};
/**
- * @inheritDoc
+ * Get the resolution of the point in degrees. For projections with degrees as
+ * the unit this will simply return the provided resolution. For other
+ * projections the point resolution is estimated by transforming the center
+ * pixel to EPSG:4326, measuring its width and height on the normal sphere,
+ * and taking the average of the width and height.
+ * @param {number} resolution Resolution.
+ * @param {ol.Coordinate} point Point.
+ * @return {number} Point resolution.
*/
-ol.Proj4jsProjection_.prototype.getPointResolution =
- function(resolution, point) {
+ol.proj.Projection.prototype.getPointResolution = function(resolution, point) {
if (this.getUnits() == ol.proj.Units.DEGREES) {
return resolution;
} else {
// Estimate point resolution by transforming the center pixel to EPSG:4326,
// measuring its width and height on the normal sphere, and taking the
// average of the width and height.
- if (goog.isNull(this.toEPSG4326_)) {
- this.toEPSG4326_ = ol.proj.getTransformFromProjections(
- this, ol.proj.getProj4jsProjectionFromCode_({
- code: 'EPSG:4326',
- extent: null
- }));
- }
+ var toEPSG4326 = ol.proj.getTransformFromProjections(
+ this, ol.proj.get('EPSG:4326'));
var vertices = [
point[0] - resolution / 2, point[1],
point[0] + resolution / 2, point[1],
point[0], point[1] - resolution / 2,
point[0], point[1] + resolution / 2
];
- vertices = this.toEPSG4326_(vertices, vertices, 2);
+ vertices = toEPSG4326(vertices, vertices, 2);
var width = ol.sphere.NORMAL.haversineDistance(
vertices.slice(0, 2), vertices.slice(2, 4));
var height = ol.sphere.NORMAL.haversineDistance(
@@ -298,21 +240,6 @@ ol.Proj4jsProjection_.prototype.getPointResolution =
};
-/**
- * @return {Proj4js.Proj} Proj4js projection.
- */
-ol.Proj4jsProjection_.prototype.getProj4jsProj = function() {
- return this.proj4jsProj_;
-};
-
-
-/**
- * @private
- * @type {Object.}
- */
-ol.proj.proj4jsProjections_ = {};
-
-
/**
* @private
* @type {Object.}
@@ -332,6 +259,7 @@ ol.proj.transforms_ = {};
* to transform between projections with equal meaning.
*
* @param {Array.} projections Projections.
+ * @api
*/
ol.proj.addEquivalentProjections = function(projections) {
ol.proj.addProjections(projections);
@@ -369,28 +297,14 @@ ol.proj.addEquivalentTransforms =
};
-/**
- * @param {ol.Proj4jsProjection_} proj4jsProjection Proj4js projection.
- * @private
- */
-ol.proj.addProj4jsProjection_ = function(proj4jsProjection) {
- var proj4jsProjections = ol.proj.proj4jsProjections_;
- var code = proj4jsProjection.getCode();
- goog.asserts.assert(!goog.object.containsKey(proj4jsProjections, code));
- proj4jsProjections[code] = proj4jsProjection;
-};
-
-
/**
* Add a Projection object to the list of supported projections.
*
- * @param {ol.proj.Projection} projection Projection object.
+ * @param {ol.proj.Projection} projection Projection instance.
* @api
*/
ol.proj.addProjection = function(projection) {
- var projections = ol.proj.projections_;
- var code = projection.getCode();
- projections[code] = projection;
+ ol.proj.projections_[projection.getCode()] = projection;
ol.proj.addTransform(projection, projection, ol.proj.cloneTransform);
};
@@ -399,8 +313,9 @@ ol.proj.addProjection = function(projection) {
* @param {Array.} projections Projections.
*/
ol.proj.addProjections = function(projections) {
+ var addedProjections = [];
goog.array.forEach(projections, function(projection) {
- ol.proj.addProjection(projection);
+ addedProjections.push(ol.proj.addProjection(projection));
});
};
@@ -409,9 +324,6 @@ ol.proj.addProjections = function(projections) {
* FIXME empty description for jsdoc
*/
ol.proj.clearAllProjections = function() {
- if (ol.ENABLE_PROJ4JS) {
- ol.proj.proj4jsProjections_ = {};
- }
ol.proj.projections_ = {};
ol.proj.transforms_ = {};
};
@@ -453,6 +365,66 @@ ol.proj.addTransform = function(source, destination, transformFn) {
};
+/**
+ * Registers coordinate transform functions to convert coordinates between the
+ * source projection and the destination projection.
+ *
+ * @param {ol.proj.ProjectionLike} source Source projection.
+ * @param {ol.proj.ProjectionLike} destination Destination projection.
+ * @param {function(ol.Coordinate): ol.Coordinate} forward The forward transform
+ * function (that is, from the source projection to the destination
+ * projection) that takes a {@link ol.Coordinate} as argument and returns
+ * the transformed {@link ol.Coordinate}.
+ * @param {function(ol.Coordinate): ol.Coordinate} inverse The inverse transform
+ * function (that is, from the destination projection to the source
+ * projection) that takes a {@link ol.Coordinate} as argument and returns
+ * the transformed {@link ol.Coordinate}.
+ * @api
+ */
+ol.proj.addCoordinateTransforms =
+ function(source, destination, forward, inverse) {
+ var sourceProj = ol.proj.get(source);
+ var destProj = ol.proj.get(destination);
+ ol.proj.addTransform(sourceProj, destProj,
+ ol.proj.createTransformFromCoordinateTransform(forward));
+ ol.proj.addTransform(destProj, sourceProj,
+ ol.proj.createTransformFromCoordinateTransform(inverse));
+};
+
+
+/**
+ * Creates a {@link ol.TransformFunction} from a simple 2D coordinate transform
+ * function.
+ * @param {function(ol.Coordinate): ol.Coordinate} transform Coordinate
+ * transform.
+ * @return {ol.TransformFunction} Transform function.
+ */
+ol.proj.createTransformFromCoordinateTransform = function(transform) {
+ return (
+ /**
+ * @param {Array.} input Input.
+ * @param {Array.=} opt_output Output.
+ * @param {number=} opt_dimension Dimension.
+ * @return {Array.} Output.
+ */
+ function(input, opt_output, opt_dimension) {
+ var length = input.length;
+ var dimension = goog.isDef(opt_dimension) ? opt_dimension : 2;
+ var output = goog.isDef(opt_output) ? opt_output : new Array(length);
+ var point, i, j;
+ for (i = 0; i < length; i += dimension) {
+ point = transform([input[i], input[i + 1]]);
+ output[i] = point[0];
+ output[i + 1] = point[1];
+ for (j = dimension - 1; j >= 2; --j) {
+ output[i + j] = input[i + j];
+ }
+ }
+ return output;
+ });
+};
+
+
/**
* Unregisters the conversion function to convert coordinates from the source
* projection to the destination projection. This method is used to clean up
@@ -493,16 +465,43 @@ ol.proj.get = function(projectionLike) {
projection = projectionLike;
} else if (goog.isString(projectionLike)) {
var code = projectionLike;
- projection = ol.proj.projections_[code];
- if (ol.HAVE_PROJ4JS && !goog.isDef(projection)) {
- projection = ol.proj.getProj4jsProjectionFromCode_({
- code: code,
- extent: null
- });
- }
- if (!goog.isDef(projection)) {
- goog.asserts.assert(goog.isDef(projection));
- projection = null;
+ var projections = ol.proj.projections_;
+ projection = projections[code];
+ if (ol.ENABLE_PROJ4JS && !goog.isDef(projection) &&
+ goog.isFunction(proj4)) {
+ var def = proj4.defs(code);
+ if (goog.isDef(def)) {
+ var units = def.units;
+ if (!goog.isDef(units)) {
+ if (goog.isDef(def.to_meter)) {
+ units = def.to_meter.toString();
+ ol.proj.METERS_PER_UNIT[units] = def.to_meter;
+ }
+ }
+ projection = new ol.proj.Projection({
+ code: code,
+ units: units,
+ axisOrientation: def.axis
+ });
+ ol.proj.addProjection(projection);
+ var currentCode, currentDef, currentProj, proj4Transform;
+ for (currentCode in projections) {
+ currentDef = proj4.defs(currentCode);
+ if (goog.isDef(currentDef)) {
+ currentProj = ol.proj.get(currentCode);
+ if (currentDef === def) {
+ ol.proj.addEquivalentProjections([currentProj, projection]);
+ } else {
+ proj4Transform = proj4(currentCode, code);
+ ol.proj.addCoordinateTransforms(currentProj, projection,
+ proj4Transform.forward, proj4Transform.inverse);
+ }
+ }
+ }
+ } else {
+ goog.asserts.assert(goog.isDef(projection));
+ projection = null;
+ }
}
} else {
projection = null;
@@ -511,32 +510,6 @@ ol.proj.get = function(projectionLike) {
};
-/**
- * @param {olx.Proj4jsProjectionOptions} options Proj4js projection options.
- * @private
- * @return {ol.Proj4jsProjection_} Proj4js projection.
- */
-ol.proj.getProj4jsProjectionFromCode_ = function(options) {
- var code = options.code;
- var proj4jsProjections = ol.proj.proj4jsProjections_;
- var proj4jsProjection = proj4jsProjections[code];
- if (!goog.isDef(proj4jsProjection)) {
- var proj4jsProj = new Proj4js.Proj(code);
- var srsCode = proj4jsProj.srsCode;
- proj4jsProjection = proj4jsProjections[srsCode];
- if (!goog.isDef(proj4jsProjection)) {
- var config = /** @type {olx.Proj4jsProjectionOptions} */
- (goog.object.clone(options));
- config.code = srsCode;
- proj4jsProjection = new ol.Proj4jsProjection_(proj4jsProj, config);
- proj4jsProjections[srsCode] = proj4jsProjection;
- }
- proj4jsProjections[code] = proj4jsProjection;
- }
- return proj4jsProjection;
-};
-
-
/**
* Checks if two projections are the same, that is every coordinate in one
* projection does represent the same geographic point as the same coordinate in
@@ -596,61 +569,6 @@ ol.proj.getTransformFromProjections =
goog.object.containsKey(transforms[sourceCode], destinationCode)) {
transform = transforms[sourceCode][destinationCode];
}
- if (ol.HAVE_PROJ4JS && !goog.isDef(transform)) {
- var proj4jsSource;
- if (sourceProjection instanceof ol.Proj4jsProjection_) {
- proj4jsSource = sourceProjection;
- } else {
- proj4jsSource =
- ol.proj.getProj4jsProjectionFromCode_({
- code: sourceCode,
- extent: null
- });
- }
- var sourceProj4jsProj = proj4jsSource.getProj4jsProj();
- var proj4jsDestination;
- if (destinationProjection instanceof ol.Proj4jsProjection_) {
- proj4jsDestination = destinationProjection;
- } else {
- proj4jsDestination =
- ol.proj.getProj4jsProjectionFromCode_({
- code: destinationCode,
- extent: null
- });
- }
- var destinationProj4jsProj = proj4jsDestination.getProj4jsProj();
- transform =
- /**
- * @param {Array.} input Input coordinate values.
- * @param {Array.=} opt_output Output array of coordinates.
- * @param {number=} opt_dimension Dimension.
- * @return {Array.} Output coordinate values.
- */
- function(input, opt_output, opt_dimension) {
- var length = input.length,
- dimension = opt_dimension > 1 ? opt_dimension : 2,
- output = opt_output;
- if (!goog.isDef(output)) {
- if (dimension > 2) {
- // preserve values beyond second dimension
- output = input.slice();
- } else {
- output = new Array(length);
- }
- }
- goog.asserts.assert(output.length % dimension === 0);
- var proj4jsPoint;
- for (var i = 0; i < length; i += dimension) {
- proj4jsPoint = new Proj4js.Point(input[i], input[i + 1]);
- proj4jsPoint = Proj4js.transform(
- sourceProj4jsProj, destinationProj4jsProj, proj4jsPoint);
- output[i] = proj4jsPoint.x;
- output[i + 1] = proj4jsPoint.y;
- }
- return output;
- };
- ol.proj.addTransform(sourceProjection, destinationProjection, transform);
- }
if (!goog.isDef(transform)) {
goog.asserts.assert(goog.isDef(transform));
transform = ol.proj.identityTransform;
@@ -749,15 +667,3 @@ ol.proj.transformWithProjections =
sourceProjection, destinationProjection);
return transformFn(point);
};
-
-
-/**
- * @param {olx.Proj4jsProjectionOptions} options Proj4js projection options.
- * @return {ol.proj.Projection} Proj4js projection.
- * @api
- */
-ol.proj.configureProj4jsProjection = function(options) {
- goog.asserts.assert(!goog.object.containsKey(
- ol.proj.proj4jsProjections_, options.code));
- return ol.proj.getProj4jsProjectionFromCode_(options);
-};
diff --git a/test/index.html b/test/index.html
index 09681d5542..e8400cbaef 100644
--- a/test/index.html
+++ b/test/index.html
@@ -13,6 +13,7 @@
+
-
diff --git a/test/spec/ol/format/wfsformat.test.js b/test/spec/ol/format/wfsformat.test.js
index 87e4873da0..411842bf2f 100644
--- a/test/spec/ol/format/wfsformat.test.js
+++ b/test/spec/ol/format/wfsformat.test.js
@@ -6,6 +6,7 @@ describe('ol.format.WFS', function() {
var features, feature;
before(function(done) {
+ proj4.defs('urn:x-ogc:def:crs:EPSG:4326', proj4.defs('EPSG:4326'));
afterLoadText('spec/ol/format/wfs/topp-states-wfs.xml', function(xml) {
try {
var config = {
@@ -54,6 +55,10 @@ describe('ol.format.WFS', function() {
describe('when parsing FeatureCollection', function() {
var response;
before(function(done) {
+ proj4.defs('EPSG:28992', '+proj=sterea +lat_0=52.15616055555555 ' +
+ '+lon_0=5.38763888888889 +k=0.9999079 +x_0=155000 +y_0=463000 ' +
+ '+ellps=bessel +towgs84=565.417,50.3319,465.552,-0.398957,0.343988,' +
+ '-1.8774,4.0725 +units=m +no_defs');
afterLoadText('spec/ol/format/wfs/boundedBy.xml',
function(xml) {
try {
diff --git a/test/spec/ol/proj/proj.test.js b/test/spec/ol/proj/proj.test.js
index 9cceae83d7..07efbcca59 100644
--- a/test/spec/ol/proj/proj.test.js
+++ b/test/spec/ol/proj/proj.test.js
@@ -128,28 +128,30 @@ describe('ol.proj', function() {
});
it('allows new Proj4js projections to be defined', function() {
- Proj4js.defs['EPSG:21781'] =
+ proj4.defs('EPSG:21781',
'+proj=somerc +lat_0=46.95240555555556 +lon_0=7.439583333333333 ' +
'+k_0=1 +x_0=600000 +y_0=200000 +ellps=bessel ' +
- '+towgs84=674.374,15.056,405.346,0,0,0,0 +units=m +no_defs';
+ '+towgs84=674.374,15.056,405.346,0,0,0,0 +units=m +no_defs');
var point = ol.proj.transform([7.439583333333333, 46.95240555555556],
'EPSG:4326', 'EPSG:21781');
expect(point[0]).to.roughlyEqual(600072.300, 1);
expect(point[1]).to.roughlyEqual(200146.976, 1);
+ delete proj4.defs['EPSG:21781'];
});
it('caches the new Proj4js projections given their srsCode', function() {
- Proj4js.defs['EPSG:21781'] =
+ proj4.defs('EPSG:21781',
'+proj=somerc +lat_0=46.95240555555556 +lon_0=7.439583333333333 ' +
'+k_0=1 +x_0=600000 +y_0=200000 +ellps=bessel ' +
- '+towgs84=674.374,15.056,405.346,0,0,0,0 +units=m +no_defs';
+ '+towgs84=674.374,15.056,405.346,0,0,0,0 +units=m +no_defs');
var code = 'urn:ogc:def:crs:EPSG:21781';
var srsCode = 'EPSG:21781';
+ proj4.defs(code, proj4.defs(srsCode));
var proj = ol.proj.get(code);
- expect(ol.proj.proj4jsProjections_.hasOwnProperty(code)).to.be.ok();
- expect(ol.proj.proj4jsProjections_.hasOwnProperty(srsCode)).to.be.ok();
var proj2 = ol.proj.get(srsCode);
- expect(proj2).to.be(proj);
+ expect(ol.proj.equivalent(proj2, proj)).to.be(true);
+ delete proj4.defs[code];
+ delete proj4.defs[srsCode];
});
it('numerically estimates point scale at the equator', function() {
@@ -186,11 +188,9 @@ describe('ol.proj', function() {
describe('ol.proj.getTransformFromProjections()', function() {
- var sm = ol.proj.get('GOOGLE');
- var gg = ol.proj.get('EPSG:4326');
-
it('returns a transform function', function() {
- var transform = ol.proj.getTransformFromProjections(sm, gg);
+ var transform = ol.proj.getTransformFromProjections(ol.proj.get('GOOGLE'),
+ ol.proj.get('EPSG:4326'));
expect(typeof transform).to.be('function');
var output = transform([-12000000, 5000000]);
@@ -200,7 +200,8 @@ describe('ol.proj', function() {
});
it('works for longer arrays', function() {
- var transform = ol.proj.getTransformFromProjections(sm, gg);
+ var transform = ol.proj.getTransformFromProjections(ol.proj.get('GOOGLE'),
+ ol.proj.get('EPSG:4326'));
expect(typeof transform).to.be('function');
var output = transform([-12000000, 5000000, -12000000, 5000000]);
@@ -318,18 +319,14 @@ describe('ol.proj', function() {
describe('ol.proj.Projection.prototype.getMetersPerUnit()', function() {
beforeEach(function() {
- Proj4js.defs['EPSG:26782'] =
+ proj4.defs('EPSG:26782',
'+proj=lcc +lat_1=29.3 +lat_2=30.7 +lat_0=28.66666666666667 ' +
'+lon_0=-91.33333333333333 +x_0=609601.2192024384 +y_0=0 ' +
- '+ellps=clrk66 +datum=NAD27 +to_meter=0.3048006096012192 +no_defs';
- ol.proj.configureProj4jsProjection({
- code: 'EPSG:26782'
- });
+ '+ellps=clrk66 +datum=NAD27 +to_meter=0.3048006096012192 +no_defs');
});
afterEach(function() {
- ol.proj.proj4jsProjections_ = {};
- delete Proj4js.defs['EPSG:26782'];
+ delete proj4.defs['EPSG:26782'];
});
it('returns value in meters', function() {
@@ -344,26 +341,6 @@ describe('ol.proj', function() {
});
- describe('ol.proj.configureProj4jsProjection()', function() {
-
- beforeEach(function() {
- ol.proj.proj4jsProjections_ = {};
- });
-
- it('returns a configured projection', function() {
- var extent = [485869.5728, 76443.1884, 837076.5648, 299941.7864];
- var epsg21781 = ol.proj.configureProj4jsProjection({
- code: 'EPSG:21781',
- extent: extent
- });
- expect(epsg21781.getCode()).to.eql('EPSG:21781');
- expect(epsg21781.getExtent()).to.be(extent);
- expect(epsg21781.getUnits()).to.be(ol.proj.Units.METERS);
- expect(epsg21781.isGlobal()).to.not.be();
- });
-
- });
-
});