| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834 | import binarySearch from "../Core/binarySearch.js";import Check from "../Core/Check.js";import defaultValue from "../Core/defaultValue.js";import defined from "../Core/defined.js";import DeveloperError from "../Core/DeveloperError.js";import Event from "../Core/Event.js";import ExtrapolationType from "../Core/ExtrapolationType.js";import JulianDate from "../Core/JulianDate.js";import LinearApproximation from "../Core/LinearApproximation.js";const PackableNumber = {  packedLength: 1,  pack: function (value, array, startingIndex) {    startingIndex = defaultValue(startingIndex, 0);    array[startingIndex] = value;  },  unpack: function (array, startingIndex, result) {    startingIndex = defaultValue(startingIndex, 0);    return array[startingIndex];  },};//We can't use splice for inserting new elements because function apply can't handle//a huge number of arguments.  See https://code.google.com/p/chromium/issues/detail?id=56588function arrayInsert(array, startIndex, items) {  let i;  const arrayLength = array.length;  const itemsLength = items.length;  const newLength = arrayLength + itemsLength;  array.length = newLength;  if (arrayLength !== startIndex) {    let q = arrayLength - 1;    for (i = newLength - 1; i >= startIndex; i--) {      array[i] = array[q--];    }  }  for (i = 0; i < itemsLength; i++) {    array[startIndex++] = items[i];  }}function convertDate(date, epoch) {  if (date instanceof JulianDate) {    return date;  }  if (typeof date === "string") {    return JulianDate.fromIso8601(date);  }  return JulianDate.addSeconds(epoch, date, new JulianDate());}const timesSpliceArgs = [];const valuesSpliceArgs = [];function mergeNewSamples(epoch, times, values, newData, packedLength) {  let newDataIndex = 0;  let i;  let prevItem;  let timesInsertionPoint;  let valuesInsertionPoint;  let currentTime;  let nextTime;  while (newDataIndex < newData.length) {    currentTime = convertDate(newData[newDataIndex], epoch);    timesInsertionPoint = binarySearch(times, currentTime, JulianDate.compare);    let timesSpliceArgsCount = 0;    let valuesSpliceArgsCount = 0;    if (timesInsertionPoint < 0) {      //Doesn't exist, insert as many additional values as we can.      timesInsertionPoint = ~timesInsertionPoint;      valuesInsertionPoint = timesInsertionPoint * packedLength;      prevItem = undefined;      nextTime = times[timesInsertionPoint];      while (newDataIndex < newData.length) {        currentTime = convertDate(newData[newDataIndex], epoch);        if (          (defined(prevItem) &&            JulianDate.compare(prevItem, currentTime) >= 0) ||          (defined(nextTime) && JulianDate.compare(currentTime, nextTime) >= 0)        ) {          break;        }        timesSpliceArgs[timesSpliceArgsCount++] = currentTime;        newDataIndex = newDataIndex + 1;        for (i = 0; i < packedLength; i++) {          valuesSpliceArgs[valuesSpliceArgsCount++] = newData[newDataIndex];          newDataIndex = newDataIndex + 1;        }        prevItem = currentTime;      }      if (timesSpliceArgsCount > 0) {        valuesSpliceArgs.length = valuesSpliceArgsCount;        arrayInsert(values, valuesInsertionPoint, valuesSpliceArgs);        timesSpliceArgs.length = timesSpliceArgsCount;        arrayInsert(times, timesInsertionPoint, timesSpliceArgs);      }    } else {      //Found an exact match      for (i = 0; i < packedLength; i++) {        newDataIndex++;        values[timesInsertionPoint * packedLength + i] = newData[newDataIndex];      }      newDataIndex++;    }  }}/** * A {@link Property} whose value is interpolated for a given time from the * provided set of samples and specified interpolation algorithm and degree. * @alias SampledProperty * @constructor * * @param {Number|Packable} type The type of property. * @param {Packable[]} [derivativeTypes] When supplied, indicates that samples will contain derivative information of the specified types. * * * @example * //Create a linearly interpolated Cartesian2 * const property = new Cesium.SampledProperty(Cesium.Cartesian2); * * //Populate it with data * property.addSample(Cesium.JulianDate.fromIso8601('2012-08-01T00:00:00.00Z'), new Cesium.Cartesian2(0, 0)); * property.addSample(Cesium.JulianDate.fromIso8601('2012-08-02T00:00:00.00Z'), new Cesium.Cartesian2(4, 7)); * * //Retrieve an interpolated value * const result = property.getValue(Cesium.JulianDate.fromIso8601('2012-08-01T12:00:00.00Z')); * * @example * //Create a simple numeric SampledProperty that uses third degree Hermite Polynomial Approximation * const property = new Cesium.SampledProperty(Number); * property.setInterpolationOptions({ *     interpolationDegree : 3, *     interpolationAlgorithm : Cesium.HermitePolynomialApproximation * }); * * //Populate it with data * property.addSample(Cesium.JulianDate.fromIso8601('2012-08-01T00:00:00.00Z'), 1.0); * property.addSample(Cesium.JulianDate.fromIso8601('2012-08-01T00:01:00.00Z'), 6.0); * property.addSample(Cesium.JulianDate.fromIso8601('2012-08-01T00:02:00.00Z'), 12.0); * property.addSample(Cesium.JulianDate.fromIso8601('2012-08-01T00:03:30.00Z'), 5.0); * property.addSample(Cesium.JulianDate.fromIso8601('2012-08-01T00:06:30.00Z'), 2.0); * * //Samples can be added in any order. * property.addSample(Cesium.JulianDate.fromIso8601('2012-08-01T00:00:30.00Z'), 6.2); * * //Retrieve an interpolated value * const result = property.getValue(Cesium.JulianDate.fromIso8601('2012-08-01T00:02:34.00Z')); * * @see SampledPositionProperty */function SampledProperty(type, derivativeTypes) {  //>>includeStart('debug', pragmas.debug);  Check.defined("type", type);  //>>includeEnd('debug');  let innerType = type;  if (innerType === Number) {    innerType = PackableNumber;  }  let packedLength = innerType.packedLength;  let packedInterpolationLength = defaultValue(    innerType.packedInterpolationLength,    packedLength  );  let inputOrder = 0;  let innerDerivativeTypes;  if (defined(derivativeTypes)) {    const length = derivativeTypes.length;    innerDerivativeTypes = new Array(length);    for (let i = 0; i < length; i++) {      let derivativeType = derivativeTypes[i];      if (derivativeType === Number) {        derivativeType = PackableNumber;      }      const derivativePackedLength = derivativeType.packedLength;      packedLength += derivativePackedLength;      packedInterpolationLength += defaultValue(        derivativeType.packedInterpolationLength,        derivativePackedLength      );      innerDerivativeTypes[i] = derivativeType;    }    inputOrder = length;  }  this._type = type;  this._innerType = innerType;  this._interpolationDegree = 1;  this._interpolationAlgorithm = LinearApproximation;  this._numberOfPoints = 0;  this._times = [];  this._values = [];  this._xTable = [];  this._yTable = [];  this._packedLength = packedLength;  this._packedInterpolationLength = packedInterpolationLength;  this._updateTableLength = true;  this._interpolationResult = new Array(packedInterpolationLength);  this._definitionChanged = new Event();  this._derivativeTypes = derivativeTypes;  this._innerDerivativeTypes = innerDerivativeTypes;  this._inputOrder = inputOrder;  this._forwardExtrapolationType = ExtrapolationType.NONE;  this._forwardExtrapolationDuration = 0;  this._backwardExtrapolationType = ExtrapolationType.NONE;  this._backwardExtrapolationDuration = 0;}Object.defineProperties(SampledProperty.prototype, {  /**   * Gets a value indicating if this property is constant.  A property is considered   * constant if getValue always returns the same result for the current definition.   * @memberof SampledProperty.prototype   *   * @type {Boolean}   * @readonly   */  isConstant: {    get: function () {      return this._values.length === 0;    },  },  /**   * Gets the event that is raised whenever the definition of this property changes.   * The definition is considered to have changed if a call to getValue would return   * a different result for the same time.   * @memberof SampledProperty.prototype   *   * @type {Event}   * @readonly   */  definitionChanged: {    get: function () {      return this._definitionChanged;    },  },  /**   * Gets the type of property.   * @memberof SampledProperty.prototype   * @type {*}   */  type: {    get: function () {      return this._type;    },  },  /**   * Gets the derivative types used by this property.   * @memberof SampledProperty.prototype   * @type {Packable[]}   */  derivativeTypes: {    get: function () {      return this._derivativeTypes;    },  },  /**   * Gets the degree of interpolation to perform when retrieving a value.   * @memberof SampledProperty.prototype   * @type {Number}   * @default 1   */  interpolationDegree: {    get: function () {      return this._interpolationDegree;    },  },  /**   * Gets the interpolation algorithm to use when retrieving a value.   * @memberof SampledProperty.prototype   * @type {InterpolationAlgorithm}   * @default LinearApproximation   */  interpolationAlgorithm: {    get: function () {      return this._interpolationAlgorithm;    },  },  /**   * Gets or sets the type of extrapolation to perform when a value   * is requested at a time after any available samples.   * @memberof SampledProperty.prototype   * @type {ExtrapolationType}   * @default ExtrapolationType.NONE   */  forwardExtrapolationType: {    get: function () {      return this._forwardExtrapolationType;    },    set: function (value) {      if (this._forwardExtrapolationType !== value) {        this._forwardExtrapolationType = value;        this._definitionChanged.raiseEvent(this);      }    },  },  /**   * Gets or sets the amount of time to extrapolate forward before   * the property becomes undefined.  A value of 0 will extrapolate forever.   * @memberof SampledProperty.prototype   * @type {Number}   * @default 0   */  forwardExtrapolationDuration: {    get: function () {      return this._forwardExtrapolationDuration;    },    set: function (value) {      if (this._forwardExtrapolationDuration !== value) {        this._forwardExtrapolationDuration = value;        this._definitionChanged.raiseEvent(this);      }    },  },  /**   * Gets or sets the type of extrapolation to perform when a value   * is requested at a time before any available samples.   * @memberof SampledProperty.prototype   * @type {ExtrapolationType}   * @default ExtrapolationType.NONE   */  backwardExtrapolationType: {    get: function () {      return this._backwardExtrapolationType;    },    set: function (value) {      if (this._backwardExtrapolationType !== value) {        this._backwardExtrapolationType = value;        this._definitionChanged.raiseEvent(this);      }    },  },  /**   * Gets or sets the amount of time to extrapolate backward   * before the property becomes undefined.  A value of 0 will extrapolate forever.   * @memberof SampledProperty.prototype   * @type {Number}   * @default 0   */  backwardExtrapolationDuration: {    get: function () {      return this._backwardExtrapolationDuration;    },    set: function (value) {      if (this._backwardExtrapolationDuration !== value) {        this._backwardExtrapolationDuration = value;        this._definitionChanged.raiseEvent(this);      }    },  },});/** * Gets the value of the property at the provided time. * * @param {JulianDate} time The time for which to retrieve the value. * @param {Object} [result] The object to store the value into, if omitted, a new instance is created and returned. * @returns {Object} The modified result parameter or a new instance if the result parameter was not supplied. */SampledProperty.prototype.getValue = function (time, result) {  //>>includeStart('debug', pragmas.debug);  Check.defined("time", time);  //>>includeEnd('debug');  const times = this._times;  const timesLength = times.length;  if (timesLength === 0) {    return undefined;  }  let timeout;  const innerType = this._innerType;  const values = this._values;  let index = binarySearch(times, time, JulianDate.compare);  if (index < 0) {    index = ~index;    if (index === 0) {      const startTime = times[index];      timeout = this._backwardExtrapolationDuration;      if (        this._backwardExtrapolationType === ExtrapolationType.NONE ||        (timeout !== 0 &&          JulianDate.secondsDifference(startTime, time) > timeout)      ) {        return undefined;      }      if (this._backwardExtrapolationType === ExtrapolationType.HOLD) {        return innerType.unpack(values, 0, result);      }    }    if (index >= timesLength) {      index = timesLength - 1;      const endTime = times[index];      timeout = this._forwardExtrapolationDuration;      if (        this._forwardExtrapolationType === ExtrapolationType.NONE ||        (timeout !== 0 && JulianDate.secondsDifference(time, endTime) > timeout)      ) {        return undefined;      }      if (this._forwardExtrapolationType === ExtrapolationType.HOLD) {        index = timesLength - 1;        return innerType.unpack(values, index * innerType.packedLength, result);      }    }    const xTable = this._xTable;    const yTable = this._yTable;    const interpolationAlgorithm = this._interpolationAlgorithm;    const packedInterpolationLength = this._packedInterpolationLength;    const inputOrder = this._inputOrder;    if (this._updateTableLength) {      this._updateTableLength = false;      const numberOfPoints = Math.min(        interpolationAlgorithm.getRequiredDataPoints(          this._interpolationDegree,          inputOrder        ),        timesLength      );      if (numberOfPoints !== this._numberOfPoints) {        this._numberOfPoints = numberOfPoints;        xTable.length = numberOfPoints;        yTable.length = numberOfPoints * packedInterpolationLength;      }    }    const degree = this._numberOfPoints - 1;    if (degree < 1) {      return undefined;    }    let firstIndex = 0;    let lastIndex = timesLength - 1;    const pointsInCollection = lastIndex - firstIndex + 1;    if (pointsInCollection >= degree + 1) {      let computedFirstIndex = index - ((degree / 2) | 0) - 1;      if (computedFirstIndex < firstIndex) {        computedFirstIndex = firstIndex;      }      let computedLastIndex = computedFirstIndex + degree;      if (computedLastIndex > lastIndex) {        computedLastIndex = lastIndex;        computedFirstIndex = computedLastIndex - degree;        if (computedFirstIndex < firstIndex) {          computedFirstIndex = firstIndex;        }      }      firstIndex = computedFirstIndex;      lastIndex = computedLastIndex;    }    const length = lastIndex - firstIndex + 1;    // Build the tables    for (let i = 0; i < length; ++i) {      xTable[i] = JulianDate.secondsDifference(        times[firstIndex + i],        times[lastIndex]      );    }    if (!defined(innerType.convertPackedArrayForInterpolation)) {      let destinationIndex = 0;      const packedLength = this._packedLength;      let sourceIndex = firstIndex * packedLength;      const stop = (lastIndex + 1) * packedLength;      while (sourceIndex < stop) {        yTable[destinationIndex] = values[sourceIndex];        sourceIndex++;        destinationIndex++;      }    } else {      innerType.convertPackedArrayForInterpolation(        values,        firstIndex,        lastIndex,        yTable      );    }    // Interpolate!    const x = JulianDate.secondsDifference(time, times[lastIndex]);    let interpolationResult;    if (inputOrder === 0 || !defined(interpolationAlgorithm.interpolate)) {      interpolationResult = interpolationAlgorithm.interpolateOrderZero(        x,        xTable,        yTable,        packedInterpolationLength,        this._interpolationResult      );    } else {      const yStride = Math.floor(packedInterpolationLength / (inputOrder + 1));      interpolationResult = interpolationAlgorithm.interpolate(        x,        xTable,        yTable,        yStride,        inputOrder,        inputOrder,        this._interpolationResult      );    }    if (!defined(innerType.unpackInterpolationResult)) {      return innerType.unpack(interpolationResult, 0, result);    }    return innerType.unpackInterpolationResult(      interpolationResult,      values,      firstIndex,      lastIndex,      result    );  }  return innerType.unpack(values, index * this._packedLength, result);};/** * Sets the algorithm and degree to use when interpolating a value. * * @param {Object} [options] Object with the following properties: * @param {InterpolationAlgorithm} [options.interpolationAlgorithm] The new interpolation algorithm.  If undefined, the existing property will be unchanged. * @param {Number} [options.interpolationDegree] The new interpolation degree.  If undefined, the existing property will be unchanged. */SampledProperty.prototype.setInterpolationOptions = function (options) {  if (!defined(options)) {    return;  }  let valuesChanged = false;  const interpolationAlgorithm = options.interpolationAlgorithm;  const interpolationDegree = options.interpolationDegree;  if (    defined(interpolationAlgorithm) &&    this._interpolationAlgorithm !== interpolationAlgorithm  ) {    this._interpolationAlgorithm = interpolationAlgorithm;    valuesChanged = true;  }  if (    defined(interpolationDegree) &&    this._interpolationDegree !== interpolationDegree  ) {    this._interpolationDegree = interpolationDegree;    valuesChanged = true;  }  if (valuesChanged) {    this._updateTableLength = true;    this._definitionChanged.raiseEvent(this);  }};/** * Adds a new sample. * * @param {JulianDate} time The sample time. * @param {Packable} value The value at the provided time. * @param {Packable[]} [derivatives] The array of derivatives at the provided time. */SampledProperty.prototype.addSample = function (time, value, derivatives) {  const innerDerivativeTypes = this._innerDerivativeTypes;  const hasDerivatives = defined(innerDerivativeTypes);  //>>includeStart('debug', pragmas.debug);  Check.defined("time", time);  Check.defined("value", value);  if (hasDerivatives) {    Check.defined("derivatives", derivatives);  }  //>>includeEnd('debug');  const innerType = this._innerType;  const data = [];  data.push(time);  innerType.pack(value, data, data.length);  if (hasDerivatives) {    const derivativesLength = innerDerivativeTypes.length;    for (let x = 0; x < derivativesLength; x++) {      innerDerivativeTypes[x].pack(derivatives[x], data, data.length);    }  }  mergeNewSamples(    undefined,    this._times,    this._values,    data,    this._packedLength  );  this._updateTableLength = true;  this._definitionChanged.raiseEvent(this);};/** * Adds an array of samples. * * @param {JulianDate[]} times An array of JulianDate instances where each index is a sample time. * @param {Packable[]} values The array of values, where each value corresponds to the provided times index. * @param {Array[]} [derivativeValues] An array where each item is the array of derivatives at the equivalent time index. * * @exception {DeveloperError} times and values must be the same length. * @exception {DeveloperError} times and derivativeValues must be the same length. */SampledProperty.prototype.addSamples = function (  times,  values,  derivativeValues) {  const innerDerivativeTypes = this._innerDerivativeTypes;  const hasDerivatives = defined(innerDerivativeTypes);  //>>includeStart('debug', pragmas.debug);  Check.defined("times", times);  Check.defined("values", values);  if (times.length !== values.length) {    throw new DeveloperError("times and values must be the same length.");  }  if (    hasDerivatives &&    (!defined(derivativeValues) || derivativeValues.length !== times.length)  ) {    throw new DeveloperError(      "times and derivativeValues must be the same length."    );  }  //>>includeEnd('debug');  const innerType = this._innerType;  const length = times.length;  const data = [];  for (let i = 0; i < length; i++) {    data.push(times[i]);    innerType.pack(values[i], data, data.length);    if (hasDerivatives) {      const derivatives = derivativeValues[i];      const derivativesLength = innerDerivativeTypes.length;      for (let x = 0; x < derivativesLength; x++) {        innerDerivativeTypes[x].pack(derivatives[x], data, data.length);      }    }  }  mergeNewSamples(    undefined,    this._times,    this._values,    data,    this._packedLength  );  this._updateTableLength = true;  this._definitionChanged.raiseEvent(this);};/** * Adds samples as a single packed array where each new sample is represented as a date, * followed by the packed representation of the corresponding value and derivatives. * * @param {Number[]} packedSamples The array of packed samples. * @param {JulianDate} [epoch] If any of the dates in packedSamples are numbers, they are considered an offset from this epoch, in seconds. */SampledProperty.prototype.addSamplesPackedArray = function (  packedSamples,  epoch) {  //>>includeStart('debug', pragmas.debug);  Check.defined("packedSamples", packedSamples);  //>>includeEnd('debug');  mergeNewSamples(    epoch,    this._times,    this._values,    packedSamples,    this._packedLength  );  this._updateTableLength = true;  this._definitionChanged.raiseEvent(this);};/** * Removes a sample at the given time, if present. * * @param {JulianDate} time The sample time. * @returns {Boolean} <code>true</code> if a sample at time was removed, <code>false</code> otherwise. */SampledProperty.prototype.removeSample = function (time) {  //>>includeStart('debug', pragmas.debug);  Check.defined("time", time);  //>>includeEnd('debug');  const index = binarySearch(this._times, time, JulianDate.compare);  if (index < 0) {    return false;  }  removeSamples(this, index, 1);  return true;};function removeSamples(property, startIndex, numberToRemove) {  const packedLength = property._packedLength;  property._times.splice(startIndex, numberToRemove);  property._values.splice(    startIndex * packedLength,    numberToRemove * packedLength  );  property._updateTableLength = true;  property._definitionChanged.raiseEvent(property);}/** * Removes all samples for the given time interval. * * @param {TimeInterval} time The time interval for which to remove all samples. */SampledProperty.prototype.removeSamples = function (timeInterval) {  //>>includeStart('debug', pragmas.debug);  Check.defined("timeInterval", timeInterval);  //>>includeEnd('debug');  const times = this._times;  let startIndex = binarySearch(times, timeInterval.start, JulianDate.compare);  if (startIndex < 0) {    startIndex = ~startIndex;  } else if (!timeInterval.isStartIncluded) {    ++startIndex;  }  let stopIndex = binarySearch(times, timeInterval.stop, JulianDate.compare);  if (stopIndex < 0) {    stopIndex = ~stopIndex;  } else if (timeInterval.isStopIncluded) {    ++stopIndex;  }  removeSamples(this, startIndex, stopIndex - startIndex);};/** * 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. */SampledProperty.prototype.equals = function (other) {  if (this === other) {    return true;  }  if (!defined(other)) {    return false;  }  if (    this._type !== other._type || //    this._interpolationDegree !== other._interpolationDegree || //    this._interpolationAlgorithm !== other._interpolationAlgorithm  ) {    return false;  }  const derivativeTypes = this._derivativeTypes;  const hasDerivatives = defined(derivativeTypes);  const otherDerivativeTypes = other._derivativeTypes;  const otherHasDerivatives = defined(otherDerivativeTypes);  if (hasDerivatives !== otherHasDerivatives) {    return false;  }  let i;  let length;  if (hasDerivatives) {    length = derivativeTypes.length;    if (length !== otherDerivativeTypes.length) {      return false;    }    for (i = 0; i < length; i++) {      if (derivativeTypes[i] !== otherDerivativeTypes[i]) {        return false;      }    }  }  const times = this._times;  const otherTimes = other._times;  length = times.length;  if (length !== otherTimes.length) {    return false;  }  for (i = 0; i < length; i++) {    if (!JulianDate.equals(times[i], otherTimes[i])) {      return false;    }  }  const values = this._values;  const otherValues = other._values;  length = values.length;  //Since time lengths are equal, values length and other length are guaranteed to be equal.  for (i = 0; i < length; i++) {    if (values[i] !== otherValues[i]) {      return false;    }  }  return true;};//Exposed for testing.SampledProperty._mergeNewSamples = mergeNewSamples;export default SampledProperty;
 |