智慧水务管理系统 - 精河县供水工程综合管理平台

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