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
JavaScript
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