-
Notifications
You must be signed in to change notification settings - Fork 3.6k
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
Changes from 2 commits
88e9e04
3621eff
23ef115
2cb5ea4
beeae99
e8f061f
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,173 @@ | ||
/*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. | ||
* 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) { | ||
//>>includeStart('debug', pragmas.debug); | ||
if (!defined(time)) { | ||
throw new DeveloperError('time is required'); | ||
} | ||
//>>includeEnd('debug'); | ||
|
||
if (!defined(result)) { | ||
result = new Cartesian3(); | ||
} | ||
|
||
var property = this._position; | ||
if (Property.isConstant(property)) { | ||
return undefined; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Wouldn't this be the zero vector instead of undefined? There was a problem hiding this comment. Choose a reason for hiding this commentThe 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. There was a problem hiding this comment. Choose a reason for hiding this commentThe 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 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, |
||
} | ||
|
||
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; | ||
} | ||
|
||
var velocity = Cartesian3.subtract(position2, position1, velocityScratch); | ||
return Cartesian3.normalize(velocity, result); | ||
}; | ||
|
||
/** | ||
* 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; | ||
}); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,166 @@ | ||
/*global defineSuite*/ | ||
defineSuite([ | ||
'DataSources/VelocityVectorProperty', | ||
'Core/Cartesian3', | ||
'Core/Event', | ||
'Core/ExtrapolationType', | ||
'Core/JulianDate', | ||
'DataSources/CallbackProperty', | ||
'DataSources/SampledPositionProperty' | ||
], function( | ||
VelocityVectorProperty, | ||
Cartesian3, | ||
Event, | ||
ExtrapolationType, | ||
JulianDate, | ||
CallbackProperty, | ||
SampledPositionProperty) { | ||
'use strict'; | ||
|
||
var time = JulianDate.now(); | ||
|
||
it('can default construct', function() { | ||
var property = new VelocityVectorProperty(); | ||
expect(property.isConstant).toBe(true); | ||
expect(property.definitionChanged).toBeInstanceOf(Event); | ||
expect(property.position).toBeUndefined(); | ||
expect(property.getValue(time)).toBe(undefined); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
}); | ||
|
||
it('can construct with arguments', function() { | ||
var position = new SampledPositionProperty(); | ||
var property = new VelocityVectorProperty(position); | ||
expect(property.isConstant).toBe(true); | ||
expect(property.definitionChanged).toBeInstanceOf(Event); | ||
expect(property.position).toBe(position); | ||
expect(property.getValue(time)).toBe(undefined); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. same as above |
||
}); | ||
|
||
it('setting position raises definitionChanged event', function() { | ||
var property = new VelocityVectorProperty(); | ||
|
||
var listener = jasmine.createSpy('listener'); | ||
property.definitionChanged.addEventListener(listener); | ||
|
||
var position = new SampledPositionProperty(); | ||
property.position = position; | ||
expect(listener).toHaveBeenCalledWith(property); | ||
}); | ||
|
||
it('subscribes/unsubscribes to position definitionChanged and propagates up', function() { | ||
var position = new SampledPositionProperty(); | ||
var property = new VelocityVectorProperty(position); | ||
|
||
var listener = jasmine.createSpy('listener'); | ||
property.definitionChanged.addEventListener(listener); | ||
|
||
//Position changing should raise out property change event | ||
position.definitionChanged.raiseEvent(position); | ||
expect(listener).toHaveBeenCalledWith(property); | ||
|
||
//Make sure it unsubscribes when value is changed | ||
property.position = undefined; | ||
|
||
listener.calls.reset(); | ||
position.definitionChanged.raiseEvent(position); | ||
expect(listener.calls.count()).toBe(0); | ||
}); | ||
|
||
it('setting position does not raise definitionChanged event for same data', function() { | ||
var position = new SampledPositionProperty(); | ||
var property = new VelocityVectorProperty(position); | ||
|
||
var listener = jasmine.createSpy('listener'); | ||
property.definitionChanged.addEventListener(listener); | ||
|
||
property.position = position; | ||
expect(listener.calls.count()).toBe(0); | ||
}); | ||
|
||
it('works without result parameter', function() { | ||
var times = [new JulianDate(0, 0), new JulianDate(0, 1.0 / 60.0)]; | ||
var values = [Cartesian3.fromDegrees(0, 0, 0), Cartesian3.fromDegrees(1, 0, 0)]; | ||
var velocity = Cartesian3.subtract(values[1], values[0], new Cartesian3()); | ||
Cartesian3.normalize(velocity, velocity); | ||
|
||
var position = new SampledPositionProperty(); | ||
position.addSamples(times, values); | ||
|
||
var property = new VelocityVectorProperty(position); | ||
|
||
expect(property.getValue(times[0])).toEqual(velocity); | ||
expect(property.getValue(times[1])).toEqual(velocity); | ||
}); | ||
|
||
it('works with result parameter', function() { | ||
var times = [new JulianDate(0, 0), new JulianDate(0, 1.0 / 60.0)]; | ||
var values = [Cartesian3.fromDegrees(0, 0, 0), Cartesian3.fromDegrees(1, 0, 0)]; | ||
var velocity = Cartesian3.subtract(values[1], values[0], new Cartesian3()); | ||
Cartesian3.normalize(velocity, velocity); | ||
|
||
var position = new SampledPositionProperty(); | ||
position.addSamples(times, values); | ||
|
||
var property = new VelocityVectorProperty(position); | ||
|
||
var expected = new Cartesian3(); | ||
var result = property.getValue(times[0], expected); | ||
expect(result).toBe(expected); | ||
expect(expected).toEqual(velocity); | ||
}); | ||
|
||
it('is undefined at zero velocity', function() { | ||
var position = new CallbackProperty(function() { | ||
return Cartesian3.fromDegrees(0, 0, 0); | ||
}, false); | ||
|
||
var property = new VelocityVectorProperty(position); | ||
expect(property.getValue(new JulianDate())).toBeUndefined(); | ||
}); | ||
|
||
it('returns undefined when position value is undefined', function() { | ||
var position = new SampledPositionProperty(); | ||
position.addSample(new JulianDate(1, 0), Cartesian3.fromDegrees(0, 0, 0)); | ||
position.forwardExtrapolationType = ExtrapolationType.NONE; | ||
position.backwardExtrapolationType = ExtrapolationType.NONE; | ||
|
||
var property = new VelocityVectorProperty(position); | ||
|
||
var result = property.getValue(new JulianDate()); | ||
expect(result).toBeUndefined(); | ||
}); | ||
|
||
it('returns undefined when position has exactly one value', function() { | ||
var position = new SampledPositionProperty(); | ||
position.addSample(new JulianDate(1, 0), Cartesian3.fromDegrees(0, 0, 0)); | ||
position.forwardExtrapolationType = ExtrapolationType.NONE; | ||
position.backwardExtrapolationType = ExtrapolationType.NONE; | ||
|
||
var property = new VelocityVectorProperty(position); | ||
|
||
var result = property.getValue(new JulianDate(1, 0)); | ||
expect(result).toBeUndefined(); | ||
}); | ||
|
||
it('equals works', function() { | ||
var position = new SampledPositionProperty(); | ||
|
||
var left = new VelocityVectorProperty(); | ||
var right = new VelocityVectorProperty(); | ||
|
||
expect(left.equals(right)).toBe(true); | ||
|
||
left.position = position; | ||
expect(left.equals(right)).toBe(false); | ||
|
||
right.position = position; | ||
expect(left.equals(right)).toBe(true); | ||
}); | ||
|
||
it('getValue throws without time', function() { | ||
var property = new VelocityVectorProperty(); | ||
expect(function() { | ||
property.getValue(); | ||
}).toThrowDeveloperError(); | ||
}); | ||
}); |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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