/*global define*/ define([ '../Core/Cartesian2', '../Core/Cartesian3', '../Core/Cartographic', '../Core/ClockRange', '../Core/ClockStep', '../Core/Color', '../Core/createGuid', '../Core/defaultValue', '../Core/defined', '../Core/defineProperties', '../Core/DeveloperError', '../Core/Ellipsoid', '../Core/Event', '../Core/ExtrapolationType', '../Core/getFilenameFromUri', '../Core/HermitePolynomialApproximation', '../Core/isArray', '../Core/Iso8601', '../Core/JulianDate', '../Core/LagrangePolynomialApproximation', '../Core/LinearApproximation', '../Core/loadJson', '../Core/Math', '../Core/Quaternion', '../Core/Rectangle', '../Core/ReferenceFrame', '../Core/RuntimeError', '../Core/Spherical', '../Core/TimeInterval', '../Core/TimeIntervalCollection', '../Scene/HorizontalOrigin', '../Scene/LabelStyle', '../Scene/VerticalOrigin', '../ThirdParty/Uri', '../ThirdParty/when', './BillboardGraphics', './ColorMaterialProperty', './CompositeMaterialProperty', './CompositePositionProperty', './CompositeProperty', './ConstantPositionProperty', './ConstantProperty', './DataSource', './DataSourceClock', './EllipseGraphics', './EllipsoidGraphics', './EntityCollection', './GridMaterialProperty', './ImageMaterialProperty', './LabelGraphics', './ModelGraphics', './PathGraphics', './PointGraphics', './PolygonGraphics', './PolylineGlowMaterialProperty', './PolylineGraphics', './PolylineOutlineMaterialProperty', './PositionPropertyArray', './RectangleGraphics', './ReferenceProperty', './SampledPositionProperty', './SampledProperty', './StripeMaterialProperty', './StripeOrientation', './TimeIntervalCollectionPositionProperty', './TimeIntervalCollectionProperty', './WallGraphics' ], function( Cartesian2, Cartesian3, Cartographic, ClockRange, ClockStep, Color, createGuid, defaultValue, defined, defineProperties, DeveloperError, Ellipsoid, Event, ExtrapolationType, getFilenameFromUri, HermitePolynomialApproximation, isArray, Iso8601, JulianDate, LagrangePolynomialApproximation, LinearApproximation, loadJson, CesiumMath, Quaternion, Rectangle, ReferenceFrame, RuntimeError, Spherical, TimeInterval, TimeIntervalCollection, HorizontalOrigin, LabelStyle, VerticalOrigin, Uri, when, BillboardGraphics, ColorMaterialProperty, CompositeMaterialProperty, CompositePositionProperty, CompositeProperty, ConstantPositionProperty, ConstantProperty, DataSource, DataSourceClock, EllipseGraphics, EllipsoidGraphics, EntityCollection, GridMaterialProperty, ImageMaterialProperty, LabelGraphics, ModelGraphics, PathGraphics, PointGraphics, PolygonGraphics, PolylineGlowMaterialProperty, PolylineGraphics, PolylineOutlineMaterialProperty, PositionPropertyArray, RectangleGraphics, ReferenceProperty, SampledPositionProperty, SampledProperty, StripeMaterialProperty, StripeOrientation, TimeIntervalCollectionPositionProperty, TimeIntervalCollectionProperty, WallGraphics) { "use strict"; var currentId; function makeReference(collection, referenceString) { if (referenceString[0] === '#') { referenceString = currentId + referenceString; } return ReferenceProperty.fromString(collection, referenceString); } var scratchCartesian = new Cartesian3(); var scratchSpherical = new Spherical(); var scratchCartographic = new Cartographic(); var scratchTimeInterval = new TimeInterval(); function unwrapColorInterval(czmlInterval) { var rgbaf = czmlInterval.rgbaf; if (defined(rgbaf)) { return rgbaf; } var rgba = czmlInterval.rgba; if (!defined(rgba)) { return undefined; } if (rgba.length === Color.length) { return [Color.byteToFloat(rgba[0]), Color.byteToFloat(rgba[1]), Color.byteToFloat(rgba[2]), Color.byteToFloat(rgba[3])]; } var len = rgba.length; rgbaf = new Array(len); for (var i = 0; i < len; i += 5) { rgbaf[i] = rgba[i]; rgbaf[i + 1] = Color.byteToFloat(rgba[i + 1]); rgbaf[i + 2] = Color.byteToFloat(rgba[i + 2]); rgbaf[i + 3] = Color.byteToFloat(rgba[i + 3]); rgbaf[i + 4] = Color.byteToFloat(rgba[i + 4]); } return rgbaf; } function unwrapImageInterval(czmlInterval, sourceUri) { var result = defaultValue(czmlInterval.image, czmlInterval); if (defined(sourceUri)) { var baseUri = new Uri(document.location.href); sourceUri = new Uri(sourceUri); result = new Uri(result).resolve(sourceUri.resolve(baseUri)).toString(); } return result; } function unwrapUriInterval(czmlInterval, sourceUri) { var result = defaultValue(czmlInterval.uri, czmlInterval); if (defined(sourceUri)) { var baseUri = new Uri(document.location.href); sourceUri = new Uri(sourceUri); result = new Uri(result).resolve(sourceUri.resolve(baseUri)).toString(); } return result; } function unwrapRectangleInterval(czmlInterval) { var wsenDegrees = czmlInterval.wsenDegrees; if (defined(wsenDegrees)) { var length = wsenDegrees.length; for (var i = 0; i < length; i++) { wsenDegrees[i] = CesiumMath.toRadians(wsenDegrees[i]); } return wsenDegrees; } return czmlInterval.wsen; } function unwrapCartesianInterval(czmlInterval) { if (defined(czmlInterval.cartesian)) { return czmlInterval.cartesian; } if (defined(czmlInterval.cartesianVelocity)) { return czmlInterval.cartesianVelocity; } if (defined(czmlInterval.unitCartesian)) { return czmlInterval.unitCartesian; } var i; var len; var result; var unitSpherical = czmlInterval.unitSpherical; if (defined(unitSpherical)) { len = unitSpherical.length; if (len === 2) { scratchSpherical.clock = unitSpherical[0]; scratchSpherical.cone = unitSpherical[1]; Cartesian3.fromSpherical(scratchSpherical, scratchCartesian); result = [scratchCartesian.x, scratchCartesian.y, scratchCartesian.z]; } else { var sphericalIt = 0; result = new Array((len / 3) * 4); for (i = 0; i < len; i += 4) { result[i] = unitSpherical[sphericalIt++]; scratchSpherical.clock = unitSpherical[sphericalIt++]; scratchSpherical.cone = unitSpherical[sphericalIt++]; Cartesian3.fromSpherical(scratchSpherical, scratchCartesian); result[i + 1] = scratchCartesian.x; result[i + 2] = scratchCartesian.y; result[i + 3] = scratchCartesian.z; } } return result; } var cartographic = czmlInterval.cartographicRadians; if (defined(cartographic)) { if (cartographic.length === 3) { scratchCartographic.longitude = cartographic[0]; scratchCartographic.latitude = cartographic[1]; scratchCartographic.height = cartographic[2]; Ellipsoid.WGS84.cartographicToCartesian(scratchCartographic, scratchCartesian); result = [scratchCartesian.x, scratchCartesian.y, scratchCartesian.z]; } else { len = cartographic.length; result = new Array(len); for (i = 0; i < len; i += 4) { scratchCartographic.longitude = cartographic[i + 1]; scratchCartographic.latitude = cartographic[i + 2]; scratchCartographic.height = cartographic[i + 3]; Ellipsoid.WGS84.cartographicToCartesian(scratchCartographic, scratchCartesian); result[i] = cartographic[i]; result[i + 1] = scratchCartesian.x; result[i + 2] = scratchCartesian.y; result[i + 3] = scratchCartesian.z; } } return result; } var cartographicDegrees = czmlInterval.cartographicDegrees; if (!defined(cartographicDegrees)) { throw new RuntimeError(JSON.stringify(czmlInterval) + ' is not a valid CZML interval.'); } if (cartographicDegrees.length === 3) { scratchCartographic.longitude = CesiumMath.toRadians(cartographicDegrees[0]); scratchCartographic.latitude = CesiumMath.toRadians(cartographicDegrees[1]); scratchCartographic.height = cartographicDegrees[2]; Ellipsoid.WGS84.cartographicToCartesian(scratchCartographic, scratchCartesian); result = [scratchCartesian.x, scratchCartesian.y, scratchCartesian.z]; } else { len = cartographicDegrees.length; result = new Array(len); for (i = 0; i < len; i += 4) { scratchCartographic.longitude = CesiumMath.toRadians(cartographicDegrees[i + 1]); scratchCartographic.latitude = CesiumMath.toRadians(cartographicDegrees[i + 2]); scratchCartographic.height = cartographicDegrees[i + 3]; Ellipsoid.WGS84.cartographicToCartesian(scratchCartographic, scratchCartesian); result[i] = cartographicDegrees[i]; result[i + 1] = scratchCartesian.x; result[i + 2] = scratchCartesian.y; result[i + 3] = scratchCartesian.z; } } return result; } function unwrapInterval(type, czmlInterval, sourceUri) { /*jshint sub:true*/ switch (type) { case Boolean: return defaultValue(czmlInterval['boolean'], czmlInterval); case Cartesian2: return czmlInterval.cartesian2; case Cartesian3: return unwrapCartesianInterval(czmlInterval); case Color: return unwrapColorInterval(czmlInterval); case StripeOrientation: return StripeOrientation[defaultValue(czmlInterval.stripeOrientation, czmlInterval)]; case HorizontalOrigin: return HorizontalOrigin[defaultValue(czmlInterval.horizontalOrigin, czmlInterval)]; case Image: return unwrapUriInterval(czmlInterval, sourceUri); case JulianDate: return JulianDate.fromIso8601(defaultValue(czmlInterval.date, czmlInterval)); case LabelStyle: return LabelStyle[defaultValue(czmlInterval.labelStyle, czmlInterval)]; case Number: return defaultValue(czmlInterval.number, czmlInterval); case String: return defaultValue(czmlInterval.string, czmlInterval); case Array: return czmlInterval.array; case Quaternion: return czmlInterval.unitQuaternion; case Rectangle: return unwrapRectangleInterval(czmlInterval); case Uri: return unwrapUriInterval(czmlInterval, sourceUri); case VerticalOrigin: return VerticalOrigin[defaultValue(czmlInterval.verticalOrigin, czmlInterval)]; default: throw new DeveloperError(type); } } var interpolators = { HERMITE : HermitePolynomialApproximation, LAGRANGE : LagrangePolynomialApproximation, LINEAR : LinearApproximation }; function updateInterpolationSettings(packetData, property) { var interpolationAlgorithm = packetData.interpolationAlgorithm; if (defined(interpolationAlgorithm) || defined(packetData.interpolationDegree)) { property.setInterpolationOptions({ interpolationAlgorithm : interpolators[interpolationAlgorithm], interpolationDegree : packetData.interpolationDegree }); } var forwardExtrapolationType = packetData.forwardExtrapolationType; if (defined(forwardExtrapolationType)) { property.forwardExtrapolationType = ExtrapolationType[forwardExtrapolationType]; } var forwardExtrapolationDuration = packetData.forwardExtrapolationDuration; if (defined(forwardExtrapolationDuration)) { property.forwardExtrapolationDuration = forwardExtrapolationDuration; } var backwardExtrapolationType = packetData.backwardExtrapolationType; if (defined(backwardExtrapolationType)) { property.backwardExtrapolationType = ExtrapolationType[backwardExtrapolationType]; } var backwardExtrapolationDuration = packetData.backwardExtrapolationDuration; if (defined(backwardExtrapolationDuration)) { property.backwardExtrapolationDuration = backwardExtrapolationDuration; } } function processProperty(type, object, propertyName, packetData, constrainedInterval, sourceUri, entityCollection) { var combinedInterval; var packetInterval = packetData.interval; if (defined(packetInterval)) { iso8601Scratch.iso8601 = packetInterval; combinedInterval = TimeInterval.fromIso8601(iso8601Scratch); if (defined(constrainedInterval)) { combinedInterval = TimeInterval.intersect(combinedInterval, constrainedInterval, scratchTimeInterval); } } else if (defined(constrainedInterval)) { combinedInterval = constrainedInterval; } var packedLength; var isSampled; var unwrappedInterval; var unwrappedIntervalLength; var isReference = defined(packetData.reference); var hasInterval = defined(combinedInterval) && !combinedInterval.equals(Iso8601.MAXIMUM_INTERVAL); if (!isReference) { unwrappedInterval = unwrapInterval(type, packetData, sourceUri); packedLength = defaultValue(type.packedLength, 1); unwrappedIntervalLength = defaultValue(unwrappedInterval.length, 1); isSampled = !defined(packetData.array) && (typeof unwrappedInterval !== 'string') && unwrappedIntervalLength > packedLength; } //Any time a constant value is assigned, it completely blows away anything else. if (!isSampled && !hasInterval) { if (isReference) { object[propertyName] = makeReference(entityCollection, packetData.reference); } else if (defined(type.unpack)) { object[propertyName] = new ConstantProperty(type.unpack(unwrappedInterval, 0)); } else { object[propertyName] = new ConstantProperty(unwrappedInterval); } return; } var property = object[propertyName]; var epoch; var packetEpoch = packetData.epoch; if (defined(packetEpoch)) { epoch = JulianDate.fromIso8601(packetEpoch); } //Without an interval, any sampled value is infinite, meaning it completely //replaces any non-sampled property that may exist. if (isSampled && !hasInterval) { if (!(property instanceof SampledProperty)) { property = new SampledProperty(type); object[propertyName] = property; } property.addSamplesPackedArray(unwrappedInterval, epoch); updateInterpolationSettings(packetData, property); return; } var interval; //A constant value with an interval is normally part of a TimeIntervalCollection, //However, if the current property is not a time-interval collection, we need //to turn it into a Composite, preserving the old data with the new interval. if (!isSampled && hasInterval) { //Create a new interval for the constant value. combinedInterval = combinedInterval.clone(); if (isReference) { combinedInterval.data = makeReference(entityCollection, packetData.reference); } else if (defined(type.unpack)) { combinedInterval.data = type.unpack(unwrappedInterval, 0); } else { combinedInterval.data = unwrappedInterval; } //If no property exists, simply use a new interval collection if (!defined(property)) { if (isReference) { property = new CompositeProperty(); } else { property = new TimeIntervalCollectionProperty(); } object[propertyName] = property; } if (!isReference && property instanceof TimeIntervalCollectionProperty) { //If we create a collection, or it already existed, use it. property.intervals.addInterval(combinedInterval); } else if (property instanceof CompositeProperty) { //If the collection was already a CompositeProperty, use it. combinedInterval.data = isReference ? combinedInterval.data : new ConstantProperty(combinedInterval.data); property.intervals.addInterval(combinedInterval); } else { //Otherwise, create a CompositeProperty but preserve the existing data. //Put the old property in an infinite interval. interval = Iso8601.MAXIMUM_INTERVAL.clone(); interval.data = property; //Create the composite. property = new CompositeProperty(); object[propertyName] = property; //add the old property interval property.intervals.addInterval(interval); //Change the new data to a ConstantProperty and add it. combinedInterval.data = isReference ? combinedInterval.data : new ConstantProperty(combinedInterval.data); property.intervals.addInterval(combinedInterval); } return; } //isSampled && hasInterval if (!defined(property)) { property = new CompositeProperty(); object[propertyName] = property; } //create a CompositeProperty but preserve the existing data. if (!(property instanceof CompositeProperty)) { //Put the old property in an infinite interval. interval = Iso8601.MAXIMUM_INTERVAL.clone(); interval.data = property; //Create the composite. property = new CompositeProperty(); object[propertyName] = property; //add the old property interval property.intervals.addInterval(interval); } //Check if the interval already exists in the composite var intervals = property.intervals; interval = intervals.findInterval(combinedInterval); if (!defined(interval) || !(interval.data instanceof SampledProperty)) { //If not, create a SampledProperty for it. interval = combinedInterval.clone(); interval.data = new SampledProperty(type); intervals.addInterval(interval); } interval.data.addSamplesPackedArray(unwrappedInterval, epoch); updateInterpolationSettings(packetData, interval.data); return; } function processPacketData(type, object, propertyName, packetData, interval, sourceUri, entityCollection) { if (!defined(packetData)) { return; } if (isArray(packetData)) { for (var i = 0, len = packetData.length; i < len; i++) { processProperty(type, object, propertyName, packetData[i], interval, sourceUri, entityCollection); } } else { processProperty(type, object, propertyName, packetData, interval, sourceUri, entityCollection); } } function processPositionProperty(object, propertyName, packetData, constrainedInterval, sourceUri, entityCollection) { var combinedInterval; var packetInterval = packetData.interval; if (defined(packetInterval)) { iso8601Scratch.iso8601 = packetInterval; combinedInterval = TimeInterval.fromIso8601(iso8601Scratch); if (defined(constrainedInterval)) { combinedInterval = TimeInterval.intersect(combinedInterval, constrainedInterval, scratchTimeInterval); } } else if (defined(constrainedInterval)) { combinedInterval = constrainedInterval; } var referenceFrame; var unwrappedInterval; var isSampled = false; var unwrappedIntervalLength; var numberOfDerivatives = defined(packetData.cartesianVelocity) ? 1 : 0; var packedLength = Cartesian3.packedLength * (numberOfDerivatives + 1); var isReference = defined(packetData.reference); var hasInterval = defined(combinedInterval) && !combinedInterval.equals(Iso8601.MAXIMUM_INTERVAL); if (!isReference) { referenceFrame = defaultValue(ReferenceFrame[packetData.referenceFrame], undefined); unwrappedInterval = unwrapCartesianInterval(packetData); unwrappedIntervalLength = defaultValue(unwrappedInterval.length, 1); isSampled = unwrappedIntervalLength > packedLength; } //Any time a constant value is assigned, it completely blows away anything else. if (!isSampled && !hasInterval) { if (isReference) { object[propertyName] = makeReference(entityCollection, packetData.reference); } else { object[propertyName] = new ConstantPositionProperty(Cartesian3.unpack(unwrappedInterval), referenceFrame); } return; } var property = object[propertyName]; var epoch; var packetEpoch = packetData.epoch; if (defined(packetEpoch)) { epoch = JulianDate.fromIso8601(packetEpoch); } //Without an interval, any sampled value is infinite, meaning it completely //replaces any non-sampled property that may exist. if (isSampled && !hasInterval) { if (!(property instanceof SampledPositionProperty) || (defined(referenceFrame) && property.referenceFrame !== referenceFrame)) { property = new SampledPositionProperty(referenceFrame, numberOfDerivatives); object[propertyName] = property; } property.addSamplesPackedArray(unwrappedInterval, epoch); updateInterpolationSettings(packetData, property); return; } var interval; //A constant value with an interval is normally part of a TimeIntervalCollection, //However, if the current property is not a time-interval collection, we need //to turn it into a Composite, preserving the old data with the new interval. if (!isSampled && hasInterval) { //Create a new interval for the constant value. combinedInterval = combinedInterval.clone(); if (isReference) { combinedInterval.data = makeReference(entityCollection, packetData.reference); } else { combinedInterval.data = Cartesian3.unpack(unwrappedInterval); } //If no property exists, simply use a new interval collection if (!defined(property)) { if (isReference) { property = new CompositePositionProperty(referenceFrame); } else { property = new TimeIntervalCollectionPositionProperty(referenceFrame); } object[propertyName] = property; } if (!isReference && property instanceof TimeIntervalCollectionPositionProperty && (defined(referenceFrame) && property.referenceFrame === referenceFrame)) { //If we create a collection, or it already existed, use it. property.intervals.addInterval(combinedInterval); } else if (property instanceof CompositePositionProperty) { //If the collection was already a CompositePositionProperty, use it. combinedInterval.data = isReference ? combinedInterval.data : new ConstantPositionProperty(combinedInterval.data, referenceFrame); property.intervals.addInterval(combinedInterval); } else { //Otherwise, create a CompositePositionProperty but preserve the existing data. //Put the old property in an infinite interval. interval = Iso8601.MAXIMUM_INTERVAL.clone(); interval.data = property; //Create the composite. property = new CompositePositionProperty(property.referenceFrame); object[propertyName] = property; //add the old property interval property.intervals.addInterval(interval); //Change the new data to a ConstantPositionProperty and add it. combinedInterval.data = isReference ? combinedInterval.data : new ConstantPositionProperty(combinedInterval.data, referenceFrame); property.intervals.addInterval(combinedInterval); } return; } //isSampled && hasInterval if (!defined(property)) { property = new CompositePositionProperty(referenceFrame); object[propertyName] = property; } else if (!(property instanceof CompositePositionProperty)) { //create a CompositeProperty but preserve the existing data. //Put the old property in an infinite interval. interval = Iso8601.MAXIMUM_INTERVAL.clone(); interval.data = property; //Create the composite. property = new CompositePositionProperty(property.referenceFrame); object[propertyName] = property; //add the old property interval property.intervals.addInterval(interval); } //Check if the interval already exists in the composite var intervals = property.intervals; interval = intervals.findInterval(combinedInterval); if (!defined(interval) || !(interval.data instanceof SampledPositionProperty) || (defined(referenceFrame) && interval.data.referenceFrame !== referenceFrame)) { //If not, create a SampledPositionProperty for it. interval = combinedInterval.clone(); interval.data = new SampledPositionProperty(referenceFrame, numberOfDerivatives); intervals.addInterval(interval); } interval.data.addSamplesPackedArray(unwrappedInterval, epoch); updateInterpolationSettings(packetData, interval.data); } function processPositionPacketData(object, propertyName, packetData, interval, sourceUri, entityCollection) { if (!defined(packetData)) { return; } if (isArray(packetData)) { for (var i = 0, len = packetData.length; i < len; i++) { processPositionProperty(object, propertyName, packetData[i], interval, sourceUri, entityCollection); } } else { processPositionProperty(object, propertyName, packetData, interval, sourceUri, entityCollection); } } function processMaterialProperty(object, propertyName, packetData, constrainedInterval, sourceUri, entityCollection) { var combinedInterval; var packetInterval = packetData.interval; if (defined(packetInterval)) { iso8601Scratch.iso8601 = packetInterval; combinedInterval = TimeInterval.fromIso8601(iso8601Scratch); if (defined(constrainedInterval)) { combinedInterval = TimeInterval.intersect(combinedInterval, constrainedInterval, scratchTimeInterval); } } else if (defined(constrainedInterval)) { combinedInterval = constrainedInterval; } var property = object[propertyName]; var existingMaterial; var existingInterval; if (defined(combinedInterval)) { if (!(property instanceof CompositeMaterialProperty)) { property = new CompositeMaterialProperty(); object[propertyName] = property; } //See if we already have data at that interval. var thisIntervals = property.intervals; existingInterval = thisIntervals.findInterval({ start : combinedInterval.start, stop : combinedInterval.stop }); if (defined(existingInterval)) { //We have an interval, but we need to make sure the //new data is the same type of material as the old data. existingMaterial = existingInterval.data; } else { //If not, create it. existingInterval = combinedInterval.clone(); thisIntervals.addInterval(existingInterval); } } else { existingMaterial = property; } var materialData; if (defined(packetData.solidColor)) { if (!(existingMaterial instanceof ColorMaterialProperty)) { existingMaterial = new ColorMaterialProperty(); } materialData = packetData.solidColor; processPacketData(Color, existingMaterial, 'color', materialData.color, undefined, undefined, entityCollection); } else if (defined(packetData.grid)) { if (!(existingMaterial instanceof GridMaterialProperty)) { existingMaterial = new GridMaterialProperty(); } materialData = packetData.grid; processPacketData(Color, existingMaterial, 'color', materialData.color, undefined, sourceUri, entityCollection); processPacketData(Number, existingMaterial, 'cellAlpha', materialData.cellAlpha, undefined, sourceUri, entityCollection); processPacketData(Cartesian2, existingMaterial, 'lineThickness', materialData.lineThickness, undefined, sourceUri, entityCollection); processPacketData(Cartesian2, existingMaterial, 'lineOffset', materialData.lineOffset, undefined, sourceUri, entityCollection); processPacketData(Cartesian2, existingMaterial, 'lineCount', materialData.lineCount, undefined, sourceUri, entityCollection); } else if (defined(packetData.image)) { if (!(existingMaterial instanceof ImageMaterialProperty)) { existingMaterial = new ImageMaterialProperty(); } materialData = packetData.image; processPacketData(Image, existingMaterial, 'image', materialData.image, undefined, sourceUri, entityCollection); processPacketData(Cartesian2, existingMaterial, 'repeat', materialData.repeat, undefined, sourceUri, entityCollection); } else if (defined(packetData.stripe)) { if (!(existingMaterial instanceof StripeMaterialProperty)) { existingMaterial = new StripeMaterialProperty(); } materialData = packetData.stripe; processPacketData(StripeOrientation, existingMaterial, 'orientation', materialData.orientation, undefined, sourceUri, entityCollection); processPacketData(Color, existingMaterial, 'evenColor', materialData.evenColor, undefined, sourceUri, entityCollection); processPacketData(Color, existingMaterial, 'oddColor', materialData.oddColor, undefined, sourceUri, entityCollection); processPacketData(Number, existingMaterial, 'offset', materialData.offset, undefined, sourceUri, entityCollection); processPacketData(Number, existingMaterial, 'repeat', materialData.repeat, undefined, sourceUri, entityCollection); } else if (defined(packetData.polylineOutline)) { if (!(existingMaterial instanceof PolylineOutlineMaterialProperty)) { existingMaterial = new PolylineOutlineMaterialProperty(); } materialData = packetData.polylineOutline; processPacketData(Color, existingMaterial, 'color', materialData.color, undefined, sourceUri, entityCollection); processPacketData(Color, existingMaterial, 'outlineColor', materialData.outlineColor, undefined, sourceUri, entityCollection); processPacketData(Number, existingMaterial, 'outlineWidth', materialData.outlineWidth, undefined, sourceUri, entityCollection); } else if (defined(packetData.polylineGlow)) { if (!(existingMaterial instanceof PolylineGlowMaterialProperty)) { existingMaterial = new PolylineGlowMaterialProperty(); } materialData = packetData.polylineGlow; processPacketData(Color, existingMaterial, 'color', materialData.color, undefined, sourceUri, entityCollection); processPacketData(Number, existingMaterial, 'glowPower', materialData.glowPower, undefined, sourceUri, entityCollection); } if (defined(existingInterval)) { existingInterval.data = existingMaterial; } else { object[propertyName] = existingMaterial; } } function processMaterialPacketData(object, propertyName, packetData, interval, sourceUri, entityCollection) { if (!defined(packetData)) { return; } if (isArray(packetData)) { for (var i = 0, len = packetData.length; i < len; i++) { processMaterialProperty(object, propertyName, packetData[i], interval, sourceUri, entityCollection); } } else { processMaterialProperty(object, propertyName, packetData, interval, sourceUri, entityCollection); } } function processName(entity, packet, entityCollection, sourceUri) { entity.name = defaultValue(packet.name, entity.name); } function processDescription(entity, packet, entityCollection, sourceUri) { var descriptionData = packet.description; if (defined(descriptionData)) { processPacketData(String, entity, 'description', descriptionData, undefined, sourceUri, entityCollection); } } function processPosition(entity, packet, entityCollection, sourceUri) { var positionData = packet.position; if (defined(positionData)) { processPositionPacketData(entity, 'position', positionData, undefined, sourceUri, entityCollection); } } function processViewFrom(entity, packet, entityCollection, sourceUri) { var viewFromData = packet.viewFrom; if (defined(viewFromData)) { processPacketData(Cartesian3, entity, 'viewFrom', viewFromData, undefined, sourceUri, entityCollection); } } function processOrientation(entity, packet, entityCollection, sourceUri) { var orientationData = packet.orientation; if (defined(orientationData)) { processPacketData(Quaternion, entity, 'orientation', orientationData, undefined, sourceUri, entityCollection); } } function processVertexData(object, positionsData, entityCollection) { var i; var len; var references = positionsData.references; if (defined(references)) { var properties = []; for (i = 0, len = references.length; i < len; i++) { properties.push(makeReference(entityCollection, references[i])); } var iso8601Interval = positionsData.interval; if (defined(iso8601Interval)) { iso8601Interval = TimeInterval.fromIso8601(iso8601Interval); if (!(object.positions instanceof CompositePositionProperty)) { object.positions = new CompositePositionProperty(); iso8601Interval.data = new PositionPropertyArray(properties); object.positions.intervals.addInterval(iso8601Interval); } } else { object.positions = new PositionPropertyArray(properties); } } else { var values = []; var tmp = positionsData.cartesian; if (defined(tmp)) { for (i = 0, len = tmp.length; i < len; i += 3) { values.push(new Cartesian3(tmp[i], tmp[i + 1], tmp[i + 2])); } positionsData.array = values; } else { tmp = positionsData.cartographicRadians; if (defined(tmp)) { for (i = 0, len = tmp.length; i < len; i += 3) { scratchCartographic.longitude = tmp[i]; scratchCartographic.latitude = tmp[i + 1]; scratchCartographic.height = tmp[i + 2]; values.push(Ellipsoid.WGS84.cartographicToCartesian(scratchCartographic)); } positionsData.array = values; } else { tmp = positionsData.cartographicDegrees; if (defined(tmp)) { for (i = 0, len = tmp.length; i < len; i += 3) { values.push(Cartesian3.fromDegrees(tmp[i], tmp[i + 1], tmp[i + 2])); } positionsData.array = values; } } } if (defined(positionsData.array)) { processPacketData(Array, object, 'positions', positionsData, undefined, undefined, entityCollection); } } } function processPositions(object, positionsData, entityCollection) { if (!defined(positionsData)) { return; } if (isArray(positionsData)) { var length = positionsData.length; for (var i = 0; i < length; i++) { processVertexData(object, positionsData[i], entityCollection); } } else { processVertexData(object, positionsData, entityCollection); } } function processAvailability(entity, packet, entityCollection, sourceUri) { var interval; var packetData = packet.availability; if (!defined(packetData)) { return; } var intervals; if (isArray(packetData)) { var length = packetData.length; for (var i = 0; i < length; i++) { if (!defined(intervals)) { intervals = new TimeIntervalCollection(); } iso8601Scratch.iso8601 = packetData[i]; interval = TimeInterval.fromIso8601(iso8601Scratch); intervals.addInterval(interval); } } else { iso8601Scratch.iso8601 = packetData; interval = TimeInterval.fromIso8601(iso8601Scratch); intervals = new TimeIntervalCollection(); intervals.addInterval(interval); } entity.availability = intervals; } var iso8601Scratch = { iso8601 : undefined }; function processBillboard(entity, packet, entityCollection, sourceUri) { var billboardData = packet.billboard; if (!defined(billboardData)) { return; } var interval; var intervalString = billboardData.interval; if (defined(intervalString)) { iso8601Scratch.iso8601 = intervalString; interval = TimeInterval.fromIso8601(iso8601Scratch); } var billboard = entity.billboard; if (!defined(billboard)) { entity.billboard = billboard = new BillboardGraphics(); } processPacketData(Color, billboard, 'color', billboardData.color, interval, sourceUri, entityCollection); processPacketData(Cartesian3, billboard, 'eyeOffset', billboardData.eyeOffset, interval, sourceUri, entityCollection); processPacketData(HorizontalOrigin, billboard, 'horizontalOrigin', billboardData.horizontalOrigin, interval, sourceUri, entityCollection); processPacketData(Image, billboard, 'image', billboardData.image, interval, sourceUri, entityCollection); processPacketData(Cartesian2, billboard, 'pixelOffset', billboardData.pixelOffset, interval, sourceUri, entityCollection); processPacketData(Number, billboard, 'scale', billboardData.scale, interval, sourceUri, entityCollection); processPacketData(Number, billboard, 'rotation', billboardData.rotation, interval, sourceUri, entityCollection); processPacketData(Cartesian3, billboard, 'alignedAxis', billboardData.alignedAxis, interval, sourceUri, entityCollection); processPacketData(Boolean, billboard, 'show', billboardData.show, interval, sourceUri, entityCollection); processPacketData(VerticalOrigin, billboard, 'verticalOrigin', billboardData.verticalOrigin, interval, sourceUri, entityCollection); } function processDocument(packet, dataSource) { var version = packet.version; if (defined(version)) { if (typeof version === 'string') { var tokens = version.split('.'); if (tokens.length === 2) { if (tokens[0] !== '1') { throw new RuntimeError('Cesium only supports CZML version 1.'); } dataSource._version = version; } } } if (!defined(dataSource._version)) { throw new RuntimeError('CZML version information invalid. It is expected to be a property on the document object in the . version format.'); } var documentPacket = dataSource._documentPacket; if (defined(packet.name)) { documentPacket.name = packet.name; } var clockPacket = packet.clock; if (defined(clockPacket)) { var clock = documentPacket.clock; if (!defined(clock)) { documentPacket.clock = { interval : clockPacket.interval, currentTime : clockPacket.currentTime, range : clockPacket.range, step : clockPacket.step, multiplier : clockPacket.multiplier }; } else { clock.interval = defaultValue(clockPacket.interval, clock.interval); clock.currentTime = defaultValue(clockPacket.currentTime, clock.currentTime); clock.range = defaultValue(clockPacket.range, clock.range); clock.step = defaultValue(clockPacket.step, clock.step); clock.multiplier = defaultValue(clockPacket.multiplier, clock.multiplier); } } } function processEllipse(entity, packet, entityCollection, sourceUri) { var ellipseData = packet.ellipse; if (!defined(ellipseData)) { return; } var interval; var intervalString = ellipseData.interval; if (defined(intervalString)) { iso8601Scratch.iso8601 = intervalString; interval = TimeInterval.fromIso8601(iso8601Scratch); } var ellipse = entity.ellipse; if (!defined(ellipse)) { entity.ellipse = ellipse = new EllipseGraphics(); } processPacketData(Boolean, ellipse, 'show', ellipseData.show, interval, sourceUri, entityCollection); processPacketData(Number, ellipse, 'rotation', ellipseData.rotation, interval, sourceUri, entityCollection); processPacketData(Number, ellipse, 'semiMajorAxis', ellipseData.semiMajorAxis, interval, sourceUri, entityCollection); processPacketData(Number, ellipse, 'semiMinorAxis', ellipseData.semiMinorAxis, interval, sourceUri, entityCollection); processPacketData(Number, ellipse, 'height', ellipseData.height, interval, sourceUri, entityCollection); processPacketData(Number, ellipse, 'extrudedHeight', ellipseData.extrudedHeight, interval, sourceUri, entityCollection); processPacketData(Number, ellipse, 'granularity', ellipseData.granularity, interval, sourceUri, entityCollection); processPacketData(Number, ellipse, 'stRotation', ellipseData.stRotation, interval, sourceUri, entityCollection); processMaterialPacketData(ellipse, 'material', ellipseData.material, interval, sourceUri, entityCollection); processPacketData(Boolean, ellipse, 'fill', ellipseData.fill, interval, sourceUri, entityCollection); processPacketData(Boolean, ellipse, 'outline', ellipseData.outline, interval, sourceUri, entityCollection); processPacketData(Color, ellipse, 'outlineColor', ellipseData.outlineColor, interval, sourceUri, entityCollection); processPacketData(Number, ellipse, 'outlineWidth', ellipseData.outlineWidth, interval, sourceUri, entityCollection); processPacketData(Number, ellipse, 'numberOfVerticalLines', ellipseData.numberOfVerticalLines, interval, sourceUri, entityCollection); } function processEllipsoid(entity, packet, entityCollection, sourceUri) { var ellipsoidData = packet.ellipsoid; if (!defined(ellipsoidData)) { return; } var interval; var intervalString = ellipsoidData.interval; if (defined(intervalString)) { iso8601Scratch.iso8601 = intervalString; interval = TimeInterval.fromIso8601(iso8601Scratch); } var ellipsoid = entity.ellipsoid; if (!defined(ellipsoid)) { entity.ellipsoid = ellipsoid = new EllipsoidGraphics(); } processPacketData(Boolean, ellipsoid, 'show', ellipsoidData.show, interval, sourceUri, entityCollection); processPacketData(Cartesian3, ellipsoid, 'radii', ellipsoidData.radii, interval, sourceUri, entityCollection); processMaterialPacketData(ellipsoid, 'material', ellipsoidData.material, interval, sourceUri, entityCollection); processPacketData(Boolean, ellipsoid, 'fill', ellipsoidData.fill, interval, sourceUri, entityCollection); processPacketData(Boolean, ellipsoid, 'outline', ellipsoidData.outline, interval, sourceUri, entityCollection); processPacketData(Color, ellipsoid, 'outlineColor', ellipsoidData.outlineColor, interval, sourceUri, entityCollection); processPacketData(Number, ellipsoid, 'outlineWidth', ellipsoidData.outlineWidth, interval, sourceUri, entityCollection); } function processLabel(entity, packet, entityCollection, sourceUri) { var labelData = packet.label; if (!defined(labelData)) { return; } var interval; var intervalString = labelData.interval; if (defined(intervalString)) { iso8601Scratch.iso8601 = intervalString; interval = TimeInterval.fromIso8601(iso8601Scratch); } var label = entity.label; if (!defined(label)) { entity.label = label = new LabelGraphics(); } processPacketData(Color, label, 'fillColor', labelData.fillColor, interval, sourceUri, entityCollection); processPacketData(Color, label, 'outlineColor', labelData.outlineColor, interval, sourceUri, entityCollection); processPacketData(Number, label, 'outlineWidth', labelData.outlineWidth, interval, sourceUri, entityCollection); processPacketData(Cartesian3, label, 'eyeOffset', labelData.eyeOffset, interval, sourceUri, entityCollection); processPacketData(HorizontalOrigin, label, 'horizontalOrigin', labelData.horizontalOrigin, interval, sourceUri, entityCollection); processPacketData(String, label, 'text', labelData.text, interval, sourceUri, entityCollection); processPacketData(Cartesian2, label, 'pixelOffset', labelData.pixelOffset, interval, sourceUri, entityCollection); processPacketData(Number, label, 'scale', labelData.scale, interval, sourceUri, entityCollection); processPacketData(Boolean, label, 'show', labelData.show, interval, sourceUri, entityCollection); processPacketData(VerticalOrigin, label, 'verticalOrigin', labelData.verticalOrigin, interval, sourceUri, entityCollection); processPacketData(String, label, 'font', labelData.font, interval, sourceUri, entityCollection); processPacketData(LabelStyle, label, 'style', labelData.style, interval, sourceUri, entityCollection); } function processModel(entity, packet, entityCollection, sourceUri) { var modelData = packet.model; if (!defined(modelData)) { return; } var interval; var intervalString = modelData.interval; if (defined(intervalString)) { iso8601Scratch.iso8601 = intervalString; interval = TimeInterval.fromIso8601(iso8601Scratch); } var model = entity.model; if (!defined(model)) { entity.model = model = new ModelGraphics(); } processPacketData(Boolean, model, 'show', modelData.show, interval, sourceUri, entityCollection); processPacketData(Number, model, 'scale', modelData.scale, interval, sourceUri, entityCollection); processPacketData(Number, model, 'minimumPixelSize', modelData.minimumPixelSize, interval, sourceUri, entityCollection); processPacketData(Uri, model, 'uri', modelData.gltf, interval, sourceUri, entityCollection); } function processPath(entity, packet, entityCollection, sourceUri) { var pathData = packet.path; if (!defined(pathData)) { return; } var interval; var intervalString = pathData.interval; if (defined(intervalString)) { iso8601Scratch.iso8601 = intervalString; interval = TimeInterval.fromIso8601(iso8601Scratch); } var path = entity.path; if (!defined(path)) { entity.path = path = new PathGraphics(); } processPacketData(Boolean, path, 'show', pathData.show, interval, sourceUri, entityCollection); processPacketData(Number, path, 'width', pathData.width, interval, sourceUri, entityCollection); processPacketData(Number, path, 'resolution', pathData.resolution, interval, sourceUri, entityCollection); processPacketData(Number, path, 'leadTime', pathData.leadTime, interval, sourceUri, entityCollection); processPacketData(Number, path, 'trailTime', pathData.trailTime, interval, sourceUri, entityCollection); processMaterialPacketData(path, 'material', pathData.material, interval, sourceUri, entityCollection); } function processPoint(entity, packet, entityCollection, sourceUri) { var pointData = packet.point; if (!defined(pointData)) { return; } var interval; var intervalString = pointData.interval; if (defined(intervalString)) { iso8601Scratch.iso8601 = intervalString; interval = TimeInterval.fromIso8601(iso8601Scratch); } var point = entity.point; if (!defined(point)) { entity.point = point = new PointGraphics(); } processPacketData(Color, point, 'color', pointData.color, interval, sourceUri, entityCollection); processPacketData(Number, point, 'pixelSize', pointData.pixelSize, interval, sourceUri, entityCollection); processPacketData(Color, point, 'outlineColor', pointData.outlineColor, interval, sourceUri, entityCollection); processPacketData(Number, point, 'outlineWidth', pointData.outlineWidth, interval, sourceUri, entityCollection); processPacketData(Boolean, point, 'show', pointData.show, interval, sourceUri, entityCollection); } function processPolygon(entity, packet, entityCollection, sourceUri) { var polygonData = packet.polygon; if (!defined(polygonData)) { return; } var interval; var intervalString = polygonData.interval; if (defined(intervalString)) { iso8601Scratch.iso8601 = intervalString; interval = TimeInterval.fromIso8601(iso8601Scratch); } var polygon = entity.polygon; if (!defined(polygon)) { entity.polygon = polygon = new PolygonGraphics(); } processPacketData(Boolean, polygon, 'show', polygonData.show, interval, sourceUri, entityCollection); processMaterialPacketData(polygon, 'material', polygonData.material, interval, sourceUri, entityCollection); processPacketData(Number, polygon, 'height', polygonData.height, interval, sourceUri, entityCollection); processPacketData(Number, polygon, 'extrudedHeight', polygonData.extrudedHeight, interval, sourceUri, entityCollection); processPacketData(Number, polygon, 'granularity', polygonData.granularity, interval, sourceUri, entityCollection); processPacketData(Number, polygon, 'stRotation', polygonData.stRotation, interval, sourceUri, entityCollection); processPacketData(Boolean, polygon, 'fill', polygonData.fill, interval, sourceUri, entityCollection); processPacketData(Boolean, polygon, 'outline', polygonData.outline, interval, sourceUri, entityCollection); processPacketData(Color, polygon, 'outlineColor', polygonData.outlineColor, interval, sourceUri, entityCollection); processPacketData(Number, polygon, 'outlineWidth', polygonData.outlineWidth, interval, sourceUri, entityCollection); processPacketData(Boolean, polygon, 'perPositionHeight', polygonData.perPositionHeight, interval, sourceUri, entityCollection); processPositions(polygon, polygonData.positions, entityCollection); } function processRectangle(entity, packet, entityCollection, sourceUri) { var rectangleData = packet.rectangle; if (!defined(rectangleData)) { return; } var interval; var intervalString = rectangleData.interval; if (defined(intervalString)) { iso8601Scratch.iso8601 = intervalString; interval = TimeInterval.fromIso8601(iso8601Scratch); } var rectangle = entity.rectangle; if (!defined(rectangle)) { entity.rectangle = rectangle = new RectangleGraphics(); } processPacketData(Boolean, rectangle, 'show', rectangleData.show, interval, sourceUri, entityCollection); processPacketData(Rectangle, rectangle, 'coordinates', rectangleData.coordinates, interval, sourceUri, entityCollection); processMaterialPacketData(rectangle, 'material', rectangleData.material, interval, sourceUri, entityCollection); processPacketData(Number, rectangle, 'height', rectangleData.height, interval, sourceUri, entityCollection); processPacketData(Number, rectangle, 'extrudedHeight', rectangleData.extrudedHeight, interval, sourceUri, entityCollection); processPacketData(Number, rectangle, 'granularity', rectangleData.granularity, interval, sourceUri, entityCollection); processPacketData(Number, rectangle, 'rotation', rectangleData.rotation, interval, sourceUri, entityCollection); processPacketData(Number, rectangle, 'stRotation', rectangleData.stRotation, interval, sourceUri, entityCollection); processPacketData(Boolean, rectangle, 'fill', rectangleData.fill, interval, sourceUri, entityCollection); processPacketData(Boolean, rectangle, 'outline', rectangleData.outline, interval, sourceUri, entityCollection); processPacketData(Color, rectangle, 'outlineColor', rectangleData.outlineColor, interval, sourceUri, entityCollection); processPacketData(Number, rectangle, 'outlineWidth', rectangleData.outlineWidth, interval, sourceUri, entityCollection); processPacketData(Boolean, rectangle, 'closeBottom', rectangleData.closeBottom, interval, sourceUri, entityCollection); processPacketData(Boolean, rectangle, 'closeTop', rectangleData.closeTop, interval, sourceUri, entityCollection); } function processWall(entity, packet, entityCollection, sourceUri) { var wallData = packet.wall; if (!defined(wallData)) { return; } var interval; var intervalString = wallData.interval; if (defined(intervalString)) { iso8601Scratch.iso8601 = intervalString; interval = TimeInterval.fromIso8601(iso8601Scratch); } var wall = entity.wall; if (!defined(wall)) { entity.wall = wall = new WallGraphics(); } processPacketData(Boolean, wall, 'show', wallData.show, interval, sourceUri, entityCollection); processMaterialPacketData(wall, 'material', wallData.material, interval, sourceUri, entityCollection); processPacketData(Array, wall, 'minimumHeights', wallData.minimumHeights, interval, sourceUri, entityCollection); processPacketData(Array, wall, 'maximumHeights', wallData.maximumHeights, interval, sourceUri, entityCollection); processPacketData(Number, wall, 'granularity', wallData.granularity, interval, sourceUri, entityCollection); processPacketData(Boolean, wall, 'fill', wallData.fill, interval, sourceUri, entityCollection); processPacketData(Boolean, wall, 'outline', wallData.outline, interval, sourceUri, entityCollection); processPacketData(Color, wall, 'outlineColor', wallData.outlineColor, interval, sourceUri, entityCollection); processPacketData(Number, wall, 'outlineWidth', wallData.outlineWidth, interval, sourceUri, entityCollection); processPositions(wall, wallData.positions, entityCollection); } function processPolyline(entity, packet, entityCollection, sourceUri) { var polylineData = packet.polyline; if (!defined(polylineData)) { return; } var interval; var intervalString = polylineData.interval; if (defined(intervalString)) { iso8601Scratch.iso8601 = intervalString; interval = TimeInterval.fromIso8601(iso8601Scratch); } var polyline = entity.polyline; if (!defined(polyline)) { entity.polyline = polyline = new PolylineGraphics(); } processPacketData(Boolean, polyline, 'show', polylineData.show, interval, sourceUri, entityCollection); processPacketData(Number, polyline, 'width', polylineData.width, interval, sourceUri, entityCollection); processMaterialPacketData(polyline, 'material', polylineData.material, interval, sourceUri, entityCollection); processPacketData(Boolean, polyline, 'followSurface', polylineData.followSurface, interval, sourceUri, entityCollection); processPacketData(Number, polyline, 'granularity', polylineData.granularity, interval, sourceUri, entityCollection); processPositions(polyline, polylineData.positions, entityCollection); } function processCzmlPacket(packet, entityCollection, updaterFunctions, sourceUri, dataSource) { var objectId = packet.id; if (!defined(objectId)) { objectId = createGuid(); } currentId = objectId; if (!defined(dataSource._version) && objectId !== 'document') { throw new RuntimeError('The first CZML packet is required to be the document object.'); } if (packet['delete'] === true) { entityCollection.removeById(objectId); } else if (objectId === 'document') { processDocument(packet, dataSource); } else { var entity = entityCollection.getOrCreateEntity(objectId); var parentId = packet.parent; if (defined(parentId)) { entity.parent = entityCollection.getOrCreateEntity(parentId); } for (var i = updaterFunctions.length - 1; i > -1; i--) { updaterFunctions[i](entity, packet, entityCollection, sourceUri); } } currentId = undefined; } function updateClock(dataSource) { var clock; var clockPacket = dataSource._documentPacket.clock; if (!defined(clockPacket)) { if (!defined(dataSource._clock)) { var availability = dataSource._entityCollection.computeAvailability(); if (!availability.start.equals(Iso8601.MINIMUM_VALUE)) { var startTime = availability.start; var stopTime = availability.stop; var totalSeconds = JulianDate.secondsDifference(stopTime, startTime); var multiplier = Math.round(totalSeconds / 120.0); clock = new DataSourceClock(); clock.startTime = JulianDate.clone(startTime); clock.stopTime = JulianDate.clone(stopTime); clock.clockRange = ClockRange.LOOP_STOP; clock.multiplier = multiplier; clock.currentTime = JulianDate.clone(startTime); clock.clockStep = ClockStep.SYSTEM_CLOCK_MULTIPLIER; dataSource._clock = clock; return true; } } return false; } if (defined(dataSource._clock)) { clock = dataSource._clock.clone(); } else { clock = new DataSourceClock(); clock.startTime = Iso8601.MINIMUM_VALUE.clone(); clock.stopTime = Iso8601.MAXIMUM_VALUE.clone(); clock.currentTime = Iso8601.MINIMUM_VALUE.clone(); clock.clockRange = ClockRange.LOOP_STOP; clock.clockStep = ClockStep.SYSTEM_CLOCK_MULTIPLIER; clock.multiplier = 1.0; } if (defined(clockPacket.interval)) { iso8601Scratch.iso8601 = clockPacket.interval; var interval = TimeInterval.fromIso8601(iso8601Scratch); clock.startTime = interval.start; clock.stopTime = interval.stop; } if (defined(clockPacket.currentTime)) { clock.currentTime = JulianDate.fromIso8601(clockPacket.currentTime); } if (defined(clockPacket.range)) { clock.clockRange = defaultValue(ClockRange[clockPacket.range], ClockRange.LOOP_STOP); } if (defined(clockPacket.step)) { clock.clockStep = defaultValue(ClockStep[clockPacket.step], ClockStep.SYSTEM_CLOCK_MULTIPLIER); } if (defined(clockPacket.multiplier)) { clock.multiplier = clockPacket.multiplier; } if (!clock.equals(dataSource._clock)) { dataSource._clock = clock.clone(dataSource._clock); return true; } return false; } function loadCzml(dataSource, czml, sourceUri, clear) { DataSource.setLoading(dataSource, true); var entityCollection = dataSource._entityCollection; if (clear) { dataSource._version = undefined; dataSource._documentPacket = new DocumentPacket(); entityCollection.removeAll(); } CzmlDataSource._processCzml(czml, entityCollection, sourceUri, undefined, dataSource); var raiseChangedEvent = updateClock(dataSource); var documentPacket = dataSource._documentPacket; if (defined(documentPacket.name) && dataSource._name !== documentPacket.name) { dataSource._name = documentPacket.name; raiseChangedEvent = true; } else if (!defined(dataSource._name) && defined(sourceUri)) { dataSource._name = getFilenameFromUri(sourceUri); raiseChangedEvent = true; } DataSource.setLoading(dataSource, false); if (raiseChangedEvent) { dataSource._changed.raiseEvent(dataSource); } } var DocumentPacket = function() { this.name = undefined; this.clock = undefined; }; /** * A {@link DataSource} which processes CZML. * @alias CzmlDataSource * @constructor * * @param {String} [name] An optional name for the data source. This value will be overwritten if a loaded document contains a name. * * @demo {@link http://cesiumjs.org/Cesium/Apps/Sandcastle/index.html?src=CZML.html|Cesium Sandcastle CZML Demo} */ var CzmlDataSource = function(name) { this._name = name; this._changed = new Event(); this._error = new Event(); this._isLoading = false; this._loading = new Event(); this._clock = undefined; this._documentPacket = new DocumentPacket(); this._version = undefined; this._entityCollection = new EntityCollection(); }; defineProperties(CzmlDataSource.prototype, { /** * Gets a human-readable name for this instance. * @memberof CzmlDataSource.prototype * @type {String} */ name : { get : function() { return this._name; } }, /** * Gets the clock settings defined by the loaded CZML. If no clock is explicitly * defined in the CZML, the combined availability of all objects is returned. If * only static data exists, this value is undefined. * @memberof CzmlDataSource.prototype * @type {DataSourceClock} */ clock : { get : function() { return this._clock; } }, /** * Gets the collection of {@link Entity} instances. * @memberof CzmlDataSource.prototype * @type {EntityCollection} */ entities : { get : function() { return this._entityCollection; } }, /** * Gets a value indicating if the data source is currently loading data. * @memberof CzmlDataSource.prototype * @type {Boolean} */ isLoading : { get : function() { return this._isLoading; } }, /** * Gets an event that will be raised when the underlying data changes. * @memberof CzmlDataSource.prototype * @type {Event} */ changedEvent : { get : function() { return this._changed; } }, /** * Gets an event that will be raised if an error is encountered during processing. * @memberof CzmlDataSource.prototype * @type {Event} */ errorEvent : { get : function() { return this._error; } }, /** * Gets an event that will be raised when the data source either starts or stops loading. * @memberof CzmlDataSource.prototype * @type {Event} */ loadingEvent : { get : function() { return this._loading; } } }); /** * Gets the array of CZML processing functions. * @memberof CzmlDataSource * @type Array */ CzmlDataSource.updaters = [ processBillboard, // processEllipse, // processEllipsoid, // processLabel, // processModel, // processName, // processDescription, // processPath, // processPoint, // processPolygon, // processPolyline, // processRectangle, // processPosition, // processViewFrom, // processWall, // processOrientation, // processAvailability]; /** * Processes the provided CZML without clearing any existing data. * * @param {Object} czml The CZML to be processed. * @param {String} sourceUri The source URI of the CZML. */ CzmlDataSource.prototype.process = function(czml, sourceUri) { //>>includeStart('debug', pragmas.debug); if (!defined(czml)) { throw new DeveloperError('czml is required.'); } //>>includeEnd('debug'); loadCzml(this, czml, sourceUri, false); }; /** * Replaces any existing data with the provided CZML. * * @param {Object} czml The CZML to be processed. * @param {String} source The source URI of the CZML. */ CzmlDataSource.prototype.load = function(czml, sourceUri) { //>>includeStart('debug', pragmas.debug); if (!defined(czml)) { throw new DeveloperError('czml is required.'); } //>>includeEnd('debug'); loadCzml(this, czml, sourceUri, true); }; /** * Asynchronously processes the CZML at the provided url without clearing any existing data. * * @param {Object} url The url to be processed. * @returns {Promise} a promise that will resolve when the CZML is processed. */ CzmlDataSource.prototype.processUrl = function(url) { //>>includeStart('debug', pragmas.debug); if (!defined(url)) { throw new DeveloperError('url is required.'); } //>>includeEnd('debug'); DataSource.setLoading(this, true); var dataSource = this; return when(loadJson(url), function(czml) { loadCzml(dataSource, czml, url, false); }).otherwise(function(error) { DataSource.setLoading(dataSource, false); dataSource._error.raiseEvent(dataSource, error); return when.reject(error); }); }; /** * Asynchronously loads the CZML at the provided url, replacing any existing data. * * @param {Object} url The url to be processed. * @returns {Promise} a promise that will resolve when the CZML is processed. */ CzmlDataSource.prototype.loadUrl = function(url) { //>>includeStart('debug', pragmas.debug); if (!defined(url)) { throw new DeveloperError('url is required.'); } //>>includeEnd('debug'); DataSource.setLoading(this, true); var dataSource = this; return when(loadJson(url), function(czml) { loadCzml(dataSource, czml, url, true); }).otherwise(function(error) { DataSource.setLoading(dataSource, false); dataSource._error.raiseEvent(dataSource, error); return when.reject(error); }); }; /** * A helper function used by custom CZML updater functions * which creates or updates a {@link Property} from a CZML packet. * @function * * @param {Function} type The constructor function for the property being processed. * @param {Object} object The object on which the property will be added or updated. * @param {String} propertyName The name of the property on the object. * @param {Object} packetData The CZML packet being processed. * @param {TimeInterval} interval A constraining interval for which the data is valid. * @param {String} sourceUri The originating uri of the data being processed. * @param {EntityCollection} entityCollection The collection being processsed. */ CzmlDataSource.processPacketData = processPacketData; /** * A helper function used by custom CZML updater functions * which creates or updates a {@link PositionProperty} from a CZML packet. * @function * * @param {Object} object The object on which the property will be added or updated. * @param {String} propertyName The name of the property on the object. * @param {Object} packetData The CZML packet being processed. * @param {TimeInterval} interval A constraining interval for which the data is valid. * @param {String} sourceUri The originating uri of the data being processed. * @param {EntityCollection} entityCollection The collection being processsed. */ CzmlDataSource.processPositionPacketData = processPositionPacketData; /** * A helper function used by custom CZML updater functions * which creates or updates a {@link MaterialProperty} from a CZML packet. * @function * * @param {Object} object The object on which the property will be added or updated. * @param {String} propertyName The name of the property on the object. * @param {Object} packetData The CZML packet being processed. * @param {TimeInterval} interval A constraining interval for which the data is valid. * @param {String} sourceUri The originating uri of the data being processed. * @param {EntityCollection} entityCollection The collection being processsed. */ CzmlDataSource.processMaterialPacketData = processMaterialPacketData; CzmlDataSource._processCzml = function(czml, entityCollection, sourceUri, updaterFunctions, dataSource) { updaterFunctions = defined(updaterFunctions) ? updaterFunctions : CzmlDataSource.updaters; if (isArray(czml)) { for (var i = 0, len = czml.length; i < len; i++) { processCzmlPacket(czml[i], entityCollection, updaterFunctions, sourceUri, dataSource); } } else { processCzmlPacket(czml, entityCollection, updaterFunctions, sourceUri, dataSource); } }; return CzmlDataSource; });