Problems with minimumLayer in UrlTemplateImageryProvider when using custom tiled images

Hi,

I am using UrlTemplateImageryProvider to supply tiled imagery for the globe. We are only interested in images for a small region of the globe, so a rectangle is also provided, as well as a minimumLevel, since the images only need to start at zoom level of ~10. I noticed that when the rectangle bounds are very close to tile bounds the application crashes. (All code refers to Source/Scene/ImageryLayer.js)

The cause is that

var clippedImageryRectangle = Rectangle.intersection(imageryRectangle, imageryBounds, clippedRectangleScratch);

at line 518 returns undefined, because the tile that is deemed to be the northwest tile should be the same as the tile containing the image. However, an adjacent tile may be chosen, possibly due to rounding when determining the tile position of the northwest corner.

I suggest performing a similar check against the imagery bounds to the check that is already being performed against the tile bounds, i.e. if the east edge of the northwest tile is very close to the west edge of the image, increase the x tile coordinate for the northwest tile, etc.

I fixed it by adding:

var veryCloseX_imageryLevel = northwestTileRectangle.width / 512.0;

var veryCloseY_imageryLevel = northwestTileRectangle.height / 512.0;

if (Math.abs(northwestTileRectangle.east - rectangle.west) < veryCloseX_imageryLevel) {

++northwestTileCoordinates.x;

}

if (Math.abs(northwestTileRectangle.south - rectangle.north) < veryCloseY_imageryLevel) {

++northwestTileCoordinates.y;

}

and

if (Math.abs(southeastTileRectangle.west - rectangle.east) < veryCloseX_imageryLevel) {

–southeastTileCoordinates.x;

}

if (Math.abs(southeastTileRectangle.north - rectangle.south) < veryCloseY_imageryLevel) {

–southeastTileCoordinates.y;

}

This meant that the northwestTileRectangle and southeastTileRectangle variables must be recomputed for the other tests, so that lines 497-511 become:

var northwestTileRectangle = imageryTilingScheme.tileXYToRectangle(northwestTileCoordinates.x, northwestTileCoordinates.y, imageryLevel);

var veryCloseX_imageryLevel = northwestTileRectangle.width / 512.0;

var veryCloseY_imageryLevel = northwestTileRectangle.height / 512.0;

if (Math.abs(northwestTileRectangle.east - rectangle.west) < veryCloseX_imageryLevel) {

++northwestTileCoordinates.x;

}

if (Math.abs(northwestTileRectangle.south - rectangle.north) < veryCloseY_imageryLevel) {

++northwestTileCoordinates.y;

}

northwestTileRectangle = imageryTilingScheme.tileXYToRectangle(northwestTileCoordinates.x, northwestTileCoordinates.y, imageryLevel);

if (Math.abs(northwestTileRectangle.south - tile.rectangle.north) < veryCloseY && northwestTileCoordinates.y < southeastTileCoordinates.y) {

++northwestTileCoordinates.y;

}

if (Math.abs(northwestTileRectangle.east - tile.rectangle.west) < veryCloseX && northwestTileCoordinates.x < southeastTileCoordinates.x) {

++northwestTileCoordinates.x;

}

var southeastTileRectangle = imageryTilingScheme.tileXYToRectangle(southeastTileCoordinates.x, southeastTileCoordinates.y, imageryLevel);

if (Math.abs(southeastTileRectangle.west - rectangle.east) < veryCloseX_imageryLevel) {

–southeastTileCoordinates.x;

}

if (Math.abs(southeastTileRectangle.north - rectangle.south) < veryCloseY_imageryLevel) {

–southeastTileCoordinates.y;

}

southeastTileRectangle = imageryTilingScheme.tileXYToRectangle(southeastTileCoordinates.x, southeastTileCoordinates.y, imageryLevel);

if (Math.abs(southeastTileRectangle.north - tile.rectangle.south) < veryCloseY && southeastTileCoordinates.y > northwestTileCoordinates.y) {

–southeastTileCoordinates.y;

}

if (Math.abs(southeastTileRectangle.west - tile.rectangle.east) < veryCloseX && southeastTileCoordinates.x > northwestTileCoordinates.x) {

–southeastTileCoordinates.x;

}

This change solved my issue, not sure whether it is something that would come up in many situations.

It may be possible to remove those extra computations of the rectangles, but I am not sure if there could be a case where one of the rectangles would have to move twice.

Also, I believe there is a mix up in determining veryCloseX and veryCloseY at line 494-495, height and width should be swapped so the code should instead be:

var veryCloseX = tile.rectangle.width / 512.0;

var veryCloseY = tile.rectangle.height / 512.0;