Source: DataSources/SampledProperty.js

  1. /*global define*/
  2. define([
  3. '../Core/binarySearch',
  4. '../Core/defaultValue',
  5. '../Core/defined',
  6. '../Core/defineProperties',
  7. '../Core/DeveloperError',
  8. '../Core/Event',
  9. '../Core/ExtrapolationType',
  10. '../Core/JulianDate',
  11. '../Core/LinearApproximation'
  12. ], function(
  13. binarySearch,
  14. defaultValue,
  15. defined,
  16. defineProperties,
  17. DeveloperError,
  18. Event,
  19. ExtrapolationType,
  20. JulianDate,
  21. LinearApproximation) {
  22. 'use strict';
  23. var PackableNumber = {
  24. packedLength : 1,
  25. pack : function(value, array, startingIndex) {
  26. startingIndex = defaultValue(startingIndex, 0);
  27. array[startingIndex] = value;
  28. },
  29. unpack : function(array, startingIndex, result) {
  30. startingIndex = defaultValue(startingIndex, 0);
  31. return array[startingIndex];
  32. }
  33. };
  34. //We can't use splice for inserting new elements because function apply can't handle
  35. //a huge number of arguments. See https://code.google.com/p/chromium/issues/detail?id=56588
  36. function arrayInsert(array, startIndex, items) {
  37. var i;
  38. var arrayLength = array.length;
  39. var itemsLength = items.length;
  40. var newLength = arrayLength + itemsLength;
  41. array.length = newLength;
  42. if (arrayLength !== startIndex) {
  43. var q = arrayLength - 1;
  44. for (i = newLength - 1; i >= startIndex; i--) {
  45. array[i] = array[q--];
  46. }
  47. }
  48. for (i = 0; i < itemsLength; i++) {
  49. array[startIndex++] = items[i];
  50. }
  51. }
  52. function convertDate(date, epoch) {
  53. if (date instanceof JulianDate) {
  54. return date;
  55. }
  56. if (typeof date === 'string') {
  57. return JulianDate.fromIso8601(date);
  58. }
  59. return JulianDate.addSeconds(epoch, date, new JulianDate());
  60. }
  61. var timesSpliceArgs = [];
  62. var valuesSpliceArgs = [];
  63. function mergeNewSamples(epoch, times, values, newData, packedLength) {
  64. var newDataIndex = 0;
  65. var i;
  66. var prevItem;
  67. var timesInsertionPoint;
  68. var valuesInsertionPoint;
  69. var currentTime;
  70. var nextTime;
  71. while (newDataIndex < newData.length) {
  72. currentTime = convertDate(newData[newDataIndex], epoch);
  73. timesInsertionPoint = binarySearch(times, currentTime, JulianDate.compare);
  74. var timesSpliceArgsCount = 0;
  75. var valuesSpliceArgsCount = 0;
  76. if (timesInsertionPoint < 0) {
  77. //Doesn't exist, insert as many additional values as we can.
  78. timesInsertionPoint = ~timesInsertionPoint;
  79. valuesInsertionPoint = timesInsertionPoint * packedLength;
  80. prevItem = undefined;
  81. nextTime = times[timesInsertionPoint];
  82. while (newDataIndex < newData.length) {
  83. currentTime = convertDate(newData[newDataIndex], epoch);
  84. if ((defined(prevItem) && JulianDate.compare(prevItem, currentTime) >= 0) || (defined(nextTime) && JulianDate.compare(currentTime, nextTime) >= 0)) {
  85. break;
  86. }
  87. timesSpliceArgs[timesSpliceArgsCount++] = currentTime;
  88. newDataIndex = newDataIndex + 1;
  89. for (i = 0; i < packedLength; i++) {
  90. valuesSpliceArgs[valuesSpliceArgsCount++] = newData[newDataIndex];
  91. newDataIndex = newDataIndex + 1;
  92. }
  93. prevItem = currentTime;
  94. }
  95. if (timesSpliceArgsCount > 0) {
  96. valuesSpliceArgs.length = valuesSpliceArgsCount;
  97. arrayInsert(values, valuesInsertionPoint, valuesSpliceArgs);
  98. timesSpliceArgs.length = timesSpliceArgsCount;
  99. arrayInsert(times, timesInsertionPoint, timesSpliceArgs);
  100. }
  101. } else {
  102. //Found an exact match
  103. for (i = 0; i < packedLength; i++) {
  104. newDataIndex++;
  105. values[(timesInsertionPoint * packedLength) + i] = newData[newDataIndex];
  106. }
  107. newDataIndex++;
  108. }
  109. }
  110. }
  111. /**
  112. * A {@link Property} whose value is interpolated for a given time from the
  113. * provided set of samples and specified interpolation algorithm and degree.
  114. * @alias SampledProperty
  115. * @constructor
  116. *
  117. * @param {Number|Packable} type The type of property.
  118. * @param {Packable[]} [derivativeTypes] When supplied, indicates that samples will contain derivative information of the specified types.
  119. *
  120. *
  121. * @example
  122. * //Create a linearly interpolated Cartesian2
  123. * var property = new Cesium.SampledProperty(Cesium.Cartesian2);
  124. *
  125. * //Populate it with data
  126. * property.addSample(Cesium.JulianDate.fromIso8601(`2012-08-01T00:00:00.00Z`), new Cesium.Cartesian2(0, 0));
  127. * property.addSample(Cesium.JulianDate.fromIso8601(`2012-08-02T00:00:00.00Z`), new Cesium.Cartesian2(4, 7));
  128. *
  129. * //Retrieve an interpolated value
  130. * var result = property.getValue(Cesium.JulianDate.fromIso8601(`2012-08-01T12:00:00.00Z`));
  131. *
  132. * @example
  133. * //Create a simple numeric SampledProperty that uses third degree Hermite Polynomial Approximation
  134. * var property = new Cesium.SampledProperty(Number);
  135. * property.setInterpolationOptions({
  136. * interpolationDegree : 3,
  137. * interpolationAlgorithm : Cesium.HermitePolynomialApproximation
  138. * });
  139. *
  140. * //Populate it with data
  141. * property.addSample(Cesium.JulianDate.fromIso8601(`2012-08-01T00:00:00.00Z`), 1.0);
  142. * property.addSample(Cesium.JulianDate.fromIso8601(`2012-08-01T00:01:00.00Z`), 6.0);
  143. * property.addSample(Cesium.JulianDate.fromIso8601(`2012-08-01T00:02:00.00Z`), 12.0);
  144. * property.addSample(Cesium.JulianDate.fromIso8601(`2012-08-01T00:03:30.00Z`), 5.0);
  145. * property.addSample(Cesium.JulianDate.fromIso8601(`2012-08-01T00:06:30.00Z`), 2.0);
  146. *
  147. * //Samples can be added in any order.
  148. * property.addSample(Cesium.JulianDate.fromIso8601(`2012-08-01T00:00:30.00Z`), 6.2);
  149. *
  150. * //Retrieve an interpolated value
  151. * var result = property.getValue(Cesium.JulianDate.fromIso8601(`2012-08-01T00:02:34.00Z`));
  152. *
  153. * @see SampledPositionProperty
  154. */
  155. function SampledProperty(type, derivativeTypes) {
  156. //>>includeStart('debug', pragmas.debug);
  157. if (!defined(type)) {
  158. throw new DeveloperError('type is required.');
  159. }
  160. //>>includeEnd('debug');
  161. var innerType = type;
  162. if (innerType === Number) {
  163. innerType = PackableNumber;
  164. }
  165. var packedLength = innerType.packedLength;
  166. var packedInterpolationLength = defaultValue(innerType.packedInterpolationLength, packedLength);
  167. var inputOrder = 0;
  168. var innerDerivativeTypes;
  169. if (defined(derivativeTypes)) {
  170. var length = derivativeTypes.length;
  171. innerDerivativeTypes = new Array(length);
  172. for (var i = 0; i < length; i++) {
  173. var derivativeType = derivativeTypes[i];
  174. if (derivativeType === Number) {
  175. derivativeType = PackableNumber;
  176. }
  177. var derivativePackedLength = derivativeType.packedLength;
  178. packedLength += derivativePackedLength;
  179. packedInterpolationLength += defaultValue(derivativeType.packedInterpolationLength, derivativePackedLength);
  180. innerDerivativeTypes[i] = derivativeType;
  181. }
  182. inputOrder = length;
  183. }
  184. this._type = type;
  185. this._innerType = innerType;
  186. this._interpolationDegree = 1;
  187. this._interpolationAlgorithm = LinearApproximation;
  188. this._numberOfPoints = 0;
  189. this._times = [];
  190. this._values = [];
  191. this._xTable = [];
  192. this._yTable = [];
  193. this._packedLength = packedLength;
  194. this._packedInterpolationLength = packedInterpolationLength;
  195. this._updateTableLength = true;
  196. this._interpolationResult = new Array(packedInterpolationLength);
  197. this._definitionChanged = new Event();
  198. this._derivativeTypes = derivativeTypes;
  199. this._innerDerivativeTypes = innerDerivativeTypes;
  200. this._inputOrder = inputOrder;
  201. this._forwardExtrapolationType = ExtrapolationType.NONE;
  202. this._forwardExtrapolationDuration = 0;
  203. this._backwardExtrapolationType = ExtrapolationType.NONE;
  204. this._backwardExtrapolationDuration = 0;
  205. }
  206. defineProperties(SampledProperty.prototype, {
  207. /**
  208. * Gets a value indicating if this property is constant. A property is considered
  209. * constant if getValue always returns the same result for the current definition.
  210. * @memberof SampledProperty.prototype
  211. *
  212. * @type {Boolean}
  213. * @readonly
  214. */
  215. isConstant : {
  216. get : function() {
  217. return this._values.length === 0;
  218. }
  219. },
  220. /**
  221. * Gets the event that is raised whenever the definition of this property changes.
  222. * The definition is considered to have changed if a call to getValue would return
  223. * a different result for the same time.
  224. * @memberof SampledProperty.prototype
  225. *
  226. * @type {Event}
  227. * @readonly
  228. */
  229. definitionChanged : {
  230. get : function() {
  231. return this._definitionChanged;
  232. }
  233. },
  234. /**
  235. * Gets the type of property.
  236. * @memberof SampledProperty.prototype
  237. * @type {Object}
  238. */
  239. type : {
  240. get : function() {
  241. return this._type;
  242. }
  243. },
  244. /**
  245. * Gets the derivative types used by this property.
  246. * @memberof SampledProperty.prototype
  247. * @type {Packable[]}
  248. */
  249. derivativeTypes : {
  250. get : function() {
  251. return this._derivativeTypes;
  252. }
  253. },
  254. /**
  255. * Gets the degree of interpolation to perform when retrieving a value.
  256. * @memberof SampledProperty.prototype
  257. * @type {Number}
  258. * @default 1
  259. */
  260. interpolationDegree : {
  261. get : function() {
  262. return this._interpolationDegree;
  263. }
  264. },
  265. /**
  266. * Gets the interpolation algorithm to use when retrieving a value.
  267. * @memberof SampledProperty.prototype
  268. * @type {InterpolationAlgorithm}
  269. * @default LinearApproximation
  270. */
  271. interpolationAlgorithm : {
  272. get : function() {
  273. return this._interpolationAlgorithm;
  274. }
  275. },
  276. /**
  277. * Gets or sets the type of extrapolation to perform when a value
  278. * is requested at a time after any available samples.
  279. * @memberof SampledProperty.prototype
  280. * @type {ExtrapolationType}
  281. * @default ExtrapolationType.NONE
  282. */
  283. forwardExtrapolationType : {
  284. get : function() {
  285. return this._forwardExtrapolationType;
  286. },
  287. set : function(value) {
  288. if (this._forwardExtrapolationType !== value) {
  289. this._forwardExtrapolationType = value;
  290. this._definitionChanged.raiseEvent(this);
  291. }
  292. }
  293. },
  294. /**
  295. * Gets or sets the amount of time to extrapolate forward before
  296. * the property becomes undefined. A value of 0 will extrapolate forever.
  297. * @memberof SampledProperty.prototype
  298. * @type {Number}
  299. * @default 0
  300. */
  301. forwardExtrapolationDuration : {
  302. get : function() {
  303. return this._forwardExtrapolationDuration;
  304. },
  305. set : function(value) {
  306. if (this._forwardExtrapolationDuration !== value) {
  307. this._forwardExtrapolationDuration = value;
  308. this._definitionChanged.raiseEvent(this);
  309. }
  310. }
  311. },
  312. /**
  313. * Gets or sets the type of extrapolation to perform when a value
  314. * is requested at a time before any available samples.
  315. * @memberof SampledProperty.prototype
  316. * @type {ExtrapolationType}
  317. * @default ExtrapolationType.NONE
  318. */
  319. backwardExtrapolationType : {
  320. get : function() {
  321. return this._backwardExtrapolationType;
  322. },
  323. set : function(value) {
  324. if (this._backwardExtrapolationType !== value) {
  325. this._backwardExtrapolationType = value;
  326. this._definitionChanged.raiseEvent(this);
  327. }
  328. }
  329. },
  330. /**
  331. * Gets or sets the amount of time to extrapolate backward
  332. * before the property becomes undefined. A value of 0 will extrapolate forever.
  333. * @memberof SampledProperty.prototype
  334. * @type {Number}
  335. * @default 0
  336. */
  337. backwardExtrapolationDuration : {
  338. get : function() {
  339. return this._backwardExtrapolationDuration;
  340. },
  341. set : function(value) {
  342. if (this._backwardExtrapolationDuration !== value) {
  343. this._backwardExtrapolationDuration = value;
  344. this._definitionChanged.raiseEvent(this);
  345. }
  346. }
  347. }
  348. });
  349. /**
  350. * Gets the value of the property at the provided time.
  351. *
  352. * @param {JulianDate} time The time for which to retrieve the value.
  353. * @param {Object} [result] The object to store the value into, if omitted, a new instance is created and returned.
  354. * @returns {Object} The modified result parameter or a new instance if the result parameter was not supplied.
  355. */
  356. SampledProperty.prototype.getValue = function(time, result) {
  357. //>>includeStart('debug', pragmas.debug);
  358. if (!defined(time)) {
  359. throw new DeveloperError('time is required.');
  360. }
  361. //>>includeEnd('debug');
  362. var times = this._times;
  363. var timesLength = times.length;
  364. if (timesLength === 0) {
  365. return undefined;
  366. }
  367. var timeout;
  368. var innerType = this._innerType;
  369. var values = this._values;
  370. var index = binarySearch(times, time, JulianDate.compare);
  371. if (index < 0) {
  372. index = ~index;
  373. if (index === 0) {
  374. var startTime = times[index];
  375. timeout = this._backwardExtrapolationDuration;
  376. if (this._backwardExtrapolationType === ExtrapolationType.NONE || (timeout !== 0 && JulianDate.secondsDifference(startTime, time) > timeout)) {
  377. return undefined;
  378. }
  379. if (this._backwardExtrapolationType === ExtrapolationType.HOLD) {
  380. return innerType.unpack(values, 0, result);
  381. }
  382. }
  383. if (index >= timesLength) {
  384. index = timesLength - 1;
  385. var endTime = times[index];
  386. timeout = this._forwardExtrapolationDuration;
  387. if (this._forwardExtrapolationType === ExtrapolationType.NONE || (timeout !== 0 && JulianDate.secondsDifference(time, endTime) > timeout)) {
  388. return undefined;
  389. }
  390. if (this._forwardExtrapolationType === ExtrapolationType.HOLD) {
  391. index = timesLength - 1;
  392. return innerType.unpack(values, index * innerType.packedLength, result);
  393. }
  394. }
  395. var xTable = this._xTable;
  396. var yTable = this._yTable;
  397. var interpolationAlgorithm = this._interpolationAlgorithm;
  398. var packedInterpolationLength = this._packedInterpolationLength;
  399. var inputOrder = this._inputOrder;
  400. if (this._updateTableLength) {
  401. this._updateTableLength = false;
  402. var numberOfPoints = Math.min(interpolationAlgorithm.getRequiredDataPoints(this._interpolationDegree, inputOrder), timesLength);
  403. if (numberOfPoints !== this._numberOfPoints) {
  404. this._numberOfPoints = numberOfPoints;
  405. xTable.length = numberOfPoints;
  406. yTable.length = numberOfPoints * packedInterpolationLength;
  407. }
  408. }
  409. var degree = this._numberOfPoints - 1;
  410. if (degree < 1) {
  411. return undefined;
  412. }
  413. var firstIndex = 0;
  414. var lastIndex = timesLength - 1;
  415. var pointsInCollection = lastIndex - firstIndex + 1;
  416. if (pointsInCollection >= degree + 1) {
  417. var computedFirstIndex = index - ((degree / 2) | 0) - 1;
  418. if (computedFirstIndex < firstIndex) {
  419. computedFirstIndex = firstIndex;
  420. }
  421. var computedLastIndex = computedFirstIndex + degree;
  422. if (computedLastIndex > lastIndex) {
  423. computedLastIndex = lastIndex;
  424. computedFirstIndex = computedLastIndex - degree;
  425. if (computedFirstIndex < firstIndex) {
  426. computedFirstIndex = firstIndex;
  427. }
  428. }
  429. firstIndex = computedFirstIndex;
  430. lastIndex = computedLastIndex;
  431. }
  432. var length = lastIndex - firstIndex + 1;
  433. // Build the tables
  434. for (var i = 0; i < length; ++i) {
  435. xTable[i] = JulianDate.secondsDifference(times[firstIndex + i], times[lastIndex]);
  436. }
  437. if (!defined(innerType.convertPackedArrayForInterpolation)) {
  438. var destinationIndex = 0;
  439. var packedLength = this._packedLength;
  440. var sourceIndex = firstIndex * packedLength;
  441. var stop = (lastIndex + 1) * packedLength;
  442. while (sourceIndex < stop) {
  443. yTable[destinationIndex] = values[sourceIndex];
  444. sourceIndex++;
  445. destinationIndex++;
  446. }
  447. } else {
  448. innerType.convertPackedArrayForInterpolation(values, firstIndex, lastIndex, yTable);
  449. }
  450. // Interpolate!
  451. var x = JulianDate.secondsDifference(time, times[lastIndex]);
  452. var interpolationResult;
  453. if (inputOrder === 0 || !defined(interpolationAlgorithm.interpolate)) {
  454. interpolationResult = interpolationAlgorithm.interpolateOrderZero(x, xTable, yTable, packedInterpolationLength, this._interpolationResult);
  455. } else {
  456. var yStride = Math.floor(packedInterpolationLength / (inputOrder + 1));
  457. interpolationResult = interpolationAlgorithm.interpolate(x, xTable, yTable, yStride, inputOrder, inputOrder, this._interpolationResult);
  458. }
  459. if (!defined(innerType.unpackInterpolationResult)) {
  460. return innerType.unpack(interpolationResult, 0, result);
  461. }
  462. return innerType.unpackInterpolationResult(interpolationResult, values, firstIndex, lastIndex, result);
  463. }
  464. return innerType.unpack(values, index * this._packedLength, result);
  465. };
  466. /**
  467. * Sets the algorithm and degree to use when interpolating a value.
  468. *
  469. * @param {Object} [options] Object with the following properties:
  470. * @param {InterpolationAlgorithm} [options.interpolationAlgorithm] The new interpolation algorithm. If undefined, the existing property will be unchanged.
  471. * @param {Number} [options.interpolationDegree] The new interpolation degree. If undefined, the existing property will be unchanged.
  472. */
  473. SampledProperty.prototype.setInterpolationOptions = function(options) {
  474. //>>includeStart('debug', pragmas.debug);
  475. if (!defined(options)) {
  476. throw new DeveloperError('options is required.');
  477. }
  478. //>>includeEnd('debug');
  479. var valuesChanged = false;
  480. var interpolationAlgorithm = options.interpolationAlgorithm;
  481. var interpolationDegree = options.interpolationDegree;
  482. if (this._interpolationAlgorithm !== interpolationAlgorithm) {
  483. this._interpolationAlgorithm = interpolationAlgorithm;
  484. valuesChanged = true;
  485. }
  486. if (this._interpolationDegree !== interpolationDegree) {
  487. this._interpolationDegree = interpolationDegree;
  488. valuesChanged = true;
  489. }
  490. if (valuesChanged) {
  491. this._updateTableLength = true;
  492. this._definitionChanged.raiseEvent(this);
  493. }
  494. };
  495. /**
  496. * Adds a new sample
  497. *
  498. * @param {JulianDate} time The sample time.
  499. * @param {Packable} value The value at the provided time.
  500. * @param {Packable[]} [derivatives] The array of derivatives at the provided time.
  501. */
  502. SampledProperty.prototype.addSample = function(time, value, derivatives) {
  503. var innerDerivativeTypes = this._innerDerivativeTypes;
  504. var hasDerivatives = defined(innerDerivativeTypes);
  505. //>>includeStart('debug', pragmas.debug);
  506. if (!defined(time)) {
  507. throw new DeveloperError('time is required.');
  508. }
  509. if (!defined(value)) {
  510. throw new DeveloperError('value is required.');
  511. }
  512. if (hasDerivatives && !defined(derivatives)) {
  513. throw new DeveloperError('derivatives is required.');
  514. }
  515. //>>includeEnd('debug');
  516. var innerType = this._innerType;
  517. var data = [];
  518. data.push(time);
  519. innerType.pack(value, data, data.length);
  520. if (hasDerivatives) {
  521. var derivativesLength = innerDerivativeTypes.length;
  522. for (var x = 0; x < derivativesLength; x++) {
  523. innerDerivativeTypes[x].pack(derivatives[x], data, data.length);
  524. }
  525. }
  526. mergeNewSamples(undefined, this._times, this._values, data, this._packedLength);
  527. this._updateTableLength = true;
  528. this._definitionChanged.raiseEvent(this);
  529. };
  530. /**
  531. * Adds an array of samples
  532. *
  533. * @param {JulianDate[]} times An array of JulianDate instances where each index is a sample time.
  534. * @param {Packable[]} values The array of values, where each value corresponds to the provided times index.
  535. * @param {Array[]} [derivativeValues] An array where each item is the array of derivatives at the equivalent time index.
  536. *
  537. * @exception {DeveloperError} times and values must be the same length.
  538. * @exception {DeveloperError} times and derivativeValues must be the same length.
  539. */
  540. SampledProperty.prototype.addSamples = function(times, values, derivativeValues) {
  541. var innerDerivativeTypes = this._innerDerivativeTypes;
  542. var hasDerivatives = defined(innerDerivativeTypes);
  543. //>>includeStart('debug', pragmas.debug);
  544. if (!defined(times)) {
  545. throw new DeveloperError('times is required.');
  546. }
  547. if (!defined(values)) {
  548. throw new DeveloperError('values is required.');
  549. }
  550. if (times.length !== values.length) {
  551. throw new DeveloperError('times and values must be the same length.');
  552. }
  553. if (hasDerivatives && (!defined(derivativeValues) || derivativeValues.length !== times.length)) {
  554. throw new DeveloperError('times and derivativeValues must be the same length.');
  555. }
  556. //>>includeEnd('debug');
  557. var innerType = this._innerType;
  558. var length = times.length;
  559. var data = [];
  560. for (var i = 0; i < length; i++) {
  561. data.push(times[i]);
  562. innerType.pack(values[i], data, data.length);
  563. if (hasDerivatives) {
  564. var derivatives = derivativeValues[i];
  565. var derivativesLength = innerDerivativeTypes.length;
  566. for (var x = 0; x < derivativesLength; x++) {
  567. innerDerivativeTypes[x].pack(derivatives[x], data, data.length);
  568. }
  569. }
  570. }
  571. mergeNewSamples(undefined, this._times, this._values, data, this._packedLength);
  572. this._updateTableLength = true;
  573. this._definitionChanged.raiseEvent(this);
  574. };
  575. /**
  576. * Adds samples as a single packed array where each new sample is represented as a date,
  577. * followed by the packed representation of the corresponding value and derivatives.
  578. *
  579. * @param {Number[]} packedSamples The array of packed samples.
  580. * @param {JulianDate} [epoch] If any of the dates in packedSamples are numbers, they are considered an offset from this epoch, in seconds.
  581. */
  582. SampledProperty.prototype.addSamplesPackedArray = function(packedSamples, epoch) {
  583. //>>includeStart('debug', pragmas.debug);
  584. if (!defined(packedSamples)) {
  585. throw new DeveloperError('packedSamples is required.');
  586. }
  587. //>>includeEnd('debug');
  588. mergeNewSamples(epoch, this._times, this._values, packedSamples, this._packedLength);
  589. this._updateTableLength = true;
  590. this._definitionChanged.raiseEvent(this);
  591. };
  592. /**
  593. * Compares this property to the provided property and returns
  594. * <code>true</code> if they are equal, <code>false</code> otherwise.
  595. *
  596. * @param {Property} [other] The other property.
  597. * @returns {Boolean} <code>true</code> if left and right are equal, <code>false</code> otherwise.
  598. */
  599. SampledProperty.prototype.equals = function(other) {
  600. if (this === other) {
  601. return true;
  602. }
  603. if (!defined(other)) {
  604. return false;
  605. }
  606. if (this._type !== other._type || //
  607. this._interpolationDegree !== other._interpolationDegree || //
  608. this._interpolationAlgorithm !== other._interpolationAlgorithm) {
  609. return false;
  610. }
  611. var derivativeTypes = this._derivativeTypes;
  612. var hasDerivatives = defined(derivativeTypes);
  613. var otherDerivativeTypes = other._derivativeTypes;
  614. var otherHasDerivatives = defined(otherDerivativeTypes);
  615. if (hasDerivatives !== otherHasDerivatives) {
  616. return false;
  617. }
  618. var i;
  619. var length;
  620. if (hasDerivatives) {
  621. length = derivativeTypes.length;
  622. if (length !== otherDerivativeTypes.length) {
  623. return false;
  624. }
  625. for (i = 0; i < length; i++) {
  626. if (derivativeTypes[i] !== otherDerivativeTypes[i]) {
  627. return false;
  628. }
  629. }
  630. }
  631. var times = this._times;
  632. var otherTimes = other._times;
  633. length = times.length;
  634. if (length !== otherTimes.length) {
  635. return false;
  636. }
  637. for (i = 0; i < length; i++) {
  638. if (!JulianDate.equals(times[i], otherTimes[i])) {
  639. return false;
  640. }
  641. }
  642. var values = this._values;
  643. var otherValues = other._values;
  644. for (i = 0; i < length; i++) {
  645. if (values[i] !== otherValues[i]) {
  646. return false;
  647. }
  648. }
  649. return true;
  650. };
  651. //Exposed for testing.
  652. SampledProperty._mergeNewSamples = mergeNewSamples;
  653. return SampledProperty;
  654. });