UNPKG

cesium

Version:

CesiumJS is a JavaScript library for creating 3D globes and 2D maps in a web browser without a plugin.

1,133 lines (1,016 loc) 110 kB
define([ '../Core/BoundingRectangle', '../Core/Cartesian2', '../Core/Cartesian3', '../Core/Cartographic', '../Core/ClockRange', '../Core/ClockStep', '../Core/Color', '../Core/CornerType', '../Core/createGuid', '../Core/defaultValue', '../Core/defined', '../Core/defineProperties', '../Core/DeveloperError', '../Core/DistanceDisplayCondition', '../Core/Ellipsoid', '../Core/Event', '../Core/ExtrapolationType', '../Core/getFilenameFromUri', '../Core/HermitePolynomialApproximation', '../Core/isArray', '../Core/Iso8601', '../Core/JulianDate', '../Core/LagrangePolynomialApproximation', '../Core/LinearApproximation', '../Core/Math', '../Core/NearFarScalar', '../Core/Quaternion', '../Core/Rectangle', '../Core/ReferenceFrame', '../Core/Resource', '../Core/RuntimeError', '../Core/Spherical', '../Core/TimeInterval', '../Core/TimeIntervalCollection', '../Scene/ColorBlendMode', '../Scene/HeightReference', '../Scene/HorizontalOrigin', '../Scene/LabelStyle', '../Scene/ShadowMode', '../Scene/VerticalOrigin', '../ThirdParty/Uri', '../ThirdParty/when', './BillboardGraphics', './BoxGraphics', './ColorMaterialProperty', './CompositeMaterialProperty', './CompositePositionProperty', './CompositeProperty', './ConstantPositionProperty', './ConstantProperty', './CorridorGraphics', './CylinderGraphics', './DataSource', './DataSourceClock', './EllipseGraphics', './EllipsoidGraphics', './EntityCluster', './EntityCollection', './GridMaterialProperty', './ImageMaterialProperty', './LabelGraphics', './ModelGraphics', './NodeTransformationProperty', './PathGraphics', './PointGraphics', './PolygonGraphics', './PolylineArrowMaterialProperty', './PolylineDashMaterialProperty', './PolylineGlowMaterialProperty', './PolylineGraphics', './PolylineOutlineMaterialProperty', './PositionPropertyArray', './PropertyArray', './PropertyBag', './RectangleGraphics', './ReferenceProperty', './Rotation', './SampledPositionProperty', './SampledProperty', './StripeMaterialProperty', './StripeOrientation', './TimeIntervalCollectionPositionProperty', './TimeIntervalCollectionProperty', './VelocityOrientationProperty', './VelocityVectorProperty', './WallGraphics' ], function( BoundingRectangle, Cartesian2, Cartesian3, Cartographic, ClockRange, ClockStep, Color, CornerType, createGuid, defaultValue, defined, defineProperties, DeveloperError, DistanceDisplayCondition, Ellipsoid, Event, ExtrapolationType, getFilenameFromUri, HermitePolynomialApproximation, isArray, Iso8601, JulianDate, LagrangePolynomialApproximation, LinearApproximation, CesiumMath, NearFarScalar, Quaternion, Rectangle, ReferenceFrame, Resource, RuntimeError, Spherical, TimeInterval, TimeIntervalCollection, ColorBlendMode, HeightReference, HorizontalOrigin, LabelStyle, ShadowMode, VerticalOrigin, Uri, when, BillboardGraphics, BoxGraphics, ColorMaterialProperty, CompositeMaterialProperty, CompositePositionProperty, CompositeProperty, ConstantPositionProperty, ConstantProperty, CorridorGraphics, CylinderGraphics, DataSource, DataSourceClock, EllipseGraphics, EllipsoidGraphics, EntityCluster, EntityCollection, GridMaterialProperty, ImageMaterialProperty, LabelGraphics, ModelGraphics, NodeTransformationProperty, PathGraphics, PointGraphics, PolygonGraphics, PolylineArrowMaterialProperty, PolylineDashMaterialProperty, PolylineGlowMaterialProperty, PolylineGraphics, PolylineOutlineMaterialProperty, PositionPropertyArray, PropertyArray, PropertyBag, RectangleGraphics, ReferenceProperty, Rotation, SampledPositionProperty, SampledProperty, StripeMaterialProperty, StripeOrientation, TimeIntervalCollectionPositionProperty, TimeIntervalCollectionProperty, VelocityOrientationProperty, VelocityVectorProperty, WallGraphics) { 'use strict'; // A marker type to distinguish CZML properties where we need to end up with a unit vector. // The data is still loaded into Cartesian3 objects but they are normalized. function UnitCartesian3() {} UnitCartesian3.packedLength = Cartesian3.packedLength; UnitCartesian3.unpack = Cartesian3.unpack; UnitCartesian3.pack = Cartesian3.pack; // As a side note, for the purposes of CZML, Quaternion always indicates a unit quaternion. var currentId; function createReferenceProperty(entityCollection, referenceString) { if (referenceString[0] === '#') { referenceString = currentId + referenceString; } return ReferenceProperty.fromString(entityCollection, referenceString); } function createSpecializedProperty(type, entityCollection, packetData) { if (defined(packetData.reference)) { return createReferenceProperty(entityCollection, packetData.reference); } if (defined(packetData.velocityReference)) { var referenceProperty = createReferenceProperty(entityCollection, packetData.velocityReference); switch (type) { case Cartesian3: case UnitCartesian3: return new VelocityVectorProperty(referenceProperty, type === UnitCartesian3); case Quaternion: return new VelocityOrientationProperty(referenceProperty); } } throw new RuntimeError(JSON.stringify(packetData) + ' is not valid CZML.'); } var scratchCartesian = new Cartesian3(); var scratchSpherical = new Spherical(); var scratchCartographic = new Cartographic(); var scratchTimeInterval = new TimeInterval(); var scratchQuaternion = new Quaternion(); function unwrapColorInterval(czmlInterval) { var rgbaf = czmlInterval.rgbaf; if (defined(rgbaf)) { return rgbaf; } var rgba = czmlInterval.rgba; if (!defined(rgba)) { return undefined; } var length = rgba.length; if (length === Color.packedLength) { return [Color.byteToFloat(rgba[0]), Color.byteToFloat(rgba[1]), Color.byteToFloat(rgba[2]), Color.byteToFloat(rgba[3])]; } rgbaf = new Array(length); for (var i = 0; i < length; 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 unwrapUriInterval(czmlInterval, sourceUri) { var uri = defaultValue(czmlInterval.uri, czmlInterval); if (defined(sourceUri)) { return sourceUri.getDerivedResource({ url: uri }); } return Resource.createIfNeeded(uri); } function unwrapRectangleInterval(czmlInterval) { var wsen = czmlInterval.wsen; if (defined(wsen)) { return wsen; } var wsenDegrees = czmlInterval.wsenDegrees; if (!defined(wsenDegrees)) { return undefined; } var length = wsenDegrees.length; if (length === Rectangle.packedLength) { return [CesiumMath.toRadians(wsenDegrees[0]), CesiumMath.toRadians(wsenDegrees[1]), CesiumMath.toRadians(wsenDegrees[2]), CesiumMath.toRadians(wsenDegrees[3])]; } wsen = new Array(length); for (var i = 0; i < length; i += 5) { wsen[i] = wsenDegrees[i]; wsen[i + 1] = CesiumMath.toRadians(wsenDegrees[i + 1]); wsen[i + 2] = CesiumMath.toRadians(wsenDegrees[i + 2]); wsen[i + 3] = CesiumMath.toRadians(wsenDegrees[i + 3]); wsen[i + 4] = CesiumMath.toRadians(wsenDegrees[i + 4]); } return wsen; } function convertUnitSphericalToCartesian(unitSpherical) { var length = unitSpherical.length; scratchSpherical.magnitude = 1.0; if (length === 2) { scratchSpherical.clock = unitSpherical[0]; scratchSpherical.cone = unitSpherical[1]; Cartesian3.fromSpherical(scratchSpherical, scratchCartesian); return [scratchCartesian.x, scratchCartesian.y, scratchCartesian.z]; } var result = new Array(length / 3 * 4); for (var i = 0, j = 0; i < length; i += 3, j += 4) { result[j] = unitSpherical[i]; scratchSpherical.clock = unitSpherical[i + 1]; scratchSpherical.cone = unitSpherical[i + 2]; Cartesian3.fromSpherical(scratchSpherical, scratchCartesian); result[j + 1] = scratchCartesian.x; result[j + 2] = scratchCartesian.y; result[j + 3] = scratchCartesian.z; } return result; } function convertSphericalToCartesian(spherical) { var length = spherical.length; if (length === 3) { scratchSpherical.clock = spherical[0]; scratchSpherical.cone = spherical[1]; scratchSpherical.magnitude = spherical[2]; Cartesian3.fromSpherical(scratchSpherical, scratchCartesian); return [scratchCartesian.x, scratchCartesian.y, scratchCartesian.z]; } var result = new Array(length); for (var i = 0; i < length; i += 4) { result[i] = spherical[i]; scratchSpherical.clock = spherical[i + 1]; scratchSpherical.cone = spherical[i + 2]; scratchSpherical.magnitude = spherical[i + 3]; Cartesian3.fromSpherical(scratchSpherical, scratchCartesian); result[i + 1] = scratchCartesian.x; result[i + 2] = scratchCartesian.y; result[i + 3] = scratchCartesian.z; } return result; } function convertCartographicRadiansToCartesian(cartographicRadians) { var length = cartographicRadians.length; if (length === 3) { scratchCartographic.longitude = cartographicRadians[0]; scratchCartographic.latitude = cartographicRadians[1]; scratchCartographic.height = cartographicRadians[2]; Ellipsoid.WGS84.cartographicToCartesian(scratchCartographic, scratchCartesian); return [scratchCartesian.x, scratchCartesian.y, scratchCartesian.z]; } var result = new Array(length); for (var i = 0; i < length; i += 4) { result[i] = cartographicRadians[i]; scratchCartographic.longitude = cartographicRadians[i + 1]; scratchCartographic.latitude = cartographicRadians[i + 2]; scratchCartographic.height = cartographicRadians[i + 3]; Ellipsoid.WGS84.cartographicToCartesian(scratchCartographic, scratchCartesian); result[i + 1] = scratchCartesian.x; result[i + 2] = scratchCartesian.y; result[i + 3] = scratchCartesian.z; } return result; } function convertCartographicDegreesToCartesian(cartographicDegrees) { var length = cartographicDegrees.length; if (length === 3) { scratchCartographic.longitude = CesiumMath.toRadians(cartographicDegrees[0]); scratchCartographic.latitude = CesiumMath.toRadians(cartographicDegrees[1]); scratchCartographic.height = cartographicDegrees[2]; Ellipsoid.WGS84.cartographicToCartesian(scratchCartographic, scratchCartesian); return [scratchCartesian.x, scratchCartesian.y, scratchCartesian.z]; } var result = new Array(length); for (var i = 0; i < length; i += 4) { result[i] = cartographicDegrees[i]; 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 + 1] = scratchCartesian.x; result[i + 2] = scratchCartesian.y; result[i + 3] = scratchCartesian.z; } return result; } function unwrapCartesianInterval(czmlInterval) { var cartesian = czmlInterval.cartesian; if (defined(cartesian)) { return cartesian; } var cartesianVelocity = czmlInterval.cartesianVelocity; if (defined(cartesianVelocity)) { return cartesianVelocity; } var unitCartesian = czmlInterval.unitCartesian; if (defined(unitCartesian)) { return unitCartesian; } var unitSpherical = czmlInterval.unitSpherical; if (defined(unitSpherical)) { return convertUnitSphericalToCartesian(unitSpherical); } var spherical = czmlInterval.spherical; if (defined(spherical)) { return convertSphericalToCartesian(spherical); } var cartographicRadians = czmlInterval.cartographicRadians; if (defined(cartographicRadians)) { return convertCartographicRadiansToCartesian(cartographicRadians); } var cartographicDegrees = czmlInterval.cartographicDegrees; if (defined(cartographicDegrees)) { return convertCartographicDegreesToCartesian(cartographicDegrees); } throw new RuntimeError(JSON.stringify(czmlInterval) + ' is not a valid CZML interval.'); } function normalizePackedCartesianArray(array, startingIndex) { Cartesian3.unpack(array, startingIndex, scratchCartesian); Cartesian3.normalize(scratchCartesian, scratchCartesian); Cartesian3.pack(scratchCartesian, array, startingIndex); } function unwrapUnitCartesianInterval(czmlInterval) { var cartesian = unwrapCartesianInterval(czmlInterval); if (cartesian.length === 3) { normalizePackedCartesianArray(cartesian, 0); return cartesian; } for (var i = 1; i < cartesian.length; i += 4) { normalizePackedCartesianArray(cartesian, i); } return cartesian; } function normalizePackedQuaternionArray(array, startingIndex) { Quaternion.unpack(array, startingIndex, scratchQuaternion); Quaternion.normalize(scratchQuaternion, scratchQuaternion); Quaternion.pack(scratchQuaternion, array, startingIndex); } function unwrapQuaternionInterval(czmlInterval) { var unitQuaternion = czmlInterval.unitQuaternion; if (defined(unitQuaternion)) { if (unitQuaternion.length === 4) { normalizePackedQuaternionArray(unitQuaternion, 0); return unitQuaternion; } for (var i = 1; i < unitQuaternion.length; i += 5) { normalizePackedQuaternionArray(unitQuaternion, i); } } return unitQuaternion; } function getPropertyType(czmlInterval) { // The associations in this function need to be kept in sync with the // associations in unwrapInterval. // Intentionally omitted due to conficts in CZML property names: // * Image (conflicts with Uri) // * Rotation (conflicts with Number) // // cartesianVelocity is also omitted due to incomplete support for // derivative information in CZML properties. // (Currently cartesianVelocity is hacked directly into the position processing code) if (typeof czmlInterval === 'boolean') { return Boolean; } else if (typeof czmlInterval === 'number') { return Number; } else if (typeof czmlInterval === 'string') { return String; } else if (czmlInterval.hasOwnProperty('array')) { return Array; } else if (czmlInterval.hasOwnProperty('boolean')) { return Boolean; } else if (czmlInterval.hasOwnProperty('boundingRectangle')) { return BoundingRectangle; } else if (czmlInterval.hasOwnProperty('cartesian2')) { return Cartesian2; } else if (czmlInterval.hasOwnProperty('cartesian') || czmlInterval.hasOwnProperty('spherical') || czmlInterval.hasOwnProperty('cartographicRadians') || czmlInterval.hasOwnProperty('cartographicDegrees')) { return Cartesian3; } else if (czmlInterval.hasOwnProperty('unitCartesian') || czmlInterval.hasOwnProperty('unitSpherical')) { return UnitCartesian3; } else if (czmlInterval.hasOwnProperty('rgba') || czmlInterval.hasOwnProperty('rgbaf')) { return Color; } else if (czmlInterval.hasOwnProperty('colorBlendMode')) { return ColorBlendMode; } else if (czmlInterval.hasOwnProperty('cornerType')) { return CornerType; } else if (czmlInterval.hasOwnProperty('heightReference')) { return HeightReference; } else if (czmlInterval.hasOwnProperty('horizontalOrigin')) { return HorizontalOrigin; } else if (czmlInterval.hasOwnProperty('date')) { return JulianDate; } else if (czmlInterval.hasOwnProperty('labelStyle')) { return LabelStyle; } else if (czmlInterval.hasOwnProperty('number')) { return Number; } else if (czmlInterval.hasOwnProperty('nearFarScalar')) { return NearFarScalar; } else if (czmlInterval.hasOwnProperty('distanceDisplayCondition')) { return DistanceDisplayCondition; } else if (czmlInterval.hasOwnProperty('object') || czmlInterval.hasOwnProperty('value')) { return Object; } else if (czmlInterval.hasOwnProperty('unitQuaternion')) { return Quaternion; } else if (czmlInterval.hasOwnProperty('shadowMode')) { return ShadowMode; } else if (czmlInterval.hasOwnProperty('string')) { return String; } else if (czmlInterval.hasOwnProperty('stripeOrientation')) { return StripeOrientation; } else if (czmlInterval.hasOwnProperty('wsen') || czmlInterval.hasOwnProperty('wsenDegrees')) { return Rectangle; } else if (czmlInterval.hasOwnProperty('uri')) { return Uri; } else if (czmlInterval.hasOwnProperty('verticalOrigin')) { return VerticalOrigin; } // fallback case return Object; } function unwrapInterval(type, czmlInterval, sourceUri) { // The associations in this function need to be kept in sync with the // associations in getPropertyType switch (type) { case Array: return czmlInterval.array; case Boolean: return defaultValue(czmlInterval['boolean'], czmlInterval); case BoundingRectangle: return czmlInterval.boundingRectangle; case Cartesian2: return czmlInterval.cartesian2; case Cartesian3: return unwrapCartesianInterval(czmlInterval); case UnitCartesian3: return unwrapUnitCartesianInterval(czmlInterval); case Color: return unwrapColorInterval(czmlInterval); case ColorBlendMode: return ColorBlendMode[defaultValue(czmlInterval.colorBlendMode, czmlInterval)]; case CornerType: return CornerType[defaultValue(czmlInterval.cornerType, czmlInterval)]; case HeightReference: return HeightReference[defaultValue(czmlInterval.heightReference, 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 NearFarScalar: return czmlInterval.nearFarScalar; case DistanceDisplayCondition: return czmlInterval.distanceDisplayCondition; case Object: return defaultValue(defaultValue(czmlInterval.object, czmlInterval.value), czmlInterval); case Quaternion: return unwrapQuaternionInterval(czmlInterval); case Rotation: return defaultValue(czmlInterval.number, czmlInterval); case ShadowMode: return ShadowMode[defaultValue(defaultValue(czmlInterval.shadowMode, czmlInterval.shadows), czmlInterval)]; case String: return defaultValue(czmlInterval.string, czmlInterval); case StripeOrientation: return StripeOrientation[defaultValue(czmlInterval.stripeOrientation, czmlInterval)]; case Rectangle: return unwrapRectangleInterval(czmlInterval); case Uri: return unwrapUriInterval(czmlInterval, sourceUri); case VerticalOrigin: return VerticalOrigin[defaultValue(czmlInterval.verticalOrigin, czmlInterval)]; default: throw new RuntimeError(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; } } var iso8601Scratch = { iso8601 : undefined }; 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; // CZML properties can be defined in many ways. Most ways represent a structure for // encoding a single value (number, string, cartesian, etc.) Regardless of the value type, // if it encodes a single value it will get loaded into a ConstantProperty eventually. // Alternatively, there are ways of defining a property that require specialized // client-side representation. Currently, these are ReferenceProperty, // and client-side velocity computation properties such as VelocityVectorProperty. var isValue = !defined(packetData.reference) && !defined(packetData.velocityReference); var hasInterval = defined(combinedInterval) && !combinedInterval.equals(Iso8601.MAXIMUM_INTERVAL); if (isValue) { unwrappedInterval = unwrapInterval(type, packetData, sourceUri); packedLength = defaultValue(type.packedLength, 1); unwrappedIntervalLength = defaultValue(unwrappedInterval.length, 1); isSampled = !defined(packetData.array) && (typeof unwrappedInterval !== 'string') && (unwrappedIntervalLength > packedLength) && (type !== Object); } //Rotation is a special case because it represents a native type (Number) //and therefore does not need to be unpacked when loaded as a constant value. var needsUnpacking = typeof type.unpack === 'function' && type !== Rotation; //Any time a constant value is assigned, it completely blows away anything else. if (!isSampled && !hasInterval) { if (isValue) { object[propertyName] = new ConstantProperty(needsUnpacking ? type.unpack(unwrappedInterval, 0) : unwrappedInterval); } else { object[propertyName] = createSpecializedProperty(type, entityCollection, packetData); } 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 (isValue) { combinedInterval.data = needsUnpacking ? type.unpack(unwrappedInterval, 0) : unwrappedInterval; } else { combinedInterval.data = createSpecializedProperty(type, entityCollection, packetData); } //If no property exists, simply use a new interval collection if (!defined(property)) { if (isValue) { property = new TimeIntervalCollectionProperty(); } else { property = new CompositeProperty(); } object[propertyName] = property; } if (isValue && 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. if (isValue) { 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. if (isValue) { 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); } 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 isValue = !defined(packetData.reference); var hasInterval = defined(combinedInterval) && !combinedInterval.equals(Iso8601.MAXIMUM_INTERVAL); if (isValue) { if (defined(packetData.referenceFrame)) { referenceFrame = ReferenceFrame[packetData.referenceFrame]; } referenceFrame = defaultValue(referenceFrame, ReferenceFrame.FIXED); 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 (isValue) { object[propertyName] = new ConstantPositionProperty(Cartesian3.unpack(unwrappedInterval), referenceFrame); } else { object[propertyName] = createReferenceProperty(entityCollection, packetData.reference); } 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 (isValue) { combinedInterval.data = Cartesian3.unpack(unwrappedInterval); } else { combinedInterval.data = createReferenceProperty(entityCollection, packetData.reference); } //If no property exists, simply use a new interval collection if (!defined(property)) { if (isValue) { property = new TimeIntervalCollectionPositionProperty(referenceFrame); } else { property = new CompositePositionProperty(referenceFrame); } object[propertyName] = property; } if (isValue && 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. if (isValue) { 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. if (isValue) { 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, 'lineCount', materialData.lineCount, undefined, sourceUri, entityCollection); processPacketData(Cartesian2, existingMaterial, 'lineThickness', materialData.lineThickness, undefined, sourceUri, entityCollection); processPacketData(Cartesian2, existingMaterial, 'lineOffset', materialData.lineOffset, 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); processPacketData(Color, existingMaterial, 'color', materialData.color, undefined, sourceUri, entityCollection); processPacketData(Boolean, existingMaterial, 'transparent', materialData.transparent, 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); } else if (defined(packetData.polylineArrow)) { if (!(existingMaterial instanceof PolylineArrowMaterialProperty)) { existingMaterial = new PolylineArrowMaterialProperty(); } materialData = packetData.polylineArrow; processPacketData(Color, existingMaterial, 'color', materialData.color, undefined, undefined, entityCollection); } else if (defined(packetData.polylineDash)) { if (!(existingMaterial instanceof PolylineDashMaterialProperty)) { existingMaterial = new PolylineDashMaterialProperty(); } materialData = packetData.polylineDash; processPacketData(Color, existingMaterial, 'color', materialData.color, undefined, undefined, entityCollection); processPacketData(Color, existingMaterial, 'gapColor', materialData.gapColor, undefined, undefined, entityCollection); processPacketData(Number, existingMaterial, 'dashLength', materialData.dashLength, undefined, sourceUri, entityCollection); processPacketData(Number, existingMaterial, 'dashPattern', materialData.dashPattern, 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, unde