PCL
EphemerisFile.h
Go to the documentation of this file.
1 // ____ ______ __
2 // / __ \ / ____// /
3 // / /_/ // / / /
4 // / ____// /___ / /___ PixInsight Class Library
5 // /_/ \____//_____/ PCL 2.7.0
6 // ----------------------------------------------------------------------------
7 // pcl/EphemerisFile.h - Released 2024-06-18T15:48:54Z
8 // ----------------------------------------------------------------------------
9 // This file is part of the PixInsight Class Library (PCL).
10 // PCL is a multiplatform C++ framework for development of PixInsight modules.
11 //
12 // Copyright (c) 2003-2024 Pleiades Astrophoto S.L. All Rights Reserved.
13 //
14 // Redistribution and use in both source and binary forms, with or without
15 // modification, is permitted provided that the following conditions are met:
16 //
17 // 1. All redistributions of source code must retain the above copyright
18 // notice, this list of conditions and the following disclaimer.
19 //
20 // 2. All redistributions in binary form must reproduce the above copyright
21 // notice, this list of conditions and the following disclaimer in the
22 // documentation and/or other materials provided with the distribution.
23 //
24 // 3. Neither the names "PixInsight" and "Pleiades Astrophoto", nor the names
25 // of their contributors, may be used to endorse or promote products derived
26 // from this software without specific prior written permission. For written
27 // permission, please contact info@pixinsight.com.
28 //
29 // 4. All products derived from this software, in any form whatsoever, must
30 // reproduce the following acknowledgment in the end-user documentation
31 // and/or other materials provided with the product:
32 //
33 // "This product is based on software from the PixInsight project, developed
34 // by Pleiades Astrophoto and its contributors (https://pixinsight.com/)."
35 //
36 // Alternatively, if that is where third-party acknowledgments normally
37 // appear, this acknowledgment must be reproduced in the product itself.
38 //
39 // THIS SOFTWARE IS PROVIDED BY PLEIADES ASTROPHOTO AND ITS CONTRIBUTORS
40 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
41 // TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
42 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL PLEIADES ASTROPHOTO OR ITS
43 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
44 // EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, BUSINESS
45 // INTERRUPTION; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; AND LOSS OF USE,
46 // DATA OR PROFITS) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
47 // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
48 // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
49 // POSSIBILITY OF SUCH DAMAGE.
50 // ----------------------------------------------------------------------------
51 
52 #ifndef __PCL_EphemerisFile_h
53 #define __PCL_EphemerisFile_h
54 
56 
57 #include <pcl/Defs.h>
58 
59 #include <pcl/Atomic.h>
60 #include <pcl/AutoLock.h>
61 #include <pcl/AutoPointer.h>
62 #include <pcl/ChebyshevFit.h>
63 #include <pcl/File.h>
64 #include <pcl/Mutex.h>
65 #include <pcl/Optional.h>
66 #include <pcl/Thread.h>
67 #include <pcl/TimePoint.h>
68 
69 #ifdef __PCL_BUILDING_PIXINSIGHT_APPLICATION
70 namespace pi
71 {
72  class JSEphemerisFileObject;
73  class JSEphemerisHandleObject;
74 }
75 #endif
76 
77 namespace pcl
78 {
79 
80 // ----------------------------------------------------------------------------
81 
82 class PCL_CLASS XMLElement;
83 
84 // ----------------------------------------------------------------------------
85 
103 struct PCL_CLASS EphemerisMetadata
104 {
114 };
115 
116 // ----------------------------------------------------------------------------
117 
133 struct PCL_CLASS EphemerisConstant
134 {
136  double value;
137 
141  EphemerisConstant( const IsoString& n = IsoString(), double v = 0 )
142  : name( n )
143  , value( v )
144  {
145  }
146 
151 
156 
160  EphemerisConstant& operator =( const EphemerisConstant& ) = default;
161 
165  EphemerisConstant& operator =( EphemerisConstant&& ) = default;
166 
171  bool operator ==( const EphemerisConstant& x ) const
172  {
173  return name.CompareIC( x.name ) == 0;
174  }
175 
181  bool operator <( const EphemerisConstant& x ) const
182  {
183  return name.CompareIC( x.name ) < 0;
184  }
185 };
186 
198 using EphemerisConstantList = Array<EphemerisConstant>;
199 
200 // ----------------------------------------------------------------------------
201 
223 {
229 
238 
243  : startTime( t )
244  , expansion( T )
245  {
246  }
247 
252 
257 
261  SerializableEphemerisData& operator =( const SerializableEphemerisData& ) = default;
262 
267 };
268 
287 
288 // ----------------------------------------------------------------------------
289 
317 {
329 
345 
355 
361 
371 
386 
391 
410 
416 
423 
429 
435 
440 
445 
450 
455 
460 
465 
470 
475 
480  const IsoString& origin,
481  const String& name = String(),
482  const String& desc = String() )
483  : objectId( id.Trimmed() )
484  , originId( origin.Trimmed() )
485  , objectName( name.Trimmed() )
486  , description( desc )
487  {
488  }
489 
494 
499 
504 
509 
514 };
515 
522 
523 // ----------------------------------------------------------------------------
524 
539 struct PCL_CLASS EphemerisObject
540 {
553 
567 
575 
580 
595 
600 
619 
625 
632 
638 
644 
649 
654 
659 
664 
669 
674 
679 
684 
688  EphemerisObject( const IsoString& a_objectId,
689  const IsoString& a_originId,
690  const String& a_objectName = String(),
691  const String& a_objectDescription = String(),
707  : objectId( a_objectId )
708  , originId( a_originId )
709  , objectName( a_objectName )
710  , objectDescription( a_objectDescription )
711  , H( a_H )
712  , G( a_G )
713  , M1( a_M1 )
714  , K1( a_K1 )
715  , M2( a_M2 )
716  , K2( a_K2 )
717  , PC( a_PC )
718  , B_V( a_B_V )
719  , U_B( a_U_B )
720  , I_R( a_I_R )
721  , D( a_D )
722  , A1( a_A1 )
723  , A2( a_A2 )
724  , A3( a_A3 )
725  , DT( a_DT )
726  {
727  }
728 
732  EphemerisObject( const EphemerisObject& ) = default;
733 
738 
742  EphemerisObject& operator =( const EphemerisObject& ) = default;
743 
747  EphemerisObject& operator =( EphemerisObject&& ) = default;
748 };
749 
756 
757 // ----------------------------------------------------------------------------
758 
798 class PCL_CLASS EphemerisFile
799 {
800 public:
801 
808  EphemerisFile() = default;
809 
817  EphemerisFile( const String& filePath )
818  {
819  Open( filePath );
820  }
821 
826  : m_file( std::move( x.m_file ) )
827  , m_startTime( x.m_startTime )
828  , m_endTime( x.m_endTime )
829  , m_constants( std::move( x.m_constants ) )
830  , m_index( std::move( x.m_index ) )
831  {
832  }
833 
837  EphemerisFile& operator =( EphemerisFile&& x )
838  {
839  m_file = std::move( x.m_file );
840  m_startTime = x.m_startTime;
841  m_endTime = x.m_endTime;
842  m_constants = std::move( x.m_constants );
843  m_index = std::move( x.m_index );
844  return *this;
845  }
846 
851  EphemerisFile( const EphemerisFile& ) = delete;
852 
857  EphemerisFile& operator =( const EphemerisFile& ) = delete;
858 
862  virtual ~EphemerisFile() noexcept( false );
863 
881  void Open( const String& filePath );
882 
896  void Close();
897 
902  bool IsOpen() const
903  {
904  return m_file.IsOpen();
905  }
906 
911  const String& FilePath() const
912  {
913  return m_file.FilePath();
914  }
915 
922  {
923  return m_startTime;
924  }
925 
931  {
932  return m_endTime;
933  }
934 
948  {
949  return m_constants;
950  }
951 
956  bool IsConstantAvailable( const IsoString& name ) const
957  {
958  return BinarySearch( m_constants.Begin(), m_constants.End(),
959  EphemerisConstant( name ) ) != m_constants.End();
960  }
961 
969  double ConstantValue( const IsoString& name ) const
970  {
972  BinarySearch( m_constants.Begin(), m_constants.End(), EphemerisConstant( name ) );
973  if ( i == m_constants.End() )
974  throw Error( "Undefined ephemeris constant '" + name + '\'' );
975  return i->value;
976  }
977 
986  {
987  EphemerisObjectList objects;
988  for ( const Index& ix : m_index )
989  objects << EphemerisObject( ix.objectId, ix.originId,
990  ix.objectName, ix.objectDescription,
991  ix.H, ix.G, ix.M1, ix.K1, ix.M2, ix.K2, ix.PC, ix.B_V, ix.U_B, ix.I_R, ix.D,
992  ix.A1, ix.A2, ix.A3, ix.DT );
993  return objects;
994  }
995 
1001  {
1002  IsoStringList ids;
1003  for ( const Index& ix : m_index )
1004  ids << ix.objectId;
1005  return ids;
1006  }
1007 
1013  {
1014  StringList names;
1015  for ( const Index& ix : m_index )
1016  names << ix.objectName;
1017  return names;
1018  }
1019 
1043  bool IsObjectAvailable( const IsoString& object, const IsoString& origin = IsoString() ) const
1044  {
1045  Array<Index>::const_iterator i = BinarySearch( m_index.Begin(), m_index.End(), Index( object, origin ) );
1046  if ( i != m_index.End() )
1047  return true;
1048  String name = object.UTF8ToUTF16();
1049  for ( const Index& index : m_index )
1050  if ( index.objectName.CompareIC( name ) == 0 )
1051  if ( origin.IsEmpty() || index.originId == origin )
1052  return true;
1053  return false;
1054  }
1055 
1069  String ObjectName( const IsoString& object, const IsoString& origin = IsoString() ) const
1070  {
1071  Array<Index>::const_iterator i = BinarySearch( m_index.Begin(), m_index.End(), Index( object, origin ) );
1072  if ( i != m_index.End() )
1073  return i->objectName;
1074  return String();
1075  }
1076 
1082  {
1083  return m_metadata;
1084  }
1085 
1098  int NumberOfHandles() const
1099  {
1100  return m_handleCount.Load();
1101  }
1102 
1151  static void Serialize( const String& filePath,
1152  TimePoint startTime, TimePoint endTime,
1154  const EphemerisMetadata& metadata = EphemerisMetadata(),
1155  const EphemerisConstantList& constants = EphemerisConstantList() );
1156 
1207 
1230 
1269 
1292 
1348 
1370 
1391  static const EphemerisFile& NutationModel();
1392 
1420 
1461 
1485 
1505 
1522  static void OverrideFundamentalEphemerides( const String& filePath );
1523 
1541  static void OverrideShortTermFundamentalEphemerides( const String& filePath );
1542 
1559  static void OverrideAsteroidEphemerides( const String& filePath );
1560 
1577  static void OverrideShortTermAsteroidEphemerides( const String& filePath );
1578 
1595  static void OverrideKBOEphemerides( const String& filePath );
1596 
1614  static void OverrideShortTermKBOEphemerides( const String& filePath );
1615 
1632  static void OverrideNutationModel( const String& filePath );
1633 
1651  static void OverrideShortTermNutationModel( const String& filePath );
1652 
1672  static void OverrideDeltaTDataFilePath( const String& filePath );
1673 
1693  static void OverrideDeltaATDataFilePath( const String& filePath );
1694 
1715  static void OverrideCIP_ITRSDataFilePath( const String& filePath );
1716 
1717 private:
1718 
1723  struct IndexNode
1724  {
1725  int32 jdi = 0; // Starting point of time span covered by this expansion, int( JD ).
1726  float jdf = 0; // Ditto, frac( JD ).
1727  uint8 n[ 4 ] = {}; // For each component: number of Chebyshev coefficients in this expansion.
1728  int64 position = 0; // File byte position of first Chebyshev coefficient.
1729 
1730  constexpr bool operator ==( const IndexNode& n ) const
1731  {
1732  return jdi == n.jdi && jdf == n.jdf;
1733  }
1734 
1735  constexpr bool operator <( const IndexNode& n ) const
1736  {
1737  return jdi < n.jdi || jdi == n.jdi && jdf < n.jdf;
1738  }
1739 
1740  constexpr int NumberOfComponents() const
1741  {
1742  return (n[0] > 0) ? ((n[1] > 0) ? ((n[2] > 0) ? ((n[3] > 0) ? 4 : 3) : 2) : 1) : 0;
1743  }
1744 
1745  constexpr int NumberOfCoefficients() const
1746  {
1747  return n[0] + n[1] + n[2] + n[3];
1748  }
1749 
1750  TimePoint StartTime() const
1751  {
1752  return TimePoint( jdi, jdf );
1753  }
1754  };
1755 
1760  struct Index
1761  {
1762  IsoString objectId; // Object identifier (mandatory, case-sensitive).
1763  IsoString originId; // Identifier of the origin of coordinates (mandatory, case-sensitive).
1764  String objectName; // Object name (optional, case-insensitive).
1765  String objectDescription; // Object description (optional, arbitrary)
1766  Optional<double> H; // Asteroid absolute magnitude.
1767  Optional<double> G; // Asteroid magnitude slope parameter.
1768  Optional<double> M1; // Comet total absolute magnitude.
1769  Optional<double> K1; // Comet total magnitude slope parameter.
1770  Optional<double> M2; // Comet nuclear absolute magnitude.
1771  Optional<double> K2; // Comet nuclear magnitude slope parameter.
1772  Optional<double> PC; // Comet nuclear magnitude phase coefficient parameter.
1773  Optional<double> B_V; // Color index B-V in magnitudes.
1774  Optional<double> U_B; // Color index U-B in magnitudes.
1775  Optional<double> I_R; // Color index I-R in magnitudes.
1776  Optional<double> D; // Diameter of the object in km.
1777  Optional<double> A1; // Comet non-gravitational acceleration, radial component (au/day^2).
1778  Optional<double> A2; // Comet non-gravitational acceleration, transverse component (au/day^2).
1779  Optional<double> A3; // Comet non-gravitational acceleration, normal component (au/day^2).
1780  Optional<double> DT; // Comet non-gravitational acceleration, perihelion time offset (days).
1781  Array<IndexNode> nodes[ 2 ]; // Expansion indexes: 0=function 1=derivative.
1782 
1783  Index( const IsoString& objectId_,
1784  const IsoString& originId_ = IsoString(),
1785  const String& objectName_ = String(),
1786  const String& objectDescription_ = String() )
1787  : objectId( objectId_.Trimmed() )
1788  , originId( originId_.Trimmed() )
1789  , objectName( objectName_.Trimmed() )
1790  , objectDescription( objectDescription_.Trimmed() )
1791  {
1792  }
1793 
1794  bool operator ==( const Index& x ) const
1795  {
1796  return objectId == x.objectId && originId == x.originId;
1797  }
1798 
1799  bool operator <( const Index& x ) const
1800  {
1801  return (objectId != x.objectId) ? objectId < x.objectId : originId < x.originId;
1802  }
1803 
1804  bool HasDerivative() const
1805  {
1806  return !nodes[1].IsEmpty();
1807  }
1808  };
1809 
1810  mutable File m_file;
1811  mutable AtomicInt m_handleCount;
1812  mutable Mutex m_mutex;
1813  TimePoint m_startTime;
1814  TimePoint m_endTime;
1815  EphemerisMetadata m_metadata;
1816  EphemerisConstantList m_constants;
1817  Array<Index> m_index;
1818 
1819  // Current data files.
1820  // If empty, i.e. if not overridden, use platform defaults.
1821  static String s_ephFilePath;
1822  static String s_ephFilePath_s;
1823  static String s_astFilePath;
1824  static String s_astFilePath_s;
1825  static String s_kboFilePath;
1826  static String s_kboFilePath_s;
1827  static String s_nutFilePath;
1828  static String s_nutFilePath_s;
1829  static String s_deltaTFilePath;
1830  static String s_deltaATFilePath;
1831  static String s_cipITRSFilePath;
1832 
1838  const Index* FindObject( const IsoString& object, const IsoString& origin ) const
1839  {
1840  if ( origin.IsEmpty() )
1841  {
1842  for ( const Index& index : m_index )
1843  if ( index.objectId == object )
1844  return &index;
1845  }
1846  else
1847  {
1848  Array<Index>::const_iterator i = BinarySearch( m_index.Begin(), m_index.End(), Index( object, origin ) );
1849  if ( i != m_index.End() )
1850  return i;
1851  }
1852  String name = object.UTF8ToUTF16();
1853  for ( const Index& index : m_index )
1854  if ( index.objectName.CompareIC( name ) == 0 )
1855  if ( origin.IsEmpty() || index.originId == origin )
1856  return &index;
1857  throw Error( "Unavailable object '" + name + "\' with origin '" + String( origin ) + "'." );
1858  }
1859 
1860 public:
1861 
1888  class PCL_CLASS Handle
1889  {
1890  public:
1891 
1896  Handle() = default;
1897 
1924  Handle( const EphemerisFile& parent, const IsoString& object, const IsoString& origin = IsoString() )
1925  {
1926  if ( !parent.IsOpen() )
1927  throw Error( "Cannot create a handle to a closed ephemeris file." );
1928  m_parent = &parent;
1929  m_parent->m_handleCount.Increment();
1930  m_index = m_parent->FindObject( object, origin );
1931  }
1932 
1936  Handle( const Handle& x )
1937  {
1938  if ( m_parent != nullptr )
1939  m_parent->m_handleCount.Decrement();
1940  m_parent = x.m_parent;
1941  m_index = x.m_index;
1942  m_node[0] = x.m_node[0];
1943  m_node[1] = x.m_node[1];
1944  m_node[2] = x.m_node[2];
1945  if ( m_parent != nullptr )
1946  m_parent->m_handleCount.Increment();
1947  }
1948 
1953  {
1954  m_parent = x.m_parent;
1955  x.m_parent = nullptr;
1956  m_index = x.m_index;
1957  m_node[0] = x.m_node[0];
1958  m_node[1] = x.m_node[1];
1959  m_node[2] = x.m_node[2];
1960  }
1961 
1965  virtual ~Handle()
1966  {
1967  if ( m_parent != nullptr )
1968  m_parent->m_handleCount.Decrement();
1969  }
1970 
1974  Handle& operator =( const Handle& x )
1975  {
1976  if ( m_parent != nullptr )
1977  m_parent->m_handleCount.Decrement();
1978  m_parent = x.m_parent;
1979  m_index = x.m_index;
1980  m_node[0] = x.m_node[0];
1981  m_node[1] = x.m_node[1];
1982  m_node[2] = x.m_node[2];
1983  if ( m_parent != nullptr )
1984  m_parent->m_handleCount.Increment();
1985  return *this;
1986  }
1987 
1991  Handle& operator =( Handle&& x )
1992  {
1993  if ( m_parent != nullptr )
1994  m_parent->m_handleCount.Decrement();
1995  m_parent = x.m_parent;
1996  x.m_parent = nullptr;
1997  m_index = x.m_index;
1998  m_node[0] = x.m_node[0];
1999  m_node[1] = x.m_node[1];
2000  m_node[2] = x.m_node[2];
2001  return *this;
2002  }
2003 
2028  {
2029  Update( t, 0 );
2030  p = m_node[0].expansion( t - m_node[0].startTime );
2031  }
2032 
2069  {
2070  ComputeState( p, t );
2071  ComputeFirstDerivative( v, t );
2072  }
2073 
2105  {
2106  if ( HasDerivative() )
2107  Update( t, 1 );
2108  else if ( m_node[1].current != m_node[0].current )
2109  {
2110  m_node[1].current = m_node[0].current;
2111  m_node[1].startTime = m_node[0].startTime;
2112  m_node[1].endTime = m_node[0].endTime;
2113  m_node[1].expansion = m_node[0].expansion.Derivative();
2114  }
2115  v = m_node[1].expansion( t - m_node[1].startTime );
2116  }
2117 
2149  {
2150  if ( HasDerivative() )
2151  Update( t, 1 );
2152  else if ( m_node[1].current != m_node[0].current )
2153  {
2154  m_node[1].current = m_node[0].current;
2155  m_node[1].startTime = m_node[0].startTime;
2156  m_node[1].endTime = m_node[0].endTime;
2157  m_node[1].expansion = m_node[0].expansion.Derivative();
2158  }
2159  if ( m_node[2].current != m_node[0].current )
2160  {
2161  m_node[2].current = m_node[0].current;
2162  m_node[2].startTime = m_node[0].startTime;
2163  m_node[2].endTime = m_node[0].endTime;
2164  m_node[2].expansion = m_node[1].expansion.Derivative();
2165  }
2166  a = m_node[2].expansion( t - m_node[2].startTime );
2167  }
2168 
2181  {
2182  Vector p;
2183  ComputeState( p, t );
2184  return p;
2185  }
2186 
2202  {
2203  Vector p, v;
2204  ComputeState( p, v, t );
2205  return MultiVector( p, v );
2206  }
2207 
2222  {
2223  Vector v;
2224  ComputeFirstDerivative( v, t );
2225  return v;
2226  }
2227 
2242  {
2243  Vector v;
2244  ComputeSecondDerivative( v, t );
2245  return v;
2246  }
2247 
2252  const EphemerisFile& ParentFile() const
2253  {
2254  return *m_parent;
2255  }
2256 
2261  const IsoString& ObjectId() const
2262  {
2263  return m_index->objectId;
2264  }
2265 
2274  const IsoString& OriginId() const
2275  {
2276  return m_index->originId;
2277  }
2278 
2285  const String& ObjectName() const
2286  {
2287  return m_index->objectName;
2288  }
2289 
2300  TimePoint StartTime( int i = 0 ) const
2301  {
2302  return m_node[Range( i, 0, 1 )].startTime;
2303  }
2304 
2315  TimePoint EndTime( int i = 0 ) const
2316  {
2317  return m_node[Range( i, 0, 1 )].endTime;
2318  }
2319 
2329  bool HasDerivative() const
2330  {
2331  return m_index->HasDerivative();
2332  }
2333 
2348  const Optional<double>& H() const
2349  {
2350  return m_index->H;
2351  }
2352 
2357  const Optional<double>& G() const
2358  {
2359  return m_index->G;
2360  }
2361 
2380  const Optional<double>& M1() const
2381  {
2382  return m_index->M1;
2383  }
2384 
2389  const Optional<double>& K1() const
2390  {
2391  return m_index->K1;
2392  }
2393 
2399  const Optional<double>& M2() const
2400  {
2401  return m_index->M2;
2402  }
2403 
2408  const Optional<double>& K2() const
2409  {
2410  return m_index->K2;
2411  }
2412 
2417  const Optional<double>& PC() const
2418  {
2419  return m_index->PC;
2420  }
2421 
2425  const Optional<double>& B_V() const
2426  {
2427  return m_index->B_V;
2428  }
2429 
2433  const Optional<double>& U_B() const
2434  {
2435  return m_index->U_B;
2436  }
2437 
2441  const Optional<double>& I_R() const
2442  {
2443  return m_index->I_R;
2444  }
2445 
2450  const Optional<double>& D() const
2451  {
2452  return m_index->D;
2453  }
2454 
2459  const Optional<double>& A1() const
2460  {
2461  return m_index->A1;
2462  }
2463 
2468  const Optional<double>& A2() const
2469  {
2470  return m_index->A2;
2471  }
2472 
2477  const Optional<double>& A3() const
2478  {
2479  return m_index->A3;
2480  }
2481 
2486  const Optional<double>& DT() const
2487  {
2488  return m_index->DT;
2489  }
2490 
2491  private:
2492 
2493  struct NodeInfo
2494  {
2495  int current = -1;
2496  TimePoint startTime;
2497  TimePoint endTime;
2498  ChebyshevFit expansion;
2499  };
2500 
2501  const EphemerisFile* m_parent = nullptr;
2502  const EphemerisFile::Index* m_index = nullptr;
2503  NodeInfo m_node[ 3 ];
2504  uint64 m_uniqueId = UniqueId();
2505 
2506  static uint64 UniqueId();
2507 
2514  void Update( TimePoint t, int index )
2515  {
2516  if ( !t.IsValid() )
2517  throw Error( "Invalid time point." );
2518  if ( t < m_parent->StartTime() || t > m_parent->EndTime() )
2519  throw Error( "Time point out of range: " + t.ToString() );
2520 
2521  const Array<IndexNode>& nodes = m_index->nodes[index];
2522  NodeInfo& info = m_node[index];
2523 
2524  for ( int N = int( nodes.Length() ), l = 0, r = N-1; ; )
2525  {
2526  int m = (l + r) >> 1;
2527  const IndexNode& node = nodes[m];
2528  TimePoint t0 = node.StartTime();
2529  if ( t < t0 )
2530  r = m;
2531  else
2532  {
2533  if ( m == N-1 || t < nodes[m+1].StartTime() )
2534  {
2535  if ( m != info.current )
2536  {
2537  ChebyshevFit::coefficient_series coefficients;
2538  {
2539  volatile AutoLock lock( m_parent->m_mutex );
2540  m_parent->m_file.SetPosition( node.position );
2541  for ( int i = 0, n = node.NumberOfComponents(); i < n; ++i )
2542  {
2543  Vector c( node.n[i] );
2544  m_parent->m_file.Read( reinterpret_cast<void*>( c.Begin() ), c.Size() );
2545  coefficients << c;
2546  }
2547  }
2548  info.current = m;
2549  info.startTime = t0;
2550  info.endTime = (m < N-1) ? nodes[m+1].StartTime() : m_parent->EndTime();
2551  info.expansion = ChebyshevFit( coefficients, 0, info.endTime - info.startTime );
2552  }
2553  break;
2554  }
2555 
2556  l = m + 1;
2557  }
2558  }
2559  }
2560 
2561  friend class PCL_CLASS Position;
2562  };
2563 
2564 private:
2565 
2566 #if defined( __clang__ )
2567 # pragma GCC diagnostic ignored "-Wunused-private-field"
2568 #endif
2569 
2570  /*
2571  * For the core JavaScript engine we need garbage-collector-safe
2572  * asynchronous destruction of these objects.
2573  */
2574  mutable bool m_finalized = false;
2575 
2576  /*
2577  * In the core JavaScript engine we must identify static objects that can be
2578  * shared and must never be destroyed. This includes fundamental
2579  * ephemerides, nutation, etc.
2580  */
2581  mutable bool m_internal = false;
2582 
2583 #if defined( __clang__ )
2584 # pragma GCC diagnostic warning "-Wunused-private-field"
2585 #endif
2586 
2587  class DeserializeObjectThread : public Thread
2588  {
2589  public:
2590 
2591  DeserializeObjectThread( const Array<const XMLElement*>& elements
2592  , File& file, fsize_type fileSize, fsize_type minPos
2593  , int startIndex, int endIndex )
2594  : m_elements( elements )
2595  , m_startIndex( startIndex )
2596  , m_endIndex( endIndex )
2597  , m_file( file )
2598  , m_fileSize( fileSize )
2599  , m_minPos( minPos )
2600  {
2601  }
2602 
2603  void Run() override;
2604 
2605  const Array<Index>& Objects() const
2606  {
2607  return m_index;
2608  }
2609 
2610  bool Succeeded() const
2611  {
2612  return m_success;
2613  }
2614 
2615  const Exception* ExceptionThrown() const
2616  {
2617  return m_exception.Ptr();
2618  }
2619 
2620  private:
2621 
2622  const Array<const XMLElement*>& m_elements;
2623  int m_startIndex, m_endIndex;
2624  File& m_file;
2625  fsize_type m_fileSize, m_minPos;
2626  Array<Index> m_index;
2627  AutoPointer<Exception> m_exception;
2628  bool m_success = false;
2629  };
2630 
2631 #ifdef __PCL_BUILDING_PIXINSIGHT_APPLICATION
2632  friend class pi::JSEphemerisFileObject;
2633  friend class pi::JSEphemerisHandleObject;
2634 #endif
2635 };
2636 
2637 // ----------------------------------------------------------------------------
2638 
2639 } // pcl
2640 
2641 #endif // __PCL_EphemerisFile_h
2642 
2643 // ----------------------------------------------------------------------------
2644 // EOF pcl/EphemerisFile.h - Released 2024-06-18T15:48:54Z
size_type Length() const noexcept
Definition: Array.h:266
iterator End()
Definition: Array.h:451
const Index * const_iterator
Definition: Array.h:117
void Increment()
Definition: Atomic.h:207
Automatic mutex lock/unlock.
Definition: AutoLock.h:84
64-bit floating point Chebyshev function approximation.
Dynamic list of ephemeris numerical constants.
Calculation of ephemerides from data stored in XEPH files.
const Optional< double > & M2() const
const Optional< double > & U_B() const
TimePoint EndTime(int i=0) const
MultiVector StateVectors(TimePoint t)
const Optional< double > & A1() const
void ComputeState(Vector &p, TimePoint t)
const Optional< double > & DT() const
const Optional< double > & B_V() const
const IsoString & ObjectId() const
const Optional< double > & A2() const
void ComputeState(Vector &p, Vector &v, TimePoint t)
Handle(const EphemerisFile &parent, const IsoString &object, const IsoString &origin=IsoString())
const Optional< double > & M1() const
Vector FirstDerivative(TimePoint t)
const Optional< double > & I_R() const
const Optional< double > & D() const
const Optional< double > & PC() const
const Optional< double > & K2() const
const Optional< double > & G() const
const EphemerisFile & ParentFile() const
Vector SecondDerivative(TimePoint t)
void ComputeFirstDerivative(Vector &v, TimePoint t)
const String & ObjectName() const
const Optional< double > & A3() const
const IsoString & OriginId() const
const Optional< double > & K1() const
TimePoint StartTime(int i=0) const
Vector StateVector(TimePoint t)
void ComputeSecondDerivative(Vector &a, TimePoint t)
const Optional< double > & H() const
Solar system ephemerides from XEPH files.
static void OverrideAsteroidEphemerides(const String &filePath)
const EphemerisMetadata & Metadata() const
static void Serialize(const String &filePath, TimePoint startTime, TimePoint endTime, const SerializableEphemerisObjectDataList &data, const EphemerisMetadata &metadata=EphemerisMetadata(), const EphemerisConstantList &constants=EphemerisConstantList())
StringList ObjectNames() const
EphemerisFile()=default
static String CIP_ITRSDataFilePath()
IsoStringList ObjectIds() const
TimePoint StartTime() const
static const EphemerisFile & FundamentalEphemerides()
EphemerisObjectList Objects() const
EphemerisFile(EphemerisFile &&x)
int NumberOfHandles() const
EphemerisFile(const String &filePath)
static const EphemerisFile & ShortTermKBOEphemerides()
static const EphemerisFile & ShortTermFundamentalEphemerides()
static void OverrideNutationModel(const String &filePath)
static void OverrideCIP_ITRSDataFilePath(const String &filePath)
static const EphemerisFile & NutationModel()
bool IsConstantAvailable(const IsoString &name) const
static void OverrideFundamentalEphemerides(const String &filePath)
static const EphemerisFile & AsteroidEphemerides()
static const EphemerisFile & KBOEphemerides()
const String & FilePath() const
String ObjectName(const IsoString &object, const IsoString &origin=IsoString()) const
static void OverrideShortTermKBOEphemerides(const String &filePath)
double ConstantValue(const IsoString &name) const
static void OverrideShortTermAsteroidEphemerides(const String &filePath)
static String DeltaTDataFilePath()
virtual ~EphemerisFile() noexcept(false)
static void OverrideShortTermNutationModel(const String &filePath)
static const EphemerisFile & ShortTermNutationModel()
bool IsObjectAvailable(const IsoString &object, const IsoString &origin=IsoString()) const
EphemerisFile(const EphemerisFile &)=delete
bool IsOpen() const
static String DeltaATDataFilePath()
static void OverrideShortTermFundamentalEphemerides(const String &filePath)
TimePoint EndTime() const
static void OverrideDeltaATDataFilePath(const String &filePath)
const EphemerisConstantList & Constants() const
static void OverrideKBOEphemerides(const String &filePath)
static const EphemerisFile & ShortTermAsteroidEphemerides()
static void OverrideDeltaTDataFilePath(const String &filePath)
A simple exception with an associated error message.
Definition: Exception.h:239
virtual void Read(void *buffer, fsize_type len)
virtual void SetPosition(fpos_type pos)
Approximation of vector-valued functions by Chebyshev polynomial expansions.
Definition: ChebyshevFit.h:102
Generic array of vectors.
Definition: MultiVector.h:101
bool IsEmpty() const noexcept
Definition: String.h:818
int CompareIC(const GenericString< T, R1, A1 > &s, bool localeAware=true) const noexcept
Definition: String.h:3820
Generic vector of arbitrary length.
Definition: Vector.h:107
Eight-bit string (ISO/IEC-8859-1 or UTF-8 string)
Definition: String.h:5425
ustring_base UTF8ToUTF16(size_type i=0, size_type n=maxPos) const
Definition: String.h:12322
Unicode (UTF-16) string.
Definition: String.h:8113
An instant in any timescale.
Definition: TimePoint.h:103
String ToString(const ISO8601ConversionOptions &options=ISO8601ConversionOptions(), double tz=0) const
Definition: TimePoint.h:362
constexpr bool IsValid() const
Definition: TimePoint.h:231
bool operator==(const Array< T, A > &x1, const Array< T, A > &x2) noexcept
Definition: Array.h:2267
bool operator<(const Array< T, A > &x1, const Array< T, A > &x2) noexcept
Definition: Array.h:2278
int64 fsize_type
Definition: Defs.h:1185
unsigned long long uint64
Definition: Defs.h:682
unsigned char uint8
Definition: Defs.h:642
signed long long int64
Definition: Defs.h:676
signed int int32
Definition: Defs.h:660
FI BinarySearch(FI i, FI j, const T &v) noexcept
Definition: Search.h:170
constexpr const T & Range(const T &x, const T &a, const T &b) noexcept
Definition: Utility.h:190
PCL root namespace.
Definition: AbstractImage.h:77
A numerical constant defined in an ephemeris file (XEPH format).
double value
The constant value.
EphemerisConstant(const EphemerisConstant &)=default
IsoString name
The constant name (case-insensitive).
EphemerisConstant(EphemerisConstant &&)=default
EphemerisConstant(const IsoString &n=IsoString(), double v=0)
Metadata items available in ephemeris files (XEPH format).
String organizationName
The name of the organization responsible for this file.
String title
A title that represents or identifies this XEPH file.
String creatorOS
The operating system on which this file was created.
String briefDescription
A brief (single-line) description of this XEPH file.
String creatorApplication
The software application or program that created this file.
String copyright
Copyright information applicable to the data stored in this XEPH file.
String description
A full description of the data stored in this XEPH file.
TimePoint creationTime
The date this file was created.
String authors
The names of one or more persons or groups that have created the data in this file.
Identifiers and descriptive data of an object available in an ephemeris file.
Optional< double > DT
Optional< double > K1
Optional< double > M1
Optional< double > B_V
Optional< double > A1
EphemerisObject(const EphemerisObject &)=default
EphemerisObject(const IsoString &a_objectId, const IsoString &a_originId, const String &a_objectName=String(), const String &a_objectDescription=String(), Optional< double > a_H=Optional< double >(), Optional< double > a_G=Optional< double >(), Optional< double > a_M1=Optional< double >(), Optional< double > a_K1=Optional< double >(), Optional< double > a_M2=Optional< double >(), Optional< double > a_K2=Optional< double >(), Optional< double > a_PC=Optional< double >(), Optional< double > a_B_V=Optional< double >(), Optional< double > a_U_B=Optional< double >(), Optional< double > a_I_R=Optional< double >(), Optional< double > a_D=Optional< double >(), Optional< double > a_A1=Optional< double >(), Optional< double > a_A2=Optional< double >(), Optional< double > a_A3=Optional< double >(), Optional< double > a_DT=Optional< double >())
Optional< double > I_R
Optional< double > A3
Optional< double > A2
Optional< double > D
Optional< double > M2
Optional< double > H
Optional< double > PC
Optional< double > K2
Optional< double > U_B
Optional< double > G
EphemerisObject(EphemerisObject &&)=default
Chebyshev polynomial expansion coefficients for ephemeris serialization.
SerializableEphemerisData(SerializableEphemerisData &&)=default
SerializableEphemerisData(TimePoint t, const ChebyshevFit &T)
SerializableEphemerisData(const SerializableEphemerisData &)=default
A set of Chebyshev polynomial expansions and associated ancillary data for ephemeris serialization.
SerializableEphemerisObjectData(SerializableEphemerisObjectData &&)=default
SerializableEphemerisObjectData(const IsoString &id, const IsoString &origin, const String &name=String(), const String &desc=String())
SerializableEphemerisObjectData(const SerializableEphemerisObjectData &)=default