SampledProperty.js 27 KB

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