Merge pull request #256 from tschaub/transform-arrays

Updating ol.TransformFunction instances so they work with arrays instead of coordinates.
This commit is contained in:
Tim Schaub
2013-03-03 14:46:22 -08:00
8 changed files with 219 additions and 63 deletions

View File

@@ -8,6 +8,7 @@ goog.require('goog.dom');
goog.require('goog.events');
goog.require('goog.events.EventType');
goog.require('goog.style');
goog.require('ol.Coordinate');
goog.require('ol.CoordinateFormatType');
goog.require('ol.MapEvent');
goog.require('ol.MapEventType');
@@ -177,7 +178,9 @@ ol.control.MousePosition.prototype.updateHTML_ = function(pixel) {
var map = this.getMap();
var coordinate = map.getCoordinateFromPixel(pixel);
if (!goog.isNull(coordinate)) {
coordinate = this.transform_(coordinate);
var vertex = [coordinate.x, coordinate.y];
vertex = this.transform_(vertex, vertex);
coordinate = new ol.Coordinate(vertex[0], vertex[1]);
if (goog.isDef(this.coordinateFormat_)) {
html = this.coordinateFormat_(coordinate);
} else {

View File

@@ -108,8 +108,10 @@ ol.Extent.prototype.getTopRight = function() {
* @return {ol.Extent} Extent.
*/
ol.Extent.prototype.transform = function(transformFn) {
var a = transformFn(new ol.Coordinate(this.minX, this.minY));
var b = transformFn(new ol.Coordinate(this.maxX, this.maxY));
return new ol.Extent(Math.min(a.x, b.x), Math.min(a.y, b.y),
Math.max(a.x, b.x), Math.max(a.y, b.y));
var input = [this.minX, this.minY, this.maxX, this.maxY];
input = transformFn(input, input, 2);
return new ol.Extent(Math.min(input[0], input[2]),
Math.min(input[1], input[3]),
Math.max(input[0], input[2]),
Math.max(input[1], input[3]));
};

View File

@@ -76,11 +76,13 @@ ol.Geolocation.prototype.disposeInternal = function() {
ol.Geolocation.prototype.handleProjectionChanged_ = function() {
var projection = this.getProjection();
if (goog.isDefAndNotNull(projection)) {
this.transformCoords_ = ol.projection.getTransform(
this.transformFn_ = ol.projection.getTransform(
ol.projection.getFromCode('EPSG:4326'), projection);
if (!goog.isNull(this.position_)) {
var vertex = [this.position_.x, this.position_.y];
vertex = this.transformFn_(vertex, vertex, 2);
this.set(ol.GeolocationProperty.POSITION,
this.transformCoords_(this.position_));
new ol.Coordinate(vertex[0], vertex[1]));
}
}
};
@@ -108,8 +110,10 @@ ol.Geolocation.prototype.positionChange_ = function(position) {
this.set(ol.GeolocationProperty.HEADING, goog.isNull(coords.heading) ?
undefined : goog.math.toRadians(coords.heading));
this.position_ = new ol.Coordinate(coords.longitude, coords.latitude);
var vertex = [coords.longitude, coords.latitude];
vertex = this.transformFn_(vertex, vertex, 2);
this.set(ol.GeolocationProperty.POSITION,
this.transformCoords_(this.position_));
new ol.Coordinate(vertex[0], vertex[1]));
this.set(ol.GeolocationProperty.SPEED,
goog.isNull(coords.speed) ? undefined : coords.speed);
};
@@ -230,7 +234,9 @@ goog.exportProperty(
/**
* @private
* @param {ol.Coordinate} coordinate Coordinate.
* @return {ol.Coordinate} Coordinate.
* @param {Array.<number>} input Input coordinate values.
* @param {Array.<number>=} opt_output Output array of coordinate values.
* @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;

View File

@@ -397,14 +397,33 @@ ol.projection.getTransform = function(source, destination) {
var destinationProj4jsProj = proj4jsDestination.getProj4jsProj();
transform =
/**
* @param {ol.Coordinate} coordinate Coordinate.
* @return {ol.Coordinate} Coordinate.
* @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(coordinate) {
var proj4jsPoint = new Proj4js.Point(coordinate.x, coordinate.y);
proj4jsPoint = Proj4js.transform(
sourceProj4jsProj, destinationProj4jsProj, proj4jsPoint);
return new ol.Coordinate(proj4jsPoint.x, proj4jsPoint.y);
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.projection.addTransform(source, destination, transform);
}
@@ -418,7 +437,7 @@ ol.projection.getTransform = function(source, destination) {
/**
* 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.
*
* @param {string} sourceCode Source code.
@@ -433,20 +452,42 @@ ol.projection.getTransformFromCodes = function(sourceCode, destinationCode) {
/**
* @param {ol.Coordinate} point Point.
* @return {ol.Coordinate} Unaltered point (same reference).
* @param {Array.<number>} input Input coordinate array.
* @param {Array.<number>=} opt_output Output array of coordinate values.
* @param {number=} opt_dimension Dimension.
* @return {Array.<number>} Input coordinate array (same array as input).
*/
ol.projection.identityTransform = function(point) {
return point;
ol.projection.identityTransform = function(input, opt_output, opt_dimension) {
if (goog.isDef(opt_output) && input !== opt_output) {
// TODO: consider making this a warning instead
goog.asserts.assert(false, 'This should not be used internally.');
for (var i = 0, ii = input.length; i < ii; ++i) {
opt_output[i] = input[i];
}
input = opt_output;
}
return input;
};
/**
* @param {ol.Coordinate} point Point.
* @return {ol.Coordinate} Equal point (different reference).
* @param {Array.<number>} input Input coordinate array.
* @param {Array.<number>=} opt_output Output array of coordinate values.
* @param {number=} opt_dimension Dimension.
* @return {Array.<number>} Output coordinate array (new array, same coordinate
* values).
*/
ol.projection.cloneTransform = function(point) {
return new ol.Coordinate(point.x, point.y);
ol.projection.cloneTransform = function(input, opt_output, opt_dimension) {
var output;
if (goog.isDef(opt_output)) {
for (var i = 0, ii = input.length; i < ii; ++i) {
opt_output[i] = input[i];
}
output = opt_output;
} else {
output = input.slice();
}
return output;
};
@@ -460,7 +501,8 @@ ol.projection.cloneTransform = function(point) {
*/
ol.projection.transform = function(point, 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 +516,6 @@ ol.projection.transformWithCodes =
function(point, sourceCode, destinationCode) {
var transformFn = ol.projection.getTransformFromCodes(
sourceCode, destinationCode);
return transformFn(point);
var output = transformFn([point.x, point.y]);
return new ol.Coordinate(output[0], output[1]);
};

View File

@@ -1,7 +1,6 @@
goog.provide('ol.projection.EPSG3857');
goog.require('goog.array');
goog.require('ol.Coordinate');
goog.require('ol.Extent');
goog.require('ol.Projection');
goog.require('ol.ProjectionUnits');
@@ -73,26 +72,59 @@ ol.projection.EPSG3857.PROJECTIONS = goog.array.map(
/**
* Transformation from EPSG:4326 to EPSG:3857.
*
* @param {ol.Coordinate} point Point.
* @return {ol.Coordinate} Point.
* @param {Array.<number>} input Input array of coordinate values.
* @param {Array.<number>=} opt_output Output array of coordinate values.
* @param {number=} opt_dimension Dimension (default is 2).
* @return {Array.<number>} Output array of coordinate values.
*/
ol.projection.EPSG3857.fromEPSG4326 = function(point) {
var x = ol.projection.EPSG3857.RADIUS * Math.PI * point.x / 180;
var y = ol.projection.EPSG3857.RADIUS *
Math.log(Math.tan(Math.PI * (point.y + 90) / 360));
return new ol.Coordinate(x, y);
ol.projection.EPSG3857.fromEPSG4326 = 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);
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.
*
* @param {ol.Coordinate} point Point.
* @return {ol.Coordinate} Point.
* @param {Array.<number>} input Input array of coordinate values.
* @param {Array.<number>=} opt_output Output array of coordinate values.
* @param {number=} opt_dimension Dimension (default is 2).
* @return {Array.<number>} Output array of coordinate values.
*/
ol.projection.EPSG3857.toEPSG4326 = function(point) {
var x = 180 * point.x / (ol.projection.EPSG3857.RADIUS * Math.PI);
var y = 360 * Math.atan(
Math.exp(point.y / ol.projection.EPSG3857.RADIUS)) / Math.PI - 90;
return new ol.Coordinate(x, y);
ol.projection.EPSG3857.toEPSG4326 = 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);
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;
};

View File

@@ -1,9 +1,12 @@
goog.provide('ol.TransformFunction');
goog.require('ol.Coordinate');
/**
* @typedef {function(ol.Coordinate): ol.Coordinate}
* A transform function accepts an array of input coordinate values, an optional
* output array, and an optional dimension (default should be 2). The function
* transforms the input coordinate values, populates the output array, and
* returns the output array.
*
* @typedef {function(Array.<number>, Array.<number>=, number=): Array.<number>}
*/
ol.TransformFunction;