Merge pull request #1228 from ahocevar/new-proj4js

Use the new proj4.js
This commit is contained in:
Andreas Hocevar
2014-07-10 13:31:17 +02:00
12 changed files with 366 additions and 413 deletions

View File

@@ -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')

View File

@@ -8,7 +8,7 @@
<link rel="stylesheet" href="../resources/bootstrap/css/bootstrap.min.css" type="text/css">
<link rel="stylesheet" href="../resources/layout.css" type="text/css">
<link rel="stylesheet" href="../resources/bootstrap/css/bootstrap-responsive.min.css" type="text/css">
<title>Tiled WMS with Proj4js projection example</title>
<title>Tiled WMS with custom projection example</title>
</head>
<body>
@@ -31,21 +31,18 @@
<div class="row-fluid">
<div class="span12">
<h4 id="title">Tiled WMS with Proj4js projection example</h4>
<h4 id="title">Tiled WMS with custom projection example</h4>
<p id="shortdesc">Example of two tiled WMS layers (Pixelmap 1:1'000'000 and national parks) using the projection EPSG:21781.</p>
<div id="docs">
<p>See the <a href="wms-custom-proj.js" target="_blank">wms-custom-proj.js source</a> to see how this is done.</p>
</div>
<div id="tags">wms, tile, tilelayer, proj4js, projection</div>
<div id="tags">wms, tile, tilelayer, projection</div>
</div>
</div>
</div>
<script src="jquery.min.js" type="text/javascript"></script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/proj4js/1.1.0/proj4js-compressed.js" type="text/javascript"></script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/proj4js/1.1.0/defs/EPSG21781.js" type="text/javascript"></script>
<script src="../resources/example-behaviour.js" type="text/javascript"></script>
<script src="loader.js?id=wms-custom-proj" type="text/javascript"></script>

View File

@@ -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;
}

View File

@@ -8,7 +8,7 @@
<link rel="stylesheet" href="../resources/bootstrap/css/bootstrap.min.css" type="text/css">
<link rel="stylesheet" href="../resources/layout.css" type="text/css">
<link rel="stylesheet" href="../resources/bootstrap/css/bootstrap-responsive.min.css" type="text/css">
<title>Single image WMS with custom projection example</title>
<title>Single image WMS with Proj4js projection example</title>
</head>
<body>
@@ -31,13 +31,13 @@
<div class="row-fluid">
<div class="span12">
<h4 id="title">Single image WMS with custom projection example</h4>
<h4 id="title">Single image WMS with Proj4js projection example</h4>
<p id="shortdesc">Example of two single image WMS layers.</p>
<div id="docs">
<p>Pixelmap 1:1'000'000 with National Parks overlay using the projection EPSG:21781.</p>
<p>See the <a href="wms-image-custom-proj.js" target="_blank">wms-image-custom-proj.js source</a> to see how this is done.</p>
</div>
<div id="tags">wms, single image, projection</div>
<div id="tags">wms, single image, proj4js, projection</div>
</div>
</div>
@@ -45,8 +45,8 @@
</div>
<script src="jquery.min.js" type="text/javascript"></script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/proj4js/1.1.0/proj4js-compressed.js" type="text/javascript"></script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/proj4js/1.1.0/defs/EPSG21781.js" type="text/javascript"></script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/proj4js/2.2.1/proj4.js" type="text/javascript"></script>
<script src="http://epsg.io/21781.js" type="text/javascript"></script>
<script src="../resources/example-behaviour.js" type="text/javascript"></script>
<script src="loader.js?id=wms-image-custom-proj" type="text/javascript"></script>

View File

@@ -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
})

View File

@@ -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,

View File

@@ -1,92 +1,22 @@
/**
* @externs
* @see http://trac.osgeo.org/proj4js/
* @see http://proj4js.org/
*/
/**
* @type {Object}
* @param {...*} var_args
* @return {undefined|Array.<number>|Object.<{
* forward: function(Array.<number>): Array.<number>,
* inverse: function(Array.<number>): Array.<number>}>}
*/
var Proj4js = {};
var proj4 = function(var_args) {};
/**
* @type {Object.<string, string>}
* @param {string} name
* @param {(string|Object)=} opt_def
* @return {undefined|Object.<string, Object.<{axis: string, units: string,
* to_meter: number}>>}
*/
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) {};

View File

@@ -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"

View File

@@ -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 <transform> 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.<string, ol.Proj4jsProjection_>}
*/
ol.proj.proj4jsProjections_ = {};
/**
* @private
* @type {Object.<string, ol.proj.Projection>}
@@ -332,6 +259,7 @@ ol.proj.transforms_ = {};
* to transform between projections with equal meaning.
*
* @param {Array.<ol.proj.Projection>} 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.<ol.proj.Projection>} 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.<number>} input Input.
* @param {Array.<number>=} opt_output Output.
* @param {number=} opt_dimension Dimension.
* @return {Array.<number>} 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.<number>} input Input coordinate values.
* @param {Array.<number>=} opt_output Output array of coordinates.
* @param {number=} opt_dimension Dimension.
* @return {Array.<number>} 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);
};

View File

@@ -13,6 +13,7 @@
<script type="text/javascript" src="../node_modules/expect.js/index.js"></script>
<script type="text/javascript" src="../node_modules/sinon/pkg/sinon.js"></script>
<script type="text/javascript" src="../node_modules/mocha/mocha.js"></script>
<script type="text/javascript" src="../node_modules/proj4/dist/proj4.js"></script>
<script type="text/javascript" src="test-extensions.js"></script>
<script>
mocha.setup({
@@ -20,7 +21,6 @@
bail: false
});
</script>
<script type="text/javascript" src="../build/proj4js/lib/proj4js-combined.js"></script>
<!-- This script is provided by the debug server (start with `build.py serve`) -->
<script type="text/javascript" src="loader.js"></script>

View File

@@ -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 {

View File

@@ -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();
});
});
});