diff --git a/CMakeLists.txt b/CMakeLists.txt index 6df1f64..7565764 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,16 +1,24 @@ CMAKE_MINIMUM_REQUIRED(VERSION 2.8) PROJECT(SGP4) +set (CMAKE_CXX_STANDARD 11) + set(CMAKE_EXPORT_COMPILE_COMMANDS ON) +set(CMAKE_CXX_EXTENSIONS OFF) + + +if(DEFINED MSVC_VERSION) + if (MSVC_VERSION GREATER_EQUAL "1900") + include(CheckCXXCompilerFlag) + CHECK_CXX_COMPILER_FLAG("/std:c++latest" _cpp_latest_flag_supported) + if (_cpp_latest_flag_supported) + add_compile_options("/std:c++latest") + endif() + endif() +endif() + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall") -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wextra") -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wshadow") -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wnon-virtual-dtor") -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pedantic") -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-long-long") -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wcast-align") -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wsign-conversion") include_directories(libsgp4) @@ -19,4 +27,4 @@ add_subdirectory(sattrack) add_subdirectory(runtest) add_subdirectory(passpredict) -file(COPY SGP4-VER.TLE DESTINATION ${PROJECT_BINARY_DIR}) +file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/SGP4-VER.TLE DESTINATION ${PROJECT_BINARY_DIR}) diff --git a/libsgp4/CMakeLists.txt b/libsgp4/CMakeLists.txt index b816645..e61792e 100644 --- a/libsgp4/CMakeLists.txt +++ b/libsgp4/CMakeLists.txt @@ -32,10 +32,9 @@ set(SRCS TleException.h Tle.h Util.h - Vector.h - ) + Vector.h) add_library(sgp4 STATIC ${SRCS} ${INCS}) add_library(sgp4s SHARED ${SRCS} ${INCS}) -install( TARGETS sgp4s LIBRARY DESTINATION lib ) -install( FILES ${INCS} DESTINATION include/SGP4 ) +install(TARGETS sgp4s DESTINATION lib) +install( FILES ${INCS} DESTINATION include/SGP4) diff --git a/libsgp4/DateTime.h b/libsgp4/DateTime.h index d7d0b60..7ab5e4c 100644 --- a/libsgp4/DateTime.h +++ b/libsgp4/DateTime.h @@ -22,6 +22,7 @@ #include #include #include +#include #include "TimeSpan.h" #include "Util.h" @@ -141,27 +142,19 @@ class DateTime static DateTime Now(bool microseconds = false) { DateTime dt; - struct timespec ts; - - if (clock_gettime(CLOCK_REALTIME, &ts) == 0) - { - if (microseconds) - { - dt = DateTime(UnixEpoch - + ts.tv_sec * TicksPerSecond - + ts.tv_nsec / 1000LL * TicksPerMicrosecond); - } - else - { - dt = DateTime(UnixEpoch - + ts.tv_sec * TicksPerSecond); - } - } + Util::UnixTimestamp ts = Util::CurrentTime(); + + if (microseconds) + { + dt = DateTime(UnixEpoch + + ts.seconds * TicksPerSecond + + ts.nanoseconds / 1000LL * TicksPerMicrosecond); + } else - { - throw 1; - } - + { + dt = DateTime(UnixEpoch + + ts.nanoseconds * TicksPerSecond); + } return dt; } diff --git a/libsgp4/Util.cc b/libsgp4/Util.cc index 2e9ee3d..5eb2f9b 100644 --- a/libsgp4/Util.cc +++ b/libsgp4/Util.cc @@ -14,41 +14,68 @@ * limitations under the License. */ +#include -#include "Util.h" - -#include -#include -#include +#ifdef _WIN32 namespace Util { - namespace - { - struct IsDigit: std::unary_function - { - bool operator()(char c) const - { - return std::isdigit(c, std::locale::classic()) == 0; - } - }; - } - - void TrimLeft(std::string& s) - { - s.erase(s.begin(), - std::find_if(s.begin(), s.end(), std::not1(IsDigit()))); - } - - void TrimRight(std::string& s) - { - s.erase(std::find_if(s.rbegin(), s.rend(), std::not1(IsDigit())).base(), - s.end()); - } - - void Trim(std::string& s) - { - TrimLeft(s); - TrimRight(s); - } + + std::atomic WindowsUtcTimeSource::m_instance = std::atomic(nullptr); + std::mutex WindowsUtcTimeSource::m_mutex; + + WindowsUtcTimeSource* WindowsUtcTimeSource::Instance() + { + WindowsUtcTimeSource* tmp = m_instance.load(std::memory_order_relaxed); + std::atomic_thread_fence(std::memory_order_acquire); + if (tmp == nullptr) + { + std::lock_guard lock(m_mutex); + if (tmp == nullptr) + { + tmp = new WindowsUtcTimeSource(); + std::atomic_thread_fence(std::memory_order_release); + m_instance.store(tmp, std::memory_order_relaxed); + } + + } + return tmp; + } + + WindowsUtcTimeSource::WindowsUtcTimeSource() + { + // we check to see if GetSystemTimePreciseAsFileTime exists. If it does, use that. Otherwise, use the non-precise version + HINSTANCE hDLL = LoadLibrary("Kernel32.dll"); + m_getUtcTimeFunc = (FuncT)GetProcAddress((HMODULE)hDLL, "GetSystemTimePreciseAsFileTime"); + + if (m_getUtcTimeFunc != nullptr) + { + m_isPrecise = true; + } + else + { + m_isPrecise = false; + m_getUtcTimeFunc = (FuncT)GetSystemTimeAsFileTime; + } + }; + + UnixTimestamp WindowsUtcTimeSource::GetUtcTime() + { + UnixTimestamp stamp; + int ticks_per_second = 10000000; // there are 1e7 100ns ticks in a second + int nanoseconds_per_tick = 100; + ULONGLONG seconds_from_windows_to_unix_epoch = 11644473600; // seconds from 1601-01-01T00:00:00Z to 1970-01-01T00:00:00Z + FILETIME ft; + m_getUtcTimeFunc(&ft); + ULARGE_INTEGER ui; + ui.LowPart = ft.dwLowDateTime; + ui.HighPart = ft.dwHighDateTime; + int64_t diff = ui.QuadPart - seconds_from_windows_to_unix_epoch * ticks_per_second; + stamp.seconds = diff / ticks_per_second; + stamp.nanoseconds = (diff - stamp.seconds * ticks_per_second) * nanoseconds_per_tick; + return stamp; + } + } + +#endif diff --git a/libsgp4/Util.h b/libsgp4/Util.h index fd79bc6..7a32c3c 100644 --- a/libsgp4/Util.h +++ b/libsgp4/Util.h @@ -18,93 +18,173 @@ #ifndef UTIL_H_ #define UTIL_H_ +#ifdef _WIN32 +#define NOMINMAX +#include +#endif + #include "Globals.h" +#include +#include +#include +#include +#include +#include #include namespace Util { - template - - bool FromString(const std::string& str, T& val) - { - std::stringstream ss(str); - return !(ss >> val).fail(); - } - - /* - * always positive result - * Mod(-3,4)= 1 fmod(-3,4)= -3 - */ - inline double Mod(const double x, const double y) - { - if (y == 0.0) - { - return x; - } - - return x - y * floor(x / y); - } - - inline double WrapNegPosPI(const double a) - { - return Mod(a + kPI, kTWOPI) - kPI; - } - - inline double WrapTwoPI(const double a) - { - return Mod(a, kTWOPI); - } - - inline double WrapNegPos180(const double a) - { - return Mod(a + 180.0, 360.0) - 180.0; - } - - inline double Wrap360(const double a) - { - return Mod(a, 360.0); - } - - inline double DegreesToRadians(const double degrees) - { - return degrees * kPI / 180.0; - } - - inline double RadiansToDegrees(const double radians) - { - return radians * 180.0 / kPI; - } - - inline double AcTan(const double sinx, const double cosx) - { - if (cosx == 0.0) - { - if (sinx > 0.0) - { - return kPI / 2.0; - } - else - { - return 3.0 * kPI / 2.0; - } - } - else - { - if (cosx > 0.0) - { - return atan(sinx / cosx); - } - else - { - return kPI + atan(sinx / cosx); - } - } - } - - void TrimLeft(std::string& s); - void TrimRight(std::string& s); - void Trim(std::string& s); + + template + + bool FromString(const std::string& str, T& val) + { + std::stringstream ss(str); + return !(ss >> val).fail(); + } + + /* + * always positive result + * Mod(-3,4)= 1 fmod(-3,4)= -3 + */ + inline double Mod(const double x, const double y) + { + if (y == 0.0) + { + return x; + } + + return x - y * floor(x / y); + } + + inline double WrapNegPosPI(const double a) + { + return Mod(a + kPI, kTWOPI) - kPI; + } + + inline double WrapTwoPI(const double a) + { + return Mod(a, kTWOPI); + } + + inline double WrapNegPos180(const double a) + { + return Mod(a + 180.0, 360.0) - 180.0; + } + + inline double Wrap360(const double a) + { + return Mod(a, 360.0); + } + + inline double DegreesToRadians(const double degrees) + { + return degrees * kPI / 180.0; + } + + inline double RadiansToDegrees(const double radians) + { + return radians * 180.0 / kPI; + } + + inline double AcTan(const double sinx, const double cosx) + { + if (cosx == 0.0) + { + if (sinx > 0.0) + { + return kPI / 2.0; + } + else + { + return 3.0 * kPI / 2.0; + } + } + else + { + if (cosx > 0.0) + { + return atan(sinx / cosx); + } + else + { + return kPI + atan(sinx / cosx); + } + } + } + + // time since unix epoch + struct UnixTimestamp + { + int64_t seconds; + int64_t nanoseconds; + }; + + #ifdef _WIN32 + typedef void (WINAPI *FuncT) (LPFILETIME lpSystemTimeAsFileTime); + + class WindowsUtcTimeSource + { + public: + inline bool IsPrecise() { return m_isPrecise; }; + + static WindowsUtcTimeSource* Instance(); + UnixTimestamp GetUtcTime(); + + private: + static std::atomic m_instance; + static std::mutex m_mutex; + FuncT m_getUtcTimeFunc; + bool m_isPrecise; + + WindowsUtcTimeSource(); + WindowsUtcTimeSource(const WindowsUtcTimeSource&) = delete; + WindowsUtcTimeSource& operator=(WindowsUtcTimeSource const&) = delete; + }; + #endif + + inline UnixTimestamp CurrentTime() + { + UnixTimestamp stamp; + #ifdef _WIN32 + stamp = WindowsUtcTimeSource::Instance()->GetUtcTime(); + #else + struct timespec ts; + if (clock_gettime(CLOCK_REALTIME, &ts) == 0) + { + stamp.seconds = ts.tv_sec; + stamp.nanoseconds = ts.tv_nsec; + } + else + { + throw 1; + } + #endif + return stamp; + } + + static inline void TrimLeft(std::string &s) + { + s.erase(s.begin(), std::find_if(s.begin(), s.end(), [](int ch) + { + return !std::isspace(ch); + })); + } + + static inline void TrimRight(std::string &s) { + s.erase(std::find_if(s.rbegin(), s.rend(), [](int ch) + { + return !std::isspace(ch); + }).base(), s.end()); + } + + static inline void Trim(std::string &s) + { + TrimLeft(s); + TrimRight(s); + } + } #endif diff --git a/passpredict/CMakeLists.txt b/passpredict/CMakeLists.txt index 5d6cf00..9975e9d 100644 --- a/passpredict/CMakeLists.txt +++ b/passpredict/CMakeLists.txt @@ -4,5 +4,4 @@ set(SRCS add_executable(passpredict ${SRCS}) target_link_libraries(passpredict - sgp4 - rt) + sgp4) diff --git a/runtest/CMakeLists.txt b/runtest/CMakeLists.txt index 7a1cf26..621d56c 100644 --- a/runtest/CMakeLists.txt +++ b/runtest/CMakeLists.txt @@ -4,5 +4,4 @@ set(SRCS add_executable(runtest ${SRCS}) target_link_libraries(runtest - sgp4 - rt) + sgp4) diff --git a/runtest/runtest.cc b/runtest/runtest.cc index 6ec6ba6..3f1e166 100644 --- a/runtest/runtest.cc +++ b/runtest/runtest.cc @@ -273,7 +273,7 @@ void RunTest(const char* infile) int main() { - const char* file_name = "SGP4-VER.TLE"; + const char* file_name = "../SGP4-VER.TLE"; RunTest(file_name); diff --git a/sattrack/CMakeLists.txt b/sattrack/CMakeLists.txt index 0664458..a8c5027 100644 --- a/sattrack/CMakeLists.txt +++ b/sattrack/CMakeLists.txt @@ -4,5 +4,4 @@ set(SRCS add_executable(sattrack ${SRCS}) target_link_libraries(sattrack - sgp4 - rt) + sgp4)