Make transform functions work with arrays
Instead of working with ol.Coordinate instances, transform functions work with arrays. This is in anticipation of using transform functions to transform large arrays of vertex coordinate values. The ol.projection.transform and ol.projection.transformWithCodes are slightly more convenient functions for dealing with ol.Coordinate instances. Whether we make this more consistent with the use of functions returned by ol.projection.getTransform is up for discussion.
This commit is contained in:
@@ -8,6 +8,7 @@ goog.require('goog.dom');
|
|||||||
goog.require('goog.events');
|
goog.require('goog.events');
|
||||||
goog.require('goog.events.EventType');
|
goog.require('goog.events.EventType');
|
||||||
goog.require('goog.style');
|
goog.require('goog.style');
|
||||||
|
goog.require('ol.Coordinate');
|
||||||
goog.require('ol.CoordinateFormatType');
|
goog.require('ol.CoordinateFormatType');
|
||||||
goog.require('ol.MapEvent');
|
goog.require('ol.MapEvent');
|
||||||
goog.require('ol.MapEventType');
|
goog.require('ol.MapEventType');
|
||||||
@@ -177,7 +178,8 @@ ol.control.MousePosition.prototype.updateHTML_ = function(pixel) {
|
|||||||
var map = this.getMap();
|
var map = this.getMap();
|
||||||
var coordinate = map.getCoordinateFromPixel(pixel);
|
var coordinate = map.getCoordinateFromPixel(pixel);
|
||||||
if (!goog.isNull(coordinate)) {
|
if (!goog.isNull(coordinate)) {
|
||||||
coordinate = this.transform_(coordinate);
|
var output = this.transform_([coordinate.x, coordinate.y]);
|
||||||
|
coordinate = new ol.Coordinate(output[0], output[1]);
|
||||||
if (goog.isDef(this.coordinateFormat_)) {
|
if (goog.isDef(this.coordinateFormat_)) {
|
||||||
html = this.coordinateFormat_(coordinate);
|
html = this.coordinateFormat_(coordinate);
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
+6
-4
@@ -108,8 +108,10 @@ ol.Extent.prototype.getTopRight = function() {
|
|||||||
* @return {ol.Extent} Extent.
|
* @return {ol.Extent} Extent.
|
||||||
*/
|
*/
|
||||||
ol.Extent.prototype.transform = function(transformFn) {
|
ol.Extent.prototype.transform = function(transformFn) {
|
||||||
var a = transformFn(new ol.Coordinate(this.minX, this.minY));
|
var input = [this.minX, this.minY, this.maxX, this.maxY];
|
||||||
var b = transformFn(new ol.Coordinate(this.maxX, this.maxY));
|
var output = transformFn(input, 2);
|
||||||
return new ol.Extent(Math.min(a.x, b.x), Math.min(a.y, b.y),
|
return new ol.Extent(Math.min(output[0], output[2]),
|
||||||
Math.max(a.x, b.x), Math.max(a.y, b.y));
|
Math.min(output[1], output[3]),
|
||||||
|
Math.max(output[0], output[2]),
|
||||||
|
Math.max(output[1], output[3]));
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -76,11 +76,12 @@ ol.Geolocation.prototype.disposeInternal = function() {
|
|||||||
ol.Geolocation.prototype.handleProjectionChanged_ = function() {
|
ol.Geolocation.prototype.handleProjectionChanged_ = function() {
|
||||||
var projection = this.getProjection();
|
var projection = this.getProjection();
|
||||||
if (goog.isDefAndNotNull(projection)) {
|
if (goog.isDefAndNotNull(projection)) {
|
||||||
this.transformCoords_ = ol.projection.getTransform(
|
this.transformFn_ = ol.projection.getTransform(
|
||||||
ol.projection.getFromCode('EPSG:4326'), projection);
|
ol.projection.getFromCode('EPSG:4326'), projection);
|
||||||
if (!goog.isNull(this.position_)) {
|
if (!goog.isNull(this.position_)) {
|
||||||
|
var output = this.transformFn_([this.position_.x, this.position_.y]);
|
||||||
this.set(ol.GeolocationProperty.POSITION,
|
this.set(ol.GeolocationProperty.POSITION,
|
||||||
this.transformCoords_(this.position_));
|
new ol.Coordinate(output[0], output[1]));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -108,8 +109,9 @@ ol.Geolocation.prototype.positionChange_ = function(position) {
|
|||||||
this.set(ol.GeolocationProperty.HEADING, goog.isNull(coords.heading) ?
|
this.set(ol.GeolocationProperty.HEADING, goog.isNull(coords.heading) ?
|
||||||
undefined : goog.math.toRadians(coords.heading));
|
undefined : goog.math.toRadians(coords.heading));
|
||||||
this.position_ = new ol.Coordinate(coords.longitude, coords.latitude);
|
this.position_ = new ol.Coordinate(coords.longitude, coords.latitude);
|
||||||
|
var output = this.transformFn_([coords.longitude, coords.latitude]);
|
||||||
this.set(ol.GeolocationProperty.POSITION,
|
this.set(ol.GeolocationProperty.POSITION,
|
||||||
this.transformCoords_(this.position_));
|
new ol.Coordinate(output[0], output[1]));
|
||||||
this.set(ol.GeolocationProperty.SPEED,
|
this.set(ol.GeolocationProperty.SPEED,
|
||||||
goog.isNull(coords.speed) ? undefined : coords.speed);
|
goog.isNull(coords.speed) ? undefined : coords.speed);
|
||||||
};
|
};
|
||||||
@@ -230,7 +232,8 @@ goog.exportProperty(
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @private
|
* @private
|
||||||
* @param {ol.Coordinate} coordinate Coordinate.
|
* @param {Array.<number>} input Input coordinate values.
|
||||||
* @return {ol.Coordinate} Coordinate.
|
* @param {number=} opt_dimension Dimension (default is 2).
|
||||||
|
* @return {Array.<number>} Output coordinate values.
|
||||||
*/
|
*/
|
||||||
ol.Geolocation.prototype.transformCoords_ = goog.functions.identity;
|
ol.Geolocation.prototype.transformFn_ = goog.functions.identity;
|
||||||
|
|||||||
+38
-18
@@ -397,14 +397,29 @@ ol.projection.getTransform = function(source, destination) {
|
|||||||
var destinationProj4jsProj = proj4jsDestination.getProj4jsProj();
|
var destinationProj4jsProj = proj4jsDestination.getProj4jsProj();
|
||||||
transform =
|
transform =
|
||||||
/**
|
/**
|
||||||
* @param {ol.Coordinate} coordinate Coordinate.
|
* @param {Array.<number>} input Input coordinate values.
|
||||||
* @return {ol.Coordinate} Coordinate.
|
* @param {number=} opt_dimension Dimension.
|
||||||
|
* @return {Array.<number>} Output coordinate values.
|
||||||
*/
|
*/
|
||||||
function(coordinate) {
|
function(input, opt_dimension) {
|
||||||
var proj4jsPoint = new Proj4js.Point(coordinate.x, coordinate.y);
|
var length = input.length,
|
||||||
proj4jsPoint = Proj4js.transform(
|
dimension = goog.isDef(opt_dimension) ? opt_dimension : 2,
|
||||||
sourceProj4jsProj, destinationProj4jsProj, proj4jsPoint);
|
output, proj4jsPoint;
|
||||||
return new ol.Coordinate(proj4jsPoint.x, proj4jsPoint.y);
|
if (dimension > 2) {
|
||||||
|
// preserve values beyond second dimension
|
||||||
|
output = input.slice();
|
||||||
|
} else {
|
||||||
|
output = new Array(length);
|
||||||
|
}
|
||||||
|
goog.asserts.assert(output.length % dimension === 0);
|
||||||
|
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.projection.addTransform(source, destination, transform);
|
ol.projection.addTransform(source, destination, transform);
|
||||||
}
|
}
|
||||||
@@ -418,7 +433,7 @@ ol.projection.getTransform = function(source, destination) {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Given the projection codes this method searches for a transformation function
|
* Given the projection codes this method searches for a transformation function
|
||||||
* to convert coordinate from the source projection to the destination
|
* to convert a coordinates array from the source projection to the destination
|
||||||
* projection.
|
* projection.
|
||||||
*
|
*
|
||||||
* @param {string} sourceCode Source code.
|
* @param {string} sourceCode Source code.
|
||||||
@@ -433,20 +448,23 @@ ol.projection.getTransformFromCodes = function(sourceCode, destinationCode) {
|
|||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {ol.Coordinate} point Point.
|
* @param {Array.<number>} input Input coordinate array.
|
||||||
* @return {ol.Coordinate} Unaltered point (same reference).
|
* @param {number=} opt_dimension Dimension.
|
||||||
|
* @return {Array.<number>} Input coordinate array (same array as input).
|
||||||
*/
|
*/
|
||||||
ol.projection.identityTransform = function(point) {
|
ol.projection.identityTransform = function(input, opt_dimension) {
|
||||||
return point;
|
return input;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {ol.Coordinate} point Point.
|
* @param {Array.<number>} input Input coordinate array.
|
||||||
* @return {ol.Coordinate} Equal point (different reference).
|
* @param {number=} opt_dimension Dimension.
|
||||||
|
* @return {Array.<number>} Output coordinate array (new array, same coordinate
|
||||||
|
* values).
|
||||||
*/
|
*/
|
||||||
ol.projection.cloneTransform = function(point) {
|
ol.projection.cloneTransform = function(input, opt_dimension) {
|
||||||
return new ol.Coordinate(point.x, point.y);
|
return input.slice();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@@ -460,7 +478,8 @@ ol.projection.cloneTransform = function(point) {
|
|||||||
*/
|
*/
|
||||||
ol.projection.transform = function(point, source, destination) {
|
ol.projection.transform = function(point, source, destination) {
|
||||||
var transformFn = ol.projection.getTransform(source, destination);
|
var transformFn = ol.projection.getTransform(source, destination);
|
||||||
return transformFn(point);
|
var output = transformFn([point.x, point.y]);
|
||||||
|
return new ol.Coordinate(output[0], output[1]);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@@ -474,5 +493,6 @@ ol.projection.transformWithCodes =
|
|||||||
function(point, sourceCode, destinationCode) {
|
function(point, sourceCode, destinationCode) {
|
||||||
var transformFn = ol.projection.getTransformFromCodes(
|
var transformFn = ol.projection.getTransformFromCodes(
|
||||||
sourceCode, destinationCode);
|
sourceCode, destinationCode);
|
||||||
return transformFn(point);
|
var output = transformFn([point.x, point.y]);
|
||||||
|
return new ol.Coordinate(output[0], output[1]);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
goog.provide('ol.projection.EPSG3857');
|
goog.provide('ol.projection.EPSG3857');
|
||||||
|
|
||||||
goog.require('goog.array');
|
goog.require('goog.array');
|
||||||
goog.require('ol.Coordinate');
|
|
||||||
goog.require('ol.Extent');
|
goog.require('ol.Extent');
|
||||||
goog.require('ol.Projection');
|
goog.require('ol.Projection');
|
||||||
goog.require('ol.ProjectionUnits');
|
goog.require('ol.ProjectionUnits');
|
||||||
@@ -73,26 +72,52 @@ ol.projection.EPSG3857.PROJECTIONS = goog.array.map(
|
|||||||
/**
|
/**
|
||||||
* Transformation from EPSG:4326 to EPSG:3857.
|
* Transformation from EPSG:4326 to EPSG:3857.
|
||||||
*
|
*
|
||||||
* @param {ol.Coordinate} point Point.
|
* @param {Array.<number>} input Input array of coordinate values.
|
||||||
* @return {ol.Coordinate} Point.
|
* @param {number=} opt_dimension Dimension (default is 2).
|
||||||
|
* @return {Array.<number>} Output array of coordinate values.
|
||||||
*/
|
*/
|
||||||
ol.projection.EPSG3857.fromEPSG4326 = function(point) {
|
ol.projection.EPSG3857.fromEPSG4326 = function(input, opt_dimension) {
|
||||||
var x = ol.projection.EPSG3857.RADIUS * Math.PI * point.x / 180;
|
var length = input.length,
|
||||||
var y = ol.projection.EPSG3857.RADIUS *
|
dimension = goog.isDef(opt_dimension) ? opt_dimension : 2,
|
||||||
Math.log(Math.tan(Math.PI * (point.y + 90) / 360));
|
output;
|
||||||
return new ol.Coordinate(x, y);
|
if (dimension > 2) {
|
||||||
|
// preserve values beyond second dimension
|
||||||
|
output = input.slice();
|
||||||
|
} else {
|
||||||
|
output = new Array(length);
|
||||||
|
}
|
||||||
|
goog.asserts.assert(output.length % dimension === 0);
|
||||||
|
for (var i = 0; i < length; i += dimension) {
|
||||||
|
output[i] = ol.projection.EPSG3857.RADIUS * Math.PI * input[i] / 180;
|
||||||
|
output[i + 1] = ol.projection.EPSG3857.RADIUS *
|
||||||
|
Math.log(Math.tan(Math.PI * (input[i + 1] + 90) / 360));
|
||||||
|
}
|
||||||
|
return output;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Transformation from EPSG:3857 to EPSG:4326.
|
* Transformation from EPSG:3857 to EPSG:4326.
|
||||||
*
|
*
|
||||||
* @param {ol.Coordinate} point Point.
|
* @param {Array.<number>} input Input array of coordinate values.
|
||||||
* @return {ol.Coordinate} Point.
|
* @param {number=} opt_dimension Dimension (default is 2).
|
||||||
|
* @return {Array.<number>} Output array of coordinate values.
|
||||||
*/
|
*/
|
||||||
ol.projection.EPSG3857.toEPSG4326 = function(point) {
|
ol.projection.EPSG3857.toEPSG4326 = function(input, opt_dimension) {
|
||||||
var x = 180 * point.x / (ol.projection.EPSG3857.RADIUS * Math.PI);
|
var length = input.length,
|
||||||
var y = 360 * Math.atan(
|
dimension = goog.isDef(opt_dimension) ? opt_dimension : 2,
|
||||||
Math.exp(point.y / ol.projection.EPSG3857.RADIUS)) / Math.PI - 90;
|
output;
|
||||||
return new ol.Coordinate(x, y);
|
if (dimension > 2) {
|
||||||
|
// preserve values beyond second dimension
|
||||||
|
output = input.slice();
|
||||||
|
} else {
|
||||||
|
output = new Array(length);
|
||||||
|
}
|
||||||
|
goog.asserts.assert(output.length % dimension === 0);
|
||||||
|
for (var i = 0; i < length; i += dimension) {
|
||||||
|
output[i] = 180 * input[i] / (ol.projection.EPSG3857.RADIUS * Math.PI);
|
||||||
|
output[i + 1] = 360 * Math.atan(
|
||||||
|
Math.exp(input[i + 1] / ol.projection.EPSG3857.RADIUS)) / Math.PI - 90;
|
||||||
|
}
|
||||||
|
return output;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,9 +1,11 @@
|
|||||||
goog.provide('ol.TransformFunction');
|
goog.provide('ol.TransformFunction');
|
||||||
|
|
||||||
goog.require('ol.Coordinate');
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @typedef {function(ol.Coordinate): ol.Coordinate}
|
* A transform function accepts an array of input coordinate values and an
|
||||||
|
* optional dimension (default should be 2). The function transforms the
|
||||||
|
* coordinate values and returns an array of the same length as the input.
|
||||||
|
*
|
||||||
|
* @typedef {function(Array.<number>, number=): Array.<number>}
|
||||||
*/
|
*/
|
||||||
ol.TransformFunction;
|
ol.TransformFunction;
|
||||||
|
|||||||
@@ -84,8 +84,8 @@ describe('ol.Extent', function() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('takes arbitrary function', function() {
|
it('takes arbitrary function', function() {
|
||||||
var transformFn = function(coordinate) {
|
var transformFn = function(input) {
|
||||||
return new ol.Coordinate(-coordinate.x, -coordinate.y);
|
return [-input[0], -input[1], -input[2], -input[3]];
|
||||||
};
|
};
|
||||||
var sourceExtent = new ol.Extent(-15, -30, 45, 60);
|
var sourceExtent = new ol.Extent(-15, -30, 45, 60);
|
||||||
var destinationExtent = sourceExtent.transform(transformFn);
|
var destinationExtent = sourceExtent.transform(transformFn);
|
||||||
|
|||||||
@@ -155,10 +155,22 @@ describe('ol.projection', function() {
|
|||||||
var transform = ol.projection.getTransform(sm, gg);
|
var transform = ol.projection.getTransform(sm, gg);
|
||||||
expect(typeof transform).toBe('function');
|
expect(typeof transform).toBe('function');
|
||||||
|
|
||||||
var coordinate = transform(new ol.Coordinate(-12000000, 5000000));
|
var output = transform([-12000000, 5000000]);
|
||||||
|
|
||||||
expect(coordinate.x).toRoughlyEqual(-107.79783409434258, 1e-9);
|
expect(output[0]).toRoughlyEqual(-107.79783409434258, 1e-9);
|
||||||
expect(coordinate.y).toRoughlyEqual(40.91627447067577, 1e-9);
|
expect(output[1]).toRoughlyEqual(40.91627447067577, 1e-9);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('works for longer arrays', function() {
|
||||||
|
var transform = ol.projection.getTransform(sm, gg);
|
||||||
|
expect(typeof transform).toBe('function');
|
||||||
|
|
||||||
|
var output = transform([-12000000, 5000000, -12000000, 5000000]);
|
||||||
|
|
||||||
|
expect(output[0]).toRoughlyEqual(-107.79783409434258, 1e-9);
|
||||||
|
expect(output[1]).toRoughlyEqual(40.91627447067577, 1e-9);
|
||||||
|
expect(output[2]).toRoughlyEqual(-107.79783409434258, 1e-9);
|
||||||
|
expect(output[3]).toRoughlyEqual(40.91627447067577, 1e-9);
|
||||||
});
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
@@ -177,14 +189,54 @@ describe('ol.projection', function() {
|
|||||||
'GOOGLE', 'EPSG:4326');
|
'GOOGLE', 'EPSG:4326');
|
||||||
expect(typeof transform).toBe('function');
|
expect(typeof transform).toBe('function');
|
||||||
|
|
||||||
var coordinate = transform(
|
var output = transform([-626172.13571216376, 6887893.4928337997]);
|
||||||
new ol.Coordinate(-626172.13571216376, 6887893.4928337997));
|
|
||||||
|
|
||||||
expect(coordinate.x).toRoughlyEqual(-5.625, 1e-9);
|
expect(output[0]).toRoughlyEqual(-5.625, 1e-9);
|
||||||
expect(coordinate.y).toRoughlyEqual(52.4827802220782, 1e-9);
|
expect(output[1]).toRoughlyEqual(52.4827802220782, 1e-9);
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('works for longer arrays of coordinate values', function() {
|
||||||
|
var transform = ol.projection.getTransformFromCodes(
|
||||||
|
'GOOGLE', 'EPSG:4326');
|
||||||
|
expect(typeof transform).toBe('function');
|
||||||
|
|
||||||
|
var output = transform([
|
||||||
|
-626172.13571216376, 6887893.4928337997,
|
||||||
|
-12000000, 5000000,
|
||||||
|
-626172.13571216376, 6887893.4928337997
|
||||||
|
]);
|
||||||
|
|
||||||
|
expect(output[0]).toRoughlyEqual(-5.625, 1e-9);
|
||||||
|
expect(output[1]).toRoughlyEqual(52.4827802220782, 1e-9);
|
||||||
|
expect(output[2]).toRoughlyEqual(-107.79783409434258, 1e-9);
|
||||||
|
expect(output[3]).toRoughlyEqual(40.91627447067577, 1e-9);
|
||||||
|
expect(output[4]).toRoughlyEqual(-5.625, 1e-9);
|
||||||
|
expect(output[5]).toRoughlyEqual(52.4827802220782, 1e-9);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('accepts a dimension', function() {
|
||||||
|
var transform = ol.projection.getTransformFromCodes(
|
||||||
|
'GOOGLE', 'EPSG:4326');
|
||||||
|
expect(typeof transform).toBe('function');
|
||||||
|
|
||||||
|
var dimension = 3;
|
||||||
|
var output = transform([
|
||||||
|
-626172.13571216376, 6887893.4928337997, 100,
|
||||||
|
-12000000, 5000000, 200,
|
||||||
|
-626172.13571216376, 6887893.4928337997, 300
|
||||||
|
], dimension);
|
||||||
|
|
||||||
|
expect(output[0]).toRoughlyEqual(-5.625, 1e-9);
|
||||||
|
expect(output[1]).toRoughlyEqual(52.4827802220782, 1e-9);
|
||||||
|
expect(output[2]).toBe(100);
|
||||||
|
expect(output[3]).toRoughlyEqual(-107.79783409434258, 1e-9);
|
||||||
|
expect(output[4]).toRoughlyEqual(40.91627447067577, 1e-9);
|
||||||
|
expect(output[5]).toBe(200);
|
||||||
|
expect(output[6]).toRoughlyEqual(-5.625, 1e-9);
|
||||||
|
expect(output[7]).toRoughlyEqual(52.4827802220782, 1e-9);
|
||||||
|
expect(output[8]).toBe(300);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('ol.projection.removeTransform()', function() {
|
describe('ol.projection.removeTransform()', function() {
|
||||||
@@ -195,7 +247,7 @@ describe('ol.projection', function() {
|
|||||||
it('removes functions cached by addTransform', function() {
|
it('removes functions cached by addTransform', function() {
|
||||||
var foo = new ol.Projection('foo', units, extent);
|
var foo = new ol.Projection('foo', units, extent);
|
||||||
var bar = new ol.Projection('bar', units, extent);
|
var bar = new ol.Projection('bar', units, extent);
|
||||||
var transform = function() {};
|
var transform = function(intput, dimension) {return input};
|
||||||
ol.projection.addTransform(foo, bar, transform);
|
ol.projection.addTransform(foo, bar, transform);
|
||||||
expect(ol.projection.transforms_).not.toBeUndefined();
|
expect(ol.projection.transforms_).not.toBeUndefined();
|
||||||
expect(ol.projection.transforms_.foo).not.toBeUndefined();
|
expect(ol.projection.transforms_.foo).not.toBeUndefined();
|
||||||
|
|||||||
Reference in New Issue
Block a user