diff --git a/src/ol/proj/epsg21781projection.exports b/src/ol/proj/epsg21781projection.exports new file mode 100644 index 0000000000..e91fe6f3d5 --- /dev/null +++ b/src/ol/proj/epsg21781projection.exports @@ -0,0 +1,2 @@ +@exportSymbol ol.proj.EPSG21781 +@exportSymbol ol.proj.EPSG21781.add diff --git a/src/ol/proj/epsg21781projection.js b/src/ol/proj/epsg21781projection.js new file mode 100644 index 0000000000..2f064f4fd6 --- /dev/null +++ b/src/ol/proj/epsg21781projection.js @@ -0,0 +1,143 @@ +goog.provide('ol.proj.EPSG21781'); + +goog.require('goog.asserts'); +goog.require('ol.Projection'); +goog.require('ol.ProjectionUnits'); +goog.require('ol.proj'); +goog.require('ol.proj.EPSG4326'); + + + +/** + * @constructor + * @extends {ol.Projection} + */ +ol.proj.EPSG21781 = function() { + goog.base(this, { + code: 'EPSG:21781', + units: ol.ProjectionUnits.METERS, + extent: ol.proj.EPSG21781.EXTENT, + global: false + }); +}; +goog.inherits(ol.proj.EPSG21781, ol.Projection); + + +/** + * @const + * @type {ol.Extent} + */ +ol.proj.EPSG21781.EXTENT = [485869.5728, 837076.5648, 76443.1884, 299941.7864]; + + +/** + * FIXME empty description for jsdoc + */ +ol.proj.EPSG21781.add = function() { + ol.proj.addEquivalentProjections(ol.proj.EPSG4326.PROJECTIONS); + var epsg21781 = new ol.proj.EPSG21781(); + ol.proj.addProjection(epsg21781); + ol.proj.addEquivalentTransforms( + ol.proj.EPSG4326.PROJECTIONS, + [epsg21781], + ol.proj.EPSG21781.fromEPSG4326, + ol.proj.EPSG21781.toEPSG4326); +}; + + +/** + * Transformation from EPSG:4326 to EPSG:21781. + * + * @see http://www.swisstopo.admin.ch/internet/swisstopo/en/home/products/software/products/skripts.html + * + * @param {Array.} input Input array of coordinate values. + * @param {Array.=} opt_output Output array of coordinate values. + * @param {number=} opt_dimension Dimension (default is 2). + * @return {Array.} Output array of coordinate values. + */ +ol.proj.EPSG21781.fromEPSG4326 = function(input, opt_output, opt_dimension) { + var n = input.length; + var dimension = goog.isDef(opt_dimension) ? opt_dimension : 2; + var output; + if (goog.isDef(opt_output)) { + output = opt_output; + } else { + if (dimension > 2) { + output = input.slice(); + } else { + output = new Array(n); + } + } + goog.asserts.assert(dimension >= 2); + goog.asserts.assert(output.length % dimension === 0); + var auxLat, auxLon, i; + for (i = 0; i < n; i += dimension) { + auxLat = 36 * input[i + 1] / 100 - 16.902866; + auxLon = 36 * input[i] / 100 - 2.67825; + output[i] = 600072.37 + + 211455.93 * auxLon - + 10938.51 * auxLon * auxLat - + 0.36 * auxLon * auxLat * auxLat - + 44.54 * auxLon * auxLon * auxLon; + output[i + 1] = 200147.07 + + 308807.95 * auxLat + + 3745.25 * auxLon * auxLon + + 76.63 * auxLat * auxLat - + 194.56 * auxLon * auxLon * auxLat + + 119.79 * auxLat * auxLat * auxLat; + } + return output; +}; + + +/** + * Transformation from EPSG:21781 to EPSG:4326. + * + * @see http://www.swisstopo.admin.ch/internet/swisstopo/en/home/products/software/products/skripts.html + * + * @param {Array.} input Input array of coordinate values. + * @param {Array.=} opt_output Output array of coordinate values. + * @param {number=} opt_dimension Dimension (default is 2). + * @return {Array.} Output array of coordinate values. + */ +ol.proj.EPSG21781.toEPSG4326 = function(input, opt_output, opt_dimension) { + var n = input.length; + var dimension = goog.isDef(opt_dimension) ? opt_dimension : 2; + var output; + if (goog.isDef(opt_output)) { + output = opt_output; + } else { + if (dimension > 2) { + output = input.slice(); + } else { + output = new Array(n); + } + } + goog.asserts.assert(dimension >= 2); + goog.asserts.assert(output.length % dimension === 0); + var auxX, auxY, i; + for (i = 0; i < n; i += dimension) { + auxY = (input[i] - 600000) / 1000000; + auxX = (input[i + 1] - 200000) / 1000000; + output[i] = 100 * (2.6779094 + + 4.728982 * auxY + + 0.791484 * auxY * auxX + + 0.1306 * auxY * auxX * auxX - + 0.0436 * auxY * auxY * auxY) / 36; + output[i + 1] = 100 * (16.9023892 + + 3.238272 * auxX - + 0.270978 * auxY * auxY - + 0.002528 * auxX * auxX - + 0.0447 * auxY * auxY * auxX - + 0.014 * auxX * auxX * auxX) / 36; + } + return output; +}; + + +/** + * @inheritDoc + */ +ol.proj.EPSG21781.prototype.getPointResolution = function(resolution, point) { + return resolution; +}; diff --git a/test/spec/ol/proj/epsg21781projection.test.js b/test/spec/ol/proj/epsg21781projection.test.js new file mode 100644 index 0000000000..a5f475c001 --- /dev/null +++ b/test/spec/ol/proj/epsg21781projection.test.js @@ -0,0 +1,50 @@ +goog.provide('ol.test.proj.EPSG21781'); + + +describe('ol.proj.EPSG21781', function() { + + var epsg21781; + beforeEach(function() { + ol.proj.EPSG21781.add(); + epsg21781 = ol.proj.get('EPSG:21781'); + expect(epsg21781).to.be.an(ol.Projection); + }); + + it('does not lose too much accuracy when round-tripping', function() { + var extent = epsg21781.getExtent(); + var roundTripped, x, y; + for (x = extent[0]; x < extent[1]; x += 50000) { + for (y = extent[2]; y < extent[3]; y += 50000) { + roundTripped = ol.proj.EPSG21781.fromEPSG4326( + ol.proj.EPSG21781.toEPSG4326([x, y])); + expect(roundTripped).to.be.an(Array); + expect(roundTripped).to.have.length(2); + expect(roundTripped[0]).to.roughlyEqual(x, 1e1); + expect(roundTripped[1]).to.roughlyEqual(y, 1e1); + } + } + }); + + it('transforms from EPSG:21781 to EPSG:4326', function() { + var wgs84 = ol.proj.transform( + [660389.515487, 185731.630396], 'EPSG:21781', 'EPSG:4326'); + expect(wgs84).to.be.an(Array); + expect(wgs84).to.have.length(2); + expect(wgs84[0]).to.roughlyEqual(8.23, 1e-3); + expect(wgs84[1]).to.roughlyEqual(46.82, 1e-3); + }); + + it('transforms from EPSG:4326 to EPSG:21781', function() { + var ch1903 = ol.proj.transform([8.23, 46.82], 'EPSG:4326', 'EPSG:21781'); + expect(ch1903).to.be.an(Array); + expect(ch1903).to.have.length(2); + expect(ch1903[0]).to.roughlyEqual(660389.515487, 1); + expect(ch1903[1]).to.roughlyEqual(185731.630396, 1); + }); + +}); + + +goog.require('ol.Projection'); +goog.require('ol.proj'); +goog.require('ol.proj.EPSG21781');