@@ -84,6 +84,7 @@ define([
84
84
'./StripeOrientation' ,
85
85
'./TimeIntervalCollectionPositionProperty' ,
86
86
'./TimeIntervalCollectionProperty' ,
87
+ './VelocityOrientationProperty' ,
87
88
'./VelocityVectorProperty' ,
88
89
'./WallGraphics'
89
90
] , function (
@@ -172,23 +173,53 @@ define([
172
173
StripeOrientation ,
173
174
TimeIntervalCollectionPositionProperty ,
174
175
TimeIntervalCollectionProperty ,
176
+ VelocityOrientationProperty ,
175
177
VelocityVectorProperty ,
176
178
WallGraphics ) {
177
179
'use strict' ;
178
180
181
+ // A marker type to distinguish CZML properties where we need to end up with a unit vector.
182
+ // The data is still loaded into Cartesian3 objects but they are normalized.
183
+ function UnitCartesian3 ( ) { }
184
+ UnitCartesian3 . packedLength = Cartesian3 . packedLength ;
185
+ UnitCartesian3 . unpack = Cartesian3 . unpack ;
186
+ UnitCartesian3 . pack = Cartesian3 . pack ;
187
+
188
+ // As a side note, for the purposes of CZML, Quaternion always indicates a unit quaternion.
189
+
179
190
var currentId ;
180
191
181
- function makeReference ( collection , referenceString ) {
192
+ function createReferenceProperty ( entityCollection , referenceString ) {
182
193
if ( referenceString [ 0 ] === '#' ) {
183
194
referenceString = currentId + referenceString ;
184
195
}
185
- return ReferenceProperty . fromString ( collection , referenceString ) ;
196
+ return ReferenceProperty . fromString ( entityCollection , referenceString ) ;
197
+ }
198
+
199
+ function createSpecializedProperty ( type , entityCollection , packetData ) {
200
+ if ( defined ( packetData . reference ) ) {
201
+ return createReferenceProperty ( entityCollection , packetData . reference ) ;
202
+ }
203
+
204
+ if ( defined ( packetData . velocityReference ) ) {
205
+ var referenceProperty = createReferenceProperty ( entityCollection , packetData . velocityReference ) ;
206
+ switch ( type ) {
207
+ case Cartesian3 :
208
+ case UnitCartesian3 :
209
+ return new VelocityVectorProperty ( referenceProperty , type === UnitCartesian3 ) ;
210
+ case Quaternion :
211
+ return new VelocityOrientationProperty ( referenceProperty ) ;
212
+ }
213
+ }
214
+
215
+ throw new RuntimeError ( JSON . stringify ( packetData ) + ' is not valid CZML.' ) ;
186
216
}
187
217
188
218
var scratchCartesian = new Cartesian3 ( ) ;
189
219
var scratchSpherical = new Spherical ( ) ;
190
220
var scratchCartographic = new Cartographic ( ) ;
191
221
var scratchTimeInterval = new TimeInterval ( ) ;
222
+ var scratchQuaternion = new Quaternion ( ) ;
192
223
193
224
function unwrapColorInterval ( czmlInterval ) {
194
225
var rgbaf = czmlInterval . rgbaf ;
@@ -398,17 +429,30 @@ define([
398
429
throw new RuntimeError ( JSON . stringify ( czmlInterval ) + ' is not a valid CZML interval.' ) ;
399
430
}
400
431
432
+ function normalizePackedCartesianArray ( array , startingIndex ) {
433
+ Cartesian3 . unpack ( array , startingIndex , scratchCartesian ) ;
434
+ Cartesian3 . normalize ( scratchCartesian , scratchCartesian ) ;
435
+ Cartesian3 . pack ( scratchCartesian , array , startingIndex ) ;
436
+ }
437
+
438
+ function unwrapUnitCartesianInterval ( czmlInterval ) {
439
+ var cartesian = unwrapCartesianInterval ( czmlInterval ) ;
440
+ if ( cartesian . length === 3 ) {
441
+ normalizePackedCartesianArray ( cartesian , 0 ) ;
442
+ return cartesian ;
443
+ }
444
+
445
+ for ( var i = 1 ; i < cartesian . length ; i += 4 ) {
446
+ normalizePackedCartesianArray ( cartesian , i ) ;
447
+ }
448
+
449
+ return cartesian ;
450
+ }
451
+
401
452
function normalizePackedQuaternionArray ( array , startingIndex ) {
402
- var x = array [ startingIndex ] ;
403
- var y = array [ startingIndex + 1 ] ;
404
- var z = array [ startingIndex + 2 ] ;
405
- var w = array [ startingIndex + 3 ] ;
406
-
407
- var inverseMagnitude = 1.0 / Math . sqrt ( x * x + y * y + z * z + w * w ) ;
408
- array [ startingIndex ] = x * inverseMagnitude ;
409
- array [ startingIndex + 1 ] = y * inverseMagnitude ;
410
- array [ startingIndex + 2 ] = z * inverseMagnitude ;
411
- array [ startingIndex + 3 ] = w * inverseMagnitude ;
453
+ Quaternion . unpack ( array , startingIndex , scratchQuaternion ) ;
454
+ Quaternion . normalize ( scratchQuaternion , scratchQuaternion ) ;
455
+ Quaternion . pack ( scratchQuaternion , array , startingIndex ) ;
412
456
}
413
457
414
458
function unwrapQuaternionInterval ( czmlInterval ) {
@@ -452,12 +496,13 @@ define([
452
496
} else if ( czmlInterval . hasOwnProperty ( 'cartesian2' ) ) {
453
497
return Cartesian2 ;
454
498
} else if ( czmlInterval . hasOwnProperty ( 'cartesian' ) ||
455
- czmlInterval . hasOwnProperty ( 'unitCartesian' ) ||
456
- czmlInterval . hasOwnProperty ( 'unitSpherical' ) ||
457
499
czmlInterval . hasOwnProperty ( 'spherical' ) ||
458
500
czmlInterval . hasOwnProperty ( 'cartographicRadians' ) ||
459
501
czmlInterval . hasOwnProperty ( 'cartographicDegrees' ) ) {
460
502
return Cartesian3 ;
503
+ } else if ( czmlInterval . hasOwnProperty ( 'unitCartesian' ) ||
504
+ czmlInterval . hasOwnProperty ( 'unitSpherical' ) ) {
505
+ return UnitCartesian3 ;
461
506
} else if ( czmlInterval . hasOwnProperty ( 'rgba' ) ||
462
507
czmlInterval . hasOwnProperty ( 'rgbaf' ) ) {
463
508
return Color ;
@@ -514,6 +559,8 @@ define([
514
559
return czmlInterval . cartesian2 ;
515
560
case Cartesian3 :
516
561
return unwrapCartesianInterval ( czmlInterval ) ;
562
+ case UnitCartesian3 :
563
+ return unwrapUnitCartesianInterval ( czmlInterval ) ;
517
564
case Color :
518
565
return unwrapColorInterval ( czmlInterval ) ;
519
566
case ColorBlendMode :
@@ -614,10 +661,17 @@ define([
614
661
var isSampled ;
615
662
var unwrappedInterval ;
616
663
var unwrappedIntervalLength ;
617
- var isReference = defined ( packetData . reference ) ;
664
+
665
+ // CZML properties can be defined in many ways. Most ways represent a structure for
666
+ // encoding a single value (number, string, cartesian, etc.) Regardless of the value type,
667
+ // if it encodes a single value it will get loaded into a ConstantProperty eventually.
668
+ // Alternatively, there are ways of defining a property that require specialized
669
+ // client-side representation. Currently, these are ReferenceProperty,
670
+ // and client-side velocity computation properties such as VelocityVectorProperty.
671
+ var isValue = ! defined ( packetData . reference ) && ! defined ( packetData . velocityReference ) ;
618
672
var hasInterval = defined ( combinedInterval ) && ! combinedInterval . equals ( Iso8601 . MAXIMUM_INTERVAL ) ;
619
673
620
- if ( ! isReference ) {
674
+ if ( isValue ) {
621
675
unwrappedInterval = unwrapInterval ( type , packetData , sourceUri , query ) ;
622
676
packedLength = defaultValue ( type . packedLength , 1 ) ;
623
677
unwrappedIntervalLength = defaultValue ( unwrappedInterval . length , 1 ) ;
@@ -630,12 +684,10 @@ define([
630
684
631
685
//Any time a constant value is assigned, it completely blows away anything else.
632
686
if ( ! isSampled && ! hasInterval ) {
633
- if ( isReference ) {
634
- object [ propertyName ] = makeReference ( entityCollection , packetData . reference ) ;
635
- } else if ( needsUnpacking ) {
636
- object [ propertyName ] = new ConstantProperty ( type . unpack ( unwrappedInterval , 0 ) ) ;
687
+ if ( isValue ) {
688
+ object [ propertyName ] = new ConstantProperty ( needsUnpacking ? type . unpack ( unwrappedInterval , 0 ) : unwrappedInterval ) ;
637
689
} else {
638
- object [ propertyName ] = new ConstantProperty ( unwrappedInterval ) ;
690
+ object [ propertyName ] = createSpecializedProperty ( type , entityCollection , packetData ) ;
639
691
}
640
692
return ;
641
693
}
@@ -668,30 +720,30 @@ define([
668
720
if ( ! isSampled && hasInterval ) {
669
721
//Create a new interval for the constant value.
670
722
combinedInterval = combinedInterval . clone ( ) ;
671
- if ( isReference ) {
672
- combinedInterval . data = makeReference ( entityCollection , packetData . reference ) ;
673
- } else if ( needsUnpacking ) {
674
- combinedInterval . data = type . unpack ( unwrappedInterval , 0 ) ;
723
+ if ( isValue ) {
724
+ combinedInterval . data = needsUnpacking ? type . unpack ( unwrappedInterval , 0 ) : unwrappedInterval ;
675
725
} else {
676
- combinedInterval . data = unwrappedInterval ;
726
+ combinedInterval . data = createSpecializedProperty ( type , entityCollection , packetData ) ;
677
727
}
678
728
679
729
//If no property exists, simply use a new interval collection
680
730
if ( ! defined ( property ) ) {
681
- if ( isReference ) {
682
- property = new CompositeProperty ( ) ;
683
- } else {
731
+ if ( isValue ) {
684
732
property = new TimeIntervalCollectionProperty ( ) ;
733
+ } else {
734
+ property = new CompositeProperty ( ) ;
685
735
}
686
736
object [ propertyName ] = property ;
687
737
}
688
738
689
- if ( ! isReference && property instanceof TimeIntervalCollectionProperty ) {
739
+ if ( isValue && property instanceof TimeIntervalCollectionProperty ) {
690
740
//If we create a collection, or it already existed, use it.
691
741
property . intervals . addInterval ( combinedInterval ) ;
692
742
} else if ( property instanceof CompositeProperty ) {
693
743
//If the collection was already a CompositeProperty, use it.
694
- combinedInterval . data = isReference ? combinedInterval . data : new ConstantProperty ( combinedInterval . data ) ;
744
+ if ( isValue ) {
745
+ combinedInterval . data = new ConstantProperty ( combinedInterval . data ) ;
746
+ }
695
747
property . intervals . addInterval ( combinedInterval ) ;
696
748
} else {
697
749
//Otherwise, create a CompositeProperty but preserve the existing data.
@@ -708,7 +760,9 @@ define([
708
760
property . intervals . addInterval ( interval ) ;
709
761
710
762
//Change the new data to a ConstantProperty and add it.
711
- combinedInterval . data = isReference ? combinedInterval . data : new ConstantProperty ( combinedInterval . data ) ;
763
+ if ( isValue ) {
764
+ combinedInterval . data = new ConstantProperty ( combinedInterval . data ) ;
765
+ }
712
766
property . intervals . addInterval ( combinedInterval ) ;
713
767
}
714
768
@@ -781,10 +835,10 @@ define([
781
835
var unwrappedIntervalLength ;
782
836
var numberOfDerivatives = defined ( packetData . cartesianVelocity ) ? 1 : 0 ;
783
837
var packedLength = Cartesian3 . packedLength * ( numberOfDerivatives + 1 ) ;
784
- var isReference = defined ( packetData . reference ) ;
838
+ var isValue = ! defined ( packetData . reference ) ;
785
839
var hasInterval = defined ( combinedInterval ) && ! combinedInterval . equals ( Iso8601 . MAXIMUM_INTERVAL ) ;
786
840
787
- if ( ! isReference ) {
841
+ if ( isValue ) {
788
842
if ( defined ( packetData . referenceFrame ) ) {
789
843
referenceFrame = ReferenceFrame [ packetData . referenceFrame ] ;
790
844
}
@@ -796,10 +850,10 @@ define([
796
850
797
851
//Any time a constant value is assigned, it completely blows away anything else.
798
852
if ( ! isSampled && ! hasInterval ) {
799
- if ( isReference ) {
800
- object [ propertyName ] = makeReference ( entityCollection , packetData . reference ) ;
801
- } else {
853
+ if ( isValue ) {
802
854
object [ propertyName ] = new ConstantPositionProperty ( Cartesian3 . unpack ( unwrappedInterval ) , referenceFrame ) ;
855
+ } else {
856
+ object [ propertyName ] = createReferenceProperty ( entityCollection , packetData . reference ) ;
803
857
}
804
858
return ;
805
859
}
@@ -832,28 +886,30 @@ define([
832
886
if ( ! isSampled && hasInterval ) {
833
887
//Create a new interval for the constant value.
834
888
combinedInterval = combinedInterval . clone ( ) ;
835
- if ( isReference ) {
836
- combinedInterval . data = makeReference ( entityCollection , packetData . reference ) ;
837
- } else {
889
+ if ( isValue ) {
838
890
combinedInterval . data = Cartesian3 . unpack ( unwrappedInterval ) ;
891
+ } else {
892
+ combinedInterval . data = createReferenceProperty ( entityCollection , packetData . reference ) ;
839
893
}
840
894
841
895
//If no property exists, simply use a new interval collection
842
896
if ( ! defined ( property ) ) {
843
- if ( isReference ) {
844
- property = new CompositePositionProperty ( referenceFrame ) ;
845
- } else {
897
+ if ( isValue ) {
846
898
property = new TimeIntervalCollectionPositionProperty ( referenceFrame ) ;
899
+ } else {
900
+ property = new CompositePositionProperty ( referenceFrame ) ;
847
901
}
848
902
object [ propertyName ] = property ;
849
903
}
850
904
851
- if ( ! isReference && property instanceof TimeIntervalCollectionPositionProperty && ( defined ( referenceFrame ) && property . referenceFrame === referenceFrame ) ) {
905
+ if ( isValue && property instanceof TimeIntervalCollectionPositionProperty && ( defined ( referenceFrame ) && property . referenceFrame === referenceFrame ) ) {
852
906
//If we create a collection, or it already existed, use it.
853
907
property . intervals . addInterval ( combinedInterval ) ;
854
908
} else if ( property instanceof CompositePositionProperty ) {
855
909
//If the collection was already a CompositePositionProperty, use it.
856
- combinedInterval . data = isReference ? combinedInterval . data : new ConstantPositionProperty ( combinedInterval . data , referenceFrame ) ;
910
+ if ( isValue ) {
911
+ combinedInterval . data = new ConstantPositionProperty ( combinedInterval . data , referenceFrame ) ;
912
+ }
857
913
property . intervals . addInterval ( combinedInterval ) ;
858
914
} else {
859
915
//Otherwise, create a CompositePositionProperty but preserve the existing data.
@@ -870,7 +926,9 @@ define([
870
926
property . intervals . addInterval ( interval ) ;
871
927
872
928
//Change the new data to a ConstantPositionProperty and add it.
873
- combinedInterval . data = isReference ? combinedInterval . data : new ConstantPositionProperty ( combinedInterval . data , referenceFrame ) ;
929
+ if ( isValue ) {
930
+ combinedInterval . data = new ConstantPositionProperty ( combinedInterval . data , referenceFrame ) ;
931
+ }
874
932
property . intervals . addInterval ( combinedInterval ) ;
875
933
}
876
934
@@ -1117,7 +1175,7 @@ define([
1117
1175
var references = packetData . references ;
1118
1176
if ( defined ( references ) ) {
1119
1177
var properties = references . map ( function ( reference ) {
1120
- return makeReference ( entityCollection , reference ) ;
1178
+ return createReferenceProperty ( entityCollection , reference ) ;
1121
1179
} ) ;
1122
1180
1123
1181
var iso8601Interval = packetData . interval ;
@@ -1154,7 +1212,7 @@ define([
1154
1212
function processPositionsPacketData ( object , propertyName , positionsData , entityCollection ) {
1155
1213
if ( defined ( positionsData . references ) ) {
1156
1214
var properties = positionsData . references . map ( function ( reference ) {
1157
- return makeReference ( entityCollection , reference ) ;
1215
+ return createReferenceProperty ( entityCollection , reference ) ;
1158
1216
} ) ;
1159
1217
1160
1218
var iso8601Interval = positionsData . interval ;
@@ -1230,11 +1288,7 @@ define([
1230
1288
return ;
1231
1289
}
1232
1290
1233
- if ( defined ( packetData . velocityReference ) ) {
1234
- billboard . alignedAxis = new VelocityVectorProperty ( makeReference ( entityCollection , packetData . velocityReference ) , true ) ;
1235
- } else {
1236
- processPacketData ( Cartesian3 , billboard , 'alignedAxis' , packetData , interval , sourceUri , entityCollection , query ) ;
1237
- }
1291
+ processPacketData ( UnitCartesian3 , billboard , 'alignedAxis' , packetData , interval , sourceUri , entityCollection , query ) ;
1238
1292
}
1239
1293
1240
1294
function processBillboard ( entity , packet , entityCollection , sourceUri , query ) {
0 commit comments