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:
@@ -49,13 +49,16 @@ ol.reproj.Image = function(sourceProj, targetProj,
|
|||||||
this.canvas_ = this.context_.canvas;
|
this.canvas_ = this.context_.canvas;
|
||||||
|
|
||||||
var transformInv = ol.proj.getTransform(targetProj, sourceProj);
|
var transformInv = ol.proj.getTransform(targetProj, sourceProj);
|
||||||
|
var maxTargetExtent = targetProj.getExtent();
|
||||||
|
var maxSourceExtent = sourceProj.getExtent();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @private
|
* @private
|
||||||
* @type {!ol.reproj.Triangulation}
|
* @type {!ol.reproj.Triangulation}
|
||||||
*/
|
*/
|
||||||
this.triangles_ = ol.reproj.triangulation.createForExtent(
|
this.triangles_ = ol.reproj.triangulation.createForExtent(
|
||||||
targetExtent, transformInv);
|
targetExtent, transformInv,
|
||||||
|
maxTargetExtent, maxSourceExtent);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @private
|
* @private
|
||||||
@@ -71,16 +74,15 @@ ol.reproj.Image = function(sourceProj, targetProj,
|
|||||||
|
|
||||||
var srcExtent = ol.reproj.triangulation.getSourceExtent(this.triangles_);
|
var srcExtent = ol.reproj.triangulation.getSourceExtent(this.triangles_);
|
||||||
|
|
||||||
var idealSourceResolution =
|
var targetCenter = ol.extent.getCenter(targetExtent);
|
||||||
targetProj.getPointResolution(targetResolution,
|
var sourceResolution = ol.reproj.calculateSourceResolution(
|
||||||
ol.extent.getCenter(targetExtent)) *
|
sourceProj, targetProj, targetCenter, targetResolution);
|
||||||
targetProj.getMetersPerUnit() / sourceProj.getMetersPerUnit();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @private
|
* @private
|
||||||
* @type {ol.ImageBase}
|
* @type {ol.ImageBase}
|
||||||
*/
|
*/
|
||||||
this.srcImage_ = getImageFunction(srcExtent, idealSourceResolution,
|
this.srcImage_ = getImageFunction(srcExtent, sourceResolution,
|
||||||
pixelRatio, sourceProj);
|
pixelRatio, sourceProj);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ goog.require('goog.array');
|
|||||||
goog.require('goog.asserts');
|
goog.require('goog.asserts');
|
||||||
goog.require('goog.events');
|
goog.require('goog.events');
|
||||||
goog.require('goog.events.EventType');
|
goog.require('goog.events.EventType');
|
||||||
|
goog.require('goog.math');
|
||||||
goog.require('goog.object');
|
goog.require('goog.object');
|
||||||
goog.require('ol.Tile');
|
goog.require('ol.Tile');
|
||||||
goog.require('ol.TileState');
|
goog.require('ol.TileState');
|
||||||
@@ -56,16 +57,11 @@ ol.reproj.Tile = function(sourceProj, sourceTileGrid,
|
|||||||
*/
|
*/
|
||||||
this.targetTileGrid_ = targetTileGrid;
|
this.targetTileGrid_ = targetTileGrid;
|
||||||
|
|
||||||
var targetExtent = targetTileGrid.getTileCoordExtent(this.getTileCoord());
|
|
||||||
var targetResolution = targetTileGrid.getResolution(z);
|
|
||||||
var transformInv = ol.proj.getTransform(targetProj, sourceProj);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @private
|
* @private
|
||||||
* @type {!ol.reproj.Triangulation}
|
* @type {!ol.reproj.Triangulation}
|
||||||
*/
|
*/
|
||||||
this.triangles_ = ol.reproj.triangulation.createForExtent(
|
this.triangles_ = [];
|
||||||
targetExtent, transformInv);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @private
|
* @private
|
||||||
@@ -79,18 +75,48 @@ ol.reproj.Tile = function(sourceProj, sourceTileGrid,
|
|||||||
*/
|
*/
|
||||||
this.sourcesListenerKeys_ = null;
|
this.sourcesListenerKeys_ = null;
|
||||||
|
|
||||||
var idealSourceResolution =
|
|
||||||
targetProj.getPointResolution(targetResolution,
|
|
||||||
ol.extent.getCenter(targetExtent)) *
|
|
||||||
targetProj.getMetersPerUnit() / sourceProj.getMetersPerUnit();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @private
|
* @private
|
||||||
* @type {number}
|
* @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 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)) {
|
if (!ol.extent.intersects(sourceTileGrid.getExtent(), srcExtent)) {
|
||||||
this.state = ol.TileState.EMPTY;
|
this.state = ol.TileState.EMPTY;
|
||||||
} else {
|
} else {
|
||||||
@@ -103,6 +129,14 @@ ol.reproj.Tile = function(sourceProj, sourceTileGrid,
|
|||||||
srcRange.minY = Math.max(srcRange.minY, srcFullRange.minY);
|
srcRange.minY = Math.max(srcRange.minY, srcFullRange.minY);
|
||||||
srcRange.maxY = Math.min(srcRange.maxY, srcFullRange.maxY);
|
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 srcX = srcRange.minX; srcX <= srcRange.maxX; srcX++) {
|
||||||
for (var srcY = srcRange.minY; srcY <= srcRange.maxY; srcY++) {
|
for (var srcY = srcRange.minY; srcY <= srcRange.maxY; srcY++) {
|
||||||
var tile = getTileFunction(this.srcZ_, srcX, srcY, pixelRatio);
|
var tile = getTileFunction(this.srcZ_, srcX, srcY, pixelRatio);
|
||||||
|
|||||||
Reference in New Issue
Block a user