Skip to content

Commit 62d63f7

Browse files
committed
Merge pull request #3908 from AnalyticalGraphicsInc/velocity-vector-property
Added VelocityVectorProperty
2 parents a5de1e1 + e8f061f commit 62d63f7

5 files changed

+374
-62
lines changed

CHANGES.md

+1
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ Change Log
88
* Deprecated
99
*
1010
* Improved KML NetworkLink compatibility by supporting the `Url` tag. [#3895](https://github.com/AnalyticalGraphicsInc/cesium/pull/3895).
11+
* Added `VelocityVectorProperty` so billboard's aligned axis can follow the velocity vector. [#3908](https://github.com/AnalyticalGraphicsInc/cesium/issues/3908)
1112
* Improve memory management for entity billboard/label/point/path visualization.
1213
* Fixed exaggerated terrain tiles disappearing. [#3676](https://github.com/AnalyticalGraphicsInc/cesium/issues/3676)
1314
* Fixed infinite horizontal 2D scrolling in IE/Edge. [#3893](https://github.com/AnalyticalGraphicsInc/cesium/issues/3893)

Source/DataSources/VelocityOrientationProperty.js

+18-60
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,8 @@ define([
1111
'../Core/Matrix3',
1212
'../Core/Quaternion',
1313
'../Core/Transforms',
14-
'./Property'
14+
'./Property',
15+
'./VelocityVectorProperty'
1516
], function(
1617
Cartesian3,
1718
defaultValue,
@@ -24,7 +25,8 @@ define([
2425
Matrix3,
2526
Quaternion,
2627
Transforms,
27-
Property) {
28+
Property,
29+
VelocityVectorProperty) {
2830
'use strict';
2931

3032
/**
@@ -47,13 +49,17 @@ define([
4749
* }));
4850
*/
4951
function VelocityOrientationProperty(position, ellipsoid) {
50-
this._position = undefined;
52+
this._velocityVectorProperty = new VelocityVectorProperty(position);
5153
this._subscription = undefined;
5254
this._ellipsoid = undefined;
5355
this._definitionChanged = new Event();
5456

55-
this.position = position;
5657
this.ellipsoid = defaultValue(ellipsoid, Ellipsoid.WGS84);
58+
59+
var that = this;
60+
this._velocityVectorProperty.definitionChanged.addEventListener(function() {
61+
that._definitionChanged.raiseEvent(that);
62+
});
5763
}
5864

5965
defineProperties(VelocityOrientationProperty.prototype, {
@@ -66,7 +72,7 @@ define([
6672
*/
6773
isConstant : {
6874
get : function() {
69-
return Property.isConstant(this._position);
75+
return Property.isConstant(this._velocityVectorProperty);
7076
}
7177
},
7278
/**
@@ -89,25 +95,10 @@ define([
8995
*/
9096
position : {
9197
get : function() {
92-
return this._position;
98+
return this._velocityVectorProperty.position;
9399
},
94100
set : function(value) {
95-
var oldValue = this._position;
96-
if (oldValue !== value) {
97-
if (defined(oldValue)) {
98-
this._subscription();
99-
}
100-
101-
this._position = value;
102-
103-
if (defined(value)) {
104-
this._subscription = value._definitionChanged.addEventListener(function() {
105-
this._definitionChanged.raiseEvent(this);
106-
}, this);
107-
}
108-
109-
this._definitionChanged.raiseEvent(this);
110-
}
101+
this._velocityVectorProperty.position = value;
111102
}
112103
},
113104
/**
@@ -130,12 +121,9 @@ define([
130121
}
131122
});
132123

133-
var position1Scratch = new Cartesian3();
134-
var position2Scratch = new Cartesian3();
124+
var positionScratch = new Cartesian3();
135125
var velocityScratch = new Cartesian3();
136-
var timeScratch = new JulianDate();
137126
var rotationScratch = new Matrix3();
138-
var step = 1.0 / 60.0;
139127

140128
/**
141129
* Gets the value of the property at the provided time.
@@ -145,43 +133,13 @@ define([
145133
* @returns {Quaternion} The modified result parameter or a new instance if the result parameter was not supplied.
146134
*/
147135
VelocityOrientationProperty.prototype.getValue = function(time, result) {
148-
//>>includeStart('debug', pragmas.debug);
149-
if (!defined(time)) {
150-
throw new DeveloperError('time is required');
151-
}
152-
//>>includeEnd('debug');
153-
154-
var property = this._position;
155-
if (Property.isConstant(property)) {
156-
return undefined;
157-
}
158-
159-
var position1 = property.getValue(time, position1Scratch);
160-
var position2 = property.getValue(JulianDate.addSeconds(time, step, timeScratch), position2Scratch);
161-
162-
//If we don't have a position for now, return undefined.
163-
if (!defined(position1)) {
164-
return undefined;
165-
}
136+
var velocity = this._velocityVectorProperty._getValue(time, velocityScratch, positionScratch);
166137

167-
//If we don't have a position for now + step, see if we have a position for now - step.
168-
if (!defined(position2)) {
169-
position2 = position1;
170-
position1 = property.getValue(JulianDate.addSeconds(time, -step, timeScratch), position2Scratch);
171-
172-
if (!defined(position1)) {
173-
return undefined;
174-
}
175-
}
176-
177-
if (Cartesian3.equals(position1, position2)) {
138+
if (!defined(velocity)) {
178139
return undefined;
179140
}
180141

181-
var velocity = Cartesian3.subtract(position2, position1, velocityScratch);
182-
Cartesian3.normalize(velocity, velocity);
183-
184-
Transforms.rotationMatrixFromPositionVelocity(position1, velocity, this._ellipsoid, rotationScratch);
142+
Transforms.rotationMatrixFromPositionVelocity(positionScratch, velocity, this._ellipsoid, rotationScratch);
185143
return Quaternion.fromRotationMatrix(rotationScratch, result);
186144
};
187145

@@ -195,7 +153,7 @@ define([
195153
VelocityOrientationProperty.prototype.equals = function(other) {
196154
return this === other ||//
197155
(other instanceof VelocityOrientationProperty &&
198-
Property.equals(this._position, other._position) &&
156+
Property.equals(this._velocityVectorProperty, other._velocityVectorProperty) &&
199157
(this._ellipsoid === other._ellipsoid ||
200158
this._ellipsoid.equals(other._ellipsoid)));
201159
};
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,187 @@
1+
/*global define*/
2+
define([
3+
'../Core/Cartesian3',
4+
'../Core/defaultValue',
5+
'../Core/defined',
6+
'../Core/defineProperties',
7+
'../Core/DeveloperError',
8+
'../Core/Event',
9+
'../Core/JulianDate',
10+
'./Property'
11+
], function(
12+
Cartesian3,
13+
defaultValue,
14+
defined,
15+
defineProperties,
16+
DeveloperError,
17+
Event,
18+
JulianDate,
19+
Property) {
20+
'use strict';
21+
22+
/**
23+
* A {@link Property} which evaluates to a {@link Cartesian3} vector
24+
* based on the velocity of the provided {@link PositionProperty}.
25+
*
26+
* @alias VelocityVectorProperty
27+
* @constructor
28+
*
29+
* @param {Property} [position] The position property used to compute the velocity.
30+
*
31+
* @example
32+
* //Create an entity with a billboard rotated to match its velocity.
33+
* var position = new Cesium.SampledProperty();
34+
* position.addSamples(...);
35+
* var entity = viewer.entities.add({
36+
* position : position,
37+
* billboard : {
38+
* image : 'image.png',
39+
* alignedAxis : new Cesium.VelocityVectorProperty(position)
40+
* }
41+
* }));
42+
*/
43+
function VelocityVectorProperty(position) {
44+
this._position = undefined;
45+
this._subscription = undefined;
46+
this._definitionChanged = new Event();
47+
48+
this.position = position;
49+
}
50+
51+
defineProperties(VelocityVectorProperty.prototype, {
52+
/**
53+
* Gets a value indicating if this property is constant.
54+
* @memberof VelocityVectorProperty.prototype
55+
*
56+
* @type {Boolean}
57+
* @readonly
58+
*/
59+
isConstant : {
60+
get : function() {
61+
return Property.isConstant(this._position);
62+
}
63+
},
64+
/**
65+
* Gets the event that is raised whenever the definition of this property changes.
66+
* @memberof VelocityVectorProperty.prototype
67+
*
68+
* @type {Event}
69+
* @readonly
70+
*/
71+
definitionChanged : {
72+
get : function() {
73+
return this._definitionChanged;
74+
}
75+
},
76+
/**
77+
* Gets or sets the position property used to compute orientation.
78+
* @memberof VelocityVectorProperty.prototype
79+
*
80+
* @type {Property}
81+
*/
82+
position : {
83+
get : function() {
84+
return this._position;
85+
},
86+
set : function(value) {
87+
var oldValue = this._position;
88+
if (oldValue !== value) {
89+
if (defined(oldValue)) {
90+
this._subscription();
91+
}
92+
93+
this._position = value;
94+
95+
if (defined(value)) {
96+
this._subscription = value._definitionChanged.addEventListener(function() {
97+
this._definitionChanged.raiseEvent(this);
98+
}, this);
99+
}
100+
101+
this._definitionChanged.raiseEvent(this);
102+
}
103+
}
104+
}
105+
});
106+
107+
var position1Scratch = new Cartesian3();
108+
var position2Scratch = new Cartesian3();
109+
var velocityScratch = new Cartesian3();
110+
var timeScratch = new JulianDate();
111+
var step = 1.0 / 60.0;
112+
113+
/**
114+
* Gets the value of the property at the provided time.
115+
*
116+
* @param {JulianDate} [time] The time for which to retrieve the value.
117+
* @param {Cartesian3} [result] The object to store the value into, if omitted, a new instance is created and returned.
118+
* @returns {Cartesian3} The modified result parameter or a new instance if the result parameter was not supplied.
119+
*/
120+
VelocityVectorProperty.prototype.getValue = function(time, result) {
121+
return this._getValue(time, result);
122+
};
123+
124+
/**
125+
* @private
126+
*/
127+
VelocityVectorProperty.prototype._getValue = function(time, velocityResult, positionResult) {
128+
//>>includeStart('debug', pragmas.debug);
129+
if (!defined(time)) {
130+
throw new DeveloperError('time is required');
131+
}
132+
//>>includeEnd('debug');
133+
134+
if (!defined(velocityResult)) {
135+
velocityResult = new Cartesian3();
136+
}
137+
138+
var property = this._position;
139+
if (Property.isConstant(property)) {
140+
return undefined;
141+
}
142+
143+
var position1 = property.getValue(time, position1Scratch);
144+
var position2 = property.getValue(JulianDate.addSeconds(time, step, timeScratch), position2Scratch);
145+
146+
//If we don't have a position for now, return undefined.
147+
if (!defined(position1)) {
148+
return undefined;
149+
}
150+
151+
//If we don't have a position for now + step, see if we have a position for now - step.
152+
if (!defined(position2)) {
153+
position2 = position1;
154+
position1 = property.getValue(JulianDate.addSeconds(time, -step, timeScratch), position2Scratch);
155+
156+
if (!defined(position1)) {
157+
return undefined;
158+
}
159+
}
160+
161+
if (Cartesian3.equals(position1, position2)) {
162+
return undefined;
163+
}
164+
165+
if (defined(positionResult)) {
166+
position1.clone(positionResult);
167+
}
168+
169+
var velocity = Cartesian3.subtract(position2, position1, velocityScratch);
170+
return Cartesian3.normalize(velocity, velocityResult);
171+
};
172+
173+
/**
174+
* Compares this property to the provided property and returns
175+
* <code>true</code> if they are equal, <code>false</code> otherwise.
176+
*
177+
* @param {Property} [other] The other property.
178+
* @returns {Boolean} <code>true</code> if left and right are equal, <code>false</code> otherwise.
179+
*/
180+
VelocityVectorProperty.prototype.equals = function(other) {
181+
return this === other ||//
182+
(other instanceof VelocityVectorProperty &&
183+
Property.equals(this._position, other._position));
184+
};
185+
186+
return VelocityVectorProperty;
187+
});

Specs/DataSources/VelocityOrientationPropertySpec.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ defineSuite([
3131
expect(property.definitionChanged).toBeInstanceOf(Event);
3232
expect(property.position).toBeUndefined();
3333
expect(property.ellipsoid).toBe(Ellipsoid.WGS84);
34-
expect(property.getValue(time)).toBe(undefined);
34+
expect(property.getValue(time)).toBeUndefined();
3535
});
3636

3737
it('can construct with arguments', function() {
@@ -41,7 +41,7 @@ defineSuite([
4141
expect(property.definitionChanged).toBeInstanceOf(Event);
4242
expect(property.position).toBe(position);
4343
expect(property.ellipsoid).toBe(Ellipsoid.UNIT_SPHERE);
44-
expect(property.getValue(time)).toBe(undefined);
44+
expect(property.getValue(time)).toBeUndefined();
4545
});
4646

4747
it('setting position raises definitionChanged event', function() {

0 commit comments

Comments
 (0)