Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix logic for stretching imagery to the edge of terrain. #970

Merged
merged 4 commits into from
Jul 30, 2013
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 8 additions & 11 deletions Source/Scene/ImageryLayer.js
Original file line number Diff line number Diff line change
@@ -453,24 +453,21 @@ define([
var veryCloseY = (tile.extent.east - tile.extent.west) / 512.0;

var northwestTileExtent = imageryTilingScheme.tileXYToExtent(northwestTileCoordinates.x, northwestTileCoordinates.y, imageryLevel);
if (Math.abs(northwestTileExtent.south - extent.north) < veryCloseY && northwestTileCoordinates.y < southeastTileCoordinates.y) {
if (Math.abs(northwestTileExtent.south - tile.extent.north) < veryCloseY && northwestTileCoordinates.y < southeastTileCoordinates.y) {
++northwestTileCoordinates.y;
}
if (Math.abs(northwestTileExtent.east - extent.west) < veryCloseX && northwestTileCoordinates.x < southeastTileCoordinates.x) {
if (Math.abs(northwestTileExtent.east - tile.extent.west) < veryCloseX && northwestTileCoordinates.x < southeastTileCoordinates.x) {
++northwestTileCoordinates.x;
}

var southeastTileExtent = imageryTilingScheme.tileXYToExtent(southeastTileCoordinates.x, southeastTileCoordinates.y, imageryLevel);
if (Math.abs(southeastTileExtent.north - extent.south) < veryCloseY && southeastTileCoordinates.y > northwestTileCoordinates.y) {
if (Math.abs(southeastTileExtent.north - tile.extent.south) < veryCloseY && southeastTileCoordinates.y > northwestTileCoordinates.y) {
--southeastTileCoordinates.y;
}
if (Math.abs(southeastTileExtent.west - extent.east) < veryCloseX && southeastTileCoordinates.x > northwestTileCoordinates.x) {
if (Math.abs(southeastTileExtent.west - tile.extent.east) < veryCloseX && southeastTileCoordinates.x > northwestTileCoordinates.x) {
--southeastTileCoordinates.x;
}

var imageryMaxX = imageryTilingScheme.getNumberOfXTilesAtLevel(imageryLevel);
var imageryMaxY = imageryTilingScheme.getNumberOfYTilesAtLevel(imageryLevel);

// Create TileImagery instances for each imagery tile overlapping this terrain tile.
// We need to do all texture coordinate computations in the imagery tile's tiling scheme.

@@ -486,11 +483,11 @@ define([
// If this is the northern-most or western-most tile in the imagery tiling scheme,
// it may not start at the northern or western edge of the terrain tile.
// Calculate where it does start.
if (!this.isBaseLayer() && northwestTileCoordinates.x === 0) {
if (!this.isBaseLayer() && Math.abs(imageryExtent.west - tile.extent.west) >= veryCloseX) {
maxU = Math.min(1.0, (imageryExtent.west - terrainExtent.west) / (terrainExtent.east - terrainExtent.west));
}

if (!this.isBaseLayer() && northwestTileCoordinates.y === 0) {
if (!this.isBaseLayer() && Math.abs(imageryExtent.north - tile.extent.north) >= veryCloseY) {
minV = Math.max(0.0, (imageryExtent.north - terrainExtent.south) / (terrainExtent.north - terrainExtent.south));
}

@@ -506,7 +503,7 @@ define([
// and there are more imagery tiles to the east of this one, the maxU
// should be 1.0 to make sure rounding errors don't make the last
// image fall shy of the edge of the terrain tile.
if (i === southeastTileCoordinates.x && (this.isBaseLayer() || i < imageryMaxX - 1)) {
if (i === southeastTileCoordinates.x && (this.isBaseLayer() || Math.abs(imageryExtent.east - tile.extent.east) < veryCloseX)) {
maxU = 1.0;
}

@@ -522,7 +519,7 @@ define([
// and there are more imagery tiles to the south of this one, the minV
// should be 0.0 to make sure rounding errors don't make the last
// image fall shy of the edge of the terrain tile.
if (j === southeastTileCoordinates.y && (this.isBaseLayer() || j < imageryMaxY - 1)) {
if (j === southeastTileCoordinates.y && (this.isBaseLayer() || Math.abs(imageryExtent.south - tile.extent.south) < veryCloseY)) {
minV = 0.0;
}

20 changes: 20 additions & 0 deletions Specs/Data/TMS/SmallArea/tilemapresource.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<TileMap version="1.0.0" tilemapservice="http://tms.osgeo.org/1.0.0">
<Title>oc.vrt</Title>
<Abstract></Abstract>
<SRS>EPSG:900913</SRS>
<BoundingBox minx="33.77813507771944" miny="-117.99489134177065" maxx="33.88755137636971" maxy="-117.83164761068497"/>
<Origin x="33.77813507771944" y="-117.99489134177065"/>
<TileFormat width="256" height="256" mime-type="image/png" extension="png"/>
<TileSets profile="mercator">
<TileSet href="11" units-per-pixel="76.43702827148438" order="11"/>
<TileSet href="12" units-per-pixel="38.21851413574219" order="12"/>
<TileSet href="13" units-per-pixel="19.10925706787110" order="13"/>
<TileSet href="14" units-per-pixel="9.55462853393555" order="14"/>
<TileSet href="15" units-per-pixel="4.77731426696777" order="15"/>
<TileSet href="16" units-per-pixel="2.38865713348389" order="16"/>
<TileSet href="17" units-per-pixel="1.19432856674194" order="17"/>
<TileSet href="18" units-per-pixel="0.59716428337097" order="18"/>
</TileSets>
</TileMap>

92 changes: 92 additions & 0 deletions Specs/Scene/ImageryLayerSpec.js
Original file line number Diff line number Diff line change
@@ -8,10 +8,13 @@ defineSuite([
'Core/loadImage',
'Core/loadWithXhr',
'Scene/BingMapsImageryProvider',
'Scene/EllipsoidTerrainProvider',
'Scene/Imagery',
'Scene/ImageryLayerCollection',
'Scene/ImageryState',
'Scene/NeverTileDiscardPolicy',
'Scene/SingleTileImageryProvider',
'Scene/TileMapServiceImageryProvider',
'Scene/WebMapServiceImageryProvider'
], function(
ImageryLayer,
@@ -22,10 +25,13 @@ defineSuite([
loadImage,
loadWithXhr,
BingMapsImageryProvider,
EllipsoidTerrainProvider,
Imagery,
ImageryLayerCollection,
ImageryState,
NeverTileDiscardPolicy,
SingleTileImageryProvider,
TileMapServiceImageryProvider,
WebMapServiceImageryProvider) {
"use strict";
/*global jasmine,describe,xdescribe,it,xit,expect,beforeEach,afterEach,beforeAll,afterAll,spyOn,runs,waits,waitsFor*/
@@ -195,4 +201,90 @@ defineSuite([
layer.destroy();
expect(layer.isDestroyed()).toEqual(true);
});

it('createTileImagerySkeletons handles a base layer that does not cover the entire globe', function() {
var provider = new TileMapServiceImageryProvider({
url : 'Data/TMS/SmallArea'
});

var layers = new ImageryLayerCollection();
var layer = layers.addImageryProvider(provider);
var terrainProvider = new EllipsoidTerrainProvider();

waitsFor(function() {
return provider.isReady() && terrainProvider.isReady();
}, 'imagery provider to become ready');

runs(function() {
var tiles = terrainProvider.getTilingScheme().createLevelZeroTiles();
layer._createTileImagerySkeletons(tiles[0], terrainProvider);
layer._createTileImagerySkeletons(tiles[1], terrainProvider);

// Both tiles should have imagery from this layer completely covering them.
expect(tiles[0].imagery.length).toBe(4);
expect(tiles[0].imagery[0].textureCoordinateExtent.x).toBe(0.0);
expect(tiles[0].imagery[0].textureCoordinateExtent.w).toBe(1.0);
expect(tiles[0].imagery[1].textureCoordinateExtent.x).toBe(0.0);
expect(tiles[0].imagery[1].textureCoordinateExtent.y).toBe(0.0);
expect(tiles[0].imagery[2].textureCoordinateExtent.z).toBe(1.0);
expect(tiles[0].imagery[2].textureCoordinateExtent.w).toBe(1.0);
expect(tiles[0].imagery[3].textureCoordinateExtent.y).toBe(0.0);
expect(tiles[0].imagery[3].textureCoordinateExtent.z).toBe(1.0);

expect(tiles[1].imagery.length).toBe(2);
expect(tiles[1].imagery[0].textureCoordinateExtent.x).toBe(0.0);
expect(tiles[1].imagery[0].textureCoordinateExtent.w).toBe(1.0);
expect(tiles[1].imagery[0].textureCoordinateExtent.z).toBe(1.0);
expect(tiles[1].imagery[1].textureCoordinateExtent.x).toBe(0.0);
expect(tiles[1].imagery[1].textureCoordinateExtent.y).toBe(0.0);
expect(tiles[1].imagery[1].textureCoordinateExtent.z).toBe(1.0);
});
});

it('createTileImagerySkeletons handles a non-base layer that does not cover the entire globe', function() {
var baseProvider = new SingleTileImageryProvider({
url : 'Data/Images/Green4x4.png'
});

var provider = new TileMapServiceImageryProvider({
url : 'Data/TMS/SmallArea'
});

var layers = new ImageryLayerCollection();
layers.addImageryProvider(baseProvider);
var layer = layers.addImageryProvider(provider);
var terrainProvider = new EllipsoidTerrainProvider();

waitsFor(function() {
return provider.isReady() && terrainProvider.isReady();
}, 'imagery provider to become ready');

runs(function() {
var tiles = terrainProvider.getTilingScheme().createLevelZeroTiles();
layer._createTileImagerySkeletons(tiles[0], terrainProvider);
layer._createTileImagerySkeletons(tiles[1], terrainProvider);

// Only the western tile should have imagery from this layer.
// And the imagery should not cover it completely.
expect(tiles[0].imagery.length).toBe(4);
expect(tiles[0].imagery[0].textureCoordinateExtent.x).not.toBe(0.0);
expect(tiles[0].imagery[0].textureCoordinateExtent.y).not.toBe(0.0);
expect(tiles[0].imagery[0].textureCoordinateExtent.z).not.toBe(1.0);
expect(tiles[0].imagery[0].textureCoordinateExtent.w).not.toBe(1.0);
expect(tiles[0].imagery[1].textureCoordinateExtent.x).not.toBe(0.0);
expect(tiles[0].imagery[1].textureCoordinateExtent.y).not.toBe(0.0);
expect(tiles[0].imagery[1].textureCoordinateExtent.z).not.toBe(1.0);
expect(tiles[0].imagery[1].textureCoordinateExtent.w).not.toBe(1.0);
expect(tiles[0].imagery[2].textureCoordinateExtent.x).not.toBe(0.0);
expect(tiles[0].imagery[2].textureCoordinateExtent.y).not.toBe(0.0);
expect(tiles[0].imagery[2].textureCoordinateExtent.z).not.toBe(1.0);
expect(tiles[0].imagery[2].textureCoordinateExtent.w).not.toBe(1.0);
expect(tiles[0].imagery[3].textureCoordinateExtent.x).not.toBe(0.0);
expect(tiles[0].imagery[3].textureCoordinateExtent.y).not.toBe(0.0);
expect(tiles[0].imagery[3].textureCoordinateExtent.z).not.toBe(1.0);
expect(tiles[0].imagery[3].textureCoordinateExtent.w).not.toBe(1.0);

expect(tiles[1].imagery.length).toBe(0);
});
});
}, 'WebGL');