All files / engine/Source/Core Iau2006XysData.js

95.57% Statements 108/113
90.47% Branches 38/42
100% Functions 6/6
95.37% Lines 103/108

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276                                                        17x   17x     17x 17x   17x         17x 17x 17x 17x 17x   17x     17x 17x   17x   17x 170x 170x   170x 1700x 1530x       170x       17x 17x     1x     13312x 13312x 13312x 13312x                                 1x           8x         8x     8x   8x 1x       8x   8x       8x 8x   8x 8x 7x     8x                                   1x         13296x 13296x   17x     13279x 13279x   6x     13273x   13273x 13273x 15x   13273x 13273x                   13273x 13273x 13273x 27x 27x     13273x 27x 27x     13273x 27x     13246x 4x   13242x 13242x 13242x     13246x   13246x 13246x 13246x 13246x     13246x 132460x     13246x 132460x   132460x 1324600x 1192140x       132460x   132460x 132460x 132460x 132460x     13246x       61x   41x       20x 20x 1x           19x         20x 20x   20x 20x 20x   20x 60000x     20x   20x      
import buildModuleUrl from "./buildModuleUrl.js";
import Frozen from "./Frozen.js";
import defined from "./defined.js";
import Iau2006XysSample from "./Iau2006XysSample.js";
import JulianDate from "./JulianDate.js";
import Resource from "./Resource.js";
import TimeStandard from "./TimeStandard.js";
 
/**
 * A set of IAU2006 XYS data that is used to evaluate the transformation between the International
 * Celestial Reference Frame (ICRF) and the International Terrestrial Reference Frame (ITRF).
 *
 * @alias Iau2006XysData
 * @constructor
 *
 * @param {object} [options] Object with the following properties:
 * @param {Resource|string} [options.xysFileUrlTemplate='Assets/IAU2006_XYS/IAU2006_XYS_{0}.json'] A template URL for obtaining the XYS data.  In the template,
 *                 `{0}` will be replaced with the file index.
 * @param {number} [options.interpolationOrder=9] The order of interpolation to perform on the XYS data.
 * @param {number} [options.sampleZeroJulianEphemerisDate=2442396.5] The Julian ephemeris date (JED) of the
 *                 first XYS sample.
 * @param {number} [options.stepSizeDays=1.0] The step size, in days, between successive XYS samples.
 * @param {number} [options.samplesPerXysFile=1000] The number of samples in each XYS file.
 * @param {number} [options.totalSamples=27426] The total number of samples in all XYS files.
 *
 * @private
 */
function Iau2006XysData(options) {
  options = options ?? Frozen.EMPTY_OBJECT;
 
  this._xysFileUrlTemplate = Resource.createIfNeeded(
    options.xysFileUrlTemplate,
  );
  this._interpolationOrder = options.interpolationOrder ?? 9;
  this._sampleZeroJulianEphemerisDate =
    options.sampleZeroJulianEphemerisDate ?? 2442396.5;
  this._sampleZeroDateTT = new JulianDate(
    this._sampleZeroJulianEphemerisDate,
    0.0,
    TimeStandard.TAI,
  );
  this._stepSizeDays = options.stepSizeDays ?? 1.0;
  this._samplesPerXysFile = options.samplesPerXysFile ?? 1000;
  this._totalSamples = options.totalSamples ?? 27426;
  this._samples = new Array(this._totalSamples * 3);
  this._chunkDownloadsInProgress = [];
 
  const order = this._interpolationOrder;
 
  // Compute denominators and X values for interpolation.
  const denom = (this._denominators = new Array(order + 1));
  const xTable = (this._xTable = new Array(order + 1));
 
  const stepN = Math.pow(this._stepSizeDays, order);
 
  for (let i = 0; i <= order; ++i) {
    denom[i] = stepN;
    xTable[i] = i * this._stepSizeDays;
 
    for (let j = 0; j <= order; ++j) {
      if (j !== i) {
        denom[i] *= i - j;
      }
    }
 
    denom[i] = 1.0 / denom[i];
  }
 
  // Allocate scratch arrays for interpolation.
  this._work = new Array(order + 1);
  this._coef = new Array(order + 1);
}
 
const julianDateScratch = new JulianDate(0, 0.0, TimeStandard.TAI);
 
function getDaysSinceEpoch(xys, dayTT, secondTT) {
  const dateTT = julianDateScratch;
  dateTT.dayNumber = dayTT;
  dateTT.secondsOfDay = secondTT;
  return JulianDate.daysDifference(dateTT, xys._sampleZeroDateTT);
}
 
/**
 * Preloads XYS data for a specified date range.
 *
 * @param {number} startDayTT The Julian day number of the beginning of the interval to preload, expressed in
 *                 the Terrestrial Time (TT) time standard.
 * @param {number} startSecondTT The seconds past noon of the beginning of the interval to preload, expressed in
 *                 the Terrestrial Time (TT) time standard.
 * @param {number} stopDayTT The Julian day number of the end of the interval to preload, expressed in
 *                 the Terrestrial Time (TT) time standard.
 * @param {number} stopSecondTT The seconds past noon of the end of the interval to preload, expressed in
 *                 the Terrestrial Time (TT) time standard.
 * @returns {Promise<void>} A promise that, when resolved, indicates that the requested interval has been
 *                    preloaded.
 */
Iau2006XysData.prototype.preload = function (
  startDayTT,
  startSecondTT,
  stopDayTT,
  stopSecondTT,
) {
  const startDaysSinceEpoch = getDaysSinceEpoch(
    this,
    startDayTT,
    startSecondTT,
  );
  const stopDaysSinceEpoch = getDaysSinceEpoch(this, stopDayTT, stopSecondTT);
 
  let startIndex =
    (startDaysSinceEpoch / this._stepSizeDays - this._interpolationOrder / 2) |
    0;
  if (startIndex < 0) {
    startIndex = 0;
  }
 
  let stopIndex =
    (stopDaysSinceEpoch / this._stepSizeDays - this._interpolationOrder / 2) |
    (0 + this._interpolationOrder);
  Iif (stopIndex >= this._totalSamples) {
    stopIndex = this._totalSamples - 1;
  }
 
  const startChunk = (startIndex / this._samplesPerXysFile) | 0;
  const stopChunk = (stopIndex / this._samplesPerXysFile) | 0;
 
  const promises = [];
  for (let i = startChunk; i <= stopChunk; ++i) {
    promises.push(requestXysChunk(this, i));
  }
 
  return Promise.all(promises);
};
 
/**
 * Computes the XYS values for a given date by interpolating.  If the required data is not yet downloaded,
 * this method will return undefined.
 *
 * @param {number} dayTT The Julian day number for which to compute the XYS value, expressed in
 *                 the Terrestrial Time (TT) time standard.
 * @param {number} secondTT The seconds past noon of the date for which to compute the XYS value, expressed in
 *                 the Terrestrial Time (TT) time standard.
 * @param {Iau2006XysSample} [result] The instance to which to copy the interpolated result.  If this parameter
 *                           is undefined, a new instance is allocated and returned.
 * @returns {Iau2006XysSample} The interpolated XYS values, or undefined if the required data for this
 *                             computation has not yet been downloaded.
 *
 * @see Iau2006XysData#preload
 */
Iau2006XysData.prototype.computeXysRadians = function (
  dayTT,
  secondTT,
  result,
) {
  const daysSinceEpoch = getDaysSinceEpoch(this, dayTT, secondTT);
  if (daysSinceEpoch < 0.0) {
    // Can't evaluate prior to the epoch of the data.
    return undefined;
  }
 
  const centerIndex = (daysSinceEpoch / this._stepSizeDays) | 0;
  if (centerIndex >= this._totalSamples) {
    // Can't evaluate after the last sample in the data.
    return undefined;
  }
 
  const degree = this._interpolationOrder;
 
  let firstIndex = centerIndex - ((degree / 2) | 0);
  if (firstIndex < 0) {
    firstIndex = 0;
  }
  let lastIndex = firstIndex + degree;
  Iif (lastIndex >= this._totalSamples) {
    lastIndex = this._totalSamples - 1;
    firstIndex = lastIndex - degree;
    if (firstIndex < 0) {
      firstIndex = 0;
    }
  }
 
  // Are all the samples we need present?
  // We can assume so if the first and last are present
  let isDataMissing = false;
  const samples = this._samples;
  if (!defined(samples[firstIndex * 3])) {
    requestXysChunk(this, (firstIndex / this._samplesPerXysFile) | 0);
    isDataMissing = true;
  }
 
  if (!defined(samples[lastIndex * 3])) {
    requestXysChunk(this, (lastIndex / this._samplesPerXysFile) | 0);
    isDataMissing = true;
  }
 
  if (isDataMissing) {
    return undefined;
  }
 
  if (!defined(result)) {
    result = new Iau2006XysSample(0.0, 0.0, 0.0);
  } else {
    result.x = 0.0;
    result.y = 0.0;
    result.s = 0.0;
  }
 
  const x = daysSinceEpoch - firstIndex * this._stepSizeDays;
 
  const work = this._work;
  const denom = this._denominators;
  const coef = this._coef;
  const xTable = this._xTable;
 
  let i, j;
  for (i = 0; i <= degree; ++i) {
    work[i] = x - xTable[i];
  }
 
  for (i = 0; i <= degree; ++i) {
    coef[i] = 1.0;
 
    for (j = 0; j <= degree; ++j) {
      if (j !== i) {
        coef[i] *= work[j];
      }
    }
 
    coef[i] *= denom[i];
 
    let sampleIndex = (firstIndex + i) * 3;
    result.x += coef[i] * samples[sampleIndex++];
    result.y += coef[i] * samples[sampleIndex++];
    result.s += coef[i] * samples[sampleIndex];
  }
 
  return result;
};
 
function requestXysChunk(xysData, chunkIndex) {
  if (xysData._chunkDownloadsInProgress[chunkIndex]) {
    // Chunk has already been requested.
    return xysData._chunkDownloadsInProgress[chunkIndex];
  }
 
  let chunkUrl;
  const xysFileUrlTemplate = xysData._xysFileUrlTemplate;
  if (defined(xysFileUrlTemplate)) {
    chunkUrl = xysFileUrlTemplate.getDerivedResource({
      templateValues: {
        0: chunkIndex,
      },
    });
  } else {
    chunkUrl = new Resource({
      url: buildModuleUrl(`Assets/IAU2006_XYS/IAU2006_XYS_${chunkIndex}.json`),
    });
  }
 
  const promise = chunkUrl.fetchJson().then(function (chunk) {
    xysData._chunkDownloadsInProgress[chunkIndex] = false;
 
    const samples = xysData._samples;
    const newSamples = chunk.samples;
    const startIndex = chunkIndex * xysData._samplesPerXysFile * 3;
 
    for (let i = 0, len = newSamples.length; i < len; ++i) {
      samples[startIndex + i] = newSamples[i];
    }
  });
  xysData._chunkDownloadsInProgress[chunkIndex] = promise;
 
  return promise;
}
export default Iau2006XysData;