Verify triangulation against source/target extents
If we do this here, we can avoid some computations on triangles that will be unused in the future anyway + reduce problems with non-global projections without specified extents.
This commit is contained in:
@@ -16,25 +16,67 @@ goog.require('ol.extent');
|
|||||||
ol.reproj.Triangulation;
|
ol.reproj.Triangulation;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds triangle to the triangulation (and reprojects the vertices) if valid.
|
||||||
|
* @private
|
||||||
|
* @param {ol.reproj.Triangulation} triangulation
|
||||||
|
* @param {ol.Coordinate} a
|
||||||
|
* @param {ol.Coordinate} b
|
||||||
|
* @param {ol.Coordinate} c
|
||||||
|
* @param {ol.TransformFunction} transformInv Inverse transform (dst -> src).
|
||||||
|
* @param {ol.Extent=} opt_maxTargetExtent
|
||||||
|
* @param {ol.Extent=} opt_maxSourceExtent
|
||||||
|
*/
|
||||||
|
ol.reproj.triangulation.addTriangleIfValid_ = function(triangulation, a, b, c,
|
||||||
|
transformInv, opt_maxTargetExtent, opt_maxSourceExtent) {
|
||||||
|
if (goog.isDefAndNotNull(opt_maxTargetExtent)) {
|
||||||
|
if (!ol.extent.containsCoordinate(opt_maxTargetExtent, a) &&
|
||||||
|
!ol.extent.containsCoordinate(opt_maxTargetExtent, b) &&
|
||||||
|
!ol.extent.containsCoordinate(opt_maxTargetExtent, c)) {
|
||||||
|
// whole triangle outside target projection extent -> ignore
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// clamp the vertices to the extent edges before transforming
|
||||||
|
a = ol.extent.closestCoordinate(opt_maxTargetExtent, a);
|
||||||
|
b = ol.extent.closestCoordinate(opt_maxTargetExtent, b);
|
||||||
|
c = ol.extent.closestCoordinate(opt_maxTargetExtent, c);
|
||||||
|
}
|
||||||
|
var aSrc = transformInv(a);
|
||||||
|
var bSrc = transformInv(b);
|
||||||
|
var cSrc = transformInv(c);
|
||||||
|
if (goog.isDefAndNotNull(opt_maxSourceExtent)) {
|
||||||
|
var srcTriangleExtent = ol.extent.boundingExtent([aSrc, bSrc, cSrc]);
|
||||||
|
if (!ol.extent.intersects(srcTriangleExtent, opt_maxSourceExtent)) {
|
||||||
|
// whole triangle outside source projection extent -> ignore
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
triangulation.push([[aSrc, a], [bSrc, b], [cSrc, c]]);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Triangulates given extent and reprojects vertices.
|
* Triangulates given extent and reprojects vertices.
|
||||||
* TODO: improved triangulation, better error handling of some trans fails
|
* TODO: improved triangulation, better error handling of some trans fails
|
||||||
* @param {ol.Extent} extent
|
* @param {ol.Extent} extent
|
||||||
* @param {ol.TransformFunction} transformInv Inverse transform (dst -> src).
|
* @param {ol.TransformFunction} transformInv Inverse transform (dst -> src).
|
||||||
|
* @param {ol.Extent=} opt_maxTargetExtent
|
||||||
|
* @param {ol.Extent=} opt_maxSourceExtent
|
||||||
* @param {number=} opt_subdiv Subdivision factor (default 4).
|
* @param {number=} opt_subdiv Subdivision factor (default 4).
|
||||||
* @return {ol.reproj.Triangulation}
|
* @return {ol.reproj.Triangulation}
|
||||||
*/
|
*/
|
||||||
ol.reproj.triangulation.createForExtent = function(extent, transformInv,
|
ol.reproj.triangulation.createForExtent = function(extent, transformInv,
|
||||||
|
opt_maxTargetExtent,
|
||||||
|
opt_maxSourceExtent,
|
||||||
opt_subdiv) {
|
opt_subdiv) {
|
||||||
|
|
||||||
var triangulation = [];
|
var triangulation = [];
|
||||||
|
|
||||||
var tlDst = ol.extent.getTopLeft(extent);
|
var tlDst = ol.extent.getTopLeft(extent);
|
||||||
var brDst = ol.extent.getBottomRight(extent);
|
var brDst = ol.extent.getBottomRight(extent);
|
||||||
|
|
||||||
var projected = {0: {}}; // cache of already transformed values
|
|
||||||
var subdiv = opt_subdiv || 4;
|
var subdiv = opt_subdiv || 4;
|
||||||
for (var y = 0; y < subdiv; y++) {
|
for (var y = 0; y < subdiv; y++) {
|
||||||
projected[y + 1] = {}; // prepare cache for the next line
|
|
||||||
for (var x = 0; x < subdiv; x++) {
|
for (var x = 0; x < subdiv; x++) {
|
||||||
// do 2 triangle: [(x, y), (x + 1, y + 1), (x, y + 1)]
|
// do 2 triangle: [(x, y), (x + 1, y + 1), (x, y + 1)]
|
||||||
// [(x, y), (x + 1, y), (x + 1, y + 1)]
|
// [(x, y), (x + 1, y), (x + 1, y + 1)]
|
||||||
@@ -56,30 +98,12 @@ ol.reproj.triangulation.createForExtent = function(extent, transformInv,
|
|||||||
goog.math.lerp(tlDst[1], brDst[1], (y + 1) / subdiv)
|
goog.math.lerp(tlDst[1], brDst[1], (y + 1) / subdiv)
|
||||||
];
|
];
|
||||||
|
|
||||||
if (!goog.isDef(projected[y][x])) {
|
ol.reproj.triangulation.addTriangleIfValid_(
|
||||||
projected[y][x] = transformInv(x0y0dst);
|
triangulation, x0y0dst, x1y1dst, x0y1dst,
|
||||||
}
|
transformInv, opt_maxTargetExtent, opt_maxSourceExtent);
|
||||||
if (!goog.isDef(projected[y][x + 1])) {
|
ol.reproj.triangulation.addTriangleIfValid_(
|
||||||
projected[y][x + 1] = transformInv(x1y0dst);
|
triangulation, x0y0dst, x1y0dst, x1y1dst,
|
||||||
}
|
transformInv, opt_maxTargetExtent, opt_maxSourceExtent);
|
||||||
if (!goog.isDef(projected[y + 1][x])) {
|
|
||||||
projected[y + 1][x] = transformInv(x0y1dst);
|
|
||||||
}
|
|
||||||
if (!goog.isDef(projected[y + 1][x + 1])) {
|
|
||||||
projected[y + 1][x + 1] = transformInv(x1y1dst);
|
|
||||||
}
|
|
||||||
|
|
||||||
triangulation.push(
|
|
||||||
[
|
|
||||||
[projected[y][x], x0y0dst],
|
|
||||||
[projected[y + 1][x + 1], x1y1dst],
|
|
||||||
[projected[y + 1][x], x0y1dst]
|
|
||||||
], [
|
|
||||||
[projected[y][x], x0y0dst],
|
|
||||||
[projected[y][x + 1], x1y0dst],
|
|
||||||
[projected[y + 1][x + 1], x1y1dst]
|
|
||||||
]
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user