You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
612 lines
20 KiB
JavaScript
612 lines
20 KiB
JavaScript
import { Cartesian3 } from "../../Source/Cesium.js";
|
|
import { Ellipsoid } from "../../Source/Cesium.js";
|
|
import { Event } from "../../Source/Cesium.js";
|
|
import { GeographicTilingScheme } from "../../Source/Cesium.js";
|
|
import { Matrix4 } from "../../Source/Cesium.js";
|
|
import { Ray } from "../../Source/Cesium.js";
|
|
import { Rectangle } from "../../Source/Cesium.js";
|
|
import { WebMercatorProjection } from "../../Source/Cesium.js";
|
|
import { WebMercatorTilingScheme } from "../../Source/Cesium.js";
|
|
import { Globe } from "../../Source/Cesium.js";
|
|
import { ImageryLayer } from "../../Source/Cesium.js";
|
|
import { ImageryLayerCollection } from "../../Source/Cesium.js";
|
|
import { ImageryLayerFeatureInfo } from "../../Source/Cesium.js";
|
|
import { ImageryProvider } from "../../Source/Cesium.js";
|
|
import createScene from "../createScene.js";
|
|
import pollToPromise from "../pollToPromise.js";
|
|
import { when } from "../../Source/Cesium.js";
|
|
|
|
describe(
|
|
"Scene/ImageryLayerCollection",
|
|
function () {
|
|
var fakeProvider = {
|
|
isReady: function () {
|
|
return false;
|
|
},
|
|
};
|
|
|
|
it("tracks the base layer on add", function () {
|
|
var layer1 = new ImageryLayer(fakeProvider);
|
|
var layer2 = new ImageryLayer(fakeProvider);
|
|
var layer3 = new ImageryLayer(fakeProvider);
|
|
var collection = new ImageryLayerCollection();
|
|
|
|
expect(layer1.isBaseLayer()).toEqual(false);
|
|
|
|
collection.add(layer1);
|
|
expect(layer1.isBaseLayer()).toEqual(true);
|
|
|
|
collection.add(layer2);
|
|
expect(layer1.isBaseLayer()).toEqual(true);
|
|
expect(layer2.isBaseLayer()).toEqual(false);
|
|
|
|
collection.add(layer3, 0);
|
|
expect(layer1.isBaseLayer()).toEqual(false);
|
|
expect(layer2.isBaseLayer()).toEqual(false);
|
|
expect(layer3.isBaseLayer()).toEqual(true);
|
|
});
|
|
|
|
it("tracks the base layer on remove", function () {
|
|
var layer1 = new ImageryLayer(fakeProvider);
|
|
var layer2 = new ImageryLayer(fakeProvider);
|
|
var layer3 = new ImageryLayer(fakeProvider);
|
|
var collection = new ImageryLayerCollection();
|
|
|
|
collection.add(layer1);
|
|
collection.add(layer2);
|
|
collection.add(layer3);
|
|
|
|
expect(layer1.isBaseLayer()).toEqual(true);
|
|
expect(layer2.isBaseLayer()).toEqual(false);
|
|
expect(layer3.isBaseLayer()).toEqual(false);
|
|
|
|
collection.remove(layer1);
|
|
expect(layer2.isBaseLayer()).toEqual(true);
|
|
expect(layer3.isBaseLayer()).toEqual(false);
|
|
|
|
collection.remove(layer3);
|
|
expect(layer2.isBaseLayer()).toEqual(true);
|
|
});
|
|
|
|
it("updates isBaseLayer on re-add", function () {
|
|
var layer1 = new ImageryLayer(fakeProvider);
|
|
var layer2 = new ImageryLayer(fakeProvider);
|
|
var collection = new ImageryLayerCollection();
|
|
|
|
layer1._isBaseLayer = true;
|
|
layer2._isBaseLayer = true;
|
|
|
|
collection.add(layer1);
|
|
collection.add(layer2);
|
|
|
|
expect(layer1.isBaseLayer()).toEqual(true);
|
|
expect(layer2.isBaseLayer()).toEqual(false);
|
|
});
|
|
|
|
it("does not crash when raising and lowering a single layer.", function () {
|
|
var layer1 = new ImageryLayer(fakeProvider);
|
|
var collection = new ImageryLayerCollection();
|
|
collection.add(layer1);
|
|
|
|
collection.raise(layer1);
|
|
collection.lower(layer1);
|
|
|
|
collection.raiseToTop(layer1);
|
|
collection.lowerToBottom(layer1);
|
|
});
|
|
|
|
it("tracks the base layer on raise and lower", function () {
|
|
var layer1 = new ImageryLayer(fakeProvider);
|
|
var layer2 = new ImageryLayer(fakeProvider);
|
|
var layer3 = new ImageryLayer(fakeProvider);
|
|
var collection = new ImageryLayerCollection();
|
|
|
|
collection.add(layer1);
|
|
collection.add(layer2);
|
|
collection.add(layer3);
|
|
|
|
expect(layer1.isBaseLayer()).toEqual(true);
|
|
expect(layer2.isBaseLayer()).toEqual(false);
|
|
expect(layer3.isBaseLayer()).toEqual(false);
|
|
|
|
collection.lower(layer1);
|
|
expect(layer1.isBaseLayer()).toEqual(true);
|
|
expect(layer2.isBaseLayer()).toEqual(false);
|
|
expect(layer3.isBaseLayer()).toEqual(false);
|
|
|
|
collection.raise(layer1);
|
|
expect(layer1.isBaseLayer()).toEqual(false);
|
|
expect(layer2.isBaseLayer()).toEqual(true);
|
|
expect(layer3.isBaseLayer()).toEqual(false);
|
|
|
|
collection.lower(layer1);
|
|
expect(layer1.isBaseLayer()).toEqual(true);
|
|
expect(layer2.isBaseLayer()).toEqual(false);
|
|
expect(layer3.isBaseLayer()).toEqual(false);
|
|
});
|
|
|
|
it("tracks the base layer on raiseToTop to lowerToBottom", function () {
|
|
var layer1 = new ImageryLayer(fakeProvider);
|
|
var layer2 = new ImageryLayer(fakeProvider);
|
|
var layer3 = new ImageryLayer(fakeProvider);
|
|
var collection = new ImageryLayerCollection();
|
|
|
|
collection.add(layer1);
|
|
collection.add(layer2);
|
|
collection.add(layer3);
|
|
|
|
expect(layer1.isBaseLayer()).toEqual(true);
|
|
expect(layer2.isBaseLayer()).toEqual(false);
|
|
expect(layer3.isBaseLayer()).toEqual(false);
|
|
|
|
collection.raiseToTop(layer1);
|
|
expect(layer1.isBaseLayer()).toEqual(false);
|
|
expect(layer2.isBaseLayer()).toEqual(true);
|
|
expect(layer3.isBaseLayer()).toEqual(false);
|
|
|
|
collection.lowerToBottom(layer1);
|
|
expect(layer1.isBaseLayer()).toEqual(true);
|
|
expect(layer2.isBaseLayer()).toEqual(false);
|
|
expect(layer3.isBaseLayer()).toEqual(false);
|
|
});
|
|
|
|
it("add throws when layer is undefined", function () {
|
|
var collection = new ImageryLayerCollection();
|
|
|
|
expect(function () {
|
|
collection.add(undefined);
|
|
}).toThrowDeveloperError();
|
|
});
|
|
|
|
it("addImageryProvider throws when imageryProvider is undefined", function () {
|
|
var collection = new ImageryLayerCollection();
|
|
|
|
expect(function () {
|
|
collection.addImageryProvider(undefined);
|
|
}).toThrowDeveloperError();
|
|
});
|
|
|
|
it("add throws when index is outside valid range", function () {
|
|
var collection = new ImageryLayerCollection();
|
|
var layer1 = new ImageryLayer(fakeProvider);
|
|
var layer2 = new ImageryLayer(fakeProvider);
|
|
|
|
expect(function () {
|
|
collection.add(layer1, 1);
|
|
}).toThrowDeveloperError();
|
|
|
|
expect(function () {
|
|
collection.add(layer1, -1);
|
|
}).toThrowDeveloperError();
|
|
|
|
collection.add(layer1, 0);
|
|
|
|
expect(function () {
|
|
collection.add(layer2, -1);
|
|
}).toThrowDeveloperError();
|
|
|
|
expect(function () {
|
|
collection.add(layer2, 2);
|
|
}).toThrowDeveloperError();
|
|
|
|
collection.add(layer2, 0);
|
|
});
|
|
|
|
it("remove ignores request to remove a layer that does not exist in the collection", function () {
|
|
var collection = new ImageryLayerCollection();
|
|
var layer1 = new ImageryLayer(fakeProvider);
|
|
expect(collection.remove(layer1)).toBe(false);
|
|
});
|
|
|
|
it("contains works as expected", function () {
|
|
var collection = new ImageryLayerCollection();
|
|
var layer1 = new ImageryLayer(fakeProvider);
|
|
var layer2 = new ImageryLayer(fakeProvider);
|
|
|
|
expect(collection.contains(layer1)).toEqual(false);
|
|
expect(collection.contains(layer2)).toEqual(false);
|
|
|
|
collection.add(layer1);
|
|
|
|
expect(collection.contains(layer1)).toEqual(true);
|
|
expect(collection.contains(layer2)).toEqual(false);
|
|
|
|
collection.add(layer2);
|
|
|
|
expect(collection.contains(layer1)).toEqual(true);
|
|
expect(collection.contains(layer2)).toEqual(true);
|
|
|
|
collection.remove(layer1);
|
|
|
|
expect(collection.contains(layer1)).toEqual(false);
|
|
expect(collection.contains(layer2)).toEqual(true);
|
|
|
|
collection.remove(layer2);
|
|
|
|
expect(collection.contains(layer1)).toEqual(false);
|
|
expect(collection.contains(layer2)).toEqual(false);
|
|
});
|
|
|
|
it("get throws if index is not provided", function () {
|
|
var collection = new ImageryLayerCollection();
|
|
expect(function () {
|
|
collection.get();
|
|
}).toThrowDeveloperError();
|
|
});
|
|
|
|
it("throws when raising an undefined layer", function () {
|
|
var collection = new ImageryLayerCollection();
|
|
|
|
expect(function () {
|
|
collection.raise(undefined);
|
|
}).toThrowDeveloperError();
|
|
});
|
|
|
|
it("throws when raising a layer not in the collection", function () {
|
|
var collection = new ImageryLayerCollection();
|
|
var layer1 = new ImageryLayer(fakeProvider);
|
|
|
|
expect(function () {
|
|
collection.raise(layer1);
|
|
}).toThrowDeveloperError();
|
|
});
|
|
|
|
it("reports whether or not it is destroyed", function () {
|
|
var collection = new ImageryLayerCollection();
|
|
expect(collection.isDestroyed()).toEqual(false);
|
|
collection.destroy();
|
|
expect(collection.isDestroyed()).toEqual(true);
|
|
});
|
|
|
|
describe("pickImageryLayerFeatures", function () {
|
|
var scene;
|
|
var globe;
|
|
var camera;
|
|
|
|
beforeAll(function () {
|
|
scene = createScene();
|
|
globe = scene.globe = new Globe();
|
|
camera = scene.camera;
|
|
|
|
scene.frameState.passes.render = true;
|
|
});
|
|
|
|
afterAll(function () {
|
|
scene.destroyForSpecs();
|
|
});
|
|
|
|
beforeEach(function () {
|
|
globe.imageryLayers.removeAll();
|
|
});
|
|
|
|
/**
|
|
* Repeatedly calls update until the load queue is empty. Returns a promise that resolves
|
|
* once the load queue is empty.
|
|
*/
|
|
function updateUntilDone(globe) {
|
|
// update until the load queue is empty.
|
|
return pollToPromise(function () {
|
|
globe._surface._debug.enableDebugOutput = true;
|
|
scene.render();
|
|
return (
|
|
globe._surface.tileProvider.ready &&
|
|
globe._surface._tileLoadQueueHigh.length === 0 &&
|
|
globe._surface._tileLoadQueueMedium.length === 0 &&
|
|
globe._surface._tileLoadQueueLow.length === 0 &&
|
|
globe._surface._debug.tilesWaitingForChildren === 0
|
|
);
|
|
});
|
|
}
|
|
|
|
it("returns undefined when pick ray does not intersect surface", function () {
|
|
var ellipsoid = Ellipsoid.WGS84;
|
|
camera.lookAt(
|
|
new Cartesian3(ellipsoid.maximumRadius, 0.0, 0.0),
|
|
new Cartesian3(0.0, 0.0, 100.0)
|
|
);
|
|
|
|
var ray = new Ray(
|
|
camera.position,
|
|
Cartesian3.negate(camera.direction, new Cartesian3())
|
|
);
|
|
var featuresPromise = scene.imageryLayers.pickImageryLayerFeatures(
|
|
ray,
|
|
scene
|
|
);
|
|
expect(featuresPromise).toBeUndefined();
|
|
});
|
|
|
|
it("returns undefined when globe has no pickable layers", function () {
|
|
var ellipsoid = Ellipsoid.WGS84;
|
|
camera.lookAt(
|
|
new Cartesian3(ellipsoid.maximumRadius, 0.0, 0.0),
|
|
new Cartesian3(0.0, 0.0, 100.0)
|
|
);
|
|
|
|
var ray = new Ray(camera.position, camera.direction);
|
|
var featuresPromise = scene.imageryLayers.pickImageryLayerFeatures(
|
|
ray,
|
|
scene
|
|
);
|
|
expect(featuresPromise).toBeUndefined();
|
|
});
|
|
|
|
it("returns undefined when ImageryProvider does not implement pickFeatures", function () {
|
|
var provider = {
|
|
ready: true,
|
|
rectangle: Rectangle.MAX_VALUE,
|
|
tileWidth: 256,
|
|
tileHeight: 256,
|
|
maximumLevel: 0,
|
|
minimumLevel: 0,
|
|
tilingScheme: new GeographicTilingScheme(),
|
|
errorEvent: new Event(),
|
|
hasAlphaChannel: true,
|
|
|
|
requestImage: function (x, y, level) {
|
|
return ImageryProvider.loadImage(this, "Data/Images/Blue.png");
|
|
},
|
|
};
|
|
|
|
globe.imageryLayers.addImageryProvider(provider);
|
|
|
|
return updateUntilDone(globe).then(function () {
|
|
var ellipsoid = Ellipsoid.WGS84;
|
|
camera.lookAt(
|
|
new Cartesian3(ellipsoid.maximumRadius, 0.0, 0.0),
|
|
new Cartesian3(0.0, 0.0, 100.0)
|
|
);
|
|
|
|
var ray = new Ray(camera.position, camera.direction);
|
|
var featuresPromise = scene.imageryLayers.pickImageryLayerFeatures(
|
|
ray,
|
|
scene
|
|
);
|
|
expect(featuresPromise).toBeUndefined();
|
|
});
|
|
});
|
|
|
|
it("returns undefined when ImageryProvider.pickFeatures returns undefined", function () {
|
|
var provider = {
|
|
ready: true,
|
|
rectangle: Rectangle.MAX_VALUE,
|
|
tileWidth: 256,
|
|
tileHeight: 256,
|
|
maximumLevel: 0,
|
|
minimumLevel: 0,
|
|
tilingScheme: new GeographicTilingScheme(),
|
|
errorEvent: new Event(),
|
|
hasAlphaChannel: true,
|
|
|
|
pickFeatures: function (x, y, level, longitude, latitude) {
|
|
return undefined;
|
|
},
|
|
|
|
requestImage: function (x, y, level) {
|
|
return ImageryProvider.loadImage(this, "Data/Images/Blue.png");
|
|
},
|
|
};
|
|
|
|
globe.imageryLayers.addImageryProvider(provider);
|
|
|
|
return updateUntilDone(globe).then(function () {
|
|
var ellipsoid = Ellipsoid.WGS84;
|
|
camera.lookAt(
|
|
new Cartesian3(ellipsoid.maximumRadius, 0.0, 0.0),
|
|
new Cartesian3(0.0, 0.0, 100.0)
|
|
);
|
|
|
|
var ray = new Ray(camera.position, camera.direction);
|
|
var featuresPromise = scene.imageryLayers.pickImageryLayerFeatures(
|
|
ray,
|
|
scene
|
|
);
|
|
expect(featuresPromise).toBeUndefined();
|
|
});
|
|
});
|
|
|
|
it("returns features from one layer", function () {
|
|
var provider = {
|
|
ready: true,
|
|
rectangle: Rectangle.MAX_VALUE,
|
|
tileWidth: 256,
|
|
tileHeight: 256,
|
|
maximumLevel: 0,
|
|
minimumLevel: 0,
|
|
tilingScheme: new GeographicTilingScheme(),
|
|
errorEvent: new Event(),
|
|
hasAlphaChannel: true,
|
|
|
|
pickFeatures: function (x, y, level, longitude, latitude) {
|
|
var deferred = when.defer();
|
|
setTimeout(function () {
|
|
var featureInfo = new ImageryLayerFeatureInfo();
|
|
featureInfo.name = "Foo";
|
|
featureInfo.description = "<strong>Foo!</strong>";
|
|
deferred.resolve([featureInfo]);
|
|
}, 1);
|
|
return deferred.promise;
|
|
},
|
|
|
|
requestImage: function (x, y, level) {
|
|
return ImageryProvider.loadImage(this, "Data/Images/Blue.png");
|
|
},
|
|
};
|
|
|
|
var currentLayer = globe.imageryLayers.addImageryProvider(provider);
|
|
|
|
return updateUntilDone(globe).then(function () {
|
|
var ellipsoid = Ellipsoid.WGS84;
|
|
camera.lookAt(
|
|
new Cartesian3(ellipsoid.maximumRadius, 0.0, 0.0),
|
|
new Cartesian3(0.0, 0.0, 100.0)
|
|
);
|
|
camera.lookAtTransform(Matrix4.IDENTITY);
|
|
|
|
var ray = new Ray(camera.position, camera.direction);
|
|
var featuresPromise = scene.imageryLayers.pickImageryLayerFeatures(
|
|
ray,
|
|
scene
|
|
);
|
|
|
|
expect(featuresPromise).toBeDefined();
|
|
|
|
return featuresPromise.then(function (features) {
|
|
expect(features.length).toBe(1);
|
|
expect(features[0].name).toEqual("Foo");
|
|
expect(features[0].description).toContain("Foo!");
|
|
expect(features[0].imageryLayer).toBe(currentLayer);
|
|
});
|
|
});
|
|
});
|
|
|
|
it("returns features from two layers", function () {
|
|
var provider1 = {
|
|
ready: true,
|
|
rectangle: Rectangle.MAX_VALUE,
|
|
tileWidth: 256,
|
|
tileHeight: 256,
|
|
maximumLevel: 0,
|
|
minimumLevel: 0,
|
|
tilingScheme: new GeographicTilingScheme(),
|
|
errorEvent: new Event(),
|
|
hasAlphaChannel: true,
|
|
|
|
pickFeatures: function (x, y, level, longitude, latitude) {
|
|
var deferred = when.defer();
|
|
setTimeout(function () {
|
|
var featureInfo = new ImageryLayerFeatureInfo();
|
|
featureInfo.name = "Foo";
|
|
featureInfo.description = "<strong>Foo!</strong>";
|
|
deferred.resolve([featureInfo]);
|
|
}, 1);
|
|
return deferred.promise;
|
|
},
|
|
|
|
requestImage: function (x, y, level) {
|
|
return ImageryProvider.loadImage(this, "Data/Images/Blue.png");
|
|
},
|
|
};
|
|
|
|
var currentLayer1 = globe.imageryLayers.addImageryProvider(provider1);
|
|
|
|
var provider2 = {
|
|
ready: true,
|
|
rectangle: Rectangle.MAX_VALUE,
|
|
tileWidth: 256,
|
|
tileHeight: 256,
|
|
maximumLevel: 0,
|
|
minimumLevel: 0,
|
|
tilingScheme: new GeographicTilingScheme(),
|
|
errorEvent: new Event(),
|
|
hasAlphaChannel: true,
|
|
|
|
pickFeatures: function (x, y, level, longitude, latitude) {
|
|
var deferred = when.defer();
|
|
setTimeout(function () {
|
|
var featureInfo = new ImageryLayerFeatureInfo();
|
|
featureInfo.name = "Bar";
|
|
featureInfo.description = "<strong>Bar!</strong>";
|
|
deferred.resolve([featureInfo]);
|
|
}, 1);
|
|
return deferred.promise;
|
|
},
|
|
|
|
requestImage: function (x, y, level) {
|
|
return ImageryProvider.loadImage(this, "Data/Images/Green.png");
|
|
},
|
|
};
|
|
|
|
var currentLayer2 = globe.imageryLayers.addImageryProvider(provider2);
|
|
|
|
return updateUntilDone(globe).then(function () {
|
|
var ellipsoid = Ellipsoid.WGS84;
|
|
camera.lookAt(
|
|
new Cartesian3(ellipsoid.maximumRadius, 0.0, 0.0),
|
|
new Cartesian3(0.0, 0.0, 100.0)
|
|
);
|
|
camera.lookAtTransform(Matrix4.IDENTITY);
|
|
|
|
var ray = new Ray(camera.position, camera.direction);
|
|
var featuresPromise = scene.imageryLayers.pickImageryLayerFeatures(
|
|
ray,
|
|
scene
|
|
);
|
|
|
|
expect(featuresPromise).toBeDefined();
|
|
|
|
return featuresPromise.then(function (features) {
|
|
expect(features.length).toBe(2);
|
|
expect(features[0].name).toEqual("Bar");
|
|
expect(features[0].description).toContain("Bar!");
|
|
expect(features[0].imageryLayer).toBe(currentLayer2);
|
|
expect(features[1].name).toEqual("Foo");
|
|
expect(features[1].description).toContain("Foo!");
|
|
expect(features[1].imageryLayer).toBe(currentLayer1);
|
|
});
|
|
});
|
|
});
|
|
|
|
it("correctly picks from a terrain tile that is partially covered by correct-level imagery and partially covered by imagery from an ancestor level", function () {
|
|
var provider = {
|
|
ready: true,
|
|
rectangle: new Rectangle(
|
|
-Math.PI,
|
|
-WebMercatorProjection.MaximumLatitude,
|
|
Math.PI,
|
|
WebMercatorProjection.MaximumLatitude
|
|
),
|
|
tileWidth: 256,
|
|
tileHeight: 256,
|
|
maximumLevel: 1,
|
|
minimumLevel: 1,
|
|
tilingScheme: new WebMercatorTilingScheme(),
|
|
errorEvent: new Event(),
|
|
hasAlphaChannel: true,
|
|
|
|
pickFeatures: function (x, y, level, longitude, latitude) {
|
|
var deferred = when.defer();
|
|
setTimeout(function () {
|
|
var featureInfo = new ImageryLayerFeatureInfo();
|
|
featureInfo.name = "L" + level + "X" + x + "Y" + y;
|
|
deferred.resolve([featureInfo]);
|
|
}, 1);
|
|
return deferred.promise;
|
|
},
|
|
|
|
requestImage: function (x, y, level) {
|
|
// At level 1, only the northwest quadrant has a valid tile.
|
|
if (level !== 1 || (x === 0 && y === 0)) {
|
|
return ImageryProvider.loadImage(this, "Data/Images/Blue.png");
|
|
}
|
|
return when.reject();
|
|
},
|
|
};
|
|
|
|
globe.imageryLayers.addImageryProvider(provider);
|
|
|
|
camera.setView({
|
|
destination: Rectangle.fromDegrees(-180.0, 0, 0, 90),
|
|
});
|
|
|
|
return updateUntilDone(globe).then(function () {
|
|
var ray = new Ray(camera.position, camera.direction);
|
|
var featuresPromise = scene.imageryLayers.pickImageryLayerFeatures(
|
|
ray,
|
|
scene
|
|
);
|
|
|
|
expect(featuresPromise).toBeDefined();
|
|
|
|
return featuresPromise.then(function (features) {
|
|
// Verify that we don't end up picking from imagery level 0.
|
|
expect(features.length).toBe(1);
|
|
expect(features[0].name).toEqual("L1X0Y0");
|
|
});
|
|
});
|
|
});
|
|
});
|
|
},
|
|
"WebGL"
|
|
);
|