Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added VelocityVectorProperty #3908

Merged
merged 6 commits into from
May 16, 2016
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ Change Log
* Deprecated
*
* Improved KML NetworkLink compatibility by supporting the `Url` tag. [#3895](https://github.com/AnalyticalGraphicsInc/cesium/pull/3895).
* Added `VelocityVectorProperty` so billboard's aligned axis can follow the velocity vector. [#3908](https://github.com/AnalyticalGraphicsInc/cesium/issues/3908)
* Fixed exaggerated terrain tiles disappearing. [#3676](https://github.com/AnalyticalGraphicsInc/cesium/issues/3676)
* Fixed infinite horizontal 2D scrolling in IE/Edge. [#3893](https://github.com/AnalyticalGraphicsInc/cesium/issues/3893)
* Fixed a bug that could cause incorrect normals to be computed for exaggerated terrain, especially for low-detail tiles. [#3904](https://github.com/AnalyticalGraphicsInc/cesium/pull/3904)
Expand Down
78 changes: 18 additions & 60 deletions Source/DataSources/VelocityOrientationProperty.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@ define([
'../Core/Matrix3',
'../Core/Quaternion',
'../Core/Transforms',
'./Property'
'./Property',
'./VelocityVectorProperty'
], function(
Cartesian3,
defaultValue,
Expand All @@ -24,7 +25,8 @@ define([
Matrix3,
Quaternion,
Transforms,
Property) {
Property,
VelocityVectorProperty) {
'use strict';

/**
Expand All @@ -47,13 +49,17 @@ define([
* }));
*/
function VelocityOrientationProperty(position, ellipsoid) {
this._position = undefined;
this._velocityVectorProperty = new VelocityVectorProperty(position);
this._subscription = undefined;
this._ellipsoid = undefined;
this._definitionChanged = new Event();

this.position = position;
this.ellipsoid = defaultValue(ellipsoid, Ellipsoid.WGS84);

var that = this;
this._velocityVectorProperty.definitionChanged.addEventListener(function() {
that._definitionChanged.raiseEvent(that);
});
}

defineProperties(VelocityOrientationProperty.prototype, {
Expand All @@ -66,7 +72,7 @@ define([
*/
isConstant : {
get : function() {
return Property.isConstant(this._position);
return Property.isConstant(this._velocityVectorProperty);
}
},
/**
Expand All @@ -89,25 +95,10 @@ define([
*/
position : {
get : function() {
return this._position;
return this._velocityVectorProperty.position;
},
set : function(value) {
var oldValue = this._position;
if (oldValue !== value) {
if (defined(oldValue)) {
this._subscription();
}

this._position = value;

if (defined(value)) {
this._subscription = value._definitionChanged.addEventListener(function() {
this._definitionChanged.raiseEvent(this);
}, this);
}

this._definitionChanged.raiseEvent(this);
}
this._velocityVectorProperty.position = value;
}
},
/**
Expand All @@ -130,12 +121,9 @@ define([
}
});

var position1Scratch = new Cartesian3();
var position2Scratch = new Cartesian3();
var positionScratch = new Cartesian3();
var velocityScratch = new Cartesian3();
var timeScratch = new JulianDate();
var rotationScratch = new Matrix3();
var step = 1.0 / 60.0;

/**
* Gets the value of the property at the provided time.
Expand All @@ -145,43 +133,13 @@ define([
* @returns {Quaternion} The modified result parameter or a new instance if the result parameter was not supplied.
*/
VelocityOrientationProperty.prototype.getValue = function(time, result) {
//>>includeStart('debug', pragmas.debug);
if (!defined(time)) {
throw new DeveloperError('time is required');
}
//>>includeEnd('debug');

var property = this._position;
if (Property.isConstant(property)) {
return undefined;
}

var position1 = property.getValue(time, position1Scratch);
var position2 = property.getValue(JulianDate.addSeconds(time, step, timeScratch), position2Scratch);

//If we don't have a position for now, return undefined.
if (!defined(position1)) {
return undefined;
}
var velocity = this._velocityVectorProperty._getValue(time, velocityScratch, positionScratch);

//If we don't have a position for now + step, see if we have a position for now - step.
if (!defined(position2)) {
position2 = position1;
position1 = property.getValue(JulianDate.addSeconds(time, -step, timeScratch), position2Scratch);

if (!defined(position1)) {
return undefined;
}
}

if (Cartesian3.equals(position1, position2)) {
if (!defined(velocity)) {
return undefined;
}

var velocity = Cartesian3.subtract(position2, position1, velocityScratch);
Cartesian3.normalize(velocity, velocity);

Transforms.rotationMatrixFromPositionVelocity(position1, velocity, this._ellipsoid, rotationScratch);
Transforms.rotationMatrixFromPositionVelocity(positionScratch, velocity, this._ellipsoid, rotationScratch);
return Quaternion.fromRotationMatrix(rotationScratch, result);
};

Expand All @@ -195,7 +153,7 @@ define([
VelocityOrientationProperty.prototype.equals = function(other) {
return this === other ||//
(other instanceof VelocityOrientationProperty &&
Property.equals(this._position, other._position) &&
Property.equals(this._velocityVectorProperty, other._velocityVectorProperty) &&
(this._ellipsoid === other._ellipsoid ||
this._ellipsoid.equals(other._ellipsoid)));
};
Expand Down
184 changes: 184 additions & 0 deletions Source/DataSources/VelocityVectorProperty.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,184 @@
/*global define*/
define([
'../Core/Cartesian3',
'../Core/defaultValue',
'../Core/defined',
'../Core/defineProperties',
'../Core/DeveloperError',
'../Core/Event',
'../Core/JulianDate',
'./Property'
], function(
Cartesian3,
defaultValue,
defined,
defineProperties,
DeveloperError,
Event,
JulianDate,
Property) {
'use strict';

/**
* A {@link Property} which evaluates to a {@link Cartesian3} vector
* based on the velocity of the provided {@link PositionProperty}.
*
* @alias VelocityVectorProperty
* @constructor
*
* @param {Property} [position] The position property used to compute the velocity.
*
* @example
* //Create an entity with position and orientation.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This example is now incorrect. I would recommend updating it to illustrate orienting a billboard along it's velocity vector.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The comment is still incorrect. Change it to something like //Create an entity with a billboard rotated to match its velocity

* var position = new Cesium.SampledProperty();
* position.addSamples(...);
* var entity = viewer.entities.add({
* position : position,
* orientation : new Cesium.VelocityVectorProperty(position)
* }));
*/
function VelocityVectorProperty(position) {
this._position = undefined;
this._subscription = undefined;
this._definitionChanged = new Event();

this.position = position;
}

defineProperties(VelocityVectorProperty.prototype, {
/**
* Gets a value indicating if this property is constant.
* @memberof VelocityVectorProperty.prototype
*
* @type {Boolean}
* @readonly
*/
isConstant : {
get : function() {
return Property.isConstant(this._position);
}
},
/**
* Gets the event that is raised whenever the definition of this property changes.
* @memberof VelocityVectorProperty.prototype
*
* @type {Event}
* @readonly
*/
definitionChanged : {
get : function() {
return this._definitionChanged;
}
},
/**
* Gets or sets the position property used to compute orientation.
* @memberof VelocityVectorProperty.prototype
*
* @type {Property}
*/
position : {
get : function() {
return this._position;
},
set : function(value) {
var oldValue = this._position;
if (oldValue !== value) {
if (defined(oldValue)) {
this._subscription();
}

this._position = value;

if (defined(value)) {
this._subscription = value._definitionChanged.addEventListener(function() {
this._definitionChanged.raiseEvent(this);
}, this);
}

this._definitionChanged.raiseEvent(this);
}
}
}
});

var position1Scratch = new Cartesian3();
var position2Scratch = new Cartesian3();
var velocityScratch = new Cartesian3();
var timeScratch = new JulianDate();
var step = 1.0 / 60.0;

/**
* Gets the value of the property at the provided time.
*
* @param {JulianDate} [time] The time for which to retrieve the value.
* @param {Cartesian3} [result] The object to store the value into, if omitted, a new instance is created and returned.
* @returns {Cartesian3} The modified result parameter or a new instance if the result parameter was not supplied.
*/
VelocityVectorProperty.prototype.getValue = function(time, result) {
return this._getValue(time, result);
};

/**
* @private
*/
VelocityVectorProperty.prototype._getValue = function(time, velocityResult, positionResult) {
//>>includeStart('debug', pragmas.debug);
if (!defined(time)) {
throw new DeveloperError('time is required');
}
//>>includeEnd('debug');

if (!defined(velocityResult)) {
velocityResult = new Cartesian3();
}

var property = this._position;
if (Property.isConstant(property)) {
return undefined;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wouldn't this be the zero vector instead of undefined?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well, I guess if you wanted the vector to always be normalized this makes sense. Just wanted to double check.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The other properties seem to return undefined when there isn't a value at that time. This code was pretty much copied from the VectorOrientationProperty. @mramato is returning undefined the right thing to do here?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, undefined just gets translated to "use the default" which is probably the best case scenario here.

}

var position1 = property.getValue(time, position1Scratch);
var position2 = property.getValue(JulianDate.addSeconds(time, step, timeScratch), position2Scratch);

//If we don't have a position for now, return undefined.
if (!defined(position1)) {
return undefined;
}

//If we don't have a position for now + step, see if we have a position for now - step.
if (!defined(position2)) {
position2 = position1;
position1 = property.getValue(JulianDate.addSeconds(time, -step, timeScratch), position2Scratch);

if (!defined(position1)) {
return undefined;
}
}

if (Cartesian3.equals(position1, position2)) {
return undefined;
}

if (defined(positionResult)) {
position1.clone(positionResult);
}

var velocity = Cartesian3.subtract(position2, position1, velocityScratch);
return Cartesian3.normalize(velocity, velocityResult);
};

/**
* Compares this property to the provided property and returns
* <code>true</code> if they are equal, <code>false</code> otherwise.
*
* @param {Property} [other] The other property.
* @returns {Boolean} <code>true</code> if left and right are equal, <code>false</code> otherwise.
*/
VelocityVectorProperty.prototype.equals = function(other) {
return this === other ||//
(other instanceof VelocityVectorProperty &&
Property.equals(this._position, other._position));
};

return VelocityVectorProperty;
});
4 changes: 2 additions & 2 deletions Specs/DataSources/VelocityOrientationPropertySpec.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ defineSuite([
expect(property.definitionChanged).toBeInstanceOf(Event);
expect(property.position).toBeUndefined();
expect(property.ellipsoid).toBe(Ellipsoid.WGS84);
expect(property.getValue(time)).toBe(undefined);
expect(property.getValue(time)).toBeUndefined();
});

it('can construct with arguments', function() {
Expand All @@ -41,7 +41,7 @@ defineSuite([
expect(property.definitionChanged).toBeInstanceOf(Event);
expect(property.position).toBe(position);
expect(property.ellipsoid).toBe(Ellipsoid.UNIT_SPHERE);
expect(property.getValue(time)).toBe(undefined);
expect(property.getValue(time)).toBeUndefined();
});

it('setting position raises definitionChanged event', function() {
Expand Down
Loading