Iau2006XysData.js 10 KB

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