52 #ifndef __PCL_EphemerisFile_h
53 #define __PCL_EphemerisFile_h
69 #ifdef __PCL_BUILDING_PIXINSIGHT_APPLICATION
72 class JSEphemerisFileObject;
73 class JSEphemerisHandleObject;
82 class PCL_CLASS XMLElement;
408 : objectId( id.Trimmed() )
409 , originId( origin.Trimmed() )
410 , objectName( name.Trimmed() )
411 , description( desc )
546 : objectId( objectId_ )
547 , originId( originId_ )
548 , objectName( objectName_ )
549 , objectDescription( objectDescription_ )
654 : m_file( std::move( x.m_file ) )
655 , m_startTime( x.m_startTime )
656 , m_endTime( x.m_endTime )
657 , m_constants( std::move( x.m_constants ) )
658 , m_index( std::move( x.m_index ) )
667 m_file = std::move( x.m_file );
668 m_startTime = x.m_startTime;
669 m_endTime = x.m_endTime;
670 m_constants = std::move( x.m_constants );
671 m_index = std::move( x.m_index );
709 void Open( const
String& filePath );
741 return m_file.FilePath();
786 return BinarySearch( m_constants.Begin(), m_constants.End(),
801 if ( i == m_constants.End() )
802 throw Error(
"Undefined ephemeris constant '" + name +
'\'' );
816 for (
const Index& ix : m_index )
818 ix.objectName, ix.objectDescription,
819 ix.H, ix.G, ix.B_V, ix.D );
849 if ( i != m_index.
End() )
852 for (
const Index& index : m_index )
853 if ( index.objectName.CompareIC( name ) == 0 )
854 if ( origin.
IsEmpty() || index.originId == origin )
875 if ( i != m_index.
End() )
876 return i->objectName;
903 return m_handleCount.Load();
954 static void Serialize(
const String& filePath,
1031 static const EphemerisFile& ShortTermFundamentalEphemerides();
1259 static String DeltaTDataFilePath();
1283 static String DeltaATDataFilePath();
1301 static String CIP_ITRSDataFilePath();
1319 static void OverrideFundamentalEphemerides(
const String& filePath );
1338 static void OverrideShortTermFundamentalEphemerides(
const String& filePath );
1356 static void OverrideAsteroidEphemerides(
const String& filePath );
1374 static void OverrideShortTermAsteroidEphemerides(
const String& filePath );
1392 static void OverrideKBOEphemerides(
const String& filePath );
1411 static void OverrideShortTermKBOEphemerides(
const String& filePath );
1429 static void OverrideNutationModel(
const String& filePath );
1448 static void OverrideShortTermNutationModel(
const String& filePath );
1469 static void OverrideDeltaTDataFilePath(
const String& filePath );
1490 static void OverrideDeltaATDataFilePath(
const String& filePath );
1512 static void OverrideCIP_ITRSDataFilePath(
const String& filePath );
1527 constexpr
bool operator ==(
const IndexNode& n )
const
1529 return jdi == n.jdi && jdf == n.jdf;
1532 constexpr
bool operator <(
const IndexNode& n )
const
1534 return jdi < n.jdi || jdi == n.jdi && jdf < n.jdf;
1537 constexpr
int NumberOfComponents()
const
1539 return (n[0] > 0) ? ((n[1] > 0) ? ((n[2] > 0) ? ((n[3] > 0) ? 4 : 3) : 2) : 1) : 0;
1542 constexpr
int NumberOfCoefficients()
const
1544 return n[0] + n[1] + n[2] + n[3];
1547 TimePoint StartTime()
const
1549 return TimePoint( jdi, jdf );
1562 String objectDescription;
1565 Optional<double> B_V;
1567 Array<IndexNode> nodes[ 2 ];
1569 Index(
const IsoString& objectId_,
1570 const IsoString& originId_ = IsoString(),
1571 const String& objectName_ = String(),
1572 const String& objectDescription_ = String() )
1573 : objectId( objectId_.Trimmed() )
1574 , originId( originId_.Trimmed() )
1575 , objectName( objectName_.Trimmed() )
1576 , objectDescription( objectDescription_.Trimmed() )
1582 return objectId == x.objectId && originId == x.originId;
1587 return (objectId != x.objectId) ? objectId < x.objectId : originId < x.originId;
1590 bool HasDerivative()
const
1592 return !nodes[1].IsEmpty();
1596 mutable File m_file;
1597 mutable AtomicInt m_handleCount;
1598 mutable Mutex m_mutex;
1599 TimePoint m_startTime;
1600 TimePoint m_endTime;
1601 EphemerisMetadata m_metadata;
1603 Array<Index> m_index;
1607 static String s_ephFilePath;
1608 static String s_ephFilePath_s;
1609 static String s_astFilePath;
1610 static String s_astFilePath_s;
1611 static String s_kboFilePath;
1612 static String s_kboFilePath_s;
1613 static String s_nutFilePath;
1614 static String s_nutFilePath_s;
1615 static String s_deltaTFilePath;
1616 static String s_deltaATFilePath;
1617 static String s_cipITRSFilePath;
1624 const Index* FindObject(
const IsoString&
object,
const IsoString& origin )
const
1626 if ( origin.IsEmpty() )
1628 for (
const Index& index : m_index )
1629 if ( index.objectId ==
object )
1635 if ( i != m_index.End() )
1639 for (
const Index& index : m_index )
1640 if ( index.objectName.CompareIC( name ) == 0 )
1641 if ( origin.IsEmpty() || index.originId == origin )
1643 throw Error(
"Unavailable object '" + name +
"\' with origin '" + String( origin ) +
"'." );
1707 throw Error(
"Cannot create a handle to a closed ephemeris file." );
1710 m_index = m_parent->FindObject(
object, origin );
1718 m_parent = x.m_parent;
1719 m_index = x.m_index;
1720 m_node[0] = x.m_node[0];
1721 m_node[1] = x.m_node[1];
1722 m_node[2] = x.m_node[2];
1723 if ( m_parent !=
nullptr )
1724 m_parent->m_handleCount.Increment();
1732 m_parent = x.m_parent;
1733 x.m_parent =
nullptr;
1734 m_index = x.m_index;
1735 m_node[0] = x.m_node[0];
1736 m_node[1] = x.m_node[1];
1737 m_node[2] = x.m_node[2];
1745 if ( m_parent !=
nullptr )
1746 m_parent->m_handleCount.Decrement();
1754 if ( m_parent !=
nullptr )
1755 m_parent->m_handleCount.Decrement();
1756 m_parent = x.m_parent;
1757 m_index = x.m_index;
1758 m_node[0] = x.m_node[0];
1759 m_node[1] = x.m_node[1];
1760 m_node[2] = x.m_node[2];
1761 if ( m_parent !=
nullptr )
1762 m_parent->m_handleCount.Increment();
1771 if ( m_parent !=
nullptr )
1772 m_parent->m_handleCount.Decrement();
1773 m_parent = x.m_parent;
1774 x.m_parent =
nullptr;
1775 m_index = x.m_index;
1776 m_node[0] = x.m_node[0];
1777 m_node[1] = x.m_node[1];
1778 m_node[2] = x.m_node[2];
1808 p = m_node[0].expansion( t - m_node[0].startTime );
1848 ComputeState( p, t );
1849 ComputeFirstDerivative( v, t );
1884 if ( HasDerivative() )
1886 else if ( m_node[1].current != m_node[0].current )
1888 m_node[1].current = m_node[0].current;
1889 m_node[1].startTime = m_node[0].startTime;
1890 m_node[1].endTime = m_node[0].endTime;
1891 m_node[1].expansion = m_node[0].expansion.Derivative();
1893 v = m_node[1].expansion( t - m_node[1].startTime );
1928 if ( HasDerivative() )
1930 else if ( m_node[1].current != m_node[0].current )
1932 m_node[1].current = m_node[0].current;
1933 m_node[1].startTime = m_node[0].startTime;
1934 m_node[1].endTime = m_node[0].endTime;
1935 m_node[1].expansion = m_node[0].expansion.Derivative();
1937 if ( m_node[2].current != m_node[0].current )
1939 m_node[2].current = m_node[0].current;
1940 m_node[2].startTime = m_node[0].startTime;
1941 m_node[2].endTime = m_node[0].endTime;
1942 m_node[2].expansion = m_node[1].expansion.Derivative();
1944 a = m_node[2].expansion( t - m_node[2].startTime );
1961 ComputeState( p, t );
1982 ComputeState( p, v, t );
2002 ComputeFirstDerivative( v, t );
2022 ComputeSecondDerivative( v, t );
2041 return m_index->objectId;
2054 return m_index->originId;
2065 return m_index->objectName;
2080 return m_node[
Range( i, 0, 1 )].startTime;
2095 return m_node[
Range( i, 0, 1 )].endTime;
2109 return m_index->HasDerivative();
2144 return m_index->B_V;
2167 const EphemerisFile::Index* m_index =
nullptr;
2168 NodeInfo m_node[ 3 ];
2169 uint64 m_uniqueId = UniqueId();
2171 static uint64 UniqueId();
2182 throw Error(
"Invalid time point." );
2183 if ( t < m_parent->StartTime() || t > m_parent->
EndTime() )
2184 throw Error(
"Time point out of range." );
2187 NodeInfo& info = m_node[index];
2189 for (
int N =
int( nodes.
Length() ), l = 0, r = N-1; ; )
2191 int m = (l + r) >> 1;
2192 const IndexNode& node = nodes[m];
2198 if ( m == N-1 || t < nodes[m+1].StartTime() )
2200 if ( m != info.current )
2204 volatile AutoLock lock( m_parent->m_mutex );
2206 for (
int i = 0, n = node.NumberOfComponents(); i < n; ++i )
2209 m_parent->m_file.
Read(
reinterpret_cast<void*
>( c.Begin() ), c.Size() );
2214 info.startTime = t0;
2215 info.endTime = (m < N-1) ? nodes[m+1].StartTime() : m_parent->
EndTime();
2216 info.expansion =
ChebyshevFit( coefficients, 0, info.endTime - info.startTime );
2226 friend class PCL_CLASS Position;
2231 #if defined( __clang__ )
2232 # pragma GCC diagnostic ignored "-Wunused-private-field"
2239 mutable bool m_finalized =
false;
2246 mutable bool m_internal =
false;
2248 #if defined( __clang__ )
2249 # pragma GCC diagnostic warning "-Wunused-private-field"
2252 class DeserializeObjectThread :
public Thread
2256 DeserializeObjectThread(
const Array<const XMLElement*>& elements
2258 ,
int startIndex,
int endIndex )
2259 : m_elements( elements )
2260 , m_startIndex( startIndex )
2261 , m_endIndex( endIndex )
2263 , m_fileSize( fileSize )
2264 , m_minPos( minPos )
2268 void Run()
override;
2270 const Array<Index>& Objects()
const
2275 bool Succeeded()
const
2280 const Exception* ExceptionThrown()
const
2282 return m_exception.Ptr();
2287 const Array<const XMLElement*>& m_elements;
2288 int m_startIndex, m_endIndex;
2291 Array<Index> m_index;
2292 AutoPointer<Exception> m_exception;
2293 bool m_success =
false;
2296 #ifdef __PCL_BUILDING_PIXINSIGHT_APPLICATION
2297 friend class pi::JSEphemerisFileObject;
2298 friend class pi::JSEphemerisHandleObject;
2306 #endif // __PCL_EphemerisFile_h