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() ); }); }); });