More robust way of handling non-global projections

If the target projection has specified extent, it is respected.
Also adds various checks to optimize performance and/or
prevent potential errors.
This commit is contained in:
Petr Sloup
2015-05-28 15:57:59 +02:00
parent 2cc2027353
commit fcffce46b4
2 changed files with 54 additions and 18 deletions

View File

@@ -49,13 +49,16 @@ ol.reproj.Image = function(sourceProj, targetProj,
this.canvas_ = this.context_.canvas;
var transformInv = ol.proj.getTransform(targetProj, sourceProj);
var maxTargetExtent = targetProj.getExtent();
var maxSourceExtent = sourceProj.getExtent();
/**
* @private
* @type {!ol.reproj.Triangulation}
*/
this.triangles_ = ol.reproj.triangulation.createForExtent(
targetExtent, transformInv);
targetExtent, transformInv,
maxTargetExtent, maxSourceExtent);
/**
* @private
@@ -71,16 +74,15 @@ ol.reproj.Image = function(sourceProj, targetProj,
var srcExtent = ol.reproj.triangulation.getSourceExtent(this.triangles_);
var idealSourceResolution =
targetProj.getPointResolution(targetResolution,
ol.extent.getCenter(targetExtent)) *
targetProj.getMetersPerUnit() / sourceProj.getMetersPerUnit();
var targetCenter = ol.extent.getCenter(targetExtent);
var sourceResolution = ol.reproj.calculateSourceResolution(
sourceProj, targetProj, targetCenter, targetResolution);
/**
* @private
* @type {ol.ImageBase}
*/
this.srcImage_ = getImageFunction(srcExtent, idealSourceResolution,
this.srcImage_ = getImageFunction(srcExtent, sourceResolution,
pixelRatio, sourceProj);
/**

View File

@@ -4,6 +4,7 @@ goog.require('goog.array');
goog.require('goog.asserts');
goog.require('goog.events');
goog.require('goog.events.EventType');
goog.require('goog.math');
goog.require('goog.object');
goog.require('ol.Tile');
goog.require('ol.TileState');
@@ -56,16 +57,11 @@ ol.reproj.Tile = function(sourceProj, sourceTileGrid,
*/
this.targetTileGrid_ = targetTileGrid;
var targetExtent = targetTileGrid.getTileCoordExtent(this.getTileCoord());
var targetResolution = targetTileGrid.getResolution(z);
var transformInv = ol.proj.getTransform(targetProj, sourceProj);
/**
* @private
* @type {!ol.reproj.Triangulation}
*/
this.triangles_ = ol.reproj.triangulation.createForExtent(
targetExtent, transformInv);
this.triangles_ = [];
/**
* @private
@@ -79,18 +75,48 @@ ol.reproj.Tile = function(sourceProj, sourceTileGrid,
*/
this.sourcesListenerKeys_ = null;
var idealSourceResolution =
targetProj.getPointResolution(targetResolution,
ol.extent.getCenter(targetExtent)) *
targetProj.getMetersPerUnit() / sourceProj.getMetersPerUnit();
/**
* @private
* @type {number}
*/
this.srcZ_ = sourceTileGrid.getZForResolution(idealSourceResolution);
this.srcZ_ = 0;
var targetExtent = targetTileGrid.getTileCoordExtent(this.getTileCoord());
var maxTargetExtent = this.targetTileGrid_.getExtent();
var maxSourceExtent = this.sourceTileGrid_.getExtent();
if (!ol.extent.intersects(maxTargetExtent, targetExtent)) {
// Tile is completely outside range -> EMPTY
// TODO: is it actually correct that the source even creates the tile ?
this.state = ol.TileState.EMPTY;
//return;
}
var transformInv = ol.proj.getTransform(targetProj, sourceProj);
this.triangles_ = ol.reproj.triangulation.createForExtent(
targetExtent, transformInv, maxTargetExtent, maxSourceExtent);
var targetCenter = ol.extent.getCenter(targetExtent);
var targetResolution = targetTileGrid.getResolution(z);
var sourceResolution = ol.reproj.calculateSourceResolution(
sourceProj, targetProj, targetCenter, targetResolution);
if (!goog.math.isFiniteNumber(sourceResolution) || sourceResolution <= 0) {
// invalid sourceResolution -> EMPTY
// probably edges of the projections when no extent is defined
this.state = ol.TileState.EMPTY;
return;
}
this.srcZ_ = sourceTileGrid.getZForResolution(sourceResolution);
var srcExtent = ol.reproj.triangulation.getSourceExtent(this.triangles_);
var sourceProjExtent = sourceProj.getExtent();
if (sourceProjExtent) {
srcExtent = ol.extent.getIntersection(srcExtent, sourceProjExtent);
}
if (!ol.extent.intersects(sourceTileGrid.getExtent(), srcExtent)) {
this.state = ol.TileState.EMPTY;
} else {
@@ -103,6 +129,14 @@ ol.reproj.Tile = function(sourceProj, sourceTileGrid,
srcRange.minY = Math.max(srcRange.minY, srcFullRange.minY);
srcRange.maxY = Math.min(srcRange.maxY, srcFullRange.maxY);
if (srcRange.getWidth() * srcRange.getHeight() > 100) {
// Too many source tiles are needed -- something probably went wrong
// This sometimes happens for certain non-global projections
// if no extent is specified.
// TODO: detect somehow better? or at least make this a define
this.state = ol.TileState.ERROR;
return;
}
for (var srcX = srcRange.minX; srcX <= srcRange.maxX; srcX++) {
for (var srcY = srcRange.minY; srcY <= srcRange.maxY; srcY++) {
var tile = getTileFunction(this.srcZ_, srcX, srcY, pixelRatio);