import { ArcType } from "../../Source/Cesium.js";
import { BoundingRectangle } from "../../Source/Cesium.js";
import { Cartesian2 } from "../../Source/Cesium.js";
import { Cartesian3 } from "../../Source/Cesium.js";
import { ClockRange } from "../../Source/Cesium.js";
import { ClockStep } from "../../Source/Cesium.js";
import { Color } from "../../Source/Cesium.js";
import { combine } from "../../Source/Cesium.js";
import { Credit } from "../../Source/Cesium.js";
import { Ellipsoid } from "../../Source/Cesium.js";
import { Event } from "../../Source/Cesium.js";
import { HeadingPitchRange } from "../../Source/Cesium.js";
import { HeadingPitchRoll } from "../../Source/Cesium.js";
import { isDataUri } from "../../Source/Cesium.js";
import { Iso8601 } from "../../Source/Cesium.js";
import { JulianDate } from "../../Source/Cesium.js";
import { Math as CesiumMath } from "../../Source/Cesium.js";
import { NearFarScalar } from "../../Source/Cesium.js";
import { PerspectiveFrustum } from "../../Source/Cesium.js";
import { Rectangle } from "../../Source/Cesium.js";
import { RequestErrorEvent } from "../../Source/Cesium.js";
import { Resource } from "../../Source/Cesium.js";
import { RuntimeError } from "../../Source/Cesium.js";
import { ColorMaterialProperty } from "../../Source/Cesium.js";
import { EntityCollection } from "../../Source/Cesium.js";
import { ImageMaterialProperty } from "../../Source/Cesium.js";
import { KmlCamera } from "../../Source/Cesium.js";
import { KmlDataSource } from "../../Source/Cesium.js";
import { KmlLookAt } from "../../Source/Cesium.js";
import { KmlTour } from "../../Source/Cesium.js";
import { KmlTourFlyTo } from "../../Source/Cesium.js";
import { KmlTourWait } from "../../Source/Cesium.js";
import { Camera } from "../../Source/Cesium.js";
import { HeightReference } from "../../Source/Cesium.js";
import { HorizontalOrigin } from "../../Source/Cesium.js";
import { LabelStyle } from "../../Source/Cesium.js";
import { SceneMode } from "../../Source/Cesium.js";
import createCamera from "../createCamera.js";
import pollToPromise from "../pollToPromise.js";
import { when } from "../../Source/Cesium.js";
describe("DataSources/KmlDataSource", function () {
var parser = new DOMParser();
//simple.png in the DATA/KML directory
var image =
"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAMAAAAoyzS7AAADAFBMVEUAAP8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADHM2paAAAAGHRFWHRTb2Z0d2FyZQBQYWludC5ORVQgdjMuMzap5+IlAAAACklEQVQI12NgAAAAAgAB4iG8MwAAAABJRU5ErkJggg==";
var uberStyle =
'\
';
var uberLineColor = Color.fromBytes(0xaa, 0xaa, 0xaa, 0xaa);
var uberLineWidth = 2;
var uberPolyColor = Color.fromBytes(0xcc, 0xcc, 0xcc, 0xcc);
var uberPolyFill = false;
var uberPolyOutline = false;
var uberIconColor = Color.fromBytes(0xdd, 0xdd, 0xdd, 0xdd);
var uberIconScale = 3;
var uberIconHeading = CesiumMath.toRadians(-45);
var uberIconHotspot = new Cartesian2(45, -42);
var uberIconHref = Resource.DEFAULT.getDerivedResource({
url: "test.png",
}).url;
var uberLabelColor = Color.fromBytes(0xee, 0xee, 0xee, 0xee);
var uberLabelScale = 4;
var expectedRefreshLinkHref = Resource.DEFAULT.getDerivedResource({
url: "./Data/KML/refresh.kml",
}).url;
var screenOverlayContainer = document.createElement("div");
var options = {
camera: {
positionWC: new Cartesian3(0.0, 0.0, 0.0),
directionWC: new Cartesian3(0.0, 0.0, 1.0),
upWC: new Cartesian3(0.0, 1.0, 0.0),
pitch: 0.0,
heading: 0.0,
frustum: new PerspectiveFrustum(),
computeViewRectangle: function () {
return Rectangle.MAX_VALUE;
},
pickEllipsoid: function () {
return undefined;
},
},
canvas: {
clientWidth: 512,
clientHeight: 512,
},
credit: "This is my credit",
screenOverlayContainer: screenOverlayContainer,
};
options.camera.frustum.fov = CesiumMath.PI_OVER_FOUR;
options.camera.frustum.aspectRatio = 1.0;
beforeEach(function () {
// Reset camera - x value will change during onStop tests
options.camera.positionWC.x = 0.0;
});
it("default constructor has expected values", function () {
var dataSource = new KmlDataSource(options);
expect(dataSource.name).toBeUndefined();
expect(dataSource.clock).toBeUndefined();
expect(dataSource.entities).toBeInstanceOf(EntityCollection);
expect(dataSource.isLoading).toBe(false);
expect(dataSource.changedEvent).toBeInstanceOf(Event);
expect(dataSource.errorEvent).toBeInstanceOf(Event);
expect(dataSource.loadingEvent).toBeInstanceOf(Event);
expect(dataSource.unsupportedNodeEvent).toBeInstanceOf(Event);
expect(dataSource.show).toBe(true);
expect(dataSource.credit).toBeInstanceOf(Credit);
});
it("setting name raises changed event", function () {
var dataSource = new KmlDataSource(options);
var spy = jasmine.createSpy("changedEvent");
dataSource.changedEvent.addEventListener(spy);
var newName = "garfield";
dataSource.name = newName;
expect(dataSource.name).toEqual(newName);
expect(spy.calls.count()).toEqual(1);
expect(spy).toHaveBeenCalledWith(dataSource);
});
it("show sets underlying entity collection show.", function () {
var dataSource = new KmlDataSource(options);
dataSource.show = false;
expect(dataSource.show).toBe(false);
expect(dataSource.show).toEqual(dataSource.entities.show);
dataSource.show = true;
expect(dataSource.show).toBe(true);
expect(dataSource.show).toEqual(dataSource.entities.show);
});
it("load throws with undefined KML", function () {
var dataSource = new KmlDataSource(options);
expect(function () {
dataSource.load(undefined);
}).toThrowDeveloperError();
});
it("load works with a KMZ file", function () {
var dataSource = new KmlDataSource(options);
return Resource.fetchBlob("Data/KML/simple.kmz")
.then(function (blob) {
return dataSource.load(blob);
})
.then(function (source) {
expect(source).toBe(dataSource);
expect(source.entities.values.length).toEqual(1);
});
});
it("load rejects loading non-KMZ file", function () {
var dataSource = new KmlDataSource(options);
var spy = jasmine.createSpy("errorEvent");
dataSource.errorEvent.addEventListener(spy);
return Resource.fetchBlob("Data/Images/Blue.png")
.then(function (blob) {
return dataSource.load(blob);
})
.otherwise(function (e) {
expect(e).toBeInstanceOf(RuntimeError);
expect(spy).toHaveBeenCalled();
});
});
it("load rejects KMZ file with no KML contained", function () {
return Resource.fetchBlob("Data/KML/empty.kmz")
.then(function (blob) {
return KmlDataSource.load(blob, options);
})
.otherwise(function (e) {
expect(e).toBeInstanceOf(RuntimeError);
expect(e.message).toEqual("KMZ file does not contain a KML document.");
});
});
it("load works with a KML URL", function () {
var dataSource = new KmlDataSource(options);
return dataSource
.load("Data/KML/simple.kml", options)
.then(function (source) {
expect(source).toBe(dataSource);
expect(source.entities.values.length).toEqual(1);
});
});
it("load works with a KML Resource", function () {
var dataSource = new KmlDataSource(options);
var resource = new Resource({
url: "Data/KML/simple.kml",
});
return dataSource.load(resource, options).then(function (source) {
expect(source).toBe(dataSource);
expect(source.entities.values.length).toEqual(1);
});
});
it("load works with a KMZ URL", function () {
var dataSource = new KmlDataSource(options);
return dataSource.load("Data/KML/simple.kmz").then(function (source) {
expect(source).toBe(dataSource);
expect(source.entities.values.length).toEqual(1);
});
});
it("load works with a KMZ URL with Windows-style paths", function () {
var dataSource = new KmlDataSource(options);
return dataSource.load("Data/KML/backslash.kmz").then(function (source) {
expect(source).toBe(dataSource);
expect(
isDataUri(source.entities.values[0]._billboard._image._value.url)
).toBe(true);
});
});
it("load works with a KMZ Resource", function () {
var dataSource = new KmlDataSource(options);
var resource = new Resource({
url: "Data/KML/simple.kmz",
});
return dataSource.load(resource).then(function (source) {
expect(source).toBe(dataSource);
expect(source.entities.values.length).toEqual(1);
});
});
it("load does deferred loading", function () {
var kml =
'\
\
\
\
\
\
';
jasmine.clock().install();
jasmine.clock().mockDate(new Date());
// Jasmine doesn't mock performance.now(), so force Date.now()
spyOn(KmlDataSource, "_getTimestamp").and.callFake(function () {
return Date.now();
});
var OrigDeferredLoading = KmlDataSource._DeferredLoading;
var deferredLoading;
spyOn(KmlDataSource, "_DeferredLoading").and.callFake(function (
datasource
) {
deferredLoading = new OrigDeferredLoading(datasource);
var process = deferredLoading._process.bind(deferredLoading);
spyOn(deferredLoading, "_process").and.callFake(function (isFirst) {
jasmine.clock().tick(1001); // Step over a second everytime, so we only process 1 feature
return process(isFirst);
});
var giveUpTime = deferredLoading._giveUpTime.bind(deferredLoading);
spyOn(deferredLoading, "_giveUpTime").and.callFake(function () {
giveUpTime();
jasmine.clock().tick(1); // Fire the setTimeout callback
});
return deferredLoading;
});
var dataSource = new KmlDataSource(options);
return dataSource
.load(parser.parseFromString(kml, "text/xml"), options)
.then(function (source) {
expect(deferredLoading._process.calls.count()).toEqual(3); // Document and 2 placemarks
jasmine.clock().uninstall();
});
});
it("load inserts missing namespace declaration into kml", function () {
var dataSource = new KmlDataSource(options);
return dataSource
.load("Data/KML/undeclaredNamespaces.kml")
.then(function (source) {
expect(source).toBe(dataSource);
expect(source.entities.values.length).toEqual(1);
});
});
it("load inserts missing namespace declaration into kmz", function () {
var dataSource = new KmlDataSource(options);
return dataSource
.load("Data/KML/undeclaredNamespaces.kmz")
.then(function (source) {
expect(source).toBe(dataSource);
expect(source.entities.values.length).toEqual(1);
});
});
it("load deletes duplicate namespace declaration in kml", function () {
var datasource = new KmlDataSource(options);
return datasource
.load("Data/KML/duplicateNamespace.kml")
.then(function (source) {
expect(source).toBe(datasource);
expect(source.entities.values.length).toEqual(1);
});
});
it("load deletes duplicate namespace declaration in kmz", function () {
var dataSource = new KmlDataSource(options);
return dataSource
.load("Data/KML/duplicateNamespace.kmz")
.then(function (source) {
expect(source).toBe(dataSource);
expect(source.entities.values.length).toEqual(1);
});
});
it("load rejects nonexistent URL", function () {
return KmlDataSource.load("test.invalid", options).otherwise(function (e) {
expect(e).toBeInstanceOf(RequestErrorEvent);
});
});
it("load rejects loading non-KML URL", function () {
return KmlDataSource.load("Data/Images/Blue.png", options).otherwise(
function (e) {
expect(e).toBeInstanceOf(RuntimeError);
}
);
});
it("load rejects valid KMZ zip URL with no KML contained", function () {
return KmlDataSource.load("Data/KML/empty.kmz", options).otherwise(
function (e) {
expect(e).toBeInstanceOf(RuntimeError);
expect(e.message).toEqual("KMZ file does not contain a KML document.");
}
);
});
it("if load contains tag with no image included, no image is added", function () {
var dataSource = new KmlDataSource(options);
return Resource.fetchBlob("Data/KML/simpleNoIcon.kml")
.then(function (blob) {
return dataSource.load(blob);
})
.then(function (source) {
expect(source.entities);
expect(source.entities.values.length).toEqual(1);
expect(source.entities._entities._array.length).toEqual(1);
expect(
source.entities._entities._array[0]._billboard._image
).toBeUndefined();
});
});
it("if load does not contain icon \
\
#testStyle\
\
';
return KmlDataSource.load(
parser.parseFromString(kml, "text/xml"),
options
).then(function (dataSource) {
var entities = dataSource.entities.values;
expect(entities.length).toEqual(1);
expect(entities[0].billboard.scale.getValue()).toEqual(3.0);
});
});
it("Styles: supports local styles with styleUrl missing #", function () {
var kml =
'\
\
\
\
testStyle\
\
';
return KmlDataSource.load(
parser.parseFromString(kml, "text/xml"),
options
).then(function (dataSource) {
var entities = dataSource.entities.values;
expect(entities.length).toEqual(1);
expect(entities[0].billboard.scale.getValue()).toEqual(3.0);
});
});
it("Styles: supports external styles with styleUrl", function () {
var kml =
'\
\
Data/KML/externalStyle.kml#testStyle\
';
return KmlDataSource.load(
parser.parseFromString(kml, "text/xml"),
options
).then(function (dataSource) {
var entities = dataSource.entities.values;
expect(entities[0].billboard.scale.getValue()).toEqual(3.0);
});
});
it("Styles: supports external style maps with styleUrl", function () {
var kml =
'\
\
Data/KML/externalStyle.kml#testStyleMap\
';
return KmlDataSource.load(
parser.parseFromString(kml, "text/xml"),
options
).then(function (dataSource) {
var entities = dataSource.entities.values;
expect(entities[0].billboard.scale.getValue()).toEqual(3.0);
});
});
it("Styles: inline styles take precedance over shared styles", function () {
var kml =
'\
\
\
\
#testStyle\
\
\
';
return KmlDataSource.load(
parser.parseFromString(kml, "text/xml"),
options
).then(function (dataSource) {
var entities = dataSource.entities.values;
expect(entities.length).toEqual(1);
var billboard = entities[0].billboard;
expect(billboard.scale.getValue()).toEqual(2.0);
expect(billboard.rotation.getValue()).toEqual(CesiumMath.toRadians(-4.0));
expect(billboard.image.getValue().url).toEqual("http://test.invalid/");
});
});
it("Styles: colorMode random", function () {
CesiumMath.setRandomNumberSeed(0);
var kml =
'\
\
\
';
return KmlDataSource.load(
parser.parseFromString(kml, "text/xml"),
options
).then(function (dataSource) {
var generatedColor = dataSource.entities.values[0].billboard.color.getValue();
expect(generatedColor.red).toBeLessThan(1.0);
expect(generatedColor.green).toBeLessThan(1.0);
expect(generatedColor.blue).toBeLessThan(1.0);
expect(generatedColor.alpha).toEqual(0.8);
});
});
it("Styles: colorMode random black", function () {
CesiumMath.setRandomNumberSeed(0);
var kml =
'\
\
\
';
return KmlDataSource.load(
parser.parseFromString(kml, "text/xml"),
options
).then(function (dataSource) {
var generatedColor = dataSource.entities.values[0].billboard.color.getValue();
expect(generatedColor.red).toEqual(0);
expect(generatedColor.green).toEqual(0);
expect(generatedColor.blue).toEqual(0);
expect(generatedColor.alpha).toEqual(0.8);
});
});
it("Styles: empty color", function () {
CesiumMath.setRandomNumberSeed(0);
var kml =
'\
\
\
';
return KmlDataSource.load(
parser.parseFromString(kml, "text/xml"),
options
).then(function (dataSource) {
expect(dataSource.entities.values[0].billboard.color).toBeUndefined();
});
});
it("Styles: Applies expected styles to Point geometry", function () {
var kml =
'\
\
' +
uberStyle +
"\
TheName\
\
absolute\
1,2,3\
\
\
";
return KmlDataSource.load(
parser.parseFromString(kml, "text/xml"),
options
).then(function (dataSource) {
var entity = dataSource.entities.values[0];
expect(entity.label).toBeDefined();
expect(entity.label.text.getValue()).toEqual("TheName");
expect(entity.label.fillColor.getValue()).toEqual(uberLabelColor);
expect(entity.label.scale.getValue()).toEqual(uberLabelScale);
expect(entity.billboard.color.getValue()).toEqual(uberIconColor);
expect(entity.billboard.scale.getValue()).toEqual(uberIconScale);
expect(entity.billboard.rotation.getValue()).toEqual(uberIconHeading);
expect(entity.billboard.image.getValue().url).toEqual(uberIconHref);
expect(entity.billboard.pixelOffset.getValue()).toEqual(uberIconHotspot);
expect(entity.polyline).toBeUndefined();
});
});
it("Styles: Applies expected styles to extruded Point geometry", function () {
var kml =
'\
\
' +
uberStyle +
"\
TheName\
\
1\
absolute\
1,2,3\
\
\
";
return KmlDataSource.load(
parser.parseFromString(kml, "text/xml"),
options
).then(function (dataSource) {
var entity = dataSource.entities.values[0];
expect(entity.label.text.getValue()).toEqual("TheName");
expect(entity.label.fillColor.getValue()).toEqual(uberLabelColor);
expect(entity.label.scale.getValue()).toEqual(uberLabelScale);
expect(entity.billboard.color.getValue()).toEqual(uberIconColor);
expect(entity.billboard.scale.getValue()).toEqual(uberIconScale);
expect(entity.billboard.rotation.getValue()).toEqual(uberIconHeading);
expect(entity.billboard.image.getValue().url).toEqual(uberIconHref);
expect(entity.billboard.pixelOffset.getValue()).toEqual(uberIconHotspot);
expect(entity.polyline.material).toBeInstanceOf(ColorMaterialProperty);
expect(entity.polyline.material.color.getValue()).toEqual(uberLineColor);
expect(entity.polyline.width.getValue()).toEqual(uberLineWidth);
});
});
it("Styles: Applies expected styles to LineString geometry", function () {
var kml =
'\
\
' +
uberStyle +
"\
TheName\
\
1,2,3 \
4,5,6 \
\
\
\
";
return KmlDataSource.load(
parser.parseFromString(kml, "text/xml"),
options
).then(function (dataSource) {
var entity = dataSource.entities.values[0];
expect(entity.polyline.material).toBeInstanceOf(ColorMaterialProperty);
expect(entity.polyline.material.color.getValue()).toEqual(uberLineColor);
expect(entity.polyline.width.getValue()).toEqual(uberLineWidth);
expect(entity.label).toBeUndefined();
expect(entity.wall).toBeUndefined();
});
});
it("Styles: Applies expected styles to extruded LineString geometry", function () {
var kml =
'\
\
' +
uberStyle +
"\
TheName\
\
1\
absolute\
1,2,3 \
4,5,6 \
\
\
\
";
return KmlDataSource.load(
parser.parseFromString(kml, "text/xml"),
options
).then(function (dataSource) {
var entity = dataSource.entities.values[0];
expect(entity.wall.material).toBeInstanceOf(ColorMaterialProperty);
expect(entity.wall.material.color.getValue()).toEqual(uberPolyColor);
expect(entity.wall.fill.getValue()).toEqual(uberPolyFill);
expect(entity.wall.outline.getValue()).toEqual(true);
expect(entity.wall.outlineColor.getValue()).toEqual(uberLineColor);
expect(entity.wall.outlineWidth.getValue()).toEqual(uberLineWidth);
expect(entity.polyline).toBeUndefined();
expect(entity.label).toBeUndefined();
});
});
it("Styles: Applies expected styles to Polygon geometry", function () {
var kml =
'\
\
' +
uberStyle +
"\
\
1\
absolute\
\
\
\
1,2,3\
4,5,6\
7,8,9\
\
\
\
\
\
";
return KmlDataSource.load(
parser.parseFromString(kml, "text/xml"),
options
).then(function (dataSource) {
var entity = dataSource.entities.values[0];
expect(entity.polygon.material).toBeInstanceOf(ColorMaterialProperty);
expect(entity.polygon.material.color.getValue()).toEqual(uberPolyColor);
expect(entity.polygon.fill.getValue()).toEqual(uberPolyFill);
expect(entity.polygon.outline.getValue()).toEqual(uberPolyOutline);
expect(entity.polygon.outlineColor.getValue()).toEqual(uberLineColor);
expect(entity.polygon.outlineWidth.getValue()).toEqual(uberLineWidth);
expect(entity.label).toBeUndefined();
});
});
it("Styles: Applies expected styles to gx:Track geometry", function () {
var kml =
'\
\
' +
uberStyle +
"\
TheName\
\
absolute\
2000-01-01T00:00:02Z\
7 8 9\
\
\
";
return KmlDataSource.load(
parser.parseFromString(kml, "text/xml"),
options
).then(function (dataSource) {
var entity = dataSource.entities.values[0];
expect(entity.label).toBeDefined();
expect(entity.label.text.getValue()).toEqual("TheName");
expect(entity.label.fillColor.getValue()).toEqual(uberLabelColor);
expect(entity.label.scale.getValue()).toEqual(uberLabelScale);
expect(entity.billboard.color.getValue()).toEqual(uberIconColor);
expect(entity.billboard.scale.getValue()).toEqual(uberIconScale);
expect(entity.billboard.rotation.getValue()).toEqual(uberIconHeading);
expect(entity.billboard.image.getValue().url).toEqual(uberIconHref);
expect(entity.billboard.pixelOffset.getValue()).toEqual(uberIconHotspot);
expect(entity.path).toBeDefined();
expect(entity.path.material).toBeInstanceOf(ColorMaterialProperty);
expect(entity.path.material.color.getValue()).toEqual(uberLineColor);
expect(entity.path.width.getValue()).toEqual(uberLineWidth);
expect(entity.path.leadTime.getValue()).toEqual(0);
expect(entity.path.trailTime).toBeUndefined();
expect(entity.polyline).toBeUndefined();
});
});
it("Styles: Applies expected styles to extruded gx:Track geometry", function () {
var kml =
'\
\
' +
uberStyle +
"\
TheName\
\
1\
absolute\
2000-01-01T00:00:02Z\
7 8 9\
\
\
";
return KmlDataSource.load(
parser.parseFromString(kml, "text/xml"),
options
).then(function (dataSource) {
var entity = dataSource.entities.values[0];
expect(entity.label.text.getValue()).toEqual("TheName");
expect(entity.label.fillColor.getValue()).toEqual(uberLabelColor);
expect(entity.label.scale.getValue()).toEqual(uberLabelScale);
expect(entity.billboard.color.getValue()).toEqual(uberIconColor);
expect(entity.billboard.scale.getValue()).toEqual(uberIconScale);
expect(entity.billboard.rotation.getValue()).toEqual(uberIconHeading);
expect(entity.billboard.image.getValue().url).toEqual(uberIconHref);
expect(entity.billboard.pixelOffset.getValue()).toEqual(uberIconHotspot);
expect(entity.path).toBeDefined();
expect(entity.path.material).toBeInstanceOf(ColorMaterialProperty);
expect(entity.path.material.color.getValue()).toEqual(uberLineColor);
expect(entity.path.width.getValue()).toEqual(uberLineWidth);
expect(entity.path.leadTime.getValue()).toEqual(0);
expect(entity.path.trailTime).toBeUndefined();
expect(entity.polyline.material).toBeInstanceOf(ColorMaterialProperty);
expect(entity.polyline.material.color.getValue()).toEqual(uberLineColor);
expect(entity.polyline.width.getValue()).toEqual(uberLineWidth);
});
});
it("Styles: Applies expected styles to gx:MultiTrack geometry", function () {
var kml =
'\
\
' +
uberStyle +
"\
TheName\
\
\
absolute\
2000-01-01T00:00:02Z\
7 8 9\
\
\
\
";
return KmlDataSource.load(
parser.parseFromString(kml, "text/xml"),
options
).then(function (dataSource) {
var entity = dataSource.entities.values[0];
expect(entity.label).toBeDefined();
expect(entity.label.text.getValue()).toEqual("TheName");
expect(entity.label.fillColor.getValue()).toEqual(uberLabelColor);
expect(entity.label.scale.getValue()).toEqual(uberLabelScale);
expect(entity.billboard.color.getValue()).toEqual(uberIconColor);
expect(entity.billboard.scale.getValue()).toEqual(uberIconScale);
expect(entity.billboard.rotation.getValue()).toEqual(uberIconHeading);
expect(entity.billboard.image.getValue().url).toEqual(uberIconHref);
expect(entity.billboard.pixelOffset.getValue()).toEqual(uberIconHotspot);
expect(entity.path).toBeDefined();
expect(entity.path.material).toBeInstanceOf(ColorMaterialProperty);
expect(entity.path.material.color.getValue()).toEqual(uberLineColor);
expect(entity.path.width.getValue()).toEqual(uberLineWidth);
expect(entity.path.leadTime.getValue()).toEqual(0);
expect(entity.path.trailTime).toBeUndefined();
expect(entity.polyline).toBeUndefined();
});
});
it("Styles: Applies expected styles to extruded gx:MultiTrack geometry", function () {
var kml =
'\
\
' +
uberStyle +
"\
TheName\
\
\
1\
absolute\
2000-01-01T00:00:02Z\
7 8 9\
\
\
\
";
return KmlDataSource.load(
parser.parseFromString(kml, "text/xml"),
options
).then(function (dataSource) {
var entity = dataSource.entities.values[0];
expect(entity.label.text.getValue()).toEqual("TheName");
expect(entity.label.fillColor.getValue()).toEqual(uberLabelColor);
expect(entity.label.scale.getValue()).toEqual(uberLabelScale);
expect(entity.billboard.color.getValue()).toEqual(uberIconColor);
expect(entity.billboard.scale.getValue()).toEqual(uberIconScale);
expect(entity.billboard.rotation.getValue()).toEqual(uberIconHeading);
expect(entity.billboard.image.getValue().url).toEqual(uberIconHref);
expect(entity.billboard.pixelOffset.getValue()).toEqual(uberIconHotspot);
expect(entity.path).toBeDefined();
expect(entity.path.material).toBeInstanceOf(ColorMaterialProperty);
expect(entity.path.material.color.getValue()).toEqual(uberLineColor);
expect(entity.path.width.getValue()).toEqual(uberLineWidth);
expect(entity.path.leadTime.getValue()).toEqual(0);
expect(entity.path.trailTime).toBeUndefined();
expect(entity.polyline.material).toBeInstanceOf(ColorMaterialProperty);
expect(entity.polyline.material.color.getValue()).toEqual(uberLineColor);
expect(entity.polyline.width.getValue()).toEqual(uberLineWidth);
});
});
it("Styles: Applies local StyleMap", function () {
var kml =
'\
\
\
\
\
normal\
\
\
\
\
';
return KmlDataSource.load(
parser.parseFromString(kml, "text/xml"),
options
).then(function (dataSource) {
var entity = dataSource.entities.values[0];
expect(entity.billboard.scale.getValue()).toBe(2.0);
});
});
it("Styles: Applies normal styleUrl StyleMap", function () {
var kml =
'\
\
\
\
normal\
\
\
\
\
#styleMapExample\
\
';
return KmlDataSource.load(
parser.parseFromString(kml, "text/xml"),
options
).then(function (dataSource) {
var entity = dataSource.entities.values[0];
expect(entity.billboard.scale.getValue()).toBe(2.0);
});
});
it("Styles: Applies normal StyleMap containing styleUrl", function () {
var kml =
'\
\
\
\
\
normal\
#normalStyle\
\
\
\
#styleMapExample\
\
';
return KmlDataSource.load(
parser.parseFromString(kml, "text/xml"),
options
).then(function (dataSource) {
var entity = dataSource.entities.values[0];
expect(entity.billboard.scale.getValue()).toBe(2.0);
});
});
it("Styles: Applies normal StyleMap containing styleUrl without #", function () {
var kml =
'\
\
\
\
\
normal\
normalStyle\
\
\
\
#styleMapExample\
\
';
return KmlDataSource.load(
parser.parseFromString(kml, "text/xml"),
options
).then(function (dataSource) {
var entity = dataSource.entities.values[0];
expect(entity.billboard.scale.getValue()).toBe(2.0);
});
});
it("IconStyle: handles empty element", function () {
var kml =
'\
\
\
';
return KmlDataSource.load(
parser.parseFromString(kml, "text/xml"),
options
).then(function (dataSource) {
var entities = dataSource.entities.values;
expect(entities[0].billboard).toBeDefined();
});
});
it("IconStyle: Sets billboard image absolute path", function () {
var kml =
'\
\
\
';
return KmlDataSource.load(
parser.parseFromString(kml, "text/xml"),
options
).then(function (dataSource) {
var entities = dataSource.entities.values;
var billboard = entities[0].billboard;
expect(billboard.image.getValue().url).toEqual(
"http://test.invalid/image.png"
);
});
});
it("IconStyle: Sets billboard with root:// Url", function () {
var kml =
'\
\
\
';
return KmlDataSource.load(
parser.parseFromString(kml, "text/xml"),
options
).then(function (dataSource) {
var entities = dataSource.entities.values;
var billboard = entities[0].billboard;
expect(billboard.image.getValue().url).toEqual(
"https://maps.google.com/mapfiles/kml/pal3/icon56.png"
);
});
});
it("IconStyle: Sets billboard image relative path", function () {
var kml =
'\
\
\
';
return KmlDataSource.load(parser.parseFromString(kml, "text/xml"), {
camera: options.camera,
canvas: options.canvas,
sourceUri: "http://test.invalid",
}).then(function (dataSource) {
var entities = dataSource.entities.values;
var billboard = entities[0].billboard;
expect(billboard.image.getValue().url).toEqual(
"http://test.invalid/image.png"
);
});
});
it("IconStyle: Sets billboard image inside KMZ", function () {
return KmlDataSource.load("Data/KML/simple.kmz", options).then(function (
dataSource
) {
var entities = dataSource.entities.values;
var billboard = entities[0].billboard;
expect(billboard.image.getValue().url).toEqual(image);
});
});
it("IconStyle: Sets billboard image with subregion", function () {
var kml =
'\
\
\
';
var expectedIconHref = Resource.DEFAULT.getDerivedResource({
url: "whiteShapes.png",
}).url;
return KmlDataSource.load(
parser.parseFromString(kml, "text/xml"),
options
).then(function (dataSource) {
var billboard = dataSource.entities.values[0].billboard;
expect(billboard.image.getValue().url).toEqual(expectedIconHref);
expect(billboard.imageSubRegion.getValue()).toEqual(
new BoundingRectangle(49, 43, 18, 18)
);
});
});
it("IconStyle: Sets billboard image with hotSpot fractions", function () {
var kml =
'\
\
\
';
return KmlDataSource.load(
parser.parseFromString(kml, "text/xml"),
options
).then(function (dataSource) {
var billboard = dataSource.entities.values[0].billboard;
expect(billboard.pixelOffset.getValue()).toEqual(new Cartesian2(8, 8));
});
});
it("IconStyle: Sets billboard image with hotSpot pixels", function () {
var kml =
'\
\
\
';
return KmlDataSource.load(
parser.parseFromString(kml, "text/xml"),
options
).then(function (dataSource) {
var billboard = dataSource.entities.values[0].billboard;
expect(billboard.pixelOffset.getValue()).toEqual(new Cartesian2(15, -14));
});
});
it("IconStyle: Sets billboard image with hotSpot insetPixels", function () {
var kml =
'\
\
\
';
return KmlDataSource.load(
parser.parseFromString(kml, "text/xml"),
options
).then(function (dataSource) {
var billboard = dataSource.entities.values[0].billboard;
expect(billboard.pixelOffset.getValue()).toEqual(new Cartesian2(-15, 14));
});
});
it("IconStyle: Sets color", function () {
var color = Color.fromBytes(0xcc, 0xdd, 0xee, 0xff);
var kml =
'\
\
\
';
return KmlDataSource.load(
parser.parseFromString(kml, "text/xml"),
options
).then(function (dataSource) {
var entities = dataSource.entities.values;
expect(entities[0].billboard.color.getValue()).toEqual(color);
});
});
it("IconStyle: Sets scale", function () {
var kml =
'\
\
\
';
return KmlDataSource.load(
parser.parseFromString(kml, "text/xml"),
options
).then(function (dataSource) {
var entities = dataSource.entities.values;
expect(entities[0].billboard.scale.getValue()).toEqual(2.2);
});
});
it("IconStyle: Sets heading", function () {
var kml =
'\
\
\
';
return KmlDataSource.load(
parser.parseFromString(kml, "text/xml"),
options
).then(function (dataSource) {
var entities = dataSource.entities.values;
expect(entities[0].billboard.rotation.getValue()).toEqual(
CesiumMath.toRadians(-4)
);
expect(entities[0].billboard.alignedAxis.getValue()).toEqual(
Cartesian3.UNIT_Z
);
});
});
it("BalloonStyle: specify all properties", function () {
var kml =
'\
\
\
The Name\
The Description\
The Address\
The Snippet\
\
\
The Property\
The Value\
\
\
';
return KmlDataSource.load(
parser.parseFromString(kml, "text/xml"),
options
).then(function (dataSource) {
var entity = dataSource.entities.values[0];
var element = document.createElement("div");
element.innerHTML = entity.description.getValue();
var div = element.firstChild;
expect(div.style["word-wrap"]).toEqual("break-word");
expect(div.style["background-color"]).toEqual("rgba(102, 68, 34, 0)");
expect(div.style.color).toEqual("rgba(0, 34, 68, 0.4)");
expect(div.textContent).toEqual(
"The Name The Description The Address The Snippet The ID The Property The Value $[prop2/displayName] $[prop2]"
);
});
});
it("BalloonStyle: entity replacement removes missing values", function () {
var kml =
'\
\
\
';
return KmlDataSource.load(
parser.parseFromString(kml, "text/xml"),
options
).then(function (dataSource) {
var entity = dataSource.entities.values[0];
var element = document.createElement("div");
element.innerHTML = entity.description.getValue();
var div = element.firstChild;
expect(div.textContent).toEqual(" ");
});
});
it("BalloonStyle: description without BalloonStyle", function () {
var kml =
'\
\
The Description\
';
return KmlDataSource.load(
parser.parseFromString(kml, "text/xml"),
options
).then(function (dataSource) {
var entity = dataSource.entities.values[0];
var element = document.createElement("div");
element.innerHTML = entity.description.getValue();
var div = element.firstChild;
expect(div.style["word-wrap"]).toEqual("break-word");
expect(div.style["background-color"]).toEqual("rgb(255, 255, 255)");
expect(div.style.color).toEqual("rgb(0, 0, 0)");
expect(div.textContent).toEqual("The Description");
});
});
it("BalloonStyle: creates table from ExtendedData", function () {
var kml =
'\
\
\
\
Property 1\
1\
\
\
2\
\
\
Property 3\
\
\
';
return KmlDataSource.load(
parser.parseFromString(kml, "text/xml"),
options
).then(function (dataSource) {
var entity = dataSource.entities.values[0];
var element = document.createElement("div");
element.innerHTML = entity.description.getValue();
var div = element.firstChild;
expect(div.style["word-wrap"]).toEqual("break-word");
expect(div.style["background-color"]).toEqual("rgb(255, 255, 255)");
expect(div.style.color).toEqual("rgb(0, 0, 0)");
var table = div.firstChild;
expect(table.localName).toEqual("table");
expect(table.rows.length).toBe(3);
expect(table.rows[0].cells.length).toEqual(2);
expect(table.rows[1].cells.length).toEqual(2);
expect(table.rows[2].cells.length).toEqual(2);
expect(table.rows[0].cells[0].textContent).toEqual("Property 1");
expect(table.rows[1].cells[0].textContent).toEqual("prop2");
expect(table.rows[2].cells[0].textContent).toEqual("Property 3");
expect(table.rows[0].cells[1].textContent).toEqual("1");
expect(table.rows[1].cells[1].textContent).toEqual("2");
expect(table.rows[2].cells[1].textContent).toEqual("");
});
});
it("BalloonStyle: does not create a description for empty ExtendedData", function () {
var kml =
'\
\
\
\
';
return KmlDataSource.load(
parser.parseFromString(kml, "text/xml"),
options
).then(function (dataSource) {
var entity = dataSource.entities.values[0];
expect(entity.description).toBeUndefined();
});
});
it("BalloonStyle: description creates links from text", function () {
var kml =
'\
\
http://cesiumjs.org\
';
return KmlDataSource.load(
parser.parseFromString(kml, "text/xml"),
options
).then(function (dataSource) {
var entity = dataSource.entities.values[0];
var element = document.createElement("div");
element.innerHTML = entity.description.getValue();
var a = element.firstChild.firstChild;
expect(a.localName).toEqual("a");
expect(a.getAttribute("href")).toEqual("http://cesiumjs.org/");
expect(a.getAttribute("target")).toEqual("_blank");
});
});
it("BalloonStyle: relative description paths absolute to sourceUri", function () {
var kml =
'\
\
]]>\
';
return KmlDataSource.load(parser.parseFromString(kml, "text/xml"), {
camera: options.camera,
canvas: options.canvas,
sourceUri: "http://test.invalid",
}).then(function (dataSource) {
var entity = dataSource.entities.values[0];
var element = document.createElement("div");
element.innerHTML = entity.description.getValue();
var a = element.firstChild.firstChild;
expect(a.localName).toEqual("img");
expect(a.getAttribute("src")).toEqual("http://test.invalid/foo/bar.png");
});
});
it("BalloonStyle: description retargets existing links to _blank", function () {
var kml =
'\
\
Homepage]]>\
';
return KmlDataSource.load(
parser.parseFromString(kml, "text/xml"),
options
).then(function (dataSource) {
var entity = dataSource.entities.values[0];
var element = document.createElement("div");
element.innerHTML = entity.description.getValue();
var a = element.firstChild.firstChild;
expect(a.localName).toEqual("a");
expect(a.textContent).toEqual("Homepage");
expect(a.getAttribute("href")).toEqual("http://cesiumjs.org/");
expect(a.getAttribute("target")).toEqual("_blank");
});
});
it("BalloonStyle: description does not create links from non-explicit urls", function () {
var kml =
'\
\
states.id google.com\
';
return KmlDataSource.load(
parser.parseFromString(kml, "text/xml"),
options
).then(function (dataSource) {
var entity = dataSource.entities.values[0];
var element = document.createElement("div");
element.innerHTML = entity.description.getValue();
var div = element.firstChild;
expect(div.innerHTML).toEqual("states.id google.com");
});
});
it("BalloonStyle: description is rewritten for embedded kmz links and images", function () {
return KmlDataSource.load("Data/KML/simple.kmz", options).then(function (
dataSource
) {
var entity = dataSource.entities.values[0];
var description = entity.description.getValue();
var div = document.createElement("div");
div.innerHTML = description;
expect(div.textContent).toEqual("image.png image.png");
var children = div.firstChild.querySelectorAll("*");
expect(children.length).toEqual(2);
var link = children[0];
expect(link.localName).toEqual("a");
expect(link.getAttribute("href")).toEqual(image);
expect(link.getAttribute("download")).toEqual("image.png");
var img = children[1];
expect(img.localName).toEqual("img");
expect(img.src).toEqual(image);
});
});
it("LabelStyle: Sets defaults", function () {
var kml =
'\
\
\
';
return KmlDataSource.load(
parser.parseFromString(kml, "text/xml"),
options
).then(function (dataSource) {
var entities = dataSource.entities.values;
var label = entities[0].label;
expect(label).toBeDefined();
expect(label.text).toBeUndefined();
expect(label.fillColor).toBeUndefined();
expect(label.outlineColor).toBeUndefined();
expect(label.outlineWidth).toBeUndefined();
expect(label.show).toBeUndefined();
expect(label.scale).toBeUndefined();
expect(label.verticalOrigin).toBeUndefined();
expect(label.eyeOffset).toBeUndefined();
expect(label.pixelOffsetScaleByDistance).toBeUndefined();
expect(label.text).toBeUndefined();
expect(label.fillColor).toBeUndefined();
expect(label.outlineColor).toBeUndefined();
expect(label.outlineWidth).toBeUndefined();
expect(label.show).toBeUndefined();
expect(label.scale).toBeUndefined();
expect(label.verticalOrigin).toBeUndefined();
expect(label.eyeOffset).toBeUndefined();
expect(label.pixelOffsetScaleByDistance).toBeUndefined();
expect(label.font.getValue()).toEqual("16px sans-serif");
expect(label.style.getValue()).toEqual(LabelStyle.FILL_AND_OUTLINE);
expect(label.horizontalOrigin.getValue()).toEqual(HorizontalOrigin.LEFT);
expect(label.pixelOffset.getValue()).toEqual(new Cartesian2(17, 0));
expect(label.translucencyByDistance.getValue()).toEqual(
new NearFarScalar(3000000, 1.0, 5000000, 0.0)
);
});
});
it("LabelStyle: Sets color", function () {
var color = Color.fromBytes(0xcc, 0xdd, 0xee, 0xff);
var kml =
'\
\
\
';
return KmlDataSource.load(
parser.parseFromString(kml, "text/xml"),
options
).then(function (dataSource) {
var entities = dataSource.entities.values;
expect(entities[0].label.fillColor.getValue()).toEqual(color);
});
});
it("LabelStyle: Sets scale", function () {
var kml =
'\
\
\
';
return KmlDataSource.load(
parser.parseFromString(kml, "text/xml"),
options
).then(function (dataSource) {
var entities = dataSource.entities.values;
expect(entities[0].label.pixelOffset.getValue()).toEqual(
new Cartesian2(33, 0)
);
});
});
it("LabelStyle: Sets pixelOffset when billboard scaled", function () {
var kml =
'\
\
\
';
return KmlDataSource.load(
parser.parseFromString(kml, "text/xml"),
options
).then(function (dataSource) {
var entities = dataSource.entities.values;
expect(entities[0].label.pixelOffset.getValue()).toEqual(
new Cartesian3(3 * 16 + 1, 0)
);
});
});
it("LabelStyle: Sets pixelOffset when billboard scaled", function () {
var kml =
'\
\
\
';
return KmlDataSource.load(
parser.parseFromString(kml, "text/xml"),
options
).then(function (dataSource) {
var entities = dataSource.entities.values;
expect(entities[0].label.pixelOffset).toBeUndefined();
expect(entities[0].label.horizontalOrigin).toBeUndefined();
});
});
it("LineStyle: Sets defaults", function () {
var kml =
'\
\
\
';
return KmlDataSource.load(
parser.parseFromString(kml, "text/xml"),
options
).then(function (dataSource) {
var entities = dataSource.entities.values;
var polyline = entities[0].polyline;
expect(polyline).toBeDefined();
expect(polyline.positions).toBeUndefined();
expect(polyline.arcType).toBeUndefined();
expect(polyline.width).toBeUndefined();
expect(polyline.show).toBeUndefined();
expect(polyline.material).toBeUndefined();
expect(polyline.granularity).toBeUndefined();
});
});
it("LineStyle: Sets color", function () {
var color = Color.fromBytes(0xcc, 0xdd, 0xee, 0xff);
var kml =
'\
\
\
';
return KmlDataSource.load(
parser.parseFromString(kml, "text/xml"),
options
).then(function (dataSource) {
var entities = dataSource.entities.values;
var polyline = entities[0].polyline;
expect(polyline.material).toBeInstanceOf(ColorMaterialProperty);
expect(polyline.material.color.getValue()).toEqual(color);
});
});
it("LineStyle: Sets width", function () {
var kml =
'\
\
\
';
return KmlDataSource.load(
parser.parseFromString(kml, "text/xml"),
options
).then(function (dataSource) {
var entities = dataSource.entities.values;
var polyline = entities[0].polyline;
expect(polyline.width.getValue()).toEqual(2.75);
});
});
it("PolyStyle: Sets defaults", function () {
var kml =
'\
\
\
';
return KmlDataSource.load(
parser.parseFromString(kml, "text/xml"),
options
).then(function (dataSource) {
var entities = dataSource.entities.values;
var polygon = entities[0].polygon;
expect(polygon).toBeDefined();
expect(polygon.hierarchy).toBeUndefined();
expect(polygon.height).toBeUndefined();
expect(polygon.extrudedHeight).toBeUndefined();
expect(polygon.show).toBeUndefined();
expect(polygon.fill).toBeUndefined();
expect(polygon.material).toBeUndefined();
expect(polygon.outlineWidth).toBeUndefined();
expect(polygon.stRotation).toBeUndefined();
expect(polygon.granularity).toBeUndefined();
expect(polygon.perPositionHeight).toBeUndefined();
expect(polygon.outline.getValue()).toBe(true);
expect(polygon.outlineColor.getValue()).toEqual(Color.WHITE);
});
});
it("PolyStyle: Sets color", function () {
var color = Color.fromBytes(0xcc, 0xdd, 0xee, 0xff);
var kml =
'\
\
\
';
return KmlDataSource.load(
parser.parseFromString(kml, "text/xml"),
options
).then(function (dataSource) {
var entities = dataSource.entities.values;
var polygon = entities[0].polygon;
expect(polygon.material).toBeInstanceOf(ColorMaterialProperty);
expect(polygon.material.color.getValue()).toEqual(color);
});
});
it("PolyStyle: Sets fill", function () {
var kml =
'\
\
\
';
return KmlDataSource.load(
parser.parseFromString(kml, "text/xml"),
options
).then(function (dataSource) {
var entities = dataSource.entities.values;
var polygon = entities[0].polygon;
expect(polygon.fill.getValue()).toEqual(false);
});
});
it("PolyStyle: Sets outline", function () {
var kml =
'\
\
\
';
return KmlDataSource.load(
parser.parseFromString(kml, "text/xml"),
options
).then(function (dataSource) {
var entities = dataSource.entities.values;
var polygon = entities[0].polygon;
expect(polygon.outline.getValue()).toEqual(false);
});
});
it("Folder: sets parent property", function () {
var kml =
'\
\
\
\
';
return KmlDataSource.load(
parser.parseFromString(kml, "text/xml"),
options
).then(function (dataSource) {
var entities = dataSource.entities;
var folder = entities.getById("parent");
var placemark = entities.getById("child");
expect(entities.values.length).toBe(2);
expect(folder).toBeDefined();
expect(placemark.parent).toBe(folder);
});
});
it("Folder: timespan for folder", function () {
var kml =
'\
\
\
\
\
2000-01-01\
2000-01-03\
\
';
return KmlDataSource.load(
parser.parseFromString(kml, "text/xml"),
options
).then(function (dataSource) {
var start = JulianDate.fromIso8601("2000-01-01");
var stop = JulianDate.fromIso8601("2000-01-03");
var entities = dataSource.entities.values;
expect(entities.length).toBe(2);
var interval = entities[0].availability;
expect(interval.start).toEqual(start);
expect(interval.stop).toEqual(stop);
expect(entities[0].availability).toEqual(entities[1].availability);
});
});
it("Folder: timespan for folder and feature", function () {
var kml =
'\
\
\
\
2000-01-02\
2000-01-03\
\
\
\
2000-01-01\
2000-01-04\
\
';
return KmlDataSource.load(
parser.parseFromString(kml, "text/xml"),
options
).then(function (dataSource) {
var startFolder = JulianDate.fromIso8601("2000-01-01");
var stopFolder = JulianDate.fromIso8601("2000-01-04");
var startFeature = JulianDate.fromIso8601("2000-01-02");
var stopFeature = JulianDate.fromIso8601("2000-01-03");
var entities = dataSource.entities.values;
expect(entities.length).toBe(2);
var interval = entities[0].availability;
expect(interval.start).toEqual(startFolder);
expect(interval.stop).toEqual(stopFolder);
interval = entities[1].availability;
expect(interval.start).toEqual(startFeature);
expect(interval.stop).toEqual(stopFeature);
});
});
it("Folder: timestamp for folder", function () {
var kml =
'\
\
\
\
\
2000-01-03\
\
';
return KmlDataSource.load(
parser.parseFromString(kml, "text/xml"),
options
).then(function (dataSource) {
var start = JulianDate.fromIso8601("2000-01-03");
var entities = dataSource.entities.values;
expect(entities.length).toBe(2);
var interval = entities[0].availability;
expect(interval.start).toEqual(start);
expect(interval.stop).toEqual(Iso8601.MAXIMUM_VALUE);
expect(entities[0].availability).toEqual(entities[1].availability);
});
});
it("Folder: timestamp for folder and feature", function () {
var kml =
'\
\
\
\
2000-01-04\
2000-01-05\
\
\
\
2000-01-03\
\
';
return KmlDataSource.load(
parser.parseFromString(kml, "text/xml"),
options
).then(function (dataSource) {
var startFolder = JulianDate.fromIso8601("2000-01-03");
var startFeature = JulianDate.fromIso8601("2000-01-04");
var stopFeature = JulianDate.fromIso8601("2000-01-05");
var entities = dataSource.entities.values;
expect(entities.length).toBe(2);
var interval = entities[0].availability;
expect(interval.start).toEqual(startFolder);
expect(interval.stop).toEqual(Iso8601.MAXIMUM_VALUE);
interval = entities[1].availability;
expect(interval.start).toEqual(startFeature);
expect(interval.stop).toEqual(stopFeature);
});
});
it("Geometry Point: handles empty Point", function () {
var kml =
'\
\
\
\
';
return KmlDataSource.load(
parser.parseFromString(kml, "text/xml"),
options
).then(function (dataSource) {
var entities = dataSource.entities.values;
expect(entities.length).toEqual(1);
expect(entities[0].position.getValue(Iso8601.MINIMUM_VALUE)).toEqual(
Cartesian3.fromDegrees(0, 0, 0)
);
expect(entities[0].polyline).toBeUndefined();
});
});
it("Geometry Point: handles invalid coordinates", function () {
var kml =
'\
\
\
absolute\
1,2,3,4\
\
';
return KmlDataSource.load(
parser.parseFromString(kml, "text/xml"),
options
).then(function (dataSource) {
var entities = dataSource.entities.values;
expect(entities.length).toEqual(1);
expect(entities[0].position.getValue(Iso8601.MINIMUM_VALUE)).toEqual(
Cartesian3.fromDegrees(1, 2, 3)
);
expect(entities[0].polyline).toBeUndefined();
});
});
it("Geometry Point: handles empty coordinates", function () {
var kml =
'\
\
\
\
\
';
return KmlDataSource.load(
parser.parseFromString(kml, "text/xml"),
options
).then(function (dataSource) {
var entities = dataSource.entities.values;
expect(entities.length).toEqual(1);
expect(entities[0].position.getValue(Iso8601.MINIMUM_VALUE)).toEqual(
Cartesian3.fromDegrees(0, 0, 0)
);
expect(entities[0].polyline).toBeUndefined();
});
});
it("Geometry Point: sets heightReference to clampToGround", function () {
var kml =
'\
\
\
1,2,3\
\
';
return KmlDataSource.load(parser.parseFromString(kml, "text/xml"), {
camera: options.camera,
canvas: options.canvas,
clampToGround: true,
}).then(function (dataSource) {
var entities = dataSource.entities.values;
expect(entities.length).toEqual(1);
expect(
entities[0].billboard.heightReference.getValue(Iso8601.MINIMUM_VALUE)
).toEqual(HeightReference.CLAMP_TO_GROUND);
expect(entities[0].polyline).toBeUndefined();
});
});
it("Geometry Point: sets position altitudeMode absolute", function () {
var kml =
'\
\
\
absolute\
1,2,3\
\
';
return KmlDataSource.load(
parser.parseFromString(kml, "text/xml"),
options
).then(function (dataSource) {
var entities = dataSource.entities.values;
expect(entities.length).toEqual(1);
expect(entities[0].position.getValue(Iso8601.MINIMUM_VALUE)).toEqual(
Cartesian3.fromDegrees(1, 2, 3)
);
expect(entities[0].billboard.pixelOffset).toBeUndefined();
expect(entities[0].polyline).toBeUndefined();
});
});
it("Geometry Point: sets position altitudeMode relativeToGround", function () {
var kml =
'\
\
\
relativeToGround\
1,2,3\
\
';
return KmlDataSource.load(
parser.parseFromString(kml, "text/xml"),
options
).then(function (dataSource) {
var entities = dataSource.entities.values;
expect(entities.length).toEqual(1);
expect(entities[0].position.getValue(Iso8601.MINIMUM_VALUE)).toEqual(
Cartesian3.fromDegrees(1, 2, 3)
);
expect(entities[0].billboard.pixelOffset).toBeUndefined();
expect(entities[0].polyline).toBeUndefined();
});
});
it("Geometry Point: does not extrude when altitudeMode is clampToGround", function () {
var kml =
'\
\
\
clampToGround\
1,2\
1\
\
';
return KmlDataSource.load(
parser.parseFromString(kml, "text/xml"),
options
).then(function (dataSource) {
var entities = dataSource.entities.values;
expect(entities.length).toEqual(1);
expect(entities[0].position.getValue(Iso8601.MINIMUM_VALUE)).toEqual(
Cartesian3.fromDegrees(1, 2, 0)
);
expect(entities[0].billboard.pixelOffset).toBeUndefined();
expect(entities[0].polyline).toBeUndefined();
});
});
it("Geometry Point: does not extrude when gx:altitudeMode is clampToSeaFloor", function () {
var kml =
'\
\
\
clampToSeaFloor\
1,2\
1\
\
';
return KmlDataSource.load(
parser.parseFromString(kml, "text/xml"),
options
).then(function (dataSource) {
var entities = dataSource.entities.values;
expect(entities.length).toEqual(1);
expect(entities[0].position.getValue(Iso8601.MINIMUM_VALUE)).toEqual(
Cartesian3.fromDegrees(1, 2)
);
expect(entities[0].polyline).toBeUndefined();
});
});
it("Geometry Point: extrudes when altitudeMode is relativeToGround", function () {
var kml =
'\
\
\
relativeToGround\
1,2,3\
1\
\
';
return KmlDataSource.load(
parser.parseFromString(kml, "text/xml"),
options
).then(function (dataSource) {
var entities = dataSource.entities.values;
expect(entities.length).toEqual(1);
expect(entities[0].position.getValue(Iso8601.MINIMUM_VALUE)).toEqual(
Cartesian3.fromDegrees(1, 2, 3)
);
expect(entities[0].polyline).toBeDefined();
var positions = entities[0].polyline.positions.getValue(
Iso8601.MINIMUM_VALUE
);
expect(positions).toEqualEpsilon(
[Cartesian3.fromDegrees(1, 2, 3), Cartesian3.fromDegrees(1, 2, 0)],
CesiumMath.EPSILON13
);
});
});
it("Geometry Point: extrudes when gx:altitudeMode is relativeToSeaFloor", function () {
var kml =
'\
\
\
relativeToSeaFloor\
1,2,3\
1\
\
';
return KmlDataSource.load(
parser.parseFromString(kml, "text/xml"),
options
).then(function (dataSource) {
var entities = dataSource.entities.values;
expect(entities.length).toEqual(1);
expect(entities[0].position.getValue(Iso8601.MINIMUM_VALUE)).toEqual(
Cartesian3.fromDegrees(1, 2, 3)
);
expect(entities[0].polyline).toBeDefined();
var positions = entities[0].polyline.positions.getValue(
Iso8601.MINIMUM_VALUE
);
expect(positions).toEqualEpsilon(
[Cartesian3.fromDegrees(1, 2, 3), Cartesian3.fromDegrees(1, 2, 0)],
CesiumMath.EPSILON13
);
});
});
it("Geometry Point: extrudes when altitudeMode is absolute", function () {
var kml =
'\
\
\
absolute\
1,2,3\
1\
\
';
return KmlDataSource.load(
parser.parseFromString(kml, "text/xml"),
options
).then(function (dataSource) {
var entities = dataSource.entities.values;
expect(entities.length).toEqual(1);
expect(entities[0].position.getValue(Iso8601.MINIMUM_VALUE)).toEqual(
Cartesian3.fromDegrees(1, 2, 3)
);
expect(entities[0].polyline).toBeDefined();
var positions = entities[0].polyline.positions.getValue(
Iso8601.MINIMUM_VALUE
);
expect(positions).toEqualEpsilon(
[Cartesian3.fromDegrees(1, 2, 3), Cartesian3.fromDegrees(1, 2, 0)],
CesiumMath.EPSILON13
);
});
});
it("Geometry Point: correctly converts coordinates using earth ellipsoid", function () {
var kml =
'\
\
\
24.070617695061806,87.90173269295278,0\
\
';
return KmlDataSource.load(
parser.parseFromString(kml, "text/xml"),
options
).then(function (dataSource) {
var entities = dataSource.entities.values;
expect(entities.length).toEqual(1);
expect(
entities[0].position.getValue(Iso8601.MINIMUM_VALUE)
).toEqualEpsilon(
new Cartesian3(213935.5635247161, 95566.36983235707, 6352461.425213023),
CesiumMath.EPSILON13
);
});
});
it("Geometry Point: correctly converts coordinates using moon ellipsoid", function () {
var kml =
'\
\
\
24.070617695061806,87.90173269295278,0\
\
';
var moonOptions = combine(options, { ellipsoid: Ellipsoid.MOON });
return KmlDataSource.load(
parser.parseFromString(kml, "text/xml"),
moonOptions
).then(function (moonDataSource) {
var entities = moonDataSource.entities.values;
expect(entities.length).toEqual(1);
expect(
entities[0].position.getValue(Iso8601.MINIMUM_VALUE)
).toEqualEpsilon(
new Cartesian3(58080.7702560248, 25945.04756005268, 1736235.0758562544),
CesiumMath.EPSILON13
);
});
});
it("Geometry Polygon: handles empty coordinates", function () {
var kml =
'\
\
\
\
\
\
\
\
\
\
';
return KmlDataSource.load(
parser.parseFromString(kml, "text/xml"),
options
).then(function (dataSource) {
var entity = dataSource.entities.values[0];
expect(entity.polygon.hierarchy).toBeUndefined();
});
});
it("Geometry Polygon: without holes", function () {
var kml =
'\
\
\
\
\
\
1,2,3\
4,5,6\
7,8,9\
\
\
\
\
';
return KmlDataSource.load(
parser.parseFromString(kml, "text/xml"),
options
).then(function (dataSource) {
var entity = dataSource.entities.values[0];
var coordinates = [
Cartesian3.fromDegrees(1, 2, 3),
Cartesian3.fromDegrees(4, 5, 6),
Cartesian3.fromDegrees(7, 8, 9),
];
expect(entity.polygon.hierarchy.getValue().positions).toEqual(
coordinates
);
});
});
it("Geometry Polygon: with holes", function () {
var kml =
'\
\
\
\
\
\
1,2,3\
4,5,6\
7,8,9\
\
\
\
\
\
\
1.1,2.1,3.1\
4.1,5.1,6.1\
7.1,8.1,9.1\
\
\
\
\
\
\
1.2,2.2,3.2\
4.2,5.2,6.2\
7.2,8.2,9.2\
\
\
\
\
';
return KmlDataSource.load(
parser.parseFromString(kml, "text/xml"),
options
).then(function (dataSource) {
var entity = dataSource.entities.values[0];
var coordinates = [
Cartesian3.fromDegrees(1, 2, 3),
Cartesian3.fromDegrees(4, 5, 6),
Cartesian3.fromDegrees(7, 8, 9),
];
var holeCoordinates = [
Cartesian3.fromDegrees(1.1, 2.1, 3.1),
Cartesian3.fromDegrees(4.1, 5.1, 6.1),
Cartesian3.fromDegrees(7.1, 8.1, 9.1),
];
var holeCoordinates2 = [
Cartesian3.fromDegrees(1.2, 2.2, 3.2),
Cartesian3.fromDegrees(4.2, 5.2, 6.2),
Cartesian3.fromDegrees(7.2, 8.2, 9.2),
];
var hierarchy = entity.polygon.hierarchy.getValue();
expect(hierarchy.positions).toEqual(coordinates);
expect(hierarchy.holes.length).toEqual(2);
expect(hierarchy.holes[0].positions).toEqual(holeCoordinates);
expect(hierarchy.holes[0].holes).toEqual([]);
expect(hierarchy.holes[1].positions).toEqual(holeCoordinates2);
expect(hierarchy.holes[1].holes).toEqual([]);
});
});
it("Geometry Polygon: altitudeMode relativeToGround and can extrude", function () {
var kml =
'\
\
\
relativeToGround\
1\
\
';
return KmlDataSource.load(
parser.parseFromString(kml, "text/xml"),
options
).then(function (dataSource) {
var entity = dataSource.entities.values[0];
expect(entity.polygon.perPositionHeight.getValue()).toEqual(true);
expect(entity.polygon.extrudedHeight.getValue()).toEqual(0);
});
});
it("Geometry Polygon: altitudeMode absolute and can extrude", function () {
var kml =
'\
\
\
absolute\
1\
\
';
return KmlDataSource.load(
parser.parseFromString(kml, "text/xml"),
options
).then(function (dataSource) {
var entity = dataSource.entities.values[0];
expect(entity.polygon.perPositionHeight.getValue()).toEqual(true);
expect(entity.polygon.extrudedHeight.getValue()).toEqual(0);
});
});
it("Geometry Polygon: altitudeMode clampToGround and cannot extrude", function () {
var kml =
'\
\
\
clampToGround\
1\
\
';
return KmlDataSource.load(
parser.parseFromString(kml, "text/xml"),
options
).then(function (dataSource) {
var entity = dataSource.entities.values[0];
expect(entity.polygon.perPositionHeight).toBeUndefined();
expect(entity.polygon.extrudedHeight).toBeUndefined();
});
});
it("Geometry Polygon: gx:altitudeMode relativeToSeaFloor and can extrude", function () {
var kml =
'\
\
\
relativeToSeaFloor\
1\
\
';
return KmlDataSource.load(
parser.parseFromString(kml, "text/xml"),
options
).then(function (dataSource) {
var entity = dataSource.entities.values[0];
expect(entity.polygon.perPositionHeight.getValue()).toEqual(true);
expect(entity.polygon.extrudedHeight.getValue()).toEqual(0);
});
});
it("Geometry Polygon: gx:altitudeMode clampToSeaFloor and can extrude", function () {
var kml =
'\
\
\
clampToSeaFloor\
1\
\
';
return KmlDataSource.load(
parser.parseFromString(kml, "text/xml"),
options
).then(function (dataSource) {
var entity = dataSource.entities.values[0];
expect(entity.polygon.perPositionHeight).toBeUndefined();
expect(entity.polygon.extrudedHeight).toBeUndefined();
});
});
it("Geometry Polygon: When loaded with the Ellipsoid.MOON, the coordinates should be on the lunar ellipsoid, otherwise on Earth.", function () {
var kml =
'\
\
\
\
\
24.070617695061806,87.90173269295278,0\
49.598705282838125,87.04553528415659,0\
34.373553362965566,86.015550572534,0\
14.570663006937881,86.60174704052636,0\
24.070617695061806,87.90173269295278,0\
\
\
\
\
';
var moonOptions = combine(options, { ellipsoid: Ellipsoid.MOON });
return KmlDataSource.load(
parser.parseFromString(kml, "text/xml"),
moonOptions
).then(function (moonDataSource) {
var entity = moonDataSource.entities.values[0];
var moonPoint = entity.polygon.hierarchy.getValue().positions[0];
expect(moonPoint).toEqualEpsilon(
new Cartesian3(58080.7702560248, 25945.04756005268, 1736235.0758562544),
CesiumMath.EPSILON13
);
});
});
it("Geometry Polygon: When loaded with the default ellipsoid, the coordinates should be on Earth.", function () {
var kml =
'\
\
\
\
\
24.070617695061806,87.90173269295278,0\
49.598705282838125,87.04553528415659,0\
34.373553362965566,86.015550572534,0\
14.570663006937881,86.60174704052636,0\
24.070617695061806,87.90173269295278,0\
\
\
\
\
';
return KmlDataSource.load(
parser.parseFromString(kml, "text/xml"),
options
).then(function (dataSource) {
var entity = dataSource.entities.values[0];
var earthPoint = entity.polygon.hierarchy.getValue().positions[0];
expect(earthPoint).toEqualEpsilon(
new Cartesian3(213935.5635247161, 95566.36983235707, 6352461.425213023),
CesiumMath.EPSILON13
);
});
});
it("Geometry LineString: handles empty element", function () {
var kml =
'\
\
\
\
';
return KmlDataSource.load(
parser.parseFromString(kml, "text/xml"),
options
).then(function (dataSource) {
var entities = dataSource.entities.values;
expect(entities.length).toEqual(1);
var entity = entities[0];
expect(entity.wall).toBeUndefined();
expect(entity.polyline).toBeDefined();
expect(entity.polyline.arcType.getValue()).toEqual(ArcType.NONE);
});
});
it("Geometry LineString: sets positions (clampToGround default)", function () {
var kml =
'\
\
\
1,2,3 \
4,5,6 \
\
\
';
return KmlDataSource.load(
parser.parseFromString(kml, "text/xml"),
options
).then(function (dataSource) {
var entities = dataSource.entities.values;
expect(entities.length).toEqual(1);
var entity = entities[0];
expect(entity.wall).toBeUndefined();
expect(entity.polyline).toBeDefined();
var positions = entity.polyline.positions.getValue(Iso8601.MINIMUM_VALUE);
expect(positions).toEqualEpsilon(
[Cartesian3.fromDegrees(1, 2), Cartesian3.fromDegrees(4, 5)],
CesiumMath.EPSILON10
);
expect(entity.polyline.arcType.getValue()).toEqual(ArcType.NONE);
});
});
it("Geometry LineString: sets wall positions when extruded", function () {
var kml =
'\
\
\
absolute\
1\
1,2,3 \
4,5,6 \
\
\
';
return KmlDataSource.load(
parser.parseFromString(kml, "text/xml"),
options
).then(function (dataSource) {
var entities = dataSource.entities.values;
expect(entities.length).toEqual(1);
var entity = entities[0];
expect(entity.polyline).toBeUndefined();
expect(entity.wall).toBeDefined();
var positions = entity.wall.positions.getValue(Iso8601.MINIMUM_VALUE);
expect(positions).toEqualEpsilon(
[Cartesian3.fromDegrees(1, 2, 3), Cartesian3.fromDegrees(4, 5, 6)],
CesiumMath.EPSILON10
);
});
});
it("Geometry LineString: sets positions altitudeMode clampToGround, cannot extrude, can tessellate", function () {
var kml =
'\
\
\
clampToGround\
1\
1\
1,2,3 4,5,6\
\
';
return KmlDataSource.load(
parser.parseFromString(kml, "text/xml"),
options
).then(function (dataSource) {
var entities = dataSource.entities.values;
expect(entities.length).toEqual(1);
var entity = entities[0];
expect(entity.polyline.arcType).toBeUndefined();
var positions = entity.polyline.positions.getValue(Iso8601.MINIMUM_VALUE);
expect(positions).toEqualEpsilon(
[Cartesian3.fromDegrees(1, 2), Cartesian3.fromDegrees(4, 5)],
CesiumMath.EPSILON10
);
});
});
it("Geometry LineString: sets positions altitudeMode gx:clampToSeaFloor, cannot extrude, can tessellate", function () {
var kml =
'\
\
\
clampToSeaFloor\
1\
1\
1,2,3 4,5,6\
\
';
return KmlDataSource.load(
parser.parseFromString(kml, "text/xml"),
options
).then(function (dataSource) {
var entities = dataSource.entities.values;
expect(entities.length).toEqual(1);
var entity = entities[0];
expect(entity.polyline.arcType).toBeUndefined();
var positions = entity.polyline.positions.getValue(Iso8601.MINIMUM_VALUE);
expect(positions).toEqualEpsilon(
[Cartesian3.fromDegrees(1, 2), Cartesian3.fromDegrees(4, 5)],
CesiumMath.EPSILON10
);
});
});
it("Geometry LineString: sets positions altitudeMode gx:relativeToSeaFloor, can extrude, cannot tessellate", function () {
var kml =
'\
\
\
relativeToSeaFloor\
1\
1\
1,2,3 4,5,6\
\
';
return KmlDataSource.load(
parser.parseFromString(kml, "text/xml"),
options
).then(function (dataSource) {
var entities = dataSource.entities.values;
expect(entities.length).toEqual(1);
var entity = entities[0];
expect(entity.polyline).toBeUndefined(true);
expect(entity.wall).toBeDefined();
var positions = entity.wall.positions.getValue(Iso8601.MINIMUM_VALUE);
expect(positions).toEqualEpsilon(
[Cartesian3.fromDegrees(1, 2, 3), Cartesian3.fromDegrees(4, 5, 6)],
CesiumMath.EPSILON10
);
});
});
it("Geometry LineString: sets positions altitudeMode relativeToGround, can extrude, cannot tessellate", function () {
var kml =
'\
\
\
relativeToGround\
1\
1\
1,2,3 4,5,6\
\
';
return KmlDataSource.load(
parser.parseFromString(kml, "text/xml"),
options
).then(function (dataSource) {
var entities = dataSource.entities.values;
expect(entities.length).toEqual(1);
var entity = entities[0];
expect(entity.polyline).toBeUndefined();
expect(entity.wall).toBeDefined();
var positions = entity.wall.positions.getValue(Iso8601.MINIMUM_VALUE);
expect(positions).toEqualEpsilon(
[Cartesian3.fromDegrees(1, 2, 3), Cartesian3.fromDegrees(4, 5, 6)],
CesiumMath.EPSILON10
);
});
});
it("Geometry LineString: sets positions altitudeMode absolute, can extrude, cannot tessellate", function () {
var kml =
'\
\
\
absolute\
1\
1\
1,2,3 4,5,6\
\
';
return KmlDataSource.load(
parser.parseFromString(kml, "text/xml"),
options
).then(function (dataSource) {
var entities = dataSource.entities.values;
expect(entities.length).toEqual(1);
var entity = entities[0];
expect(entity.polyline).toBeUndefined();
expect(entity.wall).toBeDefined();
var positions = entity.wall.positions.getValue(Iso8601.MINIMUM_VALUE);
expect(positions).toEqualEpsilon(
[Cartesian3.fromDegrees(1, 2, 3), Cartesian3.fromDegrees(4, 5, 6)],
CesiumMath.EPSILON10
);
});
});
it("Geometry gx:Track: sets position and availability", function () {
var kml =
'\
\
\
2000-01-01T00:00:00Z\
1 2 3\
2000-01-01T00:00:01Z\
4 5 6\
2000-01-01T00:00:02Z\
7 8 9\
\
';
return KmlDataSource.load(parser.parseFromString(kml, "text/xml"), {
camera: options.camera,
canvas: options.canvas,
clampToGround: true,
}).then(function (dataSource) {
var time1 = JulianDate.fromIso8601("2000-01-01T00:00:00Z");
var time2 = JulianDate.fromIso8601("2000-01-01T00:00:01Z");
var time3 = JulianDate.fromIso8601("2000-01-01T00:00:02Z");
var entity = dataSource.entities.values[0];
expect(entity.position.getValue(time1)).toEqualEpsilon(
Cartesian3.fromDegrees(1, 2, 3),
CesiumMath.EPSILON12
);
expect(entity.position.getValue(time2)).toEqualEpsilon(
Cartesian3.fromDegrees(4, 5, 6),
CesiumMath.EPSILON12
);
expect(entity.position.getValue(time3)).toEqualEpsilon(
Cartesian3.fromDegrees(7, 8, 9),
CesiumMath.EPSILON12
);
expect(entity.billboard.heightReference.getValue(time1)).toEqual(
HeightReference.CLAMP_TO_GROUND
);
expect(entity.billboard.heightReference.getValue(time2)).toEqual(
HeightReference.CLAMP_TO_GROUND
);
expect(entity.billboard.heightReference.getValue(time3)).toEqual(
HeightReference.CLAMP_TO_GROUND
);
expect(entity.polyline).toBeUndefined();
expect(entity.availability.start).toEqual(time1);
expect(entity.availability.stop).toEqual(time3);
});
});
it("Geometry gx:Track: sets position clampToGround, cannot extrude", function () {
var kml =
'\
\
\
clampToGround\
1\
2000-01-01T00:00:00Z\
1 2 3\
2000-01-01T00:00:01Z\
4 5 6\
2000-01-01T00:00:02Z\
7 8 9\
\
';
return KmlDataSource.load(parser.parseFromString(kml, "text/xml"), {
camera: options.camera,
canvas: options.canvas,
clampToGround: true,
}).then(function (dataSource) {
var time1 = JulianDate.fromIso8601("2000-01-01T00:00:00Z");
var time2 = JulianDate.fromIso8601("2000-01-01T00:00:01Z");
var time3 = JulianDate.fromIso8601("2000-01-01T00:00:02Z");
var entity = dataSource.entities.values[0];
expect(entity.position.getValue(time1)).toEqualEpsilon(
Cartesian3.fromDegrees(1, 2, 3),
CesiumMath.EPSILON12
);
expect(entity.position.getValue(time2)).toEqualEpsilon(
Cartesian3.fromDegrees(4, 5, 6),
CesiumMath.EPSILON12
);
expect(entity.position.getValue(time3)).toEqualEpsilon(
Cartesian3.fromDegrees(7, 8, 9),
CesiumMath.EPSILON12
);
expect(entity.billboard.heightReference.getValue(time1)).toEqual(
HeightReference.CLAMP_TO_GROUND
);
expect(entity.billboard.heightReference.getValue(time2)).toEqual(
HeightReference.CLAMP_TO_GROUND
);
expect(entity.billboard.heightReference.getValue(time3)).toEqual(
HeightReference.CLAMP_TO_GROUND
);
expect(entity.polyline).toBeUndefined();
});
});
it("Geometry gx:Track: sets position altitudeMode absolute, can extrude", function () {
var kml =
'\
\
\
absolute\
1\
2000-01-01T00:00:00Z\
1 2 3\
2000-01-01T00:00:01Z\
4 5 6\
2000-01-01T00:00:02Z\
7 8 9\
\
';
return KmlDataSource.load(
parser.parseFromString(kml, "text/xml"),
options
).then(function (dataSource) {
var time1 = JulianDate.fromIso8601("2000-01-01T00:00:00Z");
var time2 = JulianDate.fromIso8601("2000-01-01T00:00:01Z");
var time3 = JulianDate.fromIso8601("2000-01-01T00:00:02Z");
var entity = dataSource.entities.values[0];
expect(entity.position.getValue(time1)).toEqualEpsilon(
Cartesian3.fromDegrees(1, 2, 3),
CesiumMath.EPSILON12
);
expect(entity.position.getValue(time2)).toEqualEpsilon(
Cartesian3.fromDegrees(4, 5, 6),
CesiumMath.EPSILON12
);
expect(entity.position.getValue(time3)).toEqualEpsilon(
Cartesian3.fromDegrees(7, 8, 9),
CesiumMath.EPSILON12
);
expect(entity.polyline.positions.getValue(time1)).toEqualEpsilon(
[Cartesian3.fromDegrees(1, 2, 3), Cartesian3.fromDegrees(1, 2)],
CesiumMath.EPSILON12
);
expect(entity.polyline.positions.getValue(time2)).toEqualEpsilon(
[Cartesian3.fromDegrees(4, 5, 6), Cartesian3.fromDegrees(4, 5)],
CesiumMath.EPSILON12
);
expect(entity.polyline.positions.getValue(time3)).toEqualEpsilon(
[Cartesian3.fromDegrees(7, 8, 9), Cartesian3.fromDegrees(7, 8)],
CesiumMath.EPSILON12
);
});
});
it("Geometry gx:Track: sets position altitudeMode relativeToGround, can extrude", function () {
var kml =
'\
\
\
relativeToGround\
1\
2000-01-01T00:00:00Z\
1 2 3\
2000-01-01T00:00:01Z\
4 5 6\
2000-01-01T00:00:02Z\
7 8 9\
\
';
return KmlDataSource.load(
parser.parseFromString(kml, "text/xml"),
options
).then(function (dataSource) {
var time1 = JulianDate.fromIso8601("2000-01-01T00:00:00Z");
var time2 = JulianDate.fromIso8601("2000-01-01T00:00:01Z");
var time3 = JulianDate.fromIso8601("2000-01-01T00:00:02Z");
var entity = dataSource.entities.values[0];
expect(entity.position.getValue(time1)).toEqualEpsilon(
Cartesian3.fromDegrees(1, 2, 3),
CesiumMath.EPSILON12
);
expect(entity.position.getValue(time2)).toEqualEpsilon(
Cartesian3.fromDegrees(4, 5, 6),
CesiumMath.EPSILON12
);
expect(entity.position.getValue(time3)).toEqualEpsilon(
Cartesian3.fromDegrees(7, 8, 9),
CesiumMath.EPSILON12
);
expect(entity.polyline.positions.getValue(time1)).toEqualEpsilon(
[Cartesian3.fromDegrees(1, 2, 3), Cartesian3.fromDegrees(1, 2)],
CesiumMath.EPSILON12
);
expect(entity.polyline.positions.getValue(time2)).toEqualEpsilon(
[Cartesian3.fromDegrees(4, 5, 6), Cartesian3.fromDegrees(4, 5)],
CesiumMath.EPSILON12
);
expect(entity.polyline.positions.getValue(time3)).toEqualEpsilon(
[Cartesian3.fromDegrees(7, 8, 9), Cartesian3.fromDegrees(7, 8)],
CesiumMath.EPSILON12
);
});
});
it("Geometry gx:Track: sets position and availability when missing values", function () {
var kml =
'\
\
\
2000-01-01T00:00:00Z\
1 2 3\
2000-01-01T00:00:01Z\
4 5 6\
2000-01-01T00:00:02Z\
\
';
return KmlDataSource.load(parser.parseFromString(kml, "text/xml"), {
camera: options.camera,
canvas: options.canvas,
clampToGround: true,
}).then(function (dataSource) {
var time1 = JulianDate.fromIso8601("2000-01-01T00:00:00Z");
var time2 = JulianDate.fromIso8601("2000-01-01T00:00:01Z");
var time3 = JulianDate.fromIso8601("2000-01-01T00:00:02Z");
var entity = dataSource.entities.values[0];
expect(entity.position.getValue(time1)).toEqualEpsilon(
Cartesian3.fromDegrees(1, 2, 3),
CesiumMath.EPSILON12
);
expect(entity.position.getValue(time2)).toEqualEpsilon(
Cartesian3.fromDegrees(4, 5, 6),
CesiumMath.EPSILON12
);
expect(entity.position.getValue(time3)).toBeUndefined();
// heightReference should be constant so its available all the time
expect(entity.billboard.heightReference.getValue(time1)).toEqual(
HeightReference.CLAMP_TO_GROUND
);
expect(entity.billboard.heightReference.getValue(time2)).toEqual(
HeightReference.CLAMP_TO_GROUND
);
expect(entity.billboard.heightReference.getValue(time3)).toEqual(
HeightReference.CLAMP_TO_GROUND
);
expect(entity.availability.start).toEqual(time1);
expect(entity.availability.stop).toEqual(time2);
});
});
it("Geometry gx:MultiTrack: sets position and availability without interpolate", function () {
var kml =
'\
\
\
\
2000-01-01T00:00:00Z\
1 2 3\
2000-01-01T00:00:01Z\
4 5 6\
\
\
2000-01-01T00:00:02Z\
6 5 4\
2000-01-01T00:00:03Z\
3 2 1\
\
\
';
return KmlDataSource.load(
parser.parseFromString(kml, "text/xml"),
options
).then(function (dataSource) {
var time1 = JulianDate.fromIso8601("2000-01-01T00:00:00Z");
var time2 = JulianDate.fromIso8601("2000-01-01T00:00:01Z");
var time3 = JulianDate.fromIso8601("2000-01-01T00:00:02Z");
var time4 = JulianDate.fromIso8601("2000-01-01T00:00:03Z");
var entity = dataSource.entities.values[0];
expect(entity.availability.length).toEqual(2);
expect(entity.availability.get(0).start).toEqual(time1);
expect(entity.availability.get(0).stop).toEqual(time2);
expect(entity.availability.get(1).start).toEqual(time3);
expect(entity.availability.get(1).stop).toEqual(time4);
expect(entity.position.getValue(time1)).toEqualEpsilon(
Cartesian3.fromDegrees(1, 2),
CesiumMath.EPSILON12
);
expect(entity.position.getValue(time2)).toEqualEpsilon(
Cartesian3.fromDegrees(4, 5),
CesiumMath.EPSILON12
);
expect(entity.position.getValue(time3)).toEqualEpsilon(
Cartesian3.fromDegrees(6, 5),
CesiumMath.EPSILON12
);
expect(entity.position.getValue(time4)).toEqualEpsilon(
Cartesian3.fromDegrees(3, 2),
CesiumMath.EPSILON12
);
});
});
it("Geometry gx:MultiTrack: sets position and availability with interpolate", function () {
var kml =
'\
\
\
1\
\
2000-01-01T00:00:00Z\
1 2 3\
2000-01-01T00:00:01Z\
4 5 6\
\
\
2000-01-01T00:00:02Z\
6 5 4\
2000-01-01T00:00:03Z\
3 2 1\
\
\
';
return KmlDataSource.load(
parser.parseFromString(kml, "text/xml"),
options
).then(function (dataSource) {
var time1 = JulianDate.fromIso8601("2000-01-01T00:00:00Z");
var time2 = JulianDate.fromIso8601("2000-01-01T00:00:01Z");
var time3 = JulianDate.fromIso8601("2000-01-01T00:00:02Z");
var time4 = JulianDate.fromIso8601("2000-01-01T00:00:03Z");
var entity = dataSource.entities.values[0];
expect(entity.availability.length).toEqual(1);
expect(entity.availability.get(0).start).toEqual(time1);
expect(entity.availability.get(0).stop).toEqual(time4);
expect(entity.position.getValue(time1)).toEqualEpsilon(
Cartesian3.fromDegrees(1, 2),
CesiumMath.EPSILON12
);
expect(entity.position.getValue(time2)).toEqualEpsilon(
Cartesian3.fromDegrees(4, 5),
CesiumMath.EPSILON12
);
expect(entity.position.getValue(time3)).toEqualEpsilon(
Cartesian3.fromDegrees(6, 5),
CesiumMath.EPSILON12
);
expect(entity.position.getValue(time4)).toEqualEpsilon(
Cartesian3.fromDegrees(3, 2),
CesiumMath.EPSILON12
);
});
});
it("Geometry gx:MultiTrack: sets position and availability altitudeMode absolute, extrude, with interpolate", function () {
var kml =
'\
\
\
1\
\
absolute\
1\
2000-01-01T00:00:00Z\
1 2 3\
2000-01-01T00:00:01Z\
4 5 6\
\
\
absolute\
1\
2000-01-01T00:00:02Z\
6 5 4\
2000-01-01T00:00:03Z\
3 2 1\
\
\
';
return KmlDataSource.load(
parser.parseFromString(kml, "text/xml"),
options
).then(function (dataSource) {
var time1 = JulianDate.fromIso8601("2000-01-01T00:00:00Z");
var time2 = JulianDate.fromIso8601("2000-01-01T00:00:01Z");
var time3 = JulianDate.fromIso8601("2000-01-01T00:00:02Z");
var time4 = JulianDate.fromIso8601("2000-01-01T00:00:03Z");
var entity = dataSource.entities.values[0];
expect(entity.availability.length).toEqual(1);
expect(entity.availability.get(0).start).toEqual(time1);
expect(entity.availability.get(0).stop).toEqual(time4);
expect(entity.position.getValue(time1)).toEqual(
Cartesian3.fromDegrees(1, 2, 3)
);
expect(entity.position.getValue(time2)).toEqual(
Cartesian3.fromDegrees(4, 5, 6)
);
expect(entity.position.getValue(time3)).toEqual(
Cartesian3.fromDegrees(6, 5, 4)
);
expect(entity.position.getValue(time4)).toEqual(
Cartesian3.fromDegrees(3, 2, 1)
);
});
});
it("Geometry MultiGeometry: sets expected properties", function () {
var kml =
'\
\
\
TheName\
TheDescription\
\
1,2\
\
\
3,4\
\
\
';
return KmlDataSource.load(
parser.parseFromString(kml, "text/xml"),
options
).then(function (dataSource) {
var entities = dataSource.entities;
expect(entities.values.length).toEqual(3);
var multi = entities.getById("testID");
expect(multi).toBeDefined();
var point1 = entities.getById("testIDpoint1");
expect(point1).toBeDefined();
expect(point1.parent).toBe(multi);
expect(point1.name).toBe(multi.name);
expect(point1.description).toBe(multi.description);
expect(point1.kml).toBe(multi.kml);
expect(point1.position.getValue(Iso8601.MINIMUM_VALUE)).toEqualEpsilon(
Cartesian3.fromDegrees(1, 2),
CesiumMath.EPSILON13
);
var point2 = entities.getById("testIDpoint2");
expect(point2).toBeDefined();
expect(point2.parent).toBe(multi);
expect(point2.name).toBe(multi.name);
expect(point2.description).toBe(multi.description);
expect(point2.kml).toBe(multi.kml);
expect(point2.position.getValue(Iso8601.MINIMUM_VALUE)).toEqualEpsilon(
Cartesian3.fromDegrees(3, 4),
CesiumMath.EPSILON13
);
});
});
it("NetworkLink: Loads data", function () {
return KmlDataSource.load("Data/KML/networkLink.kml", options).then(
function (dataSource) {
var entities = dataSource.entities.values;
expect(entities.length).toEqual(2);
expect(entities[0].id).toEqual("link");
expect(entities[1].parent).toBe(entities[0]);
}
);
});
it("NetworkLink: onInterval", function () {
var kml =
'\
\
\
./Data/KML/refresh.kml\
onInterval\
1\
\
';
return KmlDataSource.load(
parser.parseFromString(kml, "text/xml"),
options
).then(function (dataSource) {
var entities = dataSource.entities.values;
expect(entities.length).toEqual(3);
var link1 = entities[0];
var folder1 = entities[1];
var placemark1 = entities[2];
expect(link1.id).toEqual("link");
expect(folder1.parent).toBe(link1);
expect(placemark1.parent).toBe(folder1);
var spy = jasmine.createSpy("refreshEvent");
dataSource.refreshEvent.addEventListener(spy);
return pollToPromise(function () {
dataSource.update(0);
return spy.calls.count() > 0;
}).then(function () {
expect(spy).toHaveBeenCalledWith(dataSource, expectedRefreshLinkHref);
expect(entities.length).toEqual(3);
var link2 = entities[0];
var folder2 = entities[1];
var placemark2 = entities[2];
expect(link2.id).toEqual("link");
expect(folder2.parent).toBe(link2);
expect(placemark2.parent).toBe(folder2);
expect(link2).toEqual(link2);
expect(folder2).not.toEqual(folder1);
expect(placemark2).not.toEqual(placemark1);
});
});
});
it("NetworkLink: onExpire", function () {
var kml =
'\
\
\
./Data/KML/refresh.kml\
onExpire\
\
';
return KmlDataSource.load(
parser.parseFromString(kml, "text/xml"),
options
).then(function (dataSource) {
var entities = dataSource.entities.values;
expect(entities.length).toEqual(3);
var link1 = entities[0];
var folder1 = entities[1];
var placemark1 = entities[2];
expect(link1.id).toEqual("link");
expect(folder1.parent).toBe(link1);
expect(placemark1.parent).toBe(folder1);
var spy = jasmine.createSpy("refreshEvent");
dataSource.refreshEvent.addEventListener(spy);
dataSource.update(0); // Document is already expired so call once
return pollToPromise(function () {
return spy.calls.count() > 0;
}).then(function () {
expect(spy).toHaveBeenCalledWith(dataSource, expectedRefreshLinkHref);
expect(entities.length).toEqual(3);
var link2 = entities[0];
var folder2 = entities[1];
var placemark2 = entities[2];
expect(link2.id).toEqual("link");
expect(folder2.parent).toBe(link2);
expect(placemark2.parent).toBe(folder2);
expect(link2).toEqual(link2);
expect(folder2).not.toEqual(folder1);
expect(placemark2).not.toEqual(placemark1);
});
});
});
it("NetworkLink: onStop", function () {
var kml =
'\
\
\
./Data/KML/refresh.kml\
onStop\
\
';
return KmlDataSource.load(
parser.parseFromString(kml, "text/xml"),
options
).then(function (dataSource) {
var entities = dataSource.entities.values;
expect(entities.length).toEqual(3);
var link1 = entities[0];
var folder1 = entities[1];
var placemark1 = entities[2];
expect(link1.id).toEqual("link");
expect(folder1.parent).toBe(link1);
expect(placemark1.parent).toBe(folder1);
var spy = jasmine.createSpy("refreshEvent");
dataSource.refreshEvent.addEventListener(spy);
// Move the camera and call update to set the last camera view
options.camera.positionWC.x = 1.0;
dataSource.update(0);
return pollToPromise(function () {
return spy.calls.count() > 0;
}).then(function () {
expect(spy).toHaveBeenCalledWith(
dataSource,
expectedRefreshLinkHref + "?BBOX=-180%2C-90%2C180%2C90"
);
expect(entities.length).toEqual(3);
var link2 = entities[0];
var folder2 = entities[1];
var placemark2 = entities[2];
expect(link2.id).toEqual("link");
expect(folder2.parent).toBe(link2);
expect(placemark2.parent).toBe(folder2);
expect(link2).toEqual(link2);
expect(folder2).not.toEqual(folder1);
expect(placemark2).not.toEqual(placemark1);
});
});
});
it("NetworkLink: Url is correct on initial load", function () {
var kml =
'\
\
\
./Data/KML/refresh.kml\
\
';
var requestNetworkLink = when.defer();
spyOn(Resource._Implementations, "loadWithXhr").and.callFake(function (
url,
responseType,
method,
data,
headers,
deferred,
overrideMimeType
) {
requestNetworkLink.resolve(url);
deferred.reject();
});
KmlDataSource.load(parser.parseFromString(kml, "text/xml"), options);
return requestNetworkLink.promise.then(function (url) {
expect(url).toEqual(expectedRefreshLinkHref);
});
});
it("NetworkLink can accept invalid but common URL tag instead of Link", function () {
var kml =
'\
\
\
./Data/KML/refresh.kml\
\
';
var requestNetworkLink = when.defer();
spyOn(Resource._Implementations, "loadWithXhr").and.callFake(function (
url,
responseType,
method,
data,
headers,
deferred,
overrideMimeType
) {
requestNetworkLink.resolve(url);
deferred.reject();
});
KmlDataSource.load(parser.parseFromString(kml, "text/xml"), options);
return requestNetworkLink.promise.then(function (url) {
expect(url).toEqual(expectedRefreshLinkHref);
});
});
it("NetworkLink: Url is correct on initial load with onStop defaults", function () {
var kml =
'\
\
\
./Data/KML/refresh.kml\
onStop\
\
';
var requestNetworkLink = when.defer();
spyOn(Resource._Implementations, "loadWithXhr").and.callFake(function (
url,
responseType,
method,
data,
headers,
deferred,
overrideMimeType
) {
requestNetworkLink.resolve(url);
deferred.reject();
});
KmlDataSource.load(parser.parseFromString(kml, "text/xml"), options);
return requestNetworkLink.promise.then(function (url) {
expect(url).toEqual(
expectedRefreshLinkHref + "?BBOX=-180%2C-90%2C180%2C90"
);
});
});
it("NetworkLink: Url is correct on initial load with httpQuery without a ?", function () {
var kml =
'\
\
\
./Data/KML/refresh.kml\
onInterval\
client=[clientName]-v[clientVersion]&v=[kmlVersion]&lang=[language]\
\
';
var requestNetworkLink = when.defer();
spyOn(Resource._Implementations, "loadWithXhr").and.callFake(function (
url,
responseType,
method,
data,
headers,
deferred,
overrideMimeType
) {
requestNetworkLink.resolve(url);
deferred.reject();
});
KmlDataSource.load(parser.parseFromString(kml, "text/xml"), options);
return requestNetworkLink.promise.then(function (url) {
expect(url).toEqual(
expectedRefreshLinkHref + "?client=Cesium-v1&v=2.2&lang=English"
);
});
});
it("NetworkLink: Url is correct on initial load with httpQuery with a ?", function () {
var kml =
'\
\
\
./Data/KML/refresh.kml\
onInterval\
?client=[clientName]-v[clientVersion]&v=[kmlVersion]&lang=[language]\
\
';
var requestNetworkLink = when.defer();
spyOn(Resource._Implementations, "loadWithXhr").and.callFake(function (
url,
responseType,
method,
data,
headers,
deferred,
overrideMimeType
) {
requestNetworkLink.resolve(url);
deferred.reject();
});
KmlDataSource.load(parser.parseFromString(kml, "text/xml"), options);
return requestNetworkLink.promise.then(function (url) {
expect(url).toEqual(
expectedRefreshLinkHref + "?client=Cesium-v1&v=2.2&lang=English"
);
});
});
it("NetworkLink: Url is correct on initial load with viewFormat without a ?", function () {
var kml =
'\
\
\
./Data/KML/refresh.kml\
onInterval\
BBOX=[bboxWest],[bboxSouth],[bboxEast],[bboxNorth];CAMERA=\
[lookatLon],[lookatLat],[lookatRange],[lookatTilt],[lookatHeading];VIEW=\
[horizFov],[vertFov],[horizPixels],[vertPixels],[terrainEnabled]\
\
';
var requestNetworkLink = when.defer();
spyOn(Resource._Implementations, "loadWithXhr").and.callFake(function (
url,
responseType,
method,
data,
headers,
deferred,
overrideMimeType
) {
requestNetworkLink.resolve(url);
deferred.reject();
});
KmlDataSource.load(parser.parseFromString(kml, "text/xml"), options);
return requestNetworkLink.promise.then(function (url) {
expect(url).toEqual(
expectedRefreshLinkHref +
"?BBOX=-180%2C-90%2C180%2C90&CAMERA=0%2C0%2C6378137%2C0%2C0&VIEW=45%2C45%2C512%2C512%2C1"
);
});
});
it("NetworkLink: Url is correct on initial load with viewFormat with a ?", function () {
var kml =
'\
\
\
./Data/KML/refresh.kml\
onInterval\
?BBOX=[bboxWest],[bboxSouth],[bboxEast],[bboxNorth];CAMERA=\
[lookatLon],[lookatLat],[lookatRange],[lookatTilt],[lookatHeading];VIEW=\
[horizFov],[vertFov],[horizPixels],[vertPixels],[terrainEnabled]\
\
';
var requestNetworkLink = when.defer();
spyOn(Resource._Implementations, "loadWithXhr").and.callFake(function (
url,
responseType,
method,
data,
headers,
deferred,
overrideMimeType
) {
requestNetworkLink.resolve(url);
deferred.reject();
});
KmlDataSource.load(parser.parseFromString(kml, "text/xml"), options);
return requestNetworkLink.promise.then(function (url) {
expect(url).toEqual(
expectedRefreshLinkHref +
"?BBOX=-180%2C-90%2C180%2C90&CAMERA=0%2C0%2C6378137%2C0%2C0&VIEW=45%2C45%2C512%2C512%2C1"
);
});
});
it("NetworkLink: Url is correct on initial load with viewFormat and httpQuery", function () {
var kml =
'\
\
\
./Data/KML/refresh.kml\
onInterval\
vf=1\
hq=1\
\
';
var requestNetworkLink = when.defer();
spyOn(Resource._Implementations, "loadWithXhr").and.callFake(function (
url,
responseType,
method,
data,
headers,
deferred,
overrideMimeType
) {
requestNetworkLink.resolve(url);
deferred.reject();
});
KmlDataSource.load(parser.parseFromString(kml, "text/xml"), options);
return requestNetworkLink.promise.then(function (url) {
expect(url).toEqual(expectedRefreshLinkHref + "?hq=1&vf=1");
});
});
it("NetworkLink: onStop when no globe is in view", function () {
var kml =
'\
\
\
./Data/KML/refresh.kml\
onStop\
\
';
var ourOptions = {
camera: {
positionWC: new Cartesian3(0.0, 0.0, 0.0),
directionWC: new Cartesian3(0.0, 0.0, 1.0),
upWC: new Cartesian3(0.0, 1.0, 0.0),
pitch: 0.0,
heading: 0.0,
frustum: {
aspectRatio: 1.0,
fov: CesiumMath.PI_OVER_FOUR,
},
computeViewRectangle: function () {
return undefined;
},
pickEllipsoid: function () {
return undefined;
},
},
canvas: options.canvas,
};
return KmlDataSource.load(
parser.parseFromString(kml, "text/xml"),
ourOptions
).then(function (dataSource) {
var entities = dataSource.entities.values;
expect(entities.length).toEqual(3);
var link1 = entities[0];
var folder1 = entities[1];
var placemark1 = entities[2];
expect(link1.id).toEqual("link");
expect(folder1.parent).toBe(link1);
expect(placemark1.parent).toBe(folder1);
var spy = jasmine.createSpy("refreshEvent");
dataSource.refreshEvent.addEventListener(spy);
// Move the camera and call update to set the last camera view
ourOptions.camera.positionWC.x = 1.0;
dataSource.update(0);
return pollToPromise(function () {
return spy.calls.count() > 0;
}).then(function () {
expect(spy).toHaveBeenCalledWith(
dataSource,
expectedRefreshLinkHref + "?BBOX=0%2C0%2C0%2C0"
);
expect(entities.length).toEqual(3);
var link2 = entities[0];
var folder2 = entities[1];
var placemark2 = entities[2];
expect(link2.id).toEqual("link");
expect(folder2.parent).toBe(link2);
expect(placemark2.parent).toBe(folder2);
expect(link2).toEqual(link2);
expect(folder2).not.toEqual(folder1);
expect(placemark2).not.toEqual(placemark1);
});
});
});
it("NetworkLink: timespan for network link", function () {
var kml =
'\
\
\
./Data/KML/simple.kml\
\
\
2000-01-01\
2000-01-03\
\
';
return KmlDataSource.load(
parser.parseFromString(kml, "text/xml"),
options
).then(function (dataSource) {
var start = JulianDate.fromIso8601("2000-01-01");
var stop = JulianDate.fromIso8601("2000-01-03");
var entities = dataSource.entities.values;
expect(entities.length).toBe(2);
var interval = entities[0].availability;
expect(interval.start).toEqual(start);
expect(interval.stop).toEqual(stop);
expect(entities[0].availability).toEqual(entities[1].availability);
});
});
it("NetworkLink: timestamp for network link", function () {
var kml =
'\
\
\
./Data/KML/simple.kml\
\
\
2000-01-03\
\
';
return KmlDataSource.load(
parser.parseFromString(kml, "text/xml"),
options
).then(function (dataSource) {
var start = JulianDate.fromIso8601("2000-01-03");
var entities = dataSource.entities.values;
expect(entities.length).toBe(2);
var interval = entities[0].availability;
expect(interval.start).toEqual(start);
expect(interval.stop).toEqual(Iso8601.MAXIMUM_VALUE);
expect(entities[0].availability).toEqual(entities[1].availability);
});
});
it("NetworkLink: within a kmz file", function () {
return KmlDataSource.load("Data/KML/multilevel.kmz", options).then(
function (dataSource) {
var entities = dataSource.entities.values;
expect(entities.length).toBe(3);
expect(entities[1].billboard).not.toBeNull();
expect(entities[1].position.getValue(Iso8601.MINIMUM_VALUE)).toEqual(
Cartesian3.fromDegrees(1, 2, 3)
);
// The root network link is loaded, then the children
// since its done recursively the lowest level entities
// end up in the collection first.
expect(entities[0].parent).toBeUndefined();
expect(entities[2].parent).toBe(entities[0]);
expect(entities[1].parent).toBe(entities[2]);
}
);
});
it("can load a KML file with explicit namespaces", function () {
return KmlDataSource.load("Data/KML/namespaced.kml", options).then(
function (dataSource) {
expect(dataSource.entities.values.length).toBe(3);
}
);
});
it("can load styles from a KML file with namespaces", function () {
return KmlDataSource.load("Data/KML/namespaced.kml", options).then(
function (dataSource) {
console.debug(dataSource.entities.values[2]);
var polyline = dataSource.entities.values[2].polyline;
var expectedColor = Color.fromBytes(0xff, 0x00, 0xff, 0x00);
var polylineColor = polyline.material.color.getValue();
expect(polylineColor).toEqual(expectedColor);
expect(polyline.width.getValue()).toEqual(10);
}
);
});
it("Boolean values can use true string", function () {
var kml =
'\
\
\
relativeToGround\
1\
\
';
return KmlDataSource.load(
parser.parseFromString(kml, "text/xml"),
options
).then(function (dataSource) {
var entity = dataSource.entities.values[0];
expect(entity.polygon.perPositionHeight.getValue()).toEqual(true);
});
});
it("Boolean values can use false string", function () {
var kml =
'\
\
\
relativeToGround\
1\
\
';
return KmlDataSource.load(
parser.parseFromString(kml, "text/xml"),
options
).then(function (dataSource) {
var entity = dataSource.entities.values[0];
expect(entity.polygon.perPositionHeight.getValue()).toEqual(true);
});
});
it("Properly finds the root feature node when it is not the first child of the KML node", function () {
var kml =
'\
\
\
\
\
bob\
\
';
return KmlDataSource.load(
parser.parseFromString(kml, "text/xml"),
options
).then(function (dataSource) {
var entity = dataSource.entities.values[0];
expect(entity.name).toBe("bob");
expect(entity.label).toBeDefined();
expect(entity.label.text.getValue()).toBe("bob");
});
});
it("Has entity collection with link to data source", function () {
var dataSource = new KmlDataSource(options);
var entityCollection = dataSource.entities;
expect(entityCollection.owner).toEqual(dataSource);
});
it("Has entity with link to entity collection", function () {
var kml =
'\
\
\
relativeToGround\
1\
\
';
return KmlDataSource.load(
parser.parseFromString(kml, "text/xml"),
options
).then(function (dataSource) {
var entityCollection = dataSource.entities;
var entity = entityCollection.values[0];
expect(entity.entityCollection).toEqual(entityCollection);
});
});
it("GroundOverlay Icon with refreshMode shows warning", function () {
var kml =
'\
\
\
http://test.invalid/image.png\
onInterval\
\
';
spyOn(console, "warn").and.callThrough();
return KmlDataSource.load(
parser.parseFromString(kml, "text/xml"),
options
).then(function (dataSource) {
expect(dataSource.entities.values.length).toEqual(1);
expect(console.warn.calls.count()).toEqual(1);
expect(console.warn).toHaveBeenCalledWith(
"KML - Unsupported Icon refreshMode: onInterval"
);
});
});
it("GroundOverly Icon with viewRefreshMode shows warning", function () {
var kml =
'\
\
\
http://test.invalid/image.png\
onStop\
\
';
spyOn(console, "warn").and.callThrough();
return KmlDataSource.load(
parser.parseFromString(kml, "text/xml"),
options
).then(function (dataSource) {
expect(dataSource.entities.values.length).toEqual(1);
expect(console.warn.calls.count()).toEqual(1);
expect(console.warn).toHaveBeenCalledWith(
"KML - Unsupported Icon viewRefreshMode: onStop"
);
});
});
it("GroundOverly Icon with gx:x, gx:y, gx:w, gx:h shows warning", function () {
var kml =
'\
\
\
\
http://test.invalid/image.png\
1\
\
\
';
spyOn(console, "warn").and.callThrough();
return KmlDataSource.load(
parser.parseFromString(kml, "text/xml"),
options
).then(function (dataSource) {
expect(dataSource.entities.values.length).toEqual(1);
expect(console.warn.calls.count()).toEqual(1);
expect(console.warn).toHaveBeenCalledWith(
"KML - gx:x, gx:y, gx:w, gx:h aren't supported for GroundOverlays"
);
});
});
it("LineStyle with gx extensions show warnings", function () {
var kml =
'\
\
\
\
\
1,2,3 \
4,5,6 \
\
\
\
';
spyOn(console, "warn").and.callThrough();
return KmlDataSource.load(
parser.parseFromString(kml, "text/xml"),
options
).then(function (dataSource) {
expect(dataSource.entities.values.length).toEqual(1);
expect(console.warn.calls.count()).toEqual(4);
expect(console.warn.calls.argsFor(0)[0]).toBe(
"KML - gx:outerColor is not supported in a LineStyle"
);
expect(console.warn.calls.argsFor(1)[0]).toBe(
"KML - gx:outerWidth is not supported in a LineStyle"
);
expect(console.warn.calls.argsFor(2)[0]).toBe(
"KML - gx:physicalWidth is not supported in a LineStyle"
);
expect(console.warn.calls.argsFor(3)[0]).toBe(
"KML - gx:labelVisibility is not supported in a LineStyle"
);
});
});
it("Folder with radioFolder listItemType shows warning", function () {
var kml =
'\
\
\
';
spyOn(console, "warn").and.callThrough();
return KmlDataSource.load(
parser.parseFromString(kml, "text/xml"),
options
).then(function (dataSource) {
expect(dataSource.entities.values.length).toEqual(1);
expect(console.warn.calls.count()).toEqual(1);
expect(console.warn).toHaveBeenCalledWith(
"KML - Unsupported ListStyle with listItemType: radioFolder"
);
});
});
it("StyleMap with highlighted key shows warning", function () {
var kml =
'\
\
\
\
normal\
\
\
\
highlighted\
\
\
\
';
spyOn(console, "warn").and.callThrough();
return KmlDataSource.load(
parser.parseFromString(kml, "text/xml"),
options
).then(function (dataSource) {
expect(dataSource.entities.values.length).toEqual(1);
expect(console.warn.calls.count()).toEqual(1);
expect(console.warn).toHaveBeenCalledWith(
"KML - Unsupported StyleMap key: highlighted"
);
});
});
it("Linestrings with gx:drawOrder shows warning", function () {
var kml =
'\
\
\
\
1\
1,2,3 \
4,5,6 \
\
\
\
';
spyOn(console, "warn").and.callThrough();
return KmlDataSource.load(
parser.parseFromString(kml, "text/xml"),
options
).then(function (dataSource) {
expect(dataSource.entities.values.length).toEqual(1);
expect(console.warn.calls.count()).toEqual(1);
expect(console.warn).toHaveBeenCalledWith(
"KML - gx:drawOrder is not supported in LineStrings when clampToGround is false"
);
});
});
it("gx:Track with gx:angles shows warning)", function () {
var kml =
'\
\
\
2000-01-01T00:00:00Z\
1 2 3\
4 5 6\
\
';
spyOn(console, "warn").and.callThrough();
return KmlDataSource.load(
parser.parseFromString(kml, "text/xml"),
options
).then(function (dataSource) {
expect(dataSource.entities.values.length).toEqual(1);
expect(console.warn.calls.count()).toEqual(1);
expect(console.warn).toHaveBeenCalledWith(
"KML - gx:angles are not supported in gx:Tracks"
);
});
});
it("Model geometry shows warning)", function () {
var kml =
'\
\
\
';
spyOn(console, "warn").and.callThrough();
return KmlDataSource.load(
parser.parseFromString(kml, "text/xml"),
options
).then(function (dataSource) {
expect(dataSource.entities.values.length).toEqual(1);
expect(console.warn.calls.count()).toEqual(1);
expect(console.warn).toHaveBeenCalledWith(
"KML - Unsupported geometry: Model"
);
});
});
it("ExtendedData with SchemaData or custom XML show warnings", function () {
var kml =
'\
\
\
1,2,3 \
4,5,6 \
\
\
\
\
\
';
spyOn(console, "warn").and.callThrough();
return KmlDataSource.load(
parser.parseFromString(kml, "text/xml"),
options
).then(function (dataSource) {
expect(dataSource.entities.values.length).toEqual(1);
expect(console.warn.calls.count()).toEqual(2);
expect(console.warn.calls.argsFor(0)[0]).toBe(
"KML - SchemaData is unsupported"
);
expect(console.warn.calls.argsFor(1)[0]).toBe(
"KML - ExtendedData with xmlns:prefix is unsupported"
);
});
});
it("Parse Camera and LookAt on features", function () {
var kml =
'\
\
\
1,2,3 \
4,5,6 \
\
\
\
\
-120\
40\
100\
90\
30\
1250\
\
';
spyOn(console, "warn").and.callThrough();
return KmlDataSource.load(
parser.parseFromString(kml, "text/xml"),
options
).then(function (dataSource) {
expect(dataSource.entities.values.length).toEqual(1);
var placemark = dataSource.entities.values[0];
expect(placemark.kml.camera).toBeInstanceOf(KmlCamera);
expect(placemark.kml.lookAt).toBeInstanceOf(KmlLookAt);
expect(placemark.kml.lookAt.position).toEqual(
Cartesian3.fromDegrees(-120, 40, 100)
);
expect(placemark.kml.lookAt.headingPitchRange).toEqualEpsilon(
new HeadingPitchRange(
CesiumMath.toRadians(90),
CesiumMath.toRadians(30 - 90),
1250
),
CesiumMath.EPSILON10
);
});
});
it("Features with a Region shows warning", function () {
var kml =
'\
\
\
1,2,3 \
4,5,6 \
\
\
\
';
spyOn(console, "warn").and.callThrough();
return KmlDataSource.load(
parser.parseFromString(kml, "text/xml"),
options
).then(function (dataSource) {
expect(dataSource.entities.values.length).toEqual(1);
expect(console.warn.calls.count()).toEqual(1);
expect(console.warn).toHaveBeenCalledWith(
"KML - Placemark Regions are unsupported"
);
});
});
it("NetworkLink with a viewRefreshMode=onRegion shows warning", function () {
var kml =
'\
\
\
./Data/KML/simple.kml\
onRegion\
\
';
spyOn(console, "warn").and.callThrough();
return KmlDataSource.load(
parser.parseFromString(kml, "text/xml"),
options
).then(function (dataSource) {
expect(dataSource.entities.values.length).toEqual(2);
expect(console.warn.calls.count()).toEqual(1);
expect(console.warn).toHaveBeenCalledWith(
"KML - Unsupported viewRefreshMode: onRegion"
);
});
});
it("Tour: reads gx:Tour)", function () {
var kml =
'\
\
\
Tour 1\
\
\
2\
\
\
3\
\
\
\
';
return KmlDataSource.load(
parser.parseFromString(kml, "text/xml"),
options
).then(function (dataSource) {
expect(dataSource.kmlTours.length).toEqual(1);
var tour = dataSource.kmlTours[0];
expect(tour).toBeInstanceOf(KmlTour);
expect(tour.name).toEqual("Tour 1");
expect(tour.id).toEqual("id_123");
expect(tour.playlist.length).toEqual(2);
expect(tour.playlist[0].duration).toEqual(2);
expect(tour.playlist[0]).toBeInstanceOf(KmlTourWait);
expect(tour.playlist[1].duration).toEqual(3);
expect(tour.playlist[1]).toBeInstanceOf(KmlTourFlyTo);
});
});
it("Tour: reads LookAt and Camera", function () {
var kml =
'\
\
\
\
\
5\
bounce\
\
10\
20\
30\
40\
50\
60\
\
\
\
4.1\
\
170.0\
-43.0\
9700\
-10.0\
33.5\
20\
\
\
\
\
';
return KmlDataSource.load(
parser.parseFromString(kml, "text/xml"),
options
).then(function (dataSource) {
expect(dataSource.kmlTours.length).toEqual(1);
var tour = dataSource.kmlTours[0];
expect(tour.playlist.length).toEqual(2);
var flyto1 = tour.playlist[0];
var flyto2 = tour.playlist[1];
expect(flyto1.flyToMode).toEqual("bounce");
expect(flyto1.duration).toEqual(5);
expect(flyto1.view).toBeInstanceOf(KmlLookAt);
expect(flyto2.duration).toEqual(4.1);
expect(flyto2.view).toBeInstanceOf(KmlCamera);
expect(flyto1.view.position).toBeInstanceOf(Cartesian3);
expect(flyto2.view.position).toBeInstanceOf(Cartesian3);
expect(flyto1.view.headingPitchRange).toBeInstanceOf(HeadingPitchRange);
expect(flyto2.view.headingPitchRoll).toBeInstanceOf(HeadingPitchRoll);
});
});
it("Tour: log KML Tour unsupported nodes", function () {
var kml =
'\
\
\
\
\
\
\
\
\
\
\
\
';
spyOn(console, "warn").and.callThrough();
return KmlDataSource.load(
parser.parseFromString(kml, "text/xml"),
options
).then(function (dataSource) {
expect(dataSource.kmlTours.length).toEqual(1);
expect(dataSource.kmlTours[0].playlist.length).toEqual(0);
expect(console.warn).toHaveBeenCalledWith(
"KML Tour unsupported node AnimatedUpdate"
);
expect(console.warn).toHaveBeenCalledWith(
"KML Tour unsupported node TourControl"
);
expect(console.warn).toHaveBeenCalledWith(
"KML Tour unsupported node SoundCue"
);
});
});
it("NetworkLink: onExpire without an expires shows warning", function () {
var kml =
'\
\
\
./Data/KML/simple.kml\
onExpire\
\
';
spyOn(console, "warn").and.callThrough();
return KmlDataSource.load(
parser.parseFromString(kml, "text/xml"),
options
).then(function (dataSource) {
expect(dataSource.entities.values.length).toEqual(2);
expect(console.warn.calls.count()).toEqual(1);
expect(console.warn).toHaveBeenCalledWith(
"KML - refreshMode of onExpire requires the NetworkLinkControl to have an expires element"
);
});
});
it("NetworkLink: Heading and pitch can be undefined if the camera is in morphing mode", function () {
var kml =
'\
\
\
./Data/KML/simple.kml\
onExpire\
\
';
var camera = createCamera({
offset: Cartesian3.fromDegrees(-110, 30, 1000),
});
Camera.clone(options.camera, camera);
var kmlOptions = {
camera: camera,
canvas: options.canvas,
};
camera._mode = SceneMode.MORPHING;
return KmlDataSource.load(
parser.parseFromString(kml, "text/xml"),
kmlOptions
).then(function (dataSource) {
expect(dataSource.entities.values.length).toEqual(2);
});
});
it("when clampToGround is false, height isn't set if the polygon is extrudable", function () {
var kml =
'\
\
\
relativeToGround\
\
';
return KmlDataSource.load(
parser.parseFromString(kml, "text/xml"),
options
).then(function (dataSource) {
var entity = dataSource.entities.values[0];
expect(entity.polygon.perPositionHeight.getValue()).toEqual(true);
expect(entity.polygon.height).toBeUndefined();
});
});
it("when clampToGround is false, height is set to 0 if polygon isn't extrudable", function () {
var kml =
'\
\
\
clampToGround\
\
';
return KmlDataSource.load(
parser.parseFromString(kml, "text/xml"),
options
).then(function (dataSource) {
var entity = dataSource.entities.values[0];
expect(entity.polygon.perPositionHeight).toBeUndefined();
expect(entity.polygon.height.getValue()).toEqual(0);
});
});
it("when a LineString is clamped to ground and tesselated, entity has a polyline geometry and ColorProperty", function () {
var kml =
'\
\
\
\
clampToGround\
true\
1,2,3\
4,5,6\
\
\
';
var clampToGroundOptions = combine(options, { clampToGround: true });
return KmlDataSource.load(
parser.parseFromString(kml, "text/xml"),
clampToGroundOptions
).then(function (dataSource) {
var entity = dataSource.entities.values[0];
expect(entity.polyline).toBeDefined();
expect(entity.polyline.clampToGround.getValue()).toEqual(true);
expect(entity.polyline.material).toBeInstanceOf(ColorMaterialProperty);
});
});
it("when a LineString is clamped to ground and tesselated with z draworder, entity has a polyline geometry and ColorProperty", function () {
var kml =
'\
\
\
\
\
clampToGround\
true\
1,2,3\
4,5,6\
\
2\
\
\
';
var clampToGroundOptions = combine(options, { clampToGround: true });
return KmlDataSource.load(
parser.parseFromString(kml, "text/xml"),
clampToGroundOptions
).then(function (dataSource) {
var entity = dataSource.entities.values[0];
expect(entity.polyline).toBeDefined();
expect(entity.polyline.clampToGround.getValue()).toEqual(true);
expect(entity.polyline.zIndex.getValue()).toBe(2);
});
});
it("correctly uses random colors", function () {
var kml =
'\n' +
"\n" +
'\n" +
'\n" +
'\n" +
"\n" +
"\n" +
"#color2\n" +
"\n" +
"\n" +
"\n" +
"\n" +
"-89.52101149718367,44.23294548447373,0 -91.98408516538682,47.97512147591338,0 -96.92502046753899,45.42403256080313,0 -89.52101149718367,44.23294548447373,0 \n" +
"\n" +
"\n" +
"\n" +
"\n" +
"\n" +
"\n" +
"#color3\n" +
"\n" +
"\n" +
"\n" +
"\n" +
"-87.93623144974434,37.55775744070508,0 -89.46217805511263,41.26028180023913,0 -96.5546236391081,37.07597093222066,0 -87.93623144974434,37.55775744070508,0 \n" +
"\n" +
"\n" +
"\n" +
"\n" +
"\n" +
"\n" +
"#color4\n" +
"\n" +
"\n" +
"\n" +
"\n" +
"-104.347585776386,32.33288590150301,0 -103.8767557883591,37.6658714706182,0 -109.2704409486033,39.04706243328442,0 -104.347585776386,32.33288590150301,0 \n" +
"\n" +
"\n" +
"\n" +
"\n" +
"\n" +
"\n" +
"\n";
CesiumMath.setRandomNumberSeed(0);
return KmlDataSource.load(
parser.parseFromString(kml, "text/xml"),
options
).then(function (dataSource) {
expect(dataSource.entities.values.length).toEqual(4);
expect(
dataSource.entities.values[2].polygon.material.color.getValue()
).not.toEqual(
dataSource.entities.values[3].polygon.material.color.getValue()
);
});
});
});