Skip to content

Commit

Permalink
Optimize coordinate transforms on flat arrays.
Browse files Browse the repository at this point in the history
This is commonly done (for instance in generating glLineFeature).  As a
crude metric, this reduces time by about a third.  For instance,
transforming ~100,000 line vertices went from around 60 ms to 40 ms.
  • Loading branch information
manthey committed Oct 16, 2018
1 parent 068882e commit 43c2233
Show file tree
Hide file tree
Showing 2 changed files with 40 additions and 2 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@
### Features
- Feature selection API is now enabled automatically if any event handlers are bounds to the feature (#921)

### Improvements
- Coordinate transforms on flat arrays are now faster (#939)

### Changes
- Removed the dependency on the vgl module for the `object` and `timestamp` classes (#918)

Expand Down
39 changes: 37 additions & 2 deletions src/transform.js
Original file line number Diff line number Diff line change
Expand Up @@ -251,6 +251,9 @@ transform.transformCoordinates = function (srcPrj, tgtPrj, coordinates, numberOf
return coordinates;
}

if (Array.isArray(coordinates) && coordinates.length >= 3 && numberOfComponents === 3 && !util.isObject(coordinates[0])) {
return transform.transformCoordinatesFlatArray3(srcPrj, tgtPrj, coordinates);
}
var trans = transform({source: srcPrj, target: tgtPrj}), output;
if (util.isObject(coordinates) && 'x' in coordinates && 'y' in coordinates) {
output = trans.forward({x: +coordinates.x, y: +coordinates.y, z: +coordinates.z || 0});
Expand Down Expand Up @@ -285,7 +288,8 @@ transform.transformCoordinates = function (srcPrj, tgtPrj, coordinates, numberOf
* @returns {geoPosition[]|number[]} The transformed coordinates
*/
transform.transformCoordinatesArray = function (trans, coordinates, numberOfComponents) {
var i, count, offset, xAcc, yAcc, zAcc, writer, output, projPoint;
var i, count, offset, xAcc, yAcc, zAcc, writer, output, projPoint,
initPoint = {};

// Default Z accessor
zAcc = function () {
Expand Down Expand Up @@ -439,12 +443,43 @@ transform.transformCoordinatesArray = function (trans, coordinates, numberOfComp
}

for (i = 0; i < count; i += offset) {
projPoint = trans.forward({x: xAcc(i), y: yAcc(i), z: zAcc(i)});
initPoint.x = xAcc(i);
initPoint.y = yAcc(i);
initPoint.z = zAcc(i);
projPoint = trans.forward(initPoint);
writer(i, projPoint.x, projPoint.y, projPoint.z);
}
return output;
};

/**
* Transform an array of coordinates from one projection into another. The
* transformation occurs in place, modifying the input coordinate array. The
* coordinates are an array of [x0, y0, z0, x1, y1, z1, ...].
*
* @param {string} srcPrj The source projection.
* @param {string} tgtPrj The destination projection.
* @param {number[]} coordinates A flat array of values.
* @returns {number[]} The transformed coordinates.
*/
transform.transformCoordinatesFlatArray3 = function (srcPrj, tgtPrj, coordinates) {
'use strict';

var src = proj4.Proj(srcPrj),
tgt = proj4.Proj(tgtPrj),
i, projPoint, initPoint = {};
for (i = coordinates.length - 3; i >= 0; i -= 3) {
initPoint.x = +coordinates[i];
initPoint.y = +coordinates[i + 1];
initPoint.z = +(coordinates[i + 2] || 0.0);
projPoint = proj4.transform(src, tgt, initPoint);
coordinates[i] = projPoint.x;
coordinates[i + 1] = projPoint.y;
coordinates[i + 2] = projPoint.z === undefined ? initPoint.z : projPoint.z;
}
return coordinates;
};

/**
* Apply an affine transformation consisting of a translation then a scaling
* to the given coordinate array. Note, the transformation occurs in place
Expand Down

0 comments on commit 43c2233

Please sign in to comment.