New C++ friendly time_conversion (#36)

* Improving codebase with newer C++17 code

* Removed C-style time_conversion library, integrated new time_conversion C++ library in tools

* Bumped version to 1.7.0

* Updated Boost to 1.84.0

* Updated CRC-Castagnoli to 1.2.0.0
This commit is contained in:
Michele Adduci
2024-01-27 16:42:20 +01:00
committed by GitHub
parent 5f3d4aab2a
commit f569f292f7
31 changed files with 2146 additions and 1927 deletions

1
.github/CODEOWNERS vendored Normal file
View File

@@ -0,0 +1 @@
* @madduci

3
.gitignore vendored
View File

@@ -38,4 +38,5 @@ bin/*
.devcontainer/
.vscode/
test_package/CMakeUserPresets.json
test_package/CMakeUserPresets.json
CMakeUserPresets.json

View File

@@ -1,9 +1,11 @@
# openE57
## [master] - 2024-XX-XX
## [1.7.0] - 2024-01-27
## Changed
- Updated Boost Libraries to 1.84.0
- Updated CRC32-Castagnoli to 1.2.0.0
- Ported the Time Conversion library from C to C++
## [1.6.5] - 2024-01-24

View File

@@ -2,7 +2,7 @@
# implementation, with support for Conan targets, to make the dependency
# management easier and reproducible on all the supported platforms
#
# Original work Copyright 2010-2012 Roland Schwarz, Riegl LMS GmbH
# Original work Copyright 2010-2012 Roland Schwarz, Riegl LMS GmbH
# Modified work Copyright 2020-2024 Michele Adduci <adduci@tutanota.com>
#
# Permission is hereby granted, free of charge, to any person or organization
@@ -42,7 +42,7 @@ cmake_minimum_required(VERSION 3.15.0 FATAL_ERROR)
# Enables the CMAKE_MSVC_RUNTIME_LIBRARY property on targets
cmake_policy(SET CMP0091 NEW)
project(openE57 VERSION 1.6.3 LANGUAGES C CXX DESCRIPTION "openE57 is a library for handling E57 files")
project(openE57 VERSION 1.7.0 LANGUAGES C CXX DESCRIPTION "openE57 is a library for handling E57 files")
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED TRUE)
@@ -56,10 +56,10 @@ if("${isSystemDir}" STREQUAL "-1")
endif("${isSystemDir}" STREQUAL "-1")
option(BUILD_DOCS "Build documentation" FALSE)
option(BUILD_EXAMPLES "Build opene57 examples" FALSE)
option(BUILD_TOOLS "Build opene57 tools" FALSE)
option(BUILD_TESTS "Build opene57 tests" FALSE)
option(BUILD_SHARED_LIBS "Build opene57 shared libraries" FALSE)
option(BUILD_EXAMPLES "Build openE57 examples" FALSE)
option(BUILD_TOOLS "Build openE57 tools" FALSE)
option(BUILD_TESTS "Build openE57 tests" FALSE)
option(BUILD_SHARED_LIBS "Build openE57 shared libraries" FALSE)
option(BUILD_WITH_MT "Build the project with /MT when using Visual Studio" FALSE)
if(BUILD_SHARED_LIBS)
@@ -72,6 +72,11 @@ if(NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE "Release")
endif()
if(BUILD_TESTS)
message(STATUS "Enabling tests")
enable_testing()
endif()
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/src)
#

View File

@@ -42,7 +42,7 @@ Available conan options are the following ones:
Platform independent:
```shell
git clone https://github.com/madduci/openE57.git
git clone https://github.com/openE57/openE57.git
cd open57
conan create . --build=missing
```
@@ -56,7 +56,7 @@ Available CMake Options are:
* BUILD_DOCS - builds the Doxygen documentation (requires Doxygen and Graphviz)
* BUILD_EXAMPLES - builds the API examples
* BUILD_TOOLS - builds the binary tools to validate and dump E57 files
* BUILD_TESTS - actually unsupported (no tests yet available)
* BUILD_TESTS - builds tests
* BUILD_SHARED_LIBS - actually unsupported (missing exported symbols)
* BUILD_WITH_MT - instructs CMake to set the correct [`CMAKE_MSVC_RUNTIME_LIBRARY`](https://cmake.org/cmake/help/latest/variable/CMAKE_MSVC_RUNTIME_LIBRARY.html?highlight=cmake_msvc_runtime_library) flag for Visual Studio
@@ -66,22 +66,22 @@ Building with Position indipendent code on Unix can be activated with the option
#### On Linux:
```shell
git clone https://github.com/madduci/openE57.git
git clone https://github.com/openE57/openE57.git
cd open57
mkdir build && cd build
conan install .. --build=missing
cmake .. -DCMAKE_BUILD_TYPE=Release
conan install --output-folder . --build=missing -s compiler.cppstd=17 -o with_tests=True -o with_tools=True ..
cmake .. -DCMAKE_BUILD_TYPE=Release -DBUILD_TESTS=ON -DBUILD_TOOLS=ON
cmake --build . --config Release --target install
```
#### On Windows:
```cmd
git clone https://github.com/madduci/openE57.git
git clone https://github.com/openE57/openE57.git
cd open57
md build && cd build
conan install .. --build=missing
cmake .. -DCMAKE_BUILD_TYPE=Release -DBUILD_WITH_MT=ON
conan install --output-folder . --build=missing -s compiler.cppstd=17 -o with_tests=True -o with_tools=True ..
cmake .. -DCMAKE_BUILD_TYPE=Release -DBUILD_WITH_MT=ON -DBUILD_TESTS=ON -DBUILD_TOOLS=ON
cmake --build . --config Release --target install
```

View File

@@ -13,7 +13,7 @@ required_conan_version = ">=1.54.0"
class Opene57Conan(ConanFile):
name = "opene57"
version = "1.6.5"
version = "1.7.0"
description = "A C++ library for reading and writing E57 files, " \
"fork of the original libE57 (http://libe57.org)"
topics = ("e57", "libe57", "3d", "astm")
@@ -23,12 +23,16 @@ class Opene57Conan(ConanFile):
exports_sources = [ "src/*", "LICENSE*", "CHANGELOG.md", "*.txt"]
settings = "os", "compiler", "arch", "build_type"
options = { "with_tools": [True, False],
"with_tests": [True, False],
"with_examples": [True, False],
"with_docs": [True, False],
"shared": [True, False],
"fPIC": [True, False]
}
default_options = {
"with_tools": False,
"with_tests": False,
"with_examples": False,
"with_docs": False,
"shared": False,
"fPIC": True
@@ -77,6 +81,9 @@ class Opene57Conan(ConanFile):
raise ConanInvalidConfiguration("C++17 support required, which your compiler does not support.")
def requirements(self):
if self.options.with_tests:
self.requires("doctest/2.4.9")
if self.options.with_tools:
self.requires("boost/1.84.0")
@@ -91,9 +98,9 @@ class Opene57Conan(ConanFile):
def generate(self):
tc = CMakeToolchain(self)
tc.variables["PROJECT_VERSION"] = self.version
tc.variables["BUILD_EXAMPLES"] = False
tc.variables["BUILD_EXAMPLES"] = self.options.with_examples
tc.variables["BUILD_TOOLS"] = self.options.with_tools
tc.variables["BUILD_TESTS"] = False
tc.variables["BUILD_TESTS"] = self.options.with_tests
tc.variables["BUILD_DOCS"] = self.options.with_docs
if is_msvc(self):

View File

@@ -22,15 +22,11 @@ set(CONFIG_PACKAGE_INSTALL_DIR lib/cmake/${PROJECT_NAME})
#
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/lib)
if(${BUILD_EXAMPLES})
if(BUILD_EXAMPLES)
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/examples)
endif()
if(${BUILD_TESTS})
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/tests)
endif()
if(${BUILD_TOOLS})
if(BUILD_TOOLS)
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/tools)
endif()

View File

@@ -24,9 +24,15 @@ if(BUILD_TOOLS)
set(Boost_USE_STATIC_RUNTIME ON)
endif()
set(Boost_USE_MULTITHREADED $<IF:$<AND:$<BOOL:${MSVC}>,$<NOT:$<BOOL:${BUILD_WITH_MT}>>>,OFF,ON>)
find_package(Boost 1.70.0 COMPONENTS program_options system thread filesystem REQUIRED)
find_package(Boost 1.70.0 REQUIRED)
list(APPEND compiler_definitions
BOOST_ALL_NO_LIB
$<$<CONFIG:RELWITHDEBINFO>:${Boost_LIB_DIAGNOSTIC_DEFINITIONS}>
$<$<CONFIG:DEBUG>:${Boost_LIB_DIAGNOSTIC_DEFINITIONS}>)
endif()
# Find doctest (Required by Tests)
if(BUILD_TESTS)
find_package(doctest REQUIRED)
enable_testing()
endif()

View File

@@ -6,12 +6,16 @@ list(APPEND compiler_definitions
#
add_library(
${PROJECT_NAME} ${LIBRARY_TYPE}
${CMAKE_CURRENT_SOURCE_DIR}/src/api.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/openE57Simple.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/openE57SimpleImpl.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/openE57.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/openE57Impl.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/time_conversion.cpp
${CMAKE_CURRENT_SOURCE_DIR}/include/openE57/impl/openE57Impl.h
${CMAKE_CURRENT_SOURCE_DIR}/include/openE57/impl/openE57SimpleImpl.h
${CMAKE_CURRENT_SOURCE_DIR}/include/openE57/impl/time_conversion.h
${CMAKE_CURRENT_SOURCE_DIR}/include/openE57/api.h
${CMAKE_CURRENT_SOURCE_DIR}/include/openE57/openE57.h
${CMAKE_CURRENT_SOURCE_DIR}/include/openE57/openE57Simple.h)
@@ -73,4 +77,43 @@ install(
${CMAKE_CURRENT_SOURCE_DIR}/include/openE57/openE57Simple.h
${CMAKE_CURRENT_BINARY_DIR}/opene57_export.h
DESTINATION
include/openE57)
include/openE57)
#
# Test Targets
#
if(BUILD_TESTS)
list(APPEND TEST_CASES
time_conversion_test
api_time_conversion_test
)
foreach(TEST_CASE ${TEST_CASES})
add_executable(${TEST_CASE} ${CMAKE_CURRENT_SOURCE_DIR}/test/${TEST_CASE}.cpp)
message(STATUS "Adding test case ${TEST_CASE}")
add_test(NAME ${TEST_CASE}
COMMAND ${TEST_CASE}
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
set_target_properties(${TEST_CASE} PROPERTIES
DEBUG_POSTFIX ${CMAKE_DEBUG_POSTFIX}
MSVC_RUNTIME_LIBRARY "${CMAKE_MSVC_RUNTIME_LIBRARY}")
target_compile_options(${TEST_CASE} PUBLIC ${compiler_options})
target_compile_definitions(${TEST_CASE} PUBLIC ${compiler_definitions})
target_link_options(${TEST_CASE} PUBLIC ${linker_flags})
target_include_directories(${TEST_CASE} PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/include
${XML_INCLUDE_DIRS}
${doctest_INCLUDE_DIRS} )
target_link_libraries(${TEST_CASE}
PRIVATE
${PROJECT_NAME}
${XML_LIBRARIES}
${CMAKE_THREAD_LIBS_INIT}
)
target_clangformat_setup(${TEST_CASE})
endforeach(TEST_CASE ${TEST_CASES})
endif()

View File

@@ -2,7 +2,7 @@
* openE57las.h - header for simple interface for reading LAS files.
*
* Copyright (c) 2009 - 2010 Kevin Ackley (kackley@gwi.net)
* Copyright (c) 2020 - 2022 Michele Adduci (adduci@tutanota.com)
* Copyright (c) 2020 - 2024 Michele Adduci (adduci@tutanota.com)
*
* Permission is hereby granted, free of charge, to any person or organization
* obtaining a copy of the software and accompanying documentation covered by
@@ -34,6 +34,7 @@
#include <vector>
#ifndef E57FOUNDATIONIMPL_H_INCLUDED
# include <openE57/impl/openE57Impl.h>
# include <openE57/impl/time_conversion.h>
#endif
namespace e57

View File

@@ -0,0 +1,192 @@
#ifndef OPEN57_API_H
#define OPEN57_API_H
#ifndef OPENE57_H_INCLUDED
# include <openE57/openE57.h>
#endif
#ifndef PI
constexpr double PI{3.1415926535897932384626433832795}; // from C++20, use <numbers>
#endif
namespace e57
{
namespace core
{
/**
* @brief The Translation structure defines a rigid body translation in Cartesian coordinates.
*/
struct Translation
{
double x{0.0}; //!< The X coordinate of the translation (in meters)
double y{0.0}; //!< The Y coordinate of the translation (in meters)
double z{0.0}; //!< The Z coordinate of the translation (in meters)
};
/**
* @brief The Quaternion structure is a quaternion which represents a rigid body rotation.
*
*/
struct Quaternion
{
double w{0.0}; //!< The real part of the quaternion. Shall be nonnegative
double x{0.0}; //!< The i coefficient of the quaternion
double y{0.0}; //!< The j coefficient of the quaternion
double z{0.0}; //!< The k coefficient of the quaternion
};
/**
* @brief The RigidBodyTransform is a structure that defines a rigid body transform in cartesian coordinates.
*/
struct RigidBodyTransform
{
Quaternion rotation{}; //!< A unit quaternion representing the rotation, R, of the transform
Translation translation{}; //!< The translation point vector, t, of the transform
};
/**
* @brief The CartesianBounds structure specifies an axis-aligned box in local cartesian coordinates.
*/
struct CartesianBounds
{
double xMinimum{0.0}; //!< The minimum extent of the bounding box in the X direction
double xMaximum{0.0}; //!< The maximum extent of the bounding box in the X direction
double yMinimum{0.0}; //!< The minimum extent of the bounding box in the Y direction
double yMaximum{0.0}; //!< The maximum extent of the bounding box in the Y direction
double zMinimum{0.0}; //!< The minimum extent of the bounding box in the Z direction
double zMaximum{0.0}; //!< The maximum extent of the bounding box in the Z direction
};
/**
* @brief The SphericalBounds structure stores the bounds of some data in spherical coordinates.
*/
struct SphericalBounds
{
double rangeMinimum{0.0}; //!< The minimum extent of the bounding region in the r direction
double rangeMaximum{0.0}; //!< The maximum extent of the bounding region in the r direction
double elevationMinimum{0.0}; //!< The minimum extent of the bounding region from the horizontal plane
double elevationMaximum{0.0}; //!< The maximum extent of the bounding region from the horizontal plane
double azimuthStart{0.0}; //!< The starting azimuth angle defining the extent of the bounding region around the z axis
double azimuthEnd{0.0}; //!< The ending azimuth angle defining the extent of the bounding region around the z axix
};
/**
* @brief The IndexBounds structure stores the minimum and maximum of rowIndex, columnIndex, and returnIndex fields for a set of points.
*/
struct IndexBounds
{
int64_t rowMinimum{0}; //!< The minimum rowIndex value of any point represented by this IndexBounds object.
int64_t rowMaximum{0}; //!< The maximum rowIndex value of any point represented by this IndexBounds object.
int64_t columnMinimum{0}; //!< The minimum columnIndex value of any point represented by this IndexBounds object.
int64_t columnMaximum{0}; //!< The maximum columnIndex value of any point represented by this IndexBounds object.
int64_t returnMinimum{0}; //!< The minimum returnIndex value of any point represented by this IndexBounds object.
int64_t returnMaximum{0}; //!< The maximum returnIndex value of any point represented by this IndexBounds object.
};
/**
* @brief The IntensityLimits Structure specifies the limits for the value of signal intensity that a sensor is capable of producing
*/
struct IntensityLimits
{
double intensityMinimum{0.0}; //!< The minimum producible intensity value. Unit is unspecified.
double intensityMaximum{0.0}; //!< The maximum producible intensity value. Unit is unspecified.
};
/**
* @brief The ColorLimits structure specifies the limits for the value of red, green, and blue color that a sensor is capable of producing.
*/
struct ColorLimits
{
double colorRedMinimum{0.0}; //!< The minimum producible red color value. Unit is unspecified.
double colorRedMaximum{0.0}; //!< The maximum producible red color value. Unit is unspecified.
double colorGreenMinimum{0.0}; //!< The minimum producible green color value. Unit is unspecified.
double colorGreenMaximum{0.0}; //!< The maximum producible green color value. Unit is unspecified.
double colorBlueMinimum{0.0}; //!< The minimum producible blue color value. Unit is unspecified.
double colorBlueMaximum{0.0}; //!< The maximum producible blue color value. Unit is unspecified.
};
/**
* @brief The UtcTime structure defines a valid UTC Date Time representation.
*/
struct UtcTime
{
uint32_t year{1970}; //!< The year 1900-9999
uint32_t month{1}; //!< The month 0-11
uint32_t day{1}; //!< The day 1-31
uint32_t hour{0}; //!< The hour 0-23
uint32_t minute{0}; //!< The minute 0-59
float seconds{0.0f}; //!< The seconds 0.0 - 59.999
};
/**
* @brief The GpsTime structure defines a valid GPS Time representation.
*/
struct GpsTime
{
uint16_t week{0}; //!< GPS week (0-1024+)
double tow{0.0}; //!< GPS time of week (0-604800.0)
double time{0.0}; //!< The time, in seconds, since GPS time was zero. This time specification may include fractions of a second.
/**
* @brief Default Constructor
*/
GpsTime() = default;
/**
* @brief Creates a new GpsTime structure by its gps time. The week and tow are computed internally.
*/
GpsTime(const double gps_time);
/**
* @brief Creates a new GpsTime structure by its gps week and tow. The gps time value is computed internally.
*/
GpsTime(const uint16_t gps_week, const double gps_tow);
};
} // namespace core
namespace utils
{
/**
* @brief This function returns the current GPS time as core::GpsTime.
*
* @return the current GPS Time as core::GpsTime
*/
[[nodiscard]] core::GpsTime current_gps_time() noexcept;
/**
* @brief This function returns the current UTC time as core::UtcTime.
* @details The date and time is encoded using a single
* floating point number, stored as an E57 Float element which is based on the Global Positioning
* System (GPS) time scale.
*
* @return the current Date/Time as core::UtcTime
*/
[[nodiscard]] core::UtcTime current_utc_time() noexcept;
/**
* @brief This function converts the date and time from the double dateTimeValue.
* @details The date and time is encoded using a single
* floating point number, stored as an E57 Float element which is based on the Global Positioning
* System (GPS) time scale.
*
* @param gps_time the value holding the GPS Date/Time value as core::GpsTime structure
* @return the UTC Date/Time as core::UtcTime
*/
[[nodiscard]] core::UtcTime utc_time_from_gps_time(const core::GpsTime& gps_time);
/**
* @brief This function converts the date and time from the structure core::UtcTime dateTimeValue.
* @details The date and time is encoded using a single
* floating point number, stored as an E57 Float element which is based on the Global Positioning
* System (GPS) time scale.
*
* @param utc_time the value holding the UTC Date/Time value as core::UtcTime structure
* @return the GPS Date/Time as core::GpsTime
*/
[[nodiscard]] core::GpsTime gps_time_from_utc_time(const core::UtcTime& utc_time);
} // namespace utils
} // namespace e57
#endif // OPEN57_API_H

View File

@@ -1,11 +1,11 @@
/**
@file CRC.h
@author Daniel Bahr
@version 1.1.0.0
@version 1.2.0.0
@copyright
@parblock
CRC++
Copyright (c) 2021, Daniel Bahr
Copyright (c) 2022, Daniel Bahr
All rights reserved.
Redistribution and use in source and binary forms, with or without
@@ -127,6 +127,12 @@
# define crcpp_constexpr const
#endif
#if defined(WIN32) || defined(_WIN32) || defined(WINCE)
/* Disable warning C4127: conditional expression is constant. */
#pragma warning(push)
#pragma warning(disable : 4127)
#endif
#ifdef CRCPP_USE_NAMESPACE
namespace CRCPP
{
@@ -230,6 +236,7 @@ public:
static const Parameters< crcpp_uint8, 8> & CRC_8();
#ifdef CRCPP_INCLUDE_ESOTERIC_CRC_DEFINITIONS
static const Parameters< crcpp_uint8, 8> & CRC_8_EBU();
static const Parameters< crcpp_uint8, 8> & CRC_8_HDLC();
static const Parameters< crcpp_uint8, 8> & CRC_8_MAXIM();
static const Parameters< crcpp_uint8, 8> & CRC_8_WCDMA();
static const Parameters< crcpp_uint8, 8> & CRC_8_LTE();
@@ -1216,6 +1223,24 @@ inline const CRC::Parameters<crcpp_uint8, 8> & CRC::CRC_8_EBU()
return parameters;
}
/**
@brief Returns a set of parameters for CRC-8 HDLC (ISO/IEC 13239:2002).
@note The parameters are static and are delayed-constructed to reduce memory footprint.
@note CRC-8 HDLC has the following parameters and check value:
- polynomial = 0x07
- initial value = 0xFF
- final XOR = 0xFF
- reflect input = true
- reflect output = true
- check value = 0x2F
@return CRC-8 HDLC parameters
*/
inline const CRC::Parameters<crcpp_uint8, 8> & CRC::CRC_8_HDLC()
{
static const Parameters<crcpp_uint8, 8> parameters = { 0x07, 0xFF, 0xFF, true, true };
return parameters;
}
/**
@brief Returns a set of parameters for CRC-8 MAXIM (aka CRC-8 DOW-CRC).
@note The parameters are static and are delayed-constructed to reduce memory footprint.
@@ -2082,4 +2107,8 @@ inline const CRC::Parameters<crcpp_uint64, 64> & CRC::CRC_64()
}
#endif
#if defined(WIN32) || defined(_WIN32) || defined(WINCE)
#pragma warning(pop)
#endif
#endif // CRCPP_CRC_H_

View File

@@ -134,23 +134,7 @@ std::string toString(T x)
ss << x;
return (ss.str());
}
#if 0 // <rs> 2011-10-03 below definition gives problems if intXX_t type equal to native type
inline std::string toString(uint64_t x) {std::ostringstream ss; ss << x; return(ss.str());}
inline std::string toString(uint32_t x) {std::ostringstream ss; ss << x; return(ss.str());}
inline std::string toString(uint16_t x) {std::ostringstream ss; ss << x; return(ss.str());}
inline std::string toString(uint8_t x) {std::ostringstream ss; ss << x; return(ss.str());}
inline std::string toString(int64_t x) {std::ostringstream ss; ss << x; return(ss.str());}
inline std::string toString(int32_t x) {std::ostringstream ss; ss << x; return(ss.str());}
inline std::string toString(int16_t x) {std::ostringstream ss; ss << x; return(ss.str());}
inline std::string toString(int8_t x) {std::ostringstream ss; ss << x; return(ss.str());}
# ifndef __GNUC__
inline std::string toString(int x) {std::ostringstream ss; ss << x; return(ss.str());}
inline std::string toString(unsigned x) {std::ostringstream ss; ss << x; return(ss.str());}
# endif
inline std::string toString(float x) {std::ostringstream ss; ss << x; return(ss.str());}
inline std::string toString(double x) {std::ostringstream ss; ss << x; return(ss.str());}
inline std::string toString(bool x) {std::ostringstream ss; ss << x; return(ss.str());}
#endif
inline std::string hexString(uint64_t x)
{
std::ostringstream ss;
@@ -261,40 +245,34 @@ class E57XmlParser;
class Encoder;
/// Version numbers of ASTM standard that this library supports
const uint32_t E57_FORMAT_MAJOR = 1; // Changed from 0 to 1 by SC
const uint32_t E57_FORMAT_MINOR = 0; // Changed from 6 to 0 by SC
constexpr uint32_t E57_FORMAT_MAJOR = 1; // Changed from 0 to 1 by SC
constexpr uint32_t E57_FORMAT_MINOR = 0; // Changed from 6 to 0 by SC
/// Version of Reference Implementation, E57_REFIMPL_REVISION_ID should be passed from compiler command line
/// All this macro trickery because E57_REFIMPL_REVISION_ID might not be numeric (e.g. 27M, or exported).
#define E57_REFIMPL_MAJOR 1 // Changed from 0 to 1 by SC
#define E57_REFIMPL_MINOR 0 // Changed from 1 to 0 by SC
constexpr int E57_REFIMPL_MAJOR = 1;
constexpr int E57_REFIMPL_MINOR = 0;
#ifndef E57_REFIMPL_REVISION_ID
# define E57_REFIMPL_REVISION_ID unknown
constexpr const char* E57_REFIMPL_REVISION_ID = "unknown";
#endif
#define STR_VALUE(arg) #arg
#define DO_QUOTE(name) STR_VALUE(name)
#define QUOTED_E57_REFIMPL_MAJOR DO_QUOTE(E57_REFIMPL_MAJOR)
#define QUOTED_E57_REFIMPL_MINOR DO_QUOTE(E57_REFIMPL_MINOR)
#define QUOTED_E57_REFIMPL_REVISION_ID DO_QUOTE(E57_REFIMPL_REVISION_ID)
#if 0
const char E57_LIBRARY_ID[] = "ReferenceImplementation " \
QUOTED_E57_REFIMPL_MAJOR \
"." \
QUOTED_E57_REFIMPL_MINOR \
"." \
QUOTED_E57_REFIMPL_REVISION_ID;
#else
const char E57_LIBRARY_ID[] = QUOTED_E57_REFIMPL_REVISION_ID;
#endif
/// Section types:
#define E57_BLOB_SECTION 0 // changed from 1 by SC to fit the standard
#define E57_COMPRESSED_VECTOR_SECTION 1 // changed from 2 by SC to fit the standard
constexpr int E57_BLOB_SECTION = 0; // changed from 1 by SC to fit the standard
constexpr int E57_COMPRESSED_VECTOR_SECTION = 1; // changed from 2 by SC to fit the standard
/// Packet types (in a compressed vector section)
#define E57_DATA_PACKET 1
#define E57_INDEX_PACKET 0 // changed from 2 by SC to fit the standard
#define E57_EMPTY_PACKET 2 // changed from 3 by SC to fit the standard
constexpr int E57_DATA_PACKET = 1;
constexpr int E57_INDEX_PACKET = 0; // changed from 2 by SC to fit the standard
constexpr int E57_EMPTY_PACKET = 2; // changed from 3 by SC to fit the standard
#ifdef E57_BIGENDIAN
# define SWAB(p) swab(p)
@@ -771,8 +749,8 @@ protected: //=================
class FloatNodeImpl : public NodeImpl
{
public:
FloatNodeImpl(std::weak_ptr<ImageFileImpl> destImageFile, double value = 0, FloatPrecision precision = E57_DOUBLE, double minimum = E57_DOUBLE_MIN,
double maximum = E57_DOUBLE_MAX);
FloatNodeImpl(std::weak_ptr<ImageFileImpl> destImageFile, double value = 0, FloatPrecision precision = FloatPrecision::E57_DOUBLE,
double minimum = E57_DOUBLE_MIN, double maximum = E57_DOUBLE_MAX);
virtual ~FloatNodeImpl(){};
virtual NodeType type();

View File

@@ -3,6 +3,7 @@
// E57SimpleImpl.h - private implementation header of E57 format reference implementation.
//
// Copyright (c) 2010 Stan Coleby (scoleby@intelisum.com)
// Copyright (c) 2020 - 2022 Michele Adduci (adduci@tutanota.com)
// All rights reserved.
//
// Permission is hereby granted, free of charge, to any person or organization
@@ -31,13 +32,6 @@
// ASTM E57.04 3D Imaging System File Format standard for interoperability
// of Lidar Data. See http://www.libe57.org.
//
//////////////////////////////////////////////////////////////////////////
//
// New E57SimpleImpl.h
// V1 May 18, 2010 Stan Coleby scoleby@intelisum.com
// V6 June 8, 2010 Stan Coleby scoleby@intelisum.com
//
//////////////////////////////////////////////////////////////////////////
//! @file E57SimpleImpl.h

View File

@@ -0,0 +1,309 @@
/**
\b REFERENCES \n
- Hofmann-Wellenhof, B., H. Lichtenegger, and J. Collins (1994). GPS Theory and
Practice, Third, revised edition. Springer-Verlag, Wien New York. pp. 38-42 \n
- http://aa.usno.navy.mil/data/docs/JulianDate.html - Julian Date Converter \n
- http://aa.usno.navy.mil/faq/docs/UT.html \n
- http://wwwmacho.mcmaster.ca/JAVA/JD.html \n
- Raquet, J. F. (2002), GPS Receiver Design Lecture Notes. Geomatics Engineering,
University of Calgary Graduate Course. \n
*/
#ifndef TIME_CONVERSION_H
#define TIME_CONVERSION_H
namespace e57
{
namespace utils
{
// Constants definition
constexpr const double SECONDS_IN_A_DAY = 86400.0;
constexpr const double SECONDS_IN_A_WEEK = SECONDS_IN_A_DAY * 7; // 604800.0
/**
* @brief Obtains the UTC time, GPS time, and Julian date from PC system time.
*
* @return true if successful, false otherwise
*/
[[nodiscard]] bool current_system_time(
unsigned short& utc_year, //!< Universal Time Coordinated [year]
unsigned char& utc_month, //!< Universal Time Coordinated [1-12 months]
unsigned char& utc_day, //!< Universal Time Coordinated [1-31 days]
unsigned char& utc_hour, //!< Universal Time Coordinated [hours]
unsigned char& utc_minute, //!< Universal Time Coordinated [minutes]
float& utc_seconds, //!< Universal Time Coordinated [s]
unsigned char& utc_offset, //!< Integer seconds that GPS is ahead of UTC time, always positive [s], obtained from a look up table
double& julian_date, //!< Number of days since noon Universal Time Jan 1, 4713 BCE (Julian calendar) [days]
unsigned short& gps_week, //!< GPS week (0-1024+) [week]
double& gps_tow //!< GPS time of week (0-604800.0) [s]
) noexcept;
/**
* @brief Obtains the Julian date from PC system time.
*
* @return true if successful, false otherwise
*/
[[nodiscard]] bool current_julian_date(double& julian_date //!< Number of days since noon Universal Time Jan 1, 4713 BCE (Julian calendar) [days]
) noexcept;
/**
* @brief Obtains the GPS time from PC system time.
*
* @return true if successful, false otherwise
*/
[[nodiscard]] bool current_gps_time(unsigned short& gps_week, //!< GPS week (0-1024+) [week]
double& gps_tow //!< GPS time of week (0-604800.0) [s]
) noexcept;
/**
* @brief Obtains the UTC time from PC system time.
*
* @return true if successful, false otherwise
*/
[[nodiscard]] bool current_utc_time(unsigned short& utc_year, //!< Universal Time Coordinated [year]
unsigned char& utc_month, //!< Universal Time Coordinated [1-12 months]
unsigned char& utc_day, //!< Universal Time Coordinated [1-31 days]
unsigned char& utc_hour, //!< Universal Time Coordinated [hours]
unsigned char& utc_minute, //!< Universal Time Coordinated [minutes]
float& utc_seconds //!< Universal Time Coordinated [s]
) noexcept;
/**
* @brief Computes the day of the week from the Julian date.
* @details http://en.wikipedia.org/wiki/Julian_day
*
* @return true if successful, false otherwise
*/
[[nodiscard]] bool day_of_week_from_julian_date(
const double julian_date, //!< Number of days since noon Universal Time Jan 1, 4713 BCE (Julian calendar) [days]
unsigned char& day_of_week //!< 0-Sunday, 1-Monday, 2-Tuesday, 3-Wednesday, 4-Thursday, 5-Friday, 6-Saturday [].
) noexcept;
/**
* @brief Computes the Julian date from GPS time
* @details Hofmann-Wellenhof, B., H. Lichtenegger, and J. Collins (1994). GPS Theory and
* Practice, Third, revised edition. Springer-Verlag, Wien New York. pp. 38-42
*
* @return true if successful, false otherwise
*/
[[nodiscard]] bool julian_date_from_gps_time(const unsigned short gps_week, //!< GPS week (0-1024+) [week]
const double gps_tow, //!< GPS time of week (0-604800.0) [s]
const unsigned char utc_offset, //!< Integer seconds that GPS is ahead of UTC time, always positive [s]
double& julian_date //!< Number of days since noon Universal Time Jan 1, 4713 BCE (Julian calendar) [days]
) noexcept;
/**
* @brief Computes the Julian date from UTC time
* @details Hofmann-Wellenhof, B., H. Lichtenegger, and J. Collins (1994). GPS Theory and
* Practice, Third, revised edition. Springer-Verlag, Wien New York. pp. 38-42
* @remarks Verified calculation using http://aa.usno.navy.mil/data/docs/JulianDate.html,
* a Julian Date Converter and http://wwwmacho.mcmaster.ca/JAVA/JD.html,
* another online converter tool. \n
*
* @return true if successful, false otherwise
*/
[[nodiscard]] bool julian_date_from_utc_time(const unsigned short utc_year, //!< Universal Time Coordinated [year]
const unsigned char utc_month, //!< Universal Time Coordinated [1-12 months]
const unsigned char utc_day, //!< Universal Time Coordinated [1-31 days]
const unsigned char utc_hour, //!< Universal Time Coordinated [hours]
const unsigned char utc_minute, //!< Universal Time Coordinated [minutes]
const float utc_seconds, //!< Universal Time Coordinated [s]
double& julian_date //!< Number of days since noon Universal Time Jan 1, 4713 BCE (Julian calendar) [days]
) noexcept;
/**
* @brief Computes GPS time from the Julian date
* @details Hofmann-Wellenhof, B., H. Lichtenegger, and J. Collins (1994). GPS Theory and
* Practice, Third, revised edition. Springer-Verlag, Wien New York. pp. 38-42
*
* @return true if successful, false otherwise
*/
[[nodiscard]] bool gps_time_from_julian_date(const double julian_date, //!< Number of days since noon Universal Time Jan 1, 4713 BCE (Julian calendar) [days]
const unsigned char utc_offset, //!< Integer seconds that GPS is ahead of UTC time, always positive [s]
unsigned short& gps_week, //!< GPS week (0-1024+) [week]
double& gps_tow //!< GPS time of week [s]
) noexcept;
/**
* @brief Computes UTC time from the Julian date
* @details Hofmann-Wellenhof, B., H. Lichtenegger, and J. Collins (1994). GPS Theory and
* Practice, Third, revised edition. Springer-Verlag, Wien New York. pp. 38-42
*
* @return true if successful, false otherwise
*/
[[nodiscard]] bool utc_time_from_julian_date(const double julian_date, //!< Number of days since noon Universal Time Jan 1, 4713 BCE (Julian calendar) [days]
unsigned short& utc_year, //!< Universal Time Coordinated [year]
unsigned char& utc_month, //!< Universal Time Coordinated [1-12 months]
unsigned char& utc_day, //!< Universal Time Coordinated [1-31 days]
unsigned char& utc_hour, //!< Universal Time Coordinated [hours]
unsigned char& utc_minute, //!< Universal Time Coordinated [minutes]
float& utc_seconds //!< Universal Time Coordinated [s]
) noexcept;
/**
* @brief Computes GPS time from UTC time
* @details Hofmann-Wellenhof, B., H. Lichtenegger, and J. Collins (1994). GPS Theory and
* Practice, Third, revised edition. Springer-Verlag, Wien New York. pp. 38-42
* @remarks The utc offset is determined automatically from a look up table
*
* @return true if successful, false otherwise
*/
[[nodiscard]] bool gps_time_from_utc_time(const unsigned short utc_year, //!< Universal Time Coordinated [year]
const unsigned char utc_month, //!< Universal Time Coordinated [1-12 months]
const unsigned char utc_day, //!< Universal Time Coordinated [1-31 days]
const unsigned char utc_hour, //!< Universal Time Coordinated [hours]
const unsigned char utc_minute, //!< Universal Time Coordinated [minutes]
const float utc_seconds, //!< Universal Time Coordinated [s]
unsigned short& gps_week, //!< GPS week (0-1024+) [week]
double& gps_tow //!< GPS time of week (0-604800.0) [s]
) noexcept;
/**
* @brief Computes GPS time from RINEX time. RINEX time looks like UTC but it is GPS time in year, month, day, hours, minutes, seconds.
* @details Hofmann-Wellenhof, B., H. Lichtenegger, and J. Collins (1994). GPS Theory and
* Practice, Third, revised edition. Springer-Verlag, Wien New York. pp. 38-42.
* RINEX version 2.11, (http://www.aiub-download.unibe.ch/rinex/rinex211.txt)
* @remarks There is no UTC offset to apply. The RINEX time system must be the GPS Time system to use this function.
*
* @return true if successful, false otherwise
*/
[[nodiscard]] bool gps_time_from_rinex_time(const unsigned short utc_year, //!< Universal Time Coordinated [year]
const unsigned char utc_month, //!< Universal Time Coordinated [1-12 months]
const unsigned char utc_day, //!< Universal Time Coordinated [1-31 days]
const unsigned char utc_hour, //!< Universal Time Coordinated [hours]
const unsigned char utc_minute, //!< Universal Time Coordinated [minutes]
const float utc_seconds, //!< Universal Time Coordinated [s]
unsigned short& gps_week, //!< GPS week (0-1024+) [week]
double& gps_tow //!< GPS time of week (0-604800.0) [s]
) noexcept;
/**
* @brief Computes UTC time from GPS time.
* @details Hofmann-Wellenhof, B., H. Lichtenegger, and J. Collins (1994). GPS Theory and
* Practice, Third, revised edition. Springer-Verlag, Wien New York. pp. 38-42.
* @remarks The utc offset is determined automatically from a look up table
*
* @return true if successful, false otherwise
*/
[[nodiscard]] bool utc_time_from_gps_time(const unsigned short gps_week, //!< GPS week (0-1024+) [week]
const double gps_tow, //!< GPS time of week (0-604800.0) [s]
unsigned short& utc_year, //!< Universal Time Coordinated [year]
unsigned char& utc_month, //!< Universal Time Coordinated [1-12 months]
unsigned char& utc_day, //!< Universal Time Coordinated [1-31 days]
unsigned char& utc_hour, //!< Universal Time Coordinated [hours]
unsigned char& utc_minute, //!< Universal Time Coordinated [minutes]
float& utc_seconds //!< Universal Time Coordinated [s]
) noexcept;
/**
* @brief This function is a look up table to determine the UTC offset from the Julian Date.
* @details Raquet, J. F. (2002), GPS Receiver Design Lecture Notes. Geomatics Engineering,
* University of Calgary Graduate Course.
* @remarks This function must be updated when the next UTC utc_offset step occurs. Current max is (13).
* \b "Offset Table" \n
* UTCOffset, UTC Date, Julian Date [days] \n
* 0, Jan 06 1980 00:00:00.0, 2444244.5000 \n
* 1, Jul 01 1981 00:00:00.0, 2444786.5000 \n
* 2, Jul 01 1982 00:00:00.0, 2445151.5000 \n
* 3, Jul 01 1983 00:00:00.0, 2445516.5000 \n
* 4, Jul 01 1985 00:00:00.0, 2446247.5000 \n
* 5, Jan 01 1988 00:00:00.0, 2447161.5000 \n
* 6, Jan 01 1990 00:00:00.0, 2447892.5000 \n
* 7, Jan 01 1991 00:00:00.0, 2448257.5000 \n
* 8, Jul 01 1992 00:00:00.0, 2448804.5000 \n
* 9, Jul 01 1993 00:00:00.0, 2449169.5000 \n
* 10, Jul 01 1994 00:00:00.0, 2449534.5000 \n
* 11, Jan 01 1996 00:00:00.0, 2450083.5000 \n
* 12, Jul 01 1997 00:00:00.0, 2450630.5000 \n
* 13, Jan 01 1999 00:00:00.0, 2451179.5000 \n
* 14, Jan 01 2006 00:00:00.0, 2453736.5000 \n
* 15, Jan 01 2009 00:00:00.0, 2454832.5000 \n
*
* @return true if successful, false otherwise
*/
[[nodiscard]] bool determine_utc_offset(
const double julian_date, //!< Number of days since noon Universal Time Jan 1, 4713 BCE (Julian calendar) [days]
unsigned char& utc_offset //!< Integer seconds that GPS is ahead of UTC time, always positive [s], obtained from a look up table
) noexcept;
/**
* @brief Determines the number of days in a month, given the month and year.
* @details Hofmann-Wellenhof, B., H. Lichtenegger, and J. Collins (1994). GPS Theory and
* Practice, Third, revised edition. Springer-Verlag, Wien New York. pp. 38-42.
*
* @return true if successful, false otherwise
*/
[[nodiscard]] bool number_days_in_month(const unsigned short year, //!< Universal Time Coordinated [year]
const unsigned char month, //!< Universal Time Coordinated [1-12 months]
unsigned char& days_in_month //!< Days in the specified month [1-28|29|30|31 days]
) noexcept;
/**
* @brief Determines if the given year is a leap year
* @details Hofmann-Wellenhof, B., H. Lichtenegger, and J. Collins (1994). GPS Theory and
* Practice, Third, revised edition. Springer-Verlag, Wien New York. pp. 38-42.
*
* @return true if successful, false otherwise
*/
[[nodiscard]] bool is_leap_year(const unsigned short year) noexcept;
/**
* @brief Determines the number of day in year given the year, month, and day
* @remarks Performed independant comparison with http://www.mbari.org/staff/coletti/doytable.html
*
* @return true if successful, false otherwise
*/
[[nodiscard]] bool day_of_year(const unsigned short utc_year, // Universal Time Coordinated [year]
const unsigned char utc_month, // Universal Time Coordinated [1-12 months]
const unsigned char utc_day, // Universal Time Coordinated [1-31 days]
unsigned short& day_of_year // number of days into the year (1-366) [days]
) noexcept;
/**
* @brief Determines the GPS time of the start of a day from the day of year and the year.
*
* @return true if successful, false otherwise
*/
[[nodiscard]] bool gps_time_from_year_and_day_of_year(const unsigned short year, // The year [year]
const unsigned short day_of_year, // The number of days into the year (1-366) [days]
unsigned short& gps_week, //!< GPS week (0-1024+) [week]
double& gps_tow //!< GPS time of week (0-604800.0) [s]
) noexcept;
/**
* @brief Determines if the UTC input values are valid.
*
* @return true if successful, false otherwise
*/
[[nodiscard]] bool is_utc_time_valid(const unsigned short utc_year, //!< Universal Time Coordinated [year]
const unsigned char utc_month, //!< Universal Time Coordinated [1-12 months]
const unsigned char utc_day, //!< Universal Time Coordinated [1-31 days]
const unsigned char utc_hour, //!< Universal Time Coordinated [hours]
const unsigned char utc_minute, //!< Universal Time Coordinated [minutes]
const float utc_seconds //!< Universal Time Coordinated [s]
) noexcept;
/**
* @brief Converts the GPS Time information into a single double value.
*
* @return true if successful, false otherwise
*/
[[nodiscard]] bool gps_time_to_value(const unsigned short gps_week, //!< GPS week (0-1024+) [week]
const double gps_tow, //!< GPS time of week (0-604800.0) [s])
double& gps_time //!< GPS time expressed as a single double value)
) noexcept;
/**
* @brief Converts the GPS Time information from a single double value to week and tow.
*
* @return true if successful, false otherwise
*/
[[nodiscard]] bool gps_time_from_value(const double gps_time, //!< GPS time expressed as a single double value)
unsigned short& gps_week, //!< GPS week (0-1024+) [week]
double& gps_tow //!< GPS time of week (0-604800.0) [s])
) noexcept;
} // namespace utils
} // namespace e57
#endif // TIME_CONVERSION_H

View File

@@ -26,8 +26,8 @@
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
#ifndef E57FOUNDATION_H_INCLUDED
#define E57FOUNDATION_H_INCLUDED
#ifndef OPENE57_H_INCLUDED
#define OPENE57_H_INCLUDED
//! @file openE57.h header file for the E57 Foundation API
@@ -60,83 +60,89 @@ using std::uint32_t;
using std::uint64_t;
using std::uint8_t;
template <class E, class T = typename std::underlying_type<E>::type>
T printable(E val)
{
return T(val);
}
// Shorthand for unicode string
//! @brief UTF-8 encodeded Unicode string
typedef std::string ustring;
//! @brief Identifiers for types of E57 elements
/** @enum e57::NodeType
* @brief Identifiers for types of E57 elements
*/
enum NodeType
{
E57_STRUCTURE = 1, //!< StructureNode class
E57_VECTOR = 2, //!< VectorNode class
E57_COMPRESSED_VECTOR = 3, //!< CompressedVectorNode class
E57_INTEGER = 4, //!< IntegerNode class
E57_SCALED_INTEGER = 5, //!< ScaledIntegerNode class
E57_FLOAT = 6, //!< FloatNode class
E57_STRING = 7, //!< StringNode class
E57_BLOB = 8 //!< BlobNode class
E57_STRUCTURE = 1, /**< StructureNode class, coded as std::int8_t of value 1 */
E57_VECTOR = 2, /**< VectorNode class, coded as std::int8_t of value 2 */
E57_COMPRESSED_VECTOR = 3, /**< CompressedVectorNode class, coded as std::int8_t of value 3 */
E57_INTEGER = 4, /**< IntegerNode class, coded as std::int8_t of value 4 */
E57_SCALED_INTEGER = 5, /**< ScaledIntegerNode class, coded as std::int8_t of value 5 */
E57_FLOAT = 6, /**< FloatNode class, coded as std::int8_t of value 6 */
E57_STRING = 7, /**< StringNode class, coded as std::int8_t of value 7 */
E57_BLOB = 8 /**< BlobNode class, coded as std::int8_t of value 8 */
};
//! @brief The IEEE floating point number precisions supported
/** @enum e57::FloatPrecision
* @brief The IEEE floating point number precisions supported
*/
enum FloatPrecision
{
E57_SINGLE = 1, //!< 32 bit IEEE floating point number format
E57_DOUBLE = 2 //!< 64 bit IEEE floating point number format
E57_SINGLE = 1, /**< 32 bit IEEE floating point number format, coded as std::int8_t of value 1 */
E57_DOUBLE = 2 /**< 64 bit IEEE floating point number format, coded as std::int8_t of value 1 */
};
//! @brief Identifies the representations of memory elements API can transfer data to/from
/** @enum e57::MemoryRepresentation
* @brief Identifies the representations of memory elements API can transfer data to/from
*/
enum MemoryRepresentation
{
E57_INT8 = 1, //!< 8 bit signed integer
E57_UINT8 = 2, //!< 8 bit unsigned integer
E57_INT16 = 3, //!< 16 bit signed integer
E57_UINT16 = 4, //!< 16 bit unsigned integer
E57_INT32 = 5, //!< 32 bit signed integer
E57_UINT32 = 6, //!< 32 bit unsigned integer
E57_INT64 = 7, //!< 64 bit signed integer
E57_BOOL = 8, //!< C++ boolean type
E57_REAL32 = 9, //!< C++ float type
E57_REAL64 = 10, //!< C++ double type
E57_USTRING = 11 //!< Unicode UTF-8 std::string
E57_INT8 = 1, /**< 8 bit signed integer, coded as std::int8_t of value 1 */
E57_UINT8 = 2, /**< 8 bit unsigned integer, coded as std::int8_t of value 2 */
E57_INT16 = 3, /**< 16 bit signed integer, coded as std::int8_t of value 3 */
E57_UINT16 = 4, /**< 16 bit unsigned integer, coded as std::int8_t of value 4 */
E57_INT32 = 5, /**< 32 bit signed integer, coded as std::int8_t of value 5 */
E57_UINT32 = 6, /**< 32 bit unsigned integer, coded as std::int8_t of value 6 */
E57_INT64 = 7, /**< 64 bit signed integer, coded as std::int8_t of value 7 */
E57_BOOL = 8, /**< C++ boolean type, coded as std::int8_t of value 8 */
E57_REAL32 = 9, /**< C++ float type, coded as std::int8_t of value 9 */
E57_REAL64 = 10, /**< C++ double type, coded as std::int8_t of value 10 */
E57_USTRING = 11 /**< Unicode UTF-8 std::string, coded as std::int8_t of value 11 */
};
//! @brief The major version number of the Foundation API
const int E57_FOUNDATION_API_MAJOR = 0;
//! @brief The minor version number of the Foundation API
const int E57_FOUNDATION_API_MINOR = 51;
//! @brief The URI of ASTM E57 v1.0 standard XML namespace
// Used to identify the standard field names and the grammar that relates them.
// Will typically be associated with the default namespace in an E57 file.
#define E57_V1_0_URI "http://www.astm.org/COMMIT/E57/2010-e57-v1.0"
constexpr const char* E57_V1_0_URI = "http://www.astm.org/COMMIT/E57/2010-e57-v1.0";
//! @cond documentNonPublic The following aren't documented
// Minimum and maximum values for integers
// see https://en.cppreference.com/w/cpp/types/numeric_limits
const int8_t E57_INT8_MIN = std::numeric_limits<int8_t>::lowest();
const int8_t E57_INT8_MAX = std::numeric_limits<int8_t>::max();
const int16_t E57_INT16_MIN = std::numeric_limits<int16_t>::lowest();
const int16_t E57_INT16_MAX = std::numeric_limits<int16_t>::max();
const int32_t E57_INT32_MIN = std::numeric_limits<int32_t>::lowest();
const int32_t E57_INT32_MAX = std::numeric_limits<int32_t>::max();
const int64_t E57_INT64_MIN = std::numeric_limits<int64_t>::lowest();
const int64_t E57_INT64_MAX = std::numeric_limits<int64_t>::max();
constexpr const int8_t E57_INT8_MIN = std::numeric_limits<int8_t>::lowest();
constexpr const int8_t E57_INT8_MAX = std::numeric_limits<int8_t>::max();
constexpr const int16_t E57_INT16_MIN = std::numeric_limits<int16_t>::lowest();
constexpr const int16_t E57_INT16_MAX = std::numeric_limits<int16_t>::max();
constexpr const int32_t E57_INT32_MIN = std::numeric_limits<int32_t>::lowest();
constexpr const int32_t E57_INT32_MAX = std::numeric_limits<int32_t>::max();
constexpr const int64_t E57_INT64_MIN = std::numeric_limits<int64_t>::lowest();
constexpr const int64_t E57_INT64_MAX = std::numeric_limits<int64_t>::max();
const uint8_t E57_UINT8_MIN = std::numeric_limits<uint8_t>::lowest();
const uint8_t E57_UINT8_MAX = std::numeric_limits<uint8_t>::max();
const uint16_t E57_UINT16_MIN = std::numeric_limits<uint16_t>::lowest();
const uint16_t E57_UINT16_MAX = std::numeric_limits<uint16_t>::max();
const uint32_t E57_UINT32_MIN = std::numeric_limits<uint32_t>::lowest();
const uint32_t E57_UINT32_MAX = std::numeric_limits<uint32_t>::max();
const uint64_t E57_UINT64_MIN = std::numeric_limits<uint64_t>::lowest();
const uint64_t E57_UINT64_MAX = std::numeric_limits<uint64_t>::max();
constexpr const uint8_t E57_UINT8_MIN = std::numeric_limits<uint8_t>::lowest();
constexpr const uint8_t E57_UINT8_MAX = std::numeric_limits<uint8_t>::max();
constexpr const uint16_t E57_UINT16_MIN = std::numeric_limits<uint16_t>::lowest();
constexpr const uint16_t E57_UINT16_MAX = std::numeric_limits<uint16_t>::max();
constexpr const uint32_t E57_UINT32_MIN = std::numeric_limits<uint32_t>::lowest();
constexpr const uint32_t E57_UINT32_MAX = std::numeric_limits<uint32_t>::max();
constexpr const uint64_t E57_UINT64_MIN = std::numeric_limits<uint64_t>::lowest();
constexpr const uint64_t E57_UINT64_MAX = std::numeric_limits<uint64_t>::max();
const float E57_FLOAT_MIN = std::numeric_limits<float>::lowest();
const float E57_FLOAT_MAX = std::numeric_limits<float>::max();
const double E57_DOUBLE_MIN = std::numeric_limits<double>::lowest();
const double E57_DOUBLE_MAX = std::numeric_limits<double>::max();
constexpr const float E57_FLOAT_MIN = std::numeric_limits<float>::lowest();
constexpr const float E57_FLOAT_MAX = std::numeric_limits<float>::max();
constexpr const double E57_DOUBLE_MIN = std::numeric_limits<double>::lowest();
constexpr const double E57_DOUBLE_MAX = std::numeric_limits<double>::max();
//! @endcond
// Forward references to classes in this header
@@ -518,7 +524,7 @@ protected: //==============
class FloatNode
{
public:
explicit FloatNode(ImageFile destImageFile, double value = 0.0, FloatPrecision precision = E57_DOUBLE, double minimum = E57_DOUBLE_MIN,
explicit FloatNode(ImageFile destImageFile, double value = 0.0, FloatPrecision precision = FloatPrecision::E57_DOUBLE, double minimum = E57_DOUBLE_MIN,
double maximum = E57_DOUBLE_MAX);
double value() const;
@@ -771,17 +777,24 @@ protected: //=================
//! \endcond
};
struct VersionInfo
{
int major;
int minor;
ustring id;
};
class E57Utilities
{
public:
// Constructor (does nothing for now)
E57Utilities(const ustring& /*configuration*/ = ""){};
// Get latest version of ASTM standard supported, and library id string
void getVersions(int& astmMajor, int& astmMinor, ustring& libraryId);
void getVersions(int& astmMajor, int& astmMinor, ustring& libraryId) noexcept;
// Get information about supported standard and library id
VersionInfo getVersion() noexcept;
// Error code translation
ustring errorCodeToString(ErrorCode ecode);
ustring errorCodeToString(ErrorCode ecode) noexcept;
// Direct read of XML representation in E57 file
int64_t rawXmlLength(const ustring& fname);
@@ -792,4 +805,4 @@ public:
} // end namespace e57
#endif
#endif // E57FOUNDATION_H_INCLUDED
#endif // OPENE57_H_INCLUDED

View File

@@ -178,8 +178,8 @@ public:
//
//! @brief The e57::DateTime is a structure for encoding date and time.
/*! @details The date and time is encoded using a single
562 floating point number, stored as an E57 Float element which is based on the Global Positioning
563 System (GPS) time scale. */
floating point number, stored as an E57 Float element which is based on the Global Positioning
System (GPS) time scale. */
class DateTime
{
@@ -439,7 +439,7 @@ public:
ustring sensorFirmwareVersion; //!< The version number for the firmware installed in the sensor at the time of data collection.
float
temperature; //!< The ambient temperature, measured at the sensor, at the time of data collection (in degrees Celsius). Shall be ? ?273.15<EFBFBD> (absolute zero).
temperature; //!< The ambient temperature, measured at the sensor, at the time of data collection (in degrees Celsius). Shall be ? ?273.15<EFBFBD> (absolute zero).
float relativeHumidity; //!< The percentage relative humidity, measured at the sensor, at the time of data collection. Shall be in the interval [0, 100].
float atmosphericPressure; //!< The atmospheric pressure, measured at the sensor, at the time of data collection (in Pascals). Shall be positive.
@@ -452,7 +452,7 @@ public:
e57::CartesianBounds
cartesianBounds; //!< The bounding region (in cartesian coordinates) of all the points in this Data3D (in the local coordinate system of the points).
e57::SphericalBounds
sphericalBounds; //!< The bounding region (in spherical coordinates) of all the points in this Data3D (in the local coordinate system of the points).
sphericalBounds; //!< The bounding region (in spherical coordinates) of all the points in this Data3D (in the local coordinate system of the points).
e57::IntensityLimits intensityLimits; //!< The limits for the value of signal intensity that the sensor is capable of producing.
e57::ColorLimits colorLimits; //!< The limits for the value of red, green, and blue color that the sensor is capable of producing.

98
src/lib/src/api.cpp Normal file
View File

@@ -0,0 +1,98 @@
#include <openE57/api.h>
#include <openE57/impl/time_conversion.h>
using namespace e57;
core::GpsTime::GpsTime(const double gps_time) : time{gps_time}
{
unsigned short gps_week{};
double gps_tow{};
if (!utils::gps_time_from_value(gps_time, gps_week, gps_tow))
{
this->week = 0;
this->tow = 0.0;
return;
}
this->week = gps_week;
this->tow = gps_tow;
}
core::GpsTime::GpsTime(const uint16_t gps_week, const double gps_tow) : week{gps_week}, tow{gps_tow}
{
double gps_time{};
if (!utils::gps_time_to_value(week, tow, gps_time))
{
this->time = 0.0;
return;
}
this->time = gps_time;
}
[[nodiscard]] core::GpsTime utils::current_gps_time() noexcept
{
uint16_t gps_week{};
double gps_tow{};
double gps_time{};
if (!utils::current_gps_time(gps_week, gps_tow))
{
return core::GpsTime{};
}
if (!utils::gps_time_to_value(gps_week, gps_tow, gps_time))
{
return core::GpsTime(0.0);
}
return core::GpsTime(gps_time);
}
[[nodiscard]] core::UtcTime utils::current_utc_time() noexcept
{
unsigned short utc_year{};
unsigned char utc_month{};
unsigned char utc_day{};
unsigned char utc_hour{};
unsigned char utc_minute{};
float utc_seconds{};
if (!utils::current_utc_time(utc_year, utc_month, utc_day, utc_hour, utc_minute, utc_seconds))
{
return core::UtcTime{};
}
return core::UtcTime{utc_year, utc_month, utc_day, utc_hour, utc_minute, utc_seconds};
}
[[nodiscard]] core::UtcTime utils::utc_time_from_gps_time(const core::GpsTime& gps_time)
{
unsigned short utc_year{};
unsigned char utc_month{};
unsigned char utc_day{};
unsigned char utc_hour{};
unsigned char utc_minute{};
float utc_seconds{};
if (!utils::utc_time_from_gps_time(gps_time.week, gps_time.tow, utc_year, utc_month, utc_day, utc_hour, utc_minute, utc_seconds))
{
return core::UtcTime{};
}
return core::UtcTime{utc_year, utc_month, utc_day, utc_hour, utc_minute, utc_seconds};
}
[[nodiscard]] core::GpsTime utils::gps_time_from_utc_time(const core::UtcTime& utc_time)
{
unsigned short gps_week{};
double gps_tow{};
if (!utils::gps_time_from_utc_time(utc_time.year, utc_time.month, utc_time.day, utc_time.hour, utc_time.minute, utc_time.seconds, gps_week, gps_tow))
{
return core::GpsTime{};
}
return core::GpsTime(gps_week, gps_tow);
}

View File

@@ -1109,7 +1109,7 @@ void Node::checkInvariant(bool doRecurse, bool doDowncast)
}
// Non-root nodes must be children of either a VectorNode or StructureNode
if (parent().type() == E57_VECTOR)
if (parent().type() == NodeType::E57_VECTOR)
{
VectorNode v = static_cast<VectorNode>(parent());
@@ -1121,7 +1121,7 @@ void Node::checkInvariant(bool doRecurse, bool doDowncast)
if (v.get(elementName()) != *this)
throw E57_EXCEPTION1(E57_ERROR_INVARIANCE_VIOLATION);
}
else if (parent().type() == E57_STRUCTURE)
else if (parent().type() == NodeType::E57_STRUCTURE)
{
StructureNode s = static_cast<StructureNode>(parent());
@@ -1163,42 +1163,42 @@ void Node::checkInvariant(bool doRecurse, bool doDowncast)
{
switch (type())
{
case E57_STRUCTURE: {
case NodeType::E57_STRUCTURE: {
StructureNode s(*this);
s.checkInvariant(doRecurse, false);
}
break;
case E57_VECTOR: {
case NodeType::E57_VECTOR: {
VectorNode v(*this);
v.checkInvariant(doRecurse, false);
}
break;
case E57_COMPRESSED_VECTOR: {
case NodeType::E57_COMPRESSED_VECTOR: {
CompressedVectorNode cv(*this);
cv.checkInvariant(doRecurse, false);
}
break;
case E57_INTEGER: {
case NodeType::E57_INTEGER: {
IntegerNode i(*this);
i.checkInvariant(doRecurse, false);
}
break;
case E57_SCALED_INTEGER: {
case NodeType::E57_SCALED_INTEGER: {
ScaledIntegerNode si(*this);
si.checkInvariant(doRecurse, false);
}
break;
case E57_FLOAT: {
case NodeType::E57_FLOAT: {
FloatNode f(*this);
f.checkInvariant(doRecurse, false);
}
break;
case E57_STRING: {
case NodeType::E57_STRING: {
StringNode s(*this);
s.checkInvariant(doRecurse, false);
}
break;
case E57_BLOB: {
case NodeType::E57_BLOB: {
BlobNode b(*this);
b.checkInvariant(doRecurse, false);
}
@@ -1453,7 +1453,7 @@ void FloatNode::checkInvariant(bool /*doRecurse*/, bool doUpcast)
if (doUpcast)
static_cast<Node>(*this).checkInvariant(false, false);
if (precision() == E57_SINGLE)
if (precision() == FloatPrecision::E57_SINGLE)
{
if (minimum() < E57_FLOAT_MIN || maximum() > E57_FLOAT_MAX)
throw E57_EXCEPTION1(E57_ERROR_INVARIANCE_VIOLATION);
@@ -1663,37 +1663,37 @@ void SourceDestBuffer::checkInvariant(bool /*doRecurse*/)
size_t min_stride = 0;
switch (memoryRepresentation())
{
case E57_INT8:
case MemoryRepresentation::E57_INT8:
min_stride = 1;
break;
case E57_UINT8:
case MemoryRepresentation::E57_UINT8:
min_stride = 1;
break;
case E57_INT16:
case MemoryRepresentation::E57_INT16:
min_stride = 2;
break;
case E57_UINT16:
case MemoryRepresentation::E57_UINT16:
min_stride = 2;
break;
case E57_INT32:
case MemoryRepresentation::E57_INT32:
min_stride = 4;
break;
case E57_UINT32:
case MemoryRepresentation::E57_UINT32:
min_stride = 4;
break;
case E57_INT64:
case MemoryRepresentation::E57_INT64:
min_stride = 8;
break;
case E57_BOOL:
case MemoryRepresentation::E57_BOOL:
min_stride = 1;
break;
case E57_REAL32:
case MemoryRepresentation::E57_REAL32:
min_stride = 4;
break;
case E57_REAL64:
case MemoryRepresentation::E57_REAL64:
min_stride = 8;
break;
case E57_USTRING:
case MemoryRepresentation::E57_USTRING:
min_stride = sizeof(ustring);
break;
default:
@@ -5183,16 +5183,6 @@ Having these functions be member functions of a constructed object allows these
at compile time.
*/
/*================*/ /*!
@fn E57Utilities::E57Utilities(const ustring &)
@brief Create an object that allows access to functions that are not associated with an ImageFile.
@details
Because the construction of the E57Utilities object may be expensive, it is recommended that an application create and save a single instance of the object to use to access its member functions without constructing a E57Utilites object on every call.
@return An object that allows access to functions that are not associated with an ImageFile.
@throw ::E57_ERROR_BAD_CONFIGURATION
@see Versions.cpp example, ImageFile::ImageFile
*/ /*================*/
/*================*/ /*!
@brief Get the version of ASTM E57 standard that the API implementation supports, and library id string.
@param [out] astmMajor The major version number of the ASTM E57 standard supported.
@@ -5201,26 +5191,37 @@ Because the construction of the E57Utilities object may be expensive, it is reco
@details
Since the E57 Foundation Implementation may be dynamically linked underneath the Foundation API, the version string for the implementation and the ASTM version that it supports can't be determined at compile-time.
This function returns these identifiers from the underlying implementation.
@throw No E57Exceptions.
@see Versions.cpp example, E57Utilities::E57Utilities
*/ /*================*/
void E57Utilities::getVersions(int& astmMajor, int& astmMinor, ustring& libraryId)
void E57Utilities::getVersions(int& astmMajor, int& astmMinor, ustring& libraryId) noexcept
{
astmMajor = E57_FORMAT_MAJOR;
astmMinor = E57_FORMAT_MINOR;
libraryId = E57_LIBRARY_ID;
}
/*================*/ /*!
@brief Get the version of ASTM E57 standard that the API implementation supports, and library id string.
@param [out] VersionInfo a structure holding information about API implementation supported.
@details
Since the E57 Foundation Implementation may be dynamically linked underneath the Foundation API, the version string for the implementation and the ASTM version that it supports can't be determined at compile-time.
This function returns these identifiers from the underlying implementation.
@see Versions.cpp example, E57Utilities::E57Utilities
*/ /*================*/
VersionInfo E57Utilities::getVersion() noexcept
{
return VersionInfo{E57_FORMAT_MAJOR, E57_FORMAT_MINOR, E57_LIBRARY_ID};
}
/*================*/ /*!
@brief Get short string description of an E57 ErrorCode.
@param [in] ecode The numeric errorCode from an E57Exception.
@details
The errorCode is translated into a one-line English string.
@return English ustring describing error.
@throw No E57Exceptions.
@see E57ExceptionsFunctions.cpp example, E57Exception::errorCode, E57Utilities::E57Utilities
*/ /*================*/
ustring E57Utilities::errorCodeToString(ErrorCode ecode)
ustring E57Utilities::errorCodeToString(ErrorCode ecode) noexcept
{
switch (ecode)
{

View File

@@ -994,8 +994,8 @@ void VectorNodeImpl::dump(int indent, ostream& os)
//=====================================================================================
SourceDestBufferImpl::SourceDestBufferImpl(std::weak_ptr<ImageFileImpl> destImageFile, const ustring pathName, int8_t* base, const size_t capacity,
bool doConversion, bool doScaling, size_t stride)
: destImageFile_(destImageFile), pathName_(pathName), memoryRepresentation_(E57_INT8), base_(reinterpret_cast<char*>(base)), capacity_(capacity),
doConversion_(doConversion), doScaling_(doScaling), stride_(stride), nextIndex_(0), ustrings_(0)
: destImageFile_(destImageFile), pathName_(pathName), memoryRepresentation_(MemoryRepresentation::E57_INT8), base_(reinterpret_cast<char*>(base)),
capacity_(capacity), doConversion_(doConversion), doScaling_(doScaling), stride_(stride), nextIndex_(0), ustrings_(0)
{
/// don't checkImageFileOpen, checkState_ will do it
checkState_();
@@ -1003,8 +1003,8 @@ SourceDestBufferImpl::SourceDestBufferImpl(std::weak_ptr<ImageFileImpl> destImag
SourceDestBufferImpl::SourceDestBufferImpl(std::weak_ptr<ImageFileImpl> destImageFile, const ustring pathName, uint8_t* base, const size_t capacity,
bool doConversion, bool doScaling, size_t stride)
: destImageFile_(destImageFile), pathName_(pathName), memoryRepresentation_(E57_UINT8), base_(reinterpret_cast<char*>(base)), capacity_(capacity),
doConversion_(doConversion), doScaling_(doScaling), stride_(stride), nextIndex_(0), ustrings_(0)
: destImageFile_(destImageFile), pathName_(pathName), memoryRepresentation_(MemoryRepresentation::E57_UINT8), base_(reinterpret_cast<char*>(base)),
capacity_(capacity), doConversion_(doConversion), doScaling_(doScaling), stride_(stride), nextIndex_(0), ustrings_(0)
{
/// don't checkImageFileOpen, checkState_ will do it
checkState_();
@@ -1012,8 +1012,8 @@ SourceDestBufferImpl::SourceDestBufferImpl(std::weak_ptr<ImageFileImpl> destImag
SourceDestBufferImpl::SourceDestBufferImpl(std::weak_ptr<ImageFileImpl> destImageFile, const ustring pathName, int16_t* base, const size_t capacity,
bool doConversion, bool doScaling, size_t stride)
: destImageFile_(destImageFile), pathName_(pathName), memoryRepresentation_(E57_INT16), base_(reinterpret_cast<char*>(base)), capacity_(capacity),
doConversion_(doConversion), doScaling_(doScaling), stride_(stride), nextIndex_(0), ustrings_(0)
: destImageFile_(destImageFile), pathName_(pathName), memoryRepresentation_(MemoryRepresentation::E57_INT16), base_(reinterpret_cast<char*>(base)),
capacity_(capacity), doConversion_(doConversion), doScaling_(doScaling), stride_(stride), nextIndex_(0), ustrings_(0)
{
/// don't checkImageFileOpen, checkState_ will do it
checkState_();
@@ -1021,8 +1021,8 @@ SourceDestBufferImpl::SourceDestBufferImpl(std::weak_ptr<ImageFileImpl> destImag
SourceDestBufferImpl::SourceDestBufferImpl(std::weak_ptr<ImageFileImpl> destImageFile, const ustring pathName, uint16_t* base, const size_t capacity,
bool doConversion, bool doScaling, size_t stride)
: destImageFile_(destImageFile), pathName_(pathName), memoryRepresentation_(E57_UINT16), base_(reinterpret_cast<char*>(base)), capacity_(capacity),
doConversion_(doConversion), doScaling_(doScaling), stride_(stride), nextIndex_(0), ustrings_(0)
: destImageFile_(destImageFile), pathName_(pathName), memoryRepresentation_(MemoryRepresentation::E57_UINT16), base_(reinterpret_cast<char*>(base)),
capacity_(capacity), doConversion_(doConversion), doScaling_(doScaling), stride_(stride), nextIndex_(0), ustrings_(0)
{
/// don't checkImageFileOpen, checkState_ will do it
checkState_();
@@ -1030,8 +1030,8 @@ SourceDestBufferImpl::SourceDestBufferImpl(std::weak_ptr<ImageFileImpl> destImag
SourceDestBufferImpl::SourceDestBufferImpl(std::weak_ptr<ImageFileImpl> destImageFile, const ustring pathName, int32_t* base, const size_t capacity,
bool doConversion, bool doScaling, size_t stride)
: destImageFile_(destImageFile), pathName_(pathName), memoryRepresentation_(E57_INT32), base_(reinterpret_cast<char*>(base)), capacity_(capacity),
doConversion_(doConversion), doScaling_(doScaling), stride_(stride), nextIndex_(0), ustrings_(0)
: destImageFile_(destImageFile), pathName_(pathName), memoryRepresentation_(MemoryRepresentation::E57_INT32), base_(reinterpret_cast<char*>(base)),
capacity_(capacity), doConversion_(doConversion), doScaling_(doScaling), stride_(stride), nextIndex_(0), ustrings_(0)
{
/// don't checkImageFileOpen, checkState_ will do it
checkState_();
@@ -1039,8 +1039,8 @@ SourceDestBufferImpl::SourceDestBufferImpl(std::weak_ptr<ImageFileImpl> destImag
SourceDestBufferImpl::SourceDestBufferImpl(std::weak_ptr<ImageFileImpl> destImageFile, const ustring pathName, uint32_t* base, const size_t capacity,
bool doConversion, bool doScaling, size_t stride)
: destImageFile_(destImageFile), pathName_(pathName), memoryRepresentation_(E57_UINT32), base_(reinterpret_cast<char*>(base)), capacity_(capacity),
doConversion_(doConversion), doScaling_(doScaling), stride_(stride), nextIndex_(0), ustrings_(0)
: destImageFile_(destImageFile), pathName_(pathName), memoryRepresentation_(MemoryRepresentation::E57_UINT32), base_(reinterpret_cast<char*>(base)),
capacity_(capacity), doConversion_(doConversion), doScaling_(doScaling), stride_(stride), nextIndex_(0), ustrings_(0)
{
/// don't checkImageFileOpen, checkState_ will do it
checkState_();
@@ -1048,8 +1048,8 @@ SourceDestBufferImpl::SourceDestBufferImpl(std::weak_ptr<ImageFileImpl> destImag
SourceDestBufferImpl::SourceDestBufferImpl(std::weak_ptr<ImageFileImpl> destImageFile, const ustring pathName, int64_t* base, const size_t capacity,
bool doConversion, bool doScaling, size_t stride)
: destImageFile_(destImageFile), pathName_(pathName), memoryRepresentation_(E57_INT64), base_(reinterpret_cast<char*>(base)), capacity_(capacity),
doConversion_(doConversion), doScaling_(doScaling), stride_(stride), nextIndex_(0), ustrings_(0)
: destImageFile_(destImageFile), pathName_(pathName), memoryRepresentation_(MemoryRepresentation::E57_INT64), base_(reinterpret_cast<char*>(base)),
capacity_(capacity), doConversion_(doConversion), doScaling_(doScaling), stride_(stride), nextIndex_(0), ustrings_(0)
{
/// don't checkImageFileOpen, checkState_ will do it
checkState_();
@@ -1057,8 +1057,8 @@ SourceDestBufferImpl::SourceDestBufferImpl(std::weak_ptr<ImageFileImpl> destImag
SourceDestBufferImpl::SourceDestBufferImpl(std::weak_ptr<ImageFileImpl> destImageFile, const ustring pathName, bool* base, const size_t capacity,
bool doConversion, bool doScaling, size_t stride)
: destImageFile_(destImageFile), pathName_(pathName), memoryRepresentation_(E57_BOOL), base_(reinterpret_cast<char*>(base)), capacity_(capacity),
doConversion_(doConversion), doScaling_(doScaling), stride_(stride), nextIndex_(0), ustrings_(0)
: destImageFile_(destImageFile), pathName_(pathName), memoryRepresentation_(MemoryRepresentation::E57_BOOL), base_(reinterpret_cast<char*>(base)),
capacity_(capacity), doConversion_(doConversion), doScaling_(doScaling), stride_(stride), nextIndex_(0), ustrings_(0)
{
/// don't checkImageFileOpen, checkState_ will do it
checkState_();
@@ -1066,8 +1066,8 @@ SourceDestBufferImpl::SourceDestBufferImpl(std::weak_ptr<ImageFileImpl> destImag
SourceDestBufferImpl::SourceDestBufferImpl(std::weak_ptr<ImageFileImpl> destImageFile, const ustring pathName, float* base, const size_t capacity,
bool doConversion, bool doScaling, size_t stride)
: destImageFile_(destImageFile), pathName_(pathName), memoryRepresentation_(E57_REAL32), base_(reinterpret_cast<char*>(base)), capacity_(capacity),
doConversion_(doConversion), doScaling_(doScaling), stride_(stride), nextIndex_(0), ustrings_(0)
: destImageFile_(destImageFile), pathName_(pathName), memoryRepresentation_(MemoryRepresentation::E57_REAL32), base_(reinterpret_cast<char*>(base)),
capacity_(capacity), doConversion_(doConversion), doScaling_(doScaling), stride_(stride), nextIndex_(0), ustrings_(0)
{
/// don't checkImageFileOpen, checkState_ will do it
checkState_();
@@ -1075,16 +1075,16 @@ SourceDestBufferImpl::SourceDestBufferImpl(std::weak_ptr<ImageFileImpl> destImag
SourceDestBufferImpl::SourceDestBufferImpl(std::weak_ptr<ImageFileImpl> destImageFile, const ustring pathName, double* base, const size_t capacity,
bool doConversion, bool doScaling, size_t stride)
: destImageFile_(destImageFile), pathName_(pathName), memoryRepresentation_(E57_REAL64), base_(reinterpret_cast<char*>(base)), capacity_(capacity),
doConversion_(doConversion), doScaling_(doScaling), stride_(stride), nextIndex_(0), ustrings_(0)
: destImageFile_(destImageFile), pathName_(pathName), memoryRepresentation_(MemoryRepresentation::E57_REAL64), base_(reinterpret_cast<char*>(base)),
capacity_(capacity), doConversion_(doConversion), doScaling_(doScaling), stride_(stride), nextIndex_(0), ustrings_(0)
{
/// don't checkImageFileOpen, checkState_ will do it
checkState_();
}
SourceDestBufferImpl::SourceDestBufferImpl(std::weak_ptr<ImageFileImpl> destImageFile, const ustring pathName, vector<ustring>* b)
: destImageFile_(destImageFile), pathName_(pathName), memoryRepresentation_(E57_USTRING), base_(0), capacity_(0 /*updated below*/), doConversion_(false),
doScaling_(false), stride_(0), nextIndex_(0), ustrings_(b)
: destImageFile_(destImageFile), pathName_(pathName), memoryRepresentation_(MemoryRepresentation::E57_USTRING), base_(0), capacity_(0 /*updated below*/),
doConversion_(false), doScaling_(false), stride_(0), nextIndex_(0), ustrings_(b)
{
/// don't checkImageFileOpen, checkState_ will do it
@@ -1141,46 +1141,46 @@ int64_t SourceDestBufferImpl::getNextInt64()
int64_t value;
switch (memoryRepresentation_)
{
case E57_INT8:
case MemoryRepresentation::E57_INT8:
value = static_cast<int64_t>(*reinterpret_cast<int8_t*>(p));
break;
case E57_UINT8:
case MemoryRepresentation::E57_UINT8:
value = static_cast<int64_t>(*reinterpret_cast<uint8_t*>(p));
break;
case E57_INT16:
case MemoryRepresentation::E57_INT16:
value = static_cast<int64_t>(*reinterpret_cast<int16_t*>(p));
break;
case E57_UINT16:
case MemoryRepresentation::E57_UINT16:
value = static_cast<int64_t>(*reinterpret_cast<uint16_t*>(p));
break;
case E57_INT32:
case MemoryRepresentation::E57_INT32:
value = static_cast<int64_t>(*reinterpret_cast<int32_t*>(p));
break;
case E57_UINT32:
case MemoryRepresentation::E57_UINT32:
value = static_cast<int64_t>(*reinterpret_cast<uint32_t*>(p));
break;
case E57_INT64:
case MemoryRepresentation::E57_INT64:
value = *reinterpret_cast<int64_t*>(p);
break;
case E57_BOOL:
case MemoryRepresentation::E57_BOOL:
if (!doConversion_)
throw E57_EXCEPTION2(E57_ERROR_CONVERSION_REQUIRED, "pathName=" + pathName_);
/// Convert bool to 0/1, all non-zero values map to 1.0
value = (*reinterpret_cast<bool*>(p)) ? 1 : 0;
break;
case E57_REAL32:
case MemoryRepresentation::E57_REAL32:
if (!doConversion_)
throw E57_EXCEPTION2(E57_ERROR_CONVERSION_REQUIRED, "pathName=" + pathName_);
//??? fault if get special value: NaN, NegInf...
value = static_cast<int64_t>(*reinterpret_cast<float*>(p));
break;
case E57_REAL64:
case MemoryRepresentation::E57_REAL64:
if (!doConversion_)
throw E57_EXCEPTION2(E57_ERROR_CONVERSION_REQUIRED, "pathName=" + pathName_);
//??? fault if get special value: NaN, NegInf...
value = static_cast<int64_t>(*reinterpret_cast<double*>(p));
break;
case E57_USTRING:
case MemoryRepresentation::E57_USTRING:
throw E57_EXCEPTION2(E57_ERROR_EXPECTING_NUMERIC, "pathName=" + pathName_);
default:
throw E57_EXCEPTION2(E57_ERROR_INTERNAL, "pathName=" + pathName_);
@@ -1217,41 +1217,41 @@ int64_t SourceDestBufferImpl::getNextInt64(double scale, double offset)
double doubleRawValue;
switch (memoryRepresentation_)
{
case E57_INT8:
case MemoryRepresentation::E57_INT8:
/// Calc (x-offset)/scale rounded to nearest integer, but keep in floating point until sure is in bounds
doubleRawValue = floor((*reinterpret_cast<int8_t*>(p) - offset) / scale + 0.5);
break;
case E57_UINT8:
case MemoryRepresentation::E57_UINT8:
/// Calc (x-offset)/scale rounded to nearest integer, but keep in floating point until sure is in bounds
doubleRawValue = floor((*reinterpret_cast<uint8_t*>(p) - offset) / scale + 0.5);
break;
case E57_INT16:
case MemoryRepresentation::E57_INT16:
/// Calc (x-offset)/scale rounded to nearest integer, but keep in floating point until sure is in bounds
doubleRawValue = floor((*reinterpret_cast<int16_t*>(p) - offset) / scale + 0.5);
break;
case E57_UINT16:
case MemoryRepresentation::E57_UINT16:
/// Calc (x-offset)/scale rounded to nearest integer, but keep in floating point until sure is in bounds
doubleRawValue = floor((*reinterpret_cast<uint16_t*>(p) - offset) / scale + 0.5);
break;
case E57_INT32:
case MemoryRepresentation::E57_INT32:
/// Calc (x-offset)/scale rounded to nearest integer, but keep in floating point until sure is in bounds
doubleRawValue = floor((*reinterpret_cast<int32_t*>(p) - offset) / scale + 0.5);
break;
case E57_UINT32:
case MemoryRepresentation::E57_UINT32:
/// Calc (x-offset)/scale rounded to nearest integer, but keep in floating point until sure is in bounds
doubleRawValue = floor((*reinterpret_cast<uint32_t*>(p) - offset) / scale + 0.5);
break;
case E57_INT64:
case MemoryRepresentation::E57_INT64:
/// Calc (x-offset)/scale rounded to nearest integer, but keep in floating point until sure is in bounds
doubleRawValue = floor((*reinterpret_cast<int64_t*>(p) - offset) / scale + 0.5);
break;
case E57_BOOL:
case MemoryRepresentation::E57_BOOL:
if (*reinterpret_cast<bool*>(p))
doubleRawValue = floor((1 - offset) / scale + 0.5);
else
doubleRawValue = floor((0 - offset) / scale + 0.5);
break;
case E57_REAL32:
case MemoryRepresentation::E57_REAL32:
if (!doConversion_)
throw E57_EXCEPTION2(E57_ERROR_CONVERSION_REQUIRED, "pathName=" + pathName_);
//??? fault if get special value: NaN, NegInf...
@@ -1259,7 +1259,7 @@ int64_t SourceDestBufferImpl::getNextInt64(double scale, double offset)
/// Calc (x-offset)/scale rounded to nearest integer, but keep in floating point until sure is in bounds
doubleRawValue = floor((*reinterpret_cast<float*>(p) - offset) / scale + 0.5);
break;
case E57_REAL64:
case MemoryRepresentation::E57_REAL64:
if (!doConversion_)
throw E57_EXCEPTION2(E57_ERROR_CONVERSION_REQUIRED, "pathName=" + pathName_);
//??? fault if get special value: NaN, NegInf...
@@ -1267,7 +1267,7 @@ int64_t SourceDestBufferImpl::getNextInt64(double scale, double offset)
/// Calc (x-offset)/scale rounded to nearest integer, but keep in floating point until sure is in bounds
doubleRawValue = floor((*reinterpret_cast<double*>(p) - offset) / scale + 0.5);
break;
case E57_USTRING:
case MemoryRepresentation::E57_USTRING:
throw E57_EXCEPTION2(E57_ERROR_EXPECTING_NUMERIC, "pathName=" + pathName_);
default:
throw E57_EXCEPTION2(E57_ERROR_INTERNAL, "pathName=" + pathName_);
@@ -1298,52 +1298,52 @@ float SourceDestBufferImpl::getNextFloat()
float value;
switch (memoryRepresentation_)
{
case E57_INT8:
case MemoryRepresentation::E57_INT8:
if (!doConversion_)
throw E57_EXCEPTION2(E57_ERROR_CONVERSION_REQUIRED, "pathName=" + pathName_);
value = static_cast<float>(*reinterpret_cast<int8_t*>(p));
break;
case E57_UINT8:
case MemoryRepresentation::E57_UINT8:
if (!doConversion_)
throw E57_EXCEPTION2(E57_ERROR_CONVERSION_REQUIRED, "pathName=" + pathName_);
value = static_cast<float>(*reinterpret_cast<uint8_t*>(p));
break;
case E57_INT16:
case MemoryRepresentation::E57_INT16:
if (!doConversion_)
throw E57_EXCEPTION2(E57_ERROR_CONVERSION_REQUIRED, "pathName=" + pathName_);
value = static_cast<float>(*reinterpret_cast<int16_t*>(p));
break;
case E57_UINT16:
case MemoryRepresentation::E57_UINT16:
if (!doConversion_)
throw E57_EXCEPTION2(E57_ERROR_CONVERSION_REQUIRED, "pathName=" + pathName_);
value = static_cast<float>(*reinterpret_cast<uint16_t*>(p));
break;
case E57_INT32:
case MemoryRepresentation::E57_INT32:
if (!doConversion_)
throw E57_EXCEPTION2(E57_ERROR_CONVERSION_REQUIRED, "pathName=" + pathName_);
value = static_cast<float>(*reinterpret_cast<int32_t*>(p));
break;
case E57_UINT32:
case MemoryRepresentation::E57_UINT32:
if (!doConversion_)
throw E57_EXCEPTION2(E57_ERROR_CONVERSION_REQUIRED, "pathName=" + pathName_);
value = static_cast<float>(*reinterpret_cast<uint32_t*>(p));
break;
case E57_INT64:
case MemoryRepresentation::E57_INT64:
if (!doConversion_)
throw E57_EXCEPTION2(E57_ERROR_CONVERSION_REQUIRED, "pathName=" + pathName_);
value = static_cast<float>(*reinterpret_cast<int64_t*>(p));
break;
case E57_BOOL:
case MemoryRepresentation::E57_BOOL:
if (!doConversion_)
throw E57_EXCEPTION2(E57_ERROR_CONVERSION_REQUIRED, "pathName=" + pathName_);
/// Convert bool to 0/1, all non-zero values map to 1.0
value = (*reinterpret_cast<bool*>(p)) ? 1.0F : 0.0F;
break;
case E57_REAL32:
case MemoryRepresentation::E57_REAL32:
value = *reinterpret_cast<float*>(p);
break;
case E57_REAL64: {
case MemoryRepresentation::E57_REAL64: {
/// Check that exponent of user's value is not too large for single precision number in file.
double d = *reinterpret_cast<double*>(p);
@@ -1353,7 +1353,7 @@ float SourceDestBufferImpl::getNextFloat()
value = static_cast<float>(d);
break;
}
case E57_USTRING:
case MemoryRepresentation::E57_USTRING:
throw E57_EXCEPTION2(E57_ERROR_EXPECTING_NUMERIC, "pathName=" + pathName_);
default:
throw E57_EXCEPTION2(E57_ERROR_INTERNAL, "pathName=" + pathName_);
@@ -1376,54 +1376,54 @@ double SourceDestBufferImpl::getNextDouble()
double value;
switch (memoryRepresentation_)
{
case E57_INT8:
case MemoryRepresentation::E57_INT8:
if (!doConversion_)
throw E57_EXCEPTION2(E57_ERROR_CONVERSION_REQUIRED, "pathName=" + pathName_);
value = static_cast<double>(*reinterpret_cast<int8_t*>(p));
break;
case E57_UINT8:
case MemoryRepresentation::E57_UINT8:
if (!doConversion_)
throw E57_EXCEPTION2(E57_ERROR_CONVERSION_REQUIRED, "pathName=" + pathName_);
value = static_cast<double>(*reinterpret_cast<uint8_t*>(p));
break;
case E57_INT16:
case MemoryRepresentation::E57_INT16:
if (!doConversion_)
throw E57_EXCEPTION2(E57_ERROR_CONVERSION_REQUIRED, "pathName=" + pathName_);
value = static_cast<double>(*reinterpret_cast<int16_t*>(p));
break;
case E57_UINT16:
case MemoryRepresentation::E57_UINT16:
if (!doConversion_)
throw E57_EXCEPTION2(E57_ERROR_CONVERSION_REQUIRED, "pathName=" + pathName_);
value = static_cast<double>(*reinterpret_cast<uint16_t*>(p));
break;
case E57_INT32:
case MemoryRepresentation::E57_INT32:
if (!doConversion_)
throw E57_EXCEPTION2(E57_ERROR_CONVERSION_REQUIRED, "pathName=" + pathName_);
value = static_cast<double>(*reinterpret_cast<int32_t*>(p));
break;
case E57_UINT32:
case MemoryRepresentation::E57_UINT32:
if (!doConversion_)
throw E57_EXCEPTION2(E57_ERROR_CONVERSION_REQUIRED, "pathName=" + pathName_);
value = static_cast<double>(*reinterpret_cast<uint32_t*>(p));
break;
case E57_INT64:
case MemoryRepresentation::E57_INT64:
if (!doConversion_)
throw E57_EXCEPTION2(E57_ERROR_CONVERSION_REQUIRED, "pathName=" + pathName_);
value = static_cast<double>(*reinterpret_cast<int64_t*>(p));
break;
case E57_BOOL:
case MemoryRepresentation::E57_BOOL:
if (!doConversion_)
throw E57_EXCEPTION2(E57_ERROR_CONVERSION_REQUIRED, "pathName=" + pathName_);
/// Convert bool to 0/1, all non-zero values map to 1.0
value = (*reinterpret_cast<bool*>(p)) ? 1.0 : 0.0;
break;
case E57_REAL32:
case MemoryRepresentation::E57_REAL32:
value = static_cast<double>(*reinterpret_cast<float*>(p));
break;
case E57_REAL64:
case MemoryRepresentation::E57_REAL64:
value = *reinterpret_cast<double*>(p);
break;
case E57_USTRING:
case MemoryRepresentation::E57_USTRING:
throw E57_EXCEPTION2(E57_ERROR_EXPECTING_NUMERIC, "pathName=" + pathName_);
default:
throw E57_EXCEPTION2(E57_ERROR_INTERNAL, "pathName=" + pathName_);
@@ -1437,7 +1437,7 @@ ustring SourceDestBufferImpl::getNextString()
/// don't checkImageFileOpen
/// Check have correct type buffer
if (memoryRepresentation_ != E57_USTRING)
if (memoryRepresentation_ != MemoryRepresentation::E57_USTRING)
throw E57_EXCEPTION2(E57_ERROR_EXPECTING_USTRING, "pathName=" + pathName_);
/// Verify index is within bounds
@@ -1461,54 +1461,54 @@ void SourceDestBufferImpl::setNextInt64(int64_t value)
switch (memoryRepresentation_)
{
case E57_INT8:
case MemoryRepresentation::E57_INT8:
if (value < E57_INT8_MIN || E57_INT8_MAX < value)
throw E57_EXCEPTION2(E57_ERROR_VALUE_NOT_REPRESENTABLE, "pathName=" + pathName_ + " value=" + toString(value));
*reinterpret_cast<int8_t*>(p) = static_cast<int8_t>(value);
break;
case E57_UINT8:
case MemoryRepresentation::E57_UINT8:
if (value < E57_UINT8_MIN || E57_UINT8_MAX < value)
throw E57_EXCEPTION2(E57_ERROR_VALUE_NOT_REPRESENTABLE, "pathName=" + pathName_ + " value=" + toString(value));
*reinterpret_cast<uint8_t*>(p) = static_cast<uint8_t>(value);
break;
case E57_INT16:
case MemoryRepresentation::E57_INT16:
if (value < E57_INT16_MIN || E57_INT16_MAX < value)
throw E57_EXCEPTION2(E57_ERROR_VALUE_NOT_REPRESENTABLE, "pathName=" + pathName_ + " value=" + toString(value));
*reinterpret_cast<int16_t*>(p) = static_cast<int16_t>(value);
break;
case E57_UINT16:
case MemoryRepresentation::E57_UINT16:
if (value < E57_UINT16_MIN || E57_UINT16_MAX < value)
throw E57_EXCEPTION2(E57_ERROR_VALUE_NOT_REPRESENTABLE, "pathName=" + pathName_ + " value=" + toString(value));
*reinterpret_cast<uint16_t*>(p) = static_cast<uint16_t>(value);
break;
case E57_INT32:
case MemoryRepresentation::E57_INT32:
if (value < E57_INT32_MIN || E57_INT32_MAX < value)
throw E57_EXCEPTION2(E57_ERROR_VALUE_NOT_REPRESENTABLE, "pathName=" + pathName_ + " value=" + toString(value));
*reinterpret_cast<int32_t*>(p) = static_cast<int32_t>(value);
break;
case E57_UINT32:
case MemoryRepresentation::E57_UINT32:
if (value < E57_UINT32_MIN || E57_UINT32_MAX < value)
throw E57_EXCEPTION2(E57_ERROR_VALUE_NOT_REPRESENTABLE, "pathName=" + pathName_ + " value=" + toString(value));
*reinterpret_cast<uint32_t*>(p) = static_cast<uint32_t>(value);
break;
case E57_INT64:
case MemoryRepresentation::E57_INT64:
*reinterpret_cast<int64_t*>(p) = static_cast<int64_t>(value);
break;
case E57_BOOL:
case MemoryRepresentation::E57_BOOL:
*reinterpret_cast<bool*>(p) = (value ? false : true);
break;
case E57_REAL32:
case MemoryRepresentation::E57_REAL32:
if (!doConversion_)
throw E57_EXCEPTION2(E57_ERROR_CONVERSION_REQUIRED, "pathName=" + pathName_);
//??? very large integers may lose some lowest bits here. error?
*reinterpret_cast<float*>(p) = static_cast<float>(value);
break;
case E57_REAL64:
case MemoryRepresentation::E57_REAL64:
if (!doConversion_)
throw E57_EXCEPTION2(E57_ERROR_CONVERSION_REQUIRED, "pathName=" + pathName_);
*reinterpret_cast<double*>(p) = static_cast<double>(value);
break;
case E57_USTRING:
case MemoryRepresentation::E57_USTRING:
throw E57_EXCEPTION2(E57_ERROR_EXPECTING_NUMERIC, "pathName=" + pathName_);
}
@@ -1539,7 +1539,7 @@ void SourceDestBufferImpl::setNextInt64(int64_t value, double scale, double offs
/// Calc x*scale+offset
double scaledValue;
if (memoryRepresentation_ == E57_REAL32 || memoryRepresentation_ == E57_REAL64)
if (memoryRepresentation_ == MemoryRepresentation::E57_REAL32 || memoryRepresentation_ == MemoryRepresentation::E57_REAL64)
{
/// Value will be stored in some floating point rep in user's buffer, so keep full resolution here.
scaledValue = value * scale + offset;
@@ -1553,43 +1553,43 @@ void SourceDestBufferImpl::setNextInt64(int64_t value, double scale, double offs
switch (memoryRepresentation_)
{
case E57_INT8:
case MemoryRepresentation::E57_INT8:
if (scaledValue < E57_INT8_MIN || E57_INT8_MAX < scaledValue)
throw E57_EXCEPTION2(E57_ERROR_SCALED_VALUE_NOT_REPRESENTABLE, "pathName=" + pathName_ + " scaledValue=" + toString(scaledValue));
*reinterpret_cast<int8_t*>(p) = static_cast<int8_t>(scaledValue);
break;
case E57_UINT8:
case MemoryRepresentation::E57_UINT8:
if (scaledValue < E57_UINT8_MIN || E57_UINT8_MAX < scaledValue)
throw E57_EXCEPTION2(E57_ERROR_SCALED_VALUE_NOT_REPRESENTABLE, "pathName=" + pathName_ + " scaledValue=" + toString(scaledValue));
*reinterpret_cast<uint8_t*>(p) = static_cast<uint8_t>(scaledValue);
break;
case E57_INT16:
case MemoryRepresentation::E57_INT16:
if (scaledValue < E57_INT16_MIN || E57_INT16_MAX < scaledValue)
throw E57_EXCEPTION2(E57_ERROR_SCALED_VALUE_NOT_REPRESENTABLE, "pathName=" + pathName_ + " scaledValue=" + toString(scaledValue));
*reinterpret_cast<int16_t*>(p) = static_cast<int16_t>(scaledValue);
break;
case E57_UINT16:
case MemoryRepresentation::E57_UINT16:
if (scaledValue < E57_UINT16_MIN || E57_UINT16_MAX < scaledValue)
throw E57_EXCEPTION2(E57_ERROR_SCALED_VALUE_NOT_REPRESENTABLE, "pathName=" + pathName_ + " scaledValue=" + toString(scaledValue));
*reinterpret_cast<uint16_t*>(p) = static_cast<uint16_t>(scaledValue);
break;
case E57_INT32:
case MemoryRepresentation::E57_INT32:
if (scaledValue < E57_INT32_MIN || E57_INT32_MAX < scaledValue)
throw E57_EXCEPTION2(E57_ERROR_SCALED_VALUE_NOT_REPRESENTABLE, "pathName=" + pathName_ + " scaledValue=" + toString(scaledValue));
*reinterpret_cast<int32_t*>(p) = static_cast<int32_t>(scaledValue);
break;
case E57_UINT32:
case MemoryRepresentation::E57_UINT32:
if (scaledValue < E57_UINT32_MIN || E57_UINT32_MAX < scaledValue)
throw E57_EXCEPTION2(E57_ERROR_SCALED_VALUE_NOT_REPRESENTABLE, "pathName=" + pathName_ + " scaledValue=" + toString(scaledValue));
*reinterpret_cast<uint32_t*>(p) = static_cast<uint32_t>(scaledValue);
break;
case E57_INT64:
case MemoryRepresentation::E57_INT64:
*reinterpret_cast<int64_t*>(p) = static_cast<int64_t>(scaledValue);
break;
case E57_BOOL:
case MemoryRepresentation::E57_BOOL:
*reinterpret_cast<bool*>(p) = (scaledValue ? false : true);
break;
case E57_REAL32:
case MemoryRepresentation::E57_REAL32:
if (!doConversion_)
throw E57_EXCEPTION2(E57_ERROR_CONVERSION_REQUIRED, "pathName=" + pathName_);
/// Check that exponent of result is not too big for single precision float
@@ -1597,12 +1597,12 @@ void SourceDestBufferImpl::setNextInt64(int64_t value, double scale, double offs
throw E57_EXCEPTION2(E57_ERROR_SCALED_VALUE_NOT_REPRESENTABLE, "pathName=" + pathName_ + " scaledValue=" + toString(scaledValue));
*reinterpret_cast<float*>(p) = static_cast<float>(scaledValue);
break;
case E57_REAL64:
case MemoryRepresentation::E57_REAL64:
if (!doConversion_)
throw E57_EXCEPTION2(E57_ERROR_CONVERSION_REQUIRED, "pathName=" + pathName_);
*reinterpret_cast<double*>(p) = scaledValue;
break;
case E57_USTRING:
case MemoryRepresentation::E57_USTRING:
throw E57_EXCEPTION2(E57_ERROR_EXPECTING_NUMERIC, "pathName=" + pathName_);
}
@@ -1622,7 +1622,7 @@ void SourceDestBufferImpl::setNextFloat(float value)
switch (memoryRepresentation_)
{
case E57_INT8:
case MemoryRepresentation::E57_INT8:
if (!doConversion_)
throw E57_EXCEPTION2(E57_ERROR_CONVERSION_REQUIRED, "pathName=" + pathName_);
//??? fault if get special value: NaN, NegInf... (all other ints below too)
@@ -1630,61 +1630,61 @@ void SourceDestBufferImpl::setNextFloat(float value)
throw E57_EXCEPTION2(E57_ERROR_VALUE_NOT_REPRESENTABLE, "pathName=" + pathName_ + " value=" + toString(value));
*reinterpret_cast<int8_t*>(p) = static_cast<int8_t>(value);
break;
case E57_UINT8:
case MemoryRepresentation::E57_UINT8:
if (!doConversion_)
throw E57_EXCEPTION2(E57_ERROR_CONVERSION_REQUIRED, "pathName=" + pathName_);
if (value < E57_UINT8_MIN || E57_UINT8_MAX < value)
throw E57_EXCEPTION2(E57_ERROR_VALUE_NOT_REPRESENTABLE, "pathName=" + pathName_ + " value=" + toString(value));
*reinterpret_cast<uint8_t*>(p) = static_cast<uint8_t>(value);
break;
case E57_INT16:
case MemoryRepresentation::E57_INT16:
if (!doConversion_)
throw E57_EXCEPTION2(E57_ERROR_CONVERSION_REQUIRED, "pathName=" + pathName_);
if (value < E57_INT16_MIN || E57_INT16_MAX < value)
throw E57_EXCEPTION2(E57_ERROR_VALUE_NOT_REPRESENTABLE, "pathName=" + pathName_ + " value=" + toString(value));
*reinterpret_cast<int16_t*>(p) = static_cast<int16_t>(value);
break;
case E57_UINT16:
case MemoryRepresentation::E57_UINT16:
if (!doConversion_)
throw E57_EXCEPTION2(E57_ERROR_CONVERSION_REQUIRED, "pathName=" + pathName_);
if (value < E57_UINT16_MIN || E57_UINT16_MAX < value)
throw E57_EXCEPTION2(E57_ERROR_VALUE_NOT_REPRESENTABLE, "pathName=" + pathName_ + " value=" + toString(value));
*reinterpret_cast<uint16_t*>(p) = static_cast<uint16_t>(value);
break;
case E57_INT32:
case MemoryRepresentation::E57_INT32:
if (!doConversion_)
throw E57_EXCEPTION2(E57_ERROR_CONVERSION_REQUIRED, "pathName=" + pathName_);
if (value < E57_INT32_MIN || E57_INT32_MAX < value)
throw E57_EXCEPTION2(E57_ERROR_VALUE_NOT_REPRESENTABLE, "pathName=" + pathName_ + " value=" + toString(value));
*reinterpret_cast<int32_t*>(p) = static_cast<int32_t>(value);
break;
case E57_UINT32:
case MemoryRepresentation::E57_UINT32:
if (!doConversion_)
throw E57_EXCEPTION2(E57_ERROR_CONVERSION_REQUIRED, "pathName=" + pathName_);
if (value < E57_UINT32_MIN || E57_UINT32_MAX < value)
throw E57_EXCEPTION2(E57_ERROR_VALUE_NOT_REPRESENTABLE, "pathName=" + pathName_ + " value=" + toString(value));
*reinterpret_cast<uint32_t*>(p) = static_cast<uint32_t>(value);
break;
case E57_INT64:
case MemoryRepresentation::E57_INT64:
if (!doConversion_)
throw E57_EXCEPTION2(E57_ERROR_CONVERSION_REQUIRED, "pathName=" + pathName_);
if (value < E57_INT64_MIN || E57_INT64_MAX < value)
throw E57_EXCEPTION2(E57_ERROR_VALUE_NOT_REPRESENTABLE, "pathName=" + pathName_ + " value=" + toString(value));
*reinterpret_cast<int64_t*>(p) = static_cast<int64_t>(value);
break;
case E57_BOOL:
case MemoryRepresentation::E57_BOOL:
if (!doConversion_)
throw E57_EXCEPTION2(E57_ERROR_CONVERSION_REQUIRED, "pathName=" + pathName_);
*reinterpret_cast<bool*>(p) = (value ? false : true);
break;
case E57_REAL32:
case MemoryRepresentation::E57_REAL32:
*reinterpret_cast<float*>(p) = value;
break;
case E57_REAL64:
case MemoryRepresentation::E57_REAL64:
//??? does this count as a conversion?
*reinterpret_cast<double*>(p) = static_cast<double>(value);
break;
case E57_USTRING:
case MemoryRepresentation::E57_USTRING:
throw E57_EXCEPTION2(E57_ERROR_EXPECTING_NUMERIC, "pathName=" + pathName_);
}
@@ -1704,7 +1704,7 @@ void SourceDestBufferImpl::setNextDouble(double value)
switch (memoryRepresentation_)
{
case E57_INT8:
case MemoryRepresentation::E57_INT8:
if (!doConversion_)
throw E57_EXCEPTION2(E57_ERROR_CONVERSION_REQUIRED, "pathName=" + pathName_);
//??? fault if get special value: NaN, NegInf... (all other ints below too)
@@ -1712,64 +1712,64 @@ void SourceDestBufferImpl::setNextDouble(double value)
throw E57_EXCEPTION2(E57_ERROR_VALUE_NOT_REPRESENTABLE, "pathName=" + pathName_ + " value=" + toString(value));
*reinterpret_cast<int8_t*>(p) = static_cast<int8_t>(value);
break;
case E57_UINT8:
case MemoryRepresentation::E57_UINT8:
if (!doConversion_)
throw E57_EXCEPTION2(E57_ERROR_CONVERSION_REQUIRED, "pathName=" + pathName_);
if (value < E57_UINT8_MIN || E57_UINT8_MAX < value)
throw E57_EXCEPTION2(E57_ERROR_VALUE_NOT_REPRESENTABLE, "pathName=" + pathName_ + " value=" + toString(value));
*reinterpret_cast<uint8_t*>(p) = static_cast<uint8_t>(value);
break;
case E57_INT16:
case MemoryRepresentation::E57_INT16:
if (!doConversion_)
throw E57_EXCEPTION2(E57_ERROR_CONVERSION_REQUIRED, "pathName=" + pathName_);
if (value < E57_INT16_MIN || E57_INT16_MAX < value)
throw E57_EXCEPTION2(E57_ERROR_VALUE_NOT_REPRESENTABLE, "pathName=" + pathName_ + " value=" + toString(value));
*reinterpret_cast<int16_t*>(p) = static_cast<int16_t>(value);
break;
case E57_UINT16:
case MemoryRepresentation::E57_UINT16:
if (!doConversion_)
throw E57_EXCEPTION2(E57_ERROR_CONVERSION_REQUIRED, "pathName=" + pathName_);
if (value < E57_UINT16_MIN || E57_UINT16_MAX < value)
throw E57_EXCEPTION2(E57_ERROR_VALUE_NOT_REPRESENTABLE, "pathName=" + pathName_ + " value=" + toString(value));
*reinterpret_cast<uint16_t*>(p) = static_cast<uint16_t>(value);
break;
case E57_INT32:
case MemoryRepresentation::E57_INT32:
if (!doConversion_)
throw E57_EXCEPTION2(E57_ERROR_CONVERSION_REQUIRED, "pathName=" + pathName_);
if (value < E57_INT32_MIN || E57_INT32_MAX < value)
throw E57_EXCEPTION2(E57_ERROR_VALUE_NOT_REPRESENTABLE, "pathName=" + pathName_ + " value=" + toString(value));
*reinterpret_cast<int32_t*>(p) = static_cast<int32_t>(value);
break;
case E57_UINT32:
case MemoryRepresentation::E57_UINT32:
if (!doConversion_)
throw E57_EXCEPTION2(E57_ERROR_CONVERSION_REQUIRED, "pathName=" + pathName_);
if (value < E57_UINT32_MIN || E57_UINT32_MAX < value)
throw E57_EXCEPTION2(E57_ERROR_VALUE_NOT_REPRESENTABLE, "pathName=" + pathName_ + " value=" + toString(value));
*reinterpret_cast<uint32_t*>(p) = static_cast<uint32_t>(value);
break;
case E57_INT64:
case MemoryRepresentation::E57_INT64:
if (!doConversion_)
throw E57_EXCEPTION2(E57_ERROR_CONVERSION_REQUIRED, "pathName=" + pathName_);
if (value < E57_INT64_MIN || E57_INT64_MAX < value)
throw E57_EXCEPTION2(E57_ERROR_VALUE_NOT_REPRESENTABLE, "pathName=" + pathName_ + " value=" + toString(value));
*reinterpret_cast<int64_t*>(p) = static_cast<int64_t>(value);
break;
case E57_BOOL:
case MemoryRepresentation::E57_BOOL:
if (!doConversion_)
throw E57_EXCEPTION2(E57_ERROR_CONVERSION_REQUIRED, "pathName=" + pathName_);
*reinterpret_cast<bool*>(p) = (value ? false : true);
break;
case E57_REAL32:
case MemoryRepresentation::E57_REAL32:
/// Does this count as conversion? It loses information.
/// Check for really large exponents that can't fit in a single precision
if (value < E57_DOUBLE_MIN || E57_DOUBLE_MAX < value)
throw E57_EXCEPTION2(E57_ERROR_VALUE_NOT_REPRESENTABLE, "pathName=" + pathName_ + " value=" + toString(value));
*reinterpret_cast<float*>(p) = static_cast<float>(value);
break;
case E57_REAL64:
case MemoryRepresentation::E57_REAL64:
*reinterpret_cast<double*>(p) = value;
break;
case E57_USTRING:
case MemoryRepresentation::E57_USTRING:
throw E57_EXCEPTION2(E57_ERROR_EXPECTING_NUMERIC, "pathName=" + pathName_);
}
@@ -1780,7 +1780,7 @@ void SourceDestBufferImpl::setNextString(const ustring& value)
{
/// don't checkImageFileOpen
if (memoryRepresentation_ != E57_USTRING)
if (memoryRepresentation_ != MemoryRepresentation::E57_USTRING)
throw E57_EXCEPTION2(E57_ERROR_EXPECTING_USTRING, "pathName=" + pathName_);
/// Verify have room.
@@ -1830,37 +1830,37 @@ void SourceDestBufferImpl::dump(int indent, ostream& os)
os << space(indent) << "memoryRepresentation: ";
switch (memoryRepresentation_)
{
case E57_INT8:
case MemoryRepresentation::E57_INT8:
os << "int8_t" << endl;
break;
case E57_UINT8:
case MemoryRepresentation::E57_UINT8:
os << "uint8_t" << endl;
break;
case E57_INT16:
case MemoryRepresentation::E57_INT16:
os << "int16_t" << endl;
break;
case E57_UINT16:
case MemoryRepresentation::E57_UINT16:
os << "uint16_t" << endl;
break;
case E57_INT32:
case MemoryRepresentation::E57_INT32:
os << "int32_t" << endl;
break;
case E57_UINT32:
case MemoryRepresentation::E57_UINT32:
os << "uint32_t" << endl;
break;
case E57_INT64:
case MemoryRepresentation::E57_INT64:
os << "int64_t" << endl;
break;
case E57_BOOL:
case MemoryRepresentation::E57_BOOL:
os << "bool" << endl;
break;
case E57_REAL32:
case MemoryRepresentation::E57_REAL32:
os << "float" << endl;
break;
case E57_REAL64:
case MemoryRepresentation::E57_REAL64:
os << "double" << endl;
break;
case E57_USTRING:
case MemoryRepresentation::E57_USTRING:
os << "ustring" << endl;
break;
default:
@@ -2469,7 +2469,7 @@ FloatNodeImpl::FloatNodeImpl(std::weak_ptr<ImageFileImpl> destImageFile, double
/// Since this ctor also used to construct single precision, and defaults for minimum/maximum are for double precision,
/// adjust bounds smaller if single.
if (precision_ == E57_SINGLE)
if (precision_ == FloatPrecision::E57_SINGLE)
{
if (minimum_ < E57_FLOAT_MIN)
minimum_ = E57_FLOAT_MIN;
@@ -2574,7 +2574,7 @@ void FloatNodeImpl::writeXml(std::shared_ptr<ImageFileImpl> /*imf*/, CheckedFile
fieldName = elementName_;
cf << space(indent) << "<" << fieldName << " type=\"Float\"";
if (precision_ == E57_SINGLE)
if (precision_ == FloatPrecision::E57_SINGLE)
{
cf << " precision=\"single\"";
@@ -2616,7 +2616,7 @@ void FloatNodeImpl::dump(int indent, ostream& os)
<< " (" << type() << ")" << endl;
NodeImpl::dump(indent, os);
os << space(indent) << "precision: ";
if (precision() == E57_SINGLE)
if (precision() == FloatPrecision::E57_SINGLE)
os << "single" << endl;
else
os << "double" << endl;
@@ -3287,9 +3287,9 @@ void E57XmlParser::startElement(const XMLCh* const uri, const XMLCh* const local
{
ustring precision_str = lookupAttribute(attributes, att_precision);
if (precision_str == "single")
pi.precision = E57_SINGLE;
pi.precision = FloatPrecision::E57_SINGLE;
else if (precision_str == "double")
pi.precision = E57_DOUBLE;
pi.precision = FloatPrecision::E57_DOUBLE;
else
{
throw E57_EXCEPTION2(E57_ERROR_BAD_XML_FORMAT, "precisionString=" + precision_str + " fileName=" + imf_->fileName() + " uri=" + toUString(uri)
@@ -3299,7 +3299,7 @@ void E57XmlParser::startElement(const XMLCh* const uri, const XMLCh* const local
else
{
/// Not defined defined in XML, so defaults to double
pi.precision = E57_DOUBLE;
pi.precision = FloatPrecision::E57_DOUBLE;
}
if (isAttributeDefined(attributes, att_minimum))
@@ -3310,7 +3310,7 @@ void E57XmlParser::startElement(const XMLCh* const uri, const XMLCh* const local
else
{
/// Not defined defined in XML, so defaults to E57_FLOAT_MIN or E57_DOUBLE_MIN
if (pi.precision == E57_SINGLE)
if (pi.precision == FloatPrecision::E57_SINGLE)
pi.floatMinimum = E57_FLOAT_MIN;
else
pi.floatMinimum = E57_DOUBLE_MIN;
@@ -3324,7 +3324,7 @@ void E57XmlParser::startElement(const XMLCh* const uri, const XMLCh* const local
else
{
/// Not defined defined in XML, so defaults to FLOAT_MAX or DOUBLE_MAX
if (pi.precision == E57_SINGLE)
if (pi.precision == FloatPrecision::E57_SINGLE)
pi.floatMaximum = E57_FLOAT_MAX;
else
pi.floatMaximum = E57_DOUBLE_MAX;
@@ -7041,7 +7041,7 @@ void BitpackEncoder::dump(int indent, std::ostream& os)
//================
BitpackFloatEncoder::BitpackFloatEncoder(unsigned bytestreamNumber, SourceDestBuffer& sbuf, unsigned outputMaxSize, FloatPrecision precision)
: BitpackEncoder(bytestreamNumber, sbuf, outputMaxSize, (precision == E57_SINGLE) ? sizeof(float) : sizeof(double)), precision_(precision)
: BitpackEncoder(bytestreamNumber, sbuf, outputMaxSize, (precision == FloatPrecision::E57_SINGLE) ? sizeof(float) : sizeof(double)), precision_(precision)
{}
uint64_t BitpackFloatEncoder::processRecords(size_t recordCount)
@@ -7054,7 +7054,7 @@ uint64_t BitpackFloatEncoder::processRecords(size_t recordCount)
/// This leaves outBufferEnd_ at a natural boundary.
outBufferShiftDown();
size_t typeSize = (precision_ == E57_SINGLE) ? sizeof(float) : sizeof(double);
size_t typeSize = (precision_ == FloatPrecision::E57_SINGLE) ? sizeof(float) : sizeof(double);
#ifdef E57_DEBUG
/// Verify that outBufferEnd_ is multiple of typeSize (so transfers of floats are aligned naturally in memory).
@@ -7069,7 +7069,7 @@ uint64_t BitpackFloatEncoder::processRecords(size_t recordCount)
if (recordCount > maxOutputRecords)
recordCount = maxOutputRecords;
if (precision_ == E57_SINGLE)
if (precision_ == FloatPrecision::E57_SINGLE)
{
/// Form the starting address for next available location in outBuffer
float* outp = reinterpret_cast<float*>(&outBuffer_[outBufferEnd_]);
@@ -7117,14 +7117,14 @@ bool BitpackFloatEncoder::registerFlushToOutput()
float BitpackFloatEncoder::bitsPerRecord()
{
return ((precision_ == E57_SINGLE) ? 32.0F : 64.0F);
return ((precision_ == FloatPrecision::E57_SINGLE) ? 32.0F : 64.0F);
}
#ifdef E57_DEBUG
void BitpackFloatEncoder::dump(int indent, std::ostream& os)
{
BitpackEncoder::dump(indent, os);
if (precision_ == E57_SINGLE)
if (precision_ == FloatPrecision::E57_SINGLE)
os << space(indent) << "precision: E57_SINGLE" << endl;
else
os << space(indent) << "precision: E57_DOUBLE" << endl;
@@ -7553,7 +7553,7 @@ void BitpackDecoder::dump(int indent, std::ostream& os)
//================================================================
BitpackFloatDecoder::BitpackFloatDecoder(unsigned bytestreamNumber, SourceDestBuffer& dbuf, FloatPrecision precision, uint64_t maxRecordCount)
: BitpackDecoder(bytestreamNumber, dbuf, (precision == E57_SINGLE) ? sizeof(float) : sizeof(double), maxRecordCount), precision_(precision)
: BitpackDecoder(bytestreamNumber, dbuf, (precision == FloatPrecision::E57_SINGLE) ? sizeof(float) : sizeof(double), maxRecordCount), precision_(precision)
{}
size_t BitpackFloatDecoder::inputProcessAligned(const char* inbuf, const size_t firstBit, const size_t endBit)
@@ -7566,7 +7566,7 @@ size_t BitpackFloatDecoder::inputProcessAligned(const char* inbuf, const size_t
size_t n = destBuffer_->capacity() - destBuffer_->nextIndex();
size_t typeSize = (precision_ == E57_SINGLE) ? sizeof(float) : sizeof(double);
size_t typeSize = (precision_ == FloatPrecision::E57_SINGLE) ? sizeof(float) : sizeof(double);
#ifdef E57_DEBUG
# if 0 // I know no way to do this portably <rs>
@@ -7598,7 +7598,7 @@ size_t BitpackFloatDecoder::inputProcessAligned(const char* inbuf, const size_t
cout << " n:" << n << endl; //???
#endif
if (precision_ == E57_SINGLE)
if (precision_ == FloatPrecision::E57_SINGLE)
{
/// Form the starting address for first data location in inBuffer
const float* inp = reinterpret_cast<const float*>(inbuf);
@@ -7644,7 +7644,7 @@ size_t BitpackFloatDecoder::inputProcessAligned(const char* inbuf, const size_t
void BitpackFloatDecoder::dump(int indent, std::ostream& os)
{
BitpackDecoder::dump(indent, os);
if (precision_ == E57_SINGLE)
if (precision_ == FloatPrecision::E57_SINGLE)
os << space(indent) << "precision: E57_SINGLE" << endl;
else
os << space(indent) << "precision: E57_DOUBLE" << endl;

View File

@@ -859,7 +859,7 @@ bool ReaderImpl ::ReadData3D(int32_t dataIndex, //!< This in the index into th
if (scan.isDefined("cartesianBounds"))
{
StructureNode bbox(scan.get("cartesianBounds"));
if (bbox.get("xMinimum").type() == E57_SCALED_INTEGER)
if (bbox.get("xMinimum").type() == NodeType::E57_SCALED_INTEGER)
{
data3DHeader.cartesianBounds.xMinimum = (double)ScaledIntegerNode(bbox.get("xMinimum")).scaledValue();
data3DHeader.cartesianBounds.xMaximum = (double)ScaledIntegerNode(bbox.get("xMaximum")).scaledValue();
@@ -868,7 +868,7 @@ bool ReaderImpl ::ReadData3D(int32_t dataIndex, //!< This in the index into th
data3DHeader.cartesianBounds.zMinimum = (double)ScaledIntegerNode(bbox.get("zMinimum")).scaledValue();
data3DHeader.cartesianBounds.zMaximum = (double)ScaledIntegerNode(bbox.get("zMaximum")).scaledValue();
}
else if (bbox.get("xMinimum").type() == E57_FLOAT)
else if (bbox.get("xMinimum").type() == NodeType::E57_FLOAT)
{
data3DHeader.cartesianBounds.xMinimum = FloatNode(bbox.get("xMinimum")).value();
data3DHeader.cartesianBounds.xMaximum = FloatNode(bbox.get("xMaximum")).value();
@@ -882,34 +882,34 @@ bool ReaderImpl ::ReadData3D(int32_t dataIndex, //!< This in the index into th
if (scan.isDefined("sphericalBounds"))
{
StructureNode sbox(scan.get("sphericalBounds"));
if (sbox.get("rangeMinimum").type() == E57_SCALED_INTEGER)
if (sbox.get("rangeMinimum").type() == NodeType::E57_SCALED_INTEGER)
{
data3DHeader.sphericalBounds.rangeMinimum = (double)ScaledIntegerNode(sbox.get("rangeMinimum")).scaledValue();
data3DHeader.sphericalBounds.rangeMaximum = (double)ScaledIntegerNode(sbox.get("rangeMaximum")).scaledValue();
}
else if (sbox.get("rangeMinimum").type() == E57_FLOAT)
else if (sbox.get("rangeMinimum").type() == NodeType::E57_FLOAT)
{
data3DHeader.sphericalBounds.rangeMinimum = FloatNode(sbox.get("rangeMinimum")).value();
data3DHeader.sphericalBounds.rangeMaximum = FloatNode(sbox.get("rangeMaximum")).value();
}
if (sbox.get("elevationMinimum").type() == E57_SCALED_INTEGER)
if (sbox.get("elevationMinimum").type() == NodeType::E57_SCALED_INTEGER)
{
data3DHeader.sphericalBounds.elevationMinimum = (double)ScaledIntegerNode(sbox.get("elevationMinimum")).scaledValue();
data3DHeader.sphericalBounds.elevationMaximum = (double)ScaledIntegerNode(sbox.get("elevationMaximum")).scaledValue();
}
else if (sbox.get("elevationMinimum").type() == E57_FLOAT)
else if (sbox.get("elevationMinimum").type() == NodeType::E57_FLOAT)
{
data3DHeader.sphericalBounds.elevationMinimum = FloatNode(sbox.get("elevationMinimum")).value();
data3DHeader.sphericalBounds.elevationMaximum = FloatNode(sbox.get("elevationMaximum")).value();
}
if (sbox.get("azimuthStart").type() == E57_SCALED_INTEGER)
if (sbox.get("azimuthStart").type() == NodeType::E57_SCALED_INTEGER)
{
data3DHeader.sphericalBounds.azimuthStart = (double)ScaledIntegerNode(sbox.get("azimuthStart")).scaledValue();
data3DHeader.sphericalBounds.azimuthEnd = (double)ScaledIntegerNode(sbox.get("azimuthEnd")).scaledValue();
}
else if (sbox.get("azimuthStart").type() == E57_FLOAT)
else if (sbox.get("azimuthStart").type() == NodeType::E57_FLOAT)
{
data3DHeader.sphericalBounds.azimuthStart = FloatNode(sbox.get("azimuthStart")).value();
data3DHeader.sphericalBounds.azimuthEnd = FloatNode(sbox.get("azimuthEnd")).value();
@@ -967,7 +967,7 @@ bool ReaderImpl ::ReadData3D(int32_t dataIndex, //!< This in the index into th
if (proto.isDefined("cartesianX"))
{
if (proto.get("cartesianX").type() == E57_SCALED_INTEGER)
if (proto.get("cartesianX").type() == NodeType::E57_SCALED_INTEGER)
{
double scale = ScaledIntegerNode(proto.get("cartesianX")).scale();
double offset = ScaledIntegerNode(proto.get("cartesianX")).offset();
@@ -977,7 +977,7 @@ bool ReaderImpl ::ReadData3D(int32_t dataIndex, //!< This in the index into th
data3DHeader.pointFields.pointRangeMaximum = (double)maximum * scale + offset;
data3DHeader.pointFields.pointRangeScaledInteger = scale;
}
else if (proto.get("cartesianX").type() == E57_FLOAT)
else if (proto.get("cartesianX").type() == NodeType::E57_FLOAT)
{
data3DHeader.pointFields.pointRangeMinimum = FloatNode(proto.get("cartesianX")).minimum();
data3DHeader.pointFields.pointRangeMaximum = FloatNode(proto.get("cartesianX")).maximum();
@@ -986,7 +986,7 @@ bool ReaderImpl ::ReadData3D(int32_t dataIndex, //!< This in the index into th
}
else if (proto.isDefined("sphericalRange"))
{
if (proto.get("sphericalRange").type() == E57_SCALED_INTEGER)
if (proto.get("sphericalRange").type() == NodeType::E57_SCALED_INTEGER)
{
double scale = ScaledIntegerNode(proto.get("sphericalRange")).scale();
double offset = ScaledIntegerNode(proto.get("sphericalRange")).offset();
@@ -996,7 +996,7 @@ bool ReaderImpl ::ReadData3D(int32_t dataIndex, //!< This in the index into th
data3DHeader.pointFields.pointRangeMaximum = (double)maximum * scale + offset;
data3DHeader.pointFields.pointRangeScaledInteger = scale;
}
else if (proto.get("sphericalRange").type() == E57_FLOAT)
else if (proto.get("sphericalRange").type() == NodeType::E57_FLOAT)
{
data3DHeader.pointFields.pointRangeMinimum = FloatNode(proto.get("sphericalRange")).minimum();
data3DHeader.pointFields.pointRangeMaximum = FloatNode(proto.get("sphericalRange")).maximum();
@@ -1015,7 +1015,7 @@ bool ReaderImpl ::ReadData3D(int32_t dataIndex, //!< This in the index into th
if (proto.isDefined("sphericalAzimuth"))
{
if (proto.get("sphericalAzimuth").type() == E57_SCALED_INTEGER)
if (proto.get("sphericalAzimuth").type() == NodeType::E57_SCALED_INTEGER)
{
double scale = ScaledIntegerNode(proto.get("sphericalAzimuth")).scale();
double offset = ScaledIntegerNode(proto.get("sphericalAzimuth")).offset();
@@ -1025,7 +1025,7 @@ bool ReaderImpl ::ReadData3D(int32_t dataIndex, //!< This in the index into th
data3DHeader.pointFields.angleMaximum = (double)maximum * scale + offset;
data3DHeader.pointFields.angleScaledInteger = scale;
}
else if (proto.get("sphericalAzimuth").type() == E57_FLOAT)
else if (proto.get("sphericalAzimuth").type() == NodeType::E57_FLOAT)
{
data3DHeader.pointFields.angleMinimum = FloatNode(proto.get("sphericalAzimuth")).minimum();
data3DHeader.pointFields.angleMaximum = FloatNode(proto.get("sphericalAzimuth")).maximum();
@@ -1059,13 +1059,13 @@ bool ReaderImpl ::ReadData3D(int32_t dataIndex, //!< This in the index into th
if (proto.isDefined("timeStamp"))
{
if (proto.get("timeStamp").type() == E57_INTEGER)
if (proto.get("timeStamp").type() == NodeType::E57_INTEGER)
{
data3DHeader.pointFields.timeMaximum = (double)IntegerNode(proto.get("timeStamp")).maximum();
data3DHeader.pointFields.timeMinimum = (double)IntegerNode(proto.get("timeStamp")).minimum();
data3DHeader.pointFields.timeScaledInteger = E57_NOT_SCALED_USE_FLOAT;
}
else if (proto.get("timeStamp").type() == E57_SCALED_INTEGER)
else if (proto.get("timeStamp").type() == NodeType::E57_SCALED_INTEGER)
{
double scale = ScaledIntegerNode(proto.get("timeStamp")).scale();
double offset = ScaledIntegerNode(proto.get("timeStamp")).offset();
@@ -1075,7 +1075,7 @@ bool ReaderImpl ::ReadData3D(int32_t dataIndex, //!< This in the index into th
data3DHeader.pointFields.timeMaximum = (double)maximum * scale + offset;
data3DHeader.pointFields.timeScaledInteger = scale;
}
else if (proto.get("timeStamp").type() == E57_FLOAT)
else if (proto.get("timeStamp").type() == NodeType::E57_FLOAT)
{
data3DHeader.pointFields.timeMinimum = FloatNode(proto.get("timeStamp")).minimum();
data3DHeader.pointFields.timeMaximum = FloatNode(proto.get("timeStamp")).maximum();
@@ -1092,17 +1092,17 @@ bool ReaderImpl ::ReadData3D(int32_t dataIndex, //!< This in the index into th
if (scan.isDefined("intensityLimits"))
{
StructureNode intbox(scan.get("intensityLimits"));
if (intbox.get("intensityMaximum").type() == E57_SCALED_INTEGER)
if (intbox.get("intensityMaximum").type() == NodeType::E57_SCALED_INTEGER)
{
data3DHeader.intensityLimits.intensityMaximum = (double)ScaledIntegerNode(intbox.get("intensityMaximum")).scaledValue();
data3DHeader.intensityLimits.intensityMinimum = (double)ScaledIntegerNode(intbox.get("intensityMinimum")).scaledValue();
}
else if (intbox.get("intensityMaximum").type() == E57_FLOAT)
else if (intbox.get("intensityMaximum").type() == NodeType::E57_FLOAT)
{
data3DHeader.intensityLimits.intensityMaximum = FloatNode(intbox.get("intensityMaximum")).value();
data3DHeader.intensityLimits.intensityMinimum = FloatNode(intbox.get("intensityMinimum")).value();
}
else if (intbox.get("intensityMaximum").type() == E57_INTEGER)
else if (intbox.get("intensityMaximum").type() == NodeType::E57_INTEGER)
{
data3DHeader.intensityLimits.intensityMaximum = (double)IntegerNode(intbox.get("intensityMaximum")).value();
data3DHeader.intensityLimits.intensityMinimum = (double)IntegerNode(intbox.get("intensityMinimum")).value();
@@ -1110,7 +1110,7 @@ bool ReaderImpl ::ReadData3D(int32_t dataIndex, //!< This in the index into th
}
if (proto.isDefined("intensity"))
{
if (proto.get("intensity").type() == E57_INTEGER)
if (proto.get("intensity").type() == NodeType::E57_INTEGER)
{
if (data3DHeader.intensityLimits.intensityMaximum == 0.)
{
@@ -1119,7 +1119,7 @@ bool ReaderImpl ::ReadData3D(int32_t dataIndex, //!< This in the index into th
}
data3DHeader.pointFields.intensityScaledInteger = E57_NOT_SCALED_USE_INTEGER;
}
else if (proto.get("intensity").type() == E57_SCALED_INTEGER)
else if (proto.get("intensity").type() == NodeType::E57_SCALED_INTEGER)
{
double scale = ScaledIntegerNode(proto.get("intensity")).scale();
double offset = ScaledIntegerNode(proto.get("intensity")).offset();
@@ -1133,7 +1133,7 @@ bool ReaderImpl ::ReadData3D(int32_t dataIndex, //!< This in the index into th
}
data3DHeader.pointFields.intensityScaledInteger = scale;
}
else if (proto.get("intensity").type() == E57_FLOAT)
else if (proto.get("intensity").type() == NodeType::E57_FLOAT)
{
if (data3DHeader.intensityLimits.intensityMaximum == 0.)
{
@@ -1159,7 +1159,7 @@ bool ReaderImpl ::ReadData3D(int32_t dataIndex, //!< This in the index into th
if (scan.isDefined("colorLimits"))
{
StructureNode colorbox(scan.get("colorLimits"));
if (colorbox.get("colorRedMaximum").type() == E57_SCALED_INTEGER)
if (colorbox.get("colorRedMaximum").type() == NodeType::E57_SCALED_INTEGER)
{
data3DHeader.colorLimits.colorRedMaximum = (double)ScaledIntegerNode(colorbox.get("colorRedMaximum")).scaledValue();
data3DHeader.colorLimits.colorRedMinimum = (double)ScaledIntegerNode(colorbox.get("colorRedMinimum")).scaledValue();
@@ -1168,7 +1168,7 @@ bool ReaderImpl ::ReadData3D(int32_t dataIndex, //!< This in the index into th
data3DHeader.colorLimits.colorBlueMaximum = (double)ScaledIntegerNode(colorbox.get("colorBlueMaximum")).scaledValue();
data3DHeader.colorLimits.colorBlueMinimum = (double)ScaledIntegerNode(colorbox.get("colorBlueMinimum")).scaledValue();
}
else if (colorbox.get("colorRedMaximum").type() == E57_FLOAT)
else if (colorbox.get("colorRedMaximum").type() == NodeType::E57_FLOAT)
{
data3DHeader.colorLimits.colorRedMaximum = FloatNode(colorbox.get("colorRedMaximum")).value();
data3DHeader.colorLimits.colorRedMinimum = FloatNode(colorbox.get("colorRedMinimum")).value();
@@ -1177,7 +1177,7 @@ bool ReaderImpl ::ReadData3D(int32_t dataIndex, //!< This in the index into th
data3DHeader.colorLimits.colorBlueMaximum = FloatNode(colorbox.get("colorBlueMaximum")).value();
data3DHeader.colorLimits.colorBlueMinimum = FloatNode(colorbox.get("colorBlueMinimum")).value();
}
else if (colorbox.get("colorRedMaximum").type() == E57_INTEGER)
else if (colorbox.get("colorRedMaximum").type() == NodeType::E57_INTEGER)
{
data3DHeader.colorLimits.colorRedMaximum = (double)IntegerNode(colorbox.get("colorRedMaximum")).value();
data3DHeader.colorLimits.colorRedMinimum = (double)IntegerNode(colorbox.get("colorRedMinimum")).value();
@@ -1190,17 +1190,17 @@ bool ReaderImpl ::ReadData3D(int32_t dataIndex, //!< This in the index into th
if ((data3DHeader.colorLimits.colorRedMaximum == 0.) && proto.isDefined("colorRed"))
{
if (proto.get("colorRed").type() == E57_INTEGER)
if (proto.get("colorRed").type() == NodeType::E57_INTEGER)
{
data3DHeader.colorLimits.colorRedMinimum = (uint16_t)IntegerNode(proto.get("colorRed")).minimum();
data3DHeader.colorLimits.colorRedMaximum = (uint16_t)IntegerNode(proto.get("colorRed")).maximum();
}
else if (proto.get("colorRed").type() == E57_FLOAT)
else if (proto.get("colorRed").type() == NodeType::E57_FLOAT)
{
data3DHeader.colorLimits.colorRedMinimum = (uint16_t)FloatNode(proto.get("colorRed")).minimum();
data3DHeader.colorLimits.colorRedMaximum = (uint16_t)FloatNode(proto.get("colorRed")).maximum();
}
else if (proto.get("colorRed").type() == E57_SCALED_INTEGER)
else if (proto.get("colorRed").type() == NodeType::E57_SCALED_INTEGER)
{
double scale = ScaledIntegerNode(proto.get("colorRed")).scale();
double offset = ScaledIntegerNode(proto.get("colorRed")).offset();
@@ -1212,17 +1212,17 @@ bool ReaderImpl ::ReadData3D(int32_t dataIndex, //!< This in the index into th
}
if ((data3DHeader.colorLimits.colorGreenMaximum == 0.) && proto.isDefined("colorGreen"))
{
if (proto.get("colorGreen").type() == E57_INTEGER)
if (proto.get("colorGreen").type() == NodeType::E57_INTEGER)
{
data3DHeader.colorLimits.colorGreenMinimum = (uint16_t)IntegerNode(proto.get("colorGreen")).minimum();
data3DHeader.colorLimits.colorGreenMaximum = (uint16_t)IntegerNode(proto.get("colorGreen")).maximum();
}
else if (proto.get("colorGreen").type() == E57_FLOAT)
else if (proto.get("colorGreen").type() == NodeType::E57_FLOAT)
{
data3DHeader.colorLimits.colorGreenMinimum = (uint16_t)FloatNode(proto.get("colorGreen")).minimum();
data3DHeader.colorLimits.colorGreenMaximum = (uint16_t)FloatNode(proto.get("colorGreen")).maximum();
}
else if (proto.get("colorGreen").type() == E57_SCALED_INTEGER)
else if (proto.get("colorGreen").type() == NodeType::E57_SCALED_INTEGER)
{
double scale = ScaledIntegerNode(proto.get("colorGreen")).scale();
double offset = ScaledIntegerNode(proto.get("colorGreen")).offset();
@@ -1234,17 +1234,17 @@ bool ReaderImpl ::ReadData3D(int32_t dataIndex, //!< This in the index into th
}
if ((data3DHeader.colorLimits.colorBlueMaximum == 0.) && proto.isDefined("colorBlue"))
{
if (proto.get("colorBlue").type() == E57_INTEGER)
if (proto.get("colorBlue").type() == NodeType::E57_INTEGER)
{
data3DHeader.colorLimits.colorBlueMinimum = (uint16_t)IntegerNode(proto.get("colorBlue")).minimum();
data3DHeader.colorLimits.colorBlueMaximum = (uint16_t)IntegerNode(proto.get("colorBlue")).maximum();
}
else if (proto.get("colorBlue").type() == E57_FLOAT)
else if (proto.get("colorBlue").type() == NodeType::E57_FLOAT)
{
data3DHeader.colorLimits.colorBlueMinimum = (uint16_t)FloatNode(proto.get("colorBlue")).minimum();
data3DHeader.colorLimits.colorBlueMaximum = (uint16_t)FloatNode(proto.get("colorBlue")).maximum();
}
else if (proto.get("colorBlue").type() == E57_SCALED_INTEGER)
else if (proto.get("colorBlue").type() == NodeType::E57_SCALED_INTEGER)
{
double scale = ScaledIntegerNode(proto.get("colorBlue")).scale();
double offset = ScaledIntegerNode(proto.get("colorBlue")).offset();
@@ -1449,7 +1449,7 @@ CompressedVectorReader ReaderImpl ::SetUpData3DPointsData(
{
ustring name = proto.get(protoIndex).elementName();
NodeType type = proto.get(protoIndex).type();
bool scaled = type == E57_SCALED_INTEGER ? true : false;
bool scaled = type == NodeType::E57_SCALED_INTEGER ? true : false;
if ((name.compare("cartesianX") == 0) && proto.isDefined("cartesianX") && (cartesianX != NULL))
destBuffers.push_back(SourceDestBuffer(imf_, "cartesianX", cartesianX, (unsigned)count, true, scaled));
@@ -2147,16 +2147,18 @@ int32_t WriterImpl ::NewData3D(Data3D& data3DHeader,
if (data3DHeader.pointFields.pointRangeScaledInteger > 0.)
proto.set("cartesianX", ScaledIntegerNode(imf_, 0, pointRangeMinimum, pointRangeMaximum, pointRangeScale, pointRangeOffset));
else
proto.set("cartesianX", FloatNode(imf_, 0., (data3DHeader.pointFields.pointRangeScaledInteger < 0.) ? E57_DOUBLE : E57_SINGLE,
data3DHeader.pointFields.pointRangeMinimum, data3DHeader.pointFields.pointRangeMaximum));
proto.set("cartesianX",
FloatNode(imf_, 0., (data3DHeader.pointFields.pointRangeScaledInteger < 0.) ? FloatPrecision::E57_DOUBLE : FloatPrecision::E57_SINGLE,
data3DHeader.pointFields.pointRangeMinimum, data3DHeader.pointFields.pointRangeMaximum));
}
if (data3DHeader.pointFields.cartesianYField)
{
if (data3DHeader.pointFields.pointRangeScaledInteger > 0.)
proto.set("cartesianY", ScaledIntegerNode(imf_, 0, pointRangeMinimum, pointRangeMaximum, pointRangeScale, pointRangeOffset));
else
proto.set("cartesianY", FloatNode(imf_, 0., (data3DHeader.pointFields.pointRangeScaledInteger < 0.) ? E57_DOUBLE : E57_SINGLE,
data3DHeader.pointFields.pointRangeMinimum, data3DHeader.pointFields.pointRangeMaximum));
proto.set("cartesianY",
FloatNode(imf_, 0., (data3DHeader.pointFields.pointRangeScaledInteger < 0.) ? FloatPrecision::E57_DOUBLE : FloatPrecision::E57_SINGLE,
data3DHeader.pointFields.pointRangeMinimum, data3DHeader.pointFields.pointRangeMaximum));
}
#ifdef TEST_EXTENSIONS
proto.set("ext:extraField1", IntegerNode(imf_, 0, 0, 255));
@@ -2166,8 +2168,9 @@ int32_t WriterImpl ::NewData3D(Data3D& data3DHeader,
if (data3DHeader.pointFields.pointRangeScaledInteger > 0.)
proto.set("cartesianZ", ScaledIntegerNode(imf_, 0, pointRangeMinimum, pointRangeMaximum, pointRangeScale, pointRangeOffset));
else
proto.set("cartesianZ", FloatNode(imf_, 0., (data3DHeader.pointFields.pointRangeScaledInteger < 0.) ? E57_DOUBLE : E57_SINGLE,
data3DHeader.pointFields.pointRangeMinimum, data3DHeader.pointFields.pointRangeMaximum));
proto.set("cartesianZ",
FloatNode(imf_, 0., (data3DHeader.pointFields.pointRangeScaledInteger < 0.) ? FloatPrecision::E57_DOUBLE : FloatPrecision::E57_SINGLE,
data3DHeader.pointFields.pointRangeMinimum, data3DHeader.pointFields.pointRangeMaximum));
}
if (data3DHeader.pointFields.sphericalRangeField)
@@ -2175,8 +2178,9 @@ int32_t WriterImpl ::NewData3D(Data3D& data3DHeader,
if (data3DHeader.pointFields.pointRangeScaledInteger > 0.)
proto.set("sphericalRange", ScaledIntegerNode(imf_, 0, pointRangeMinimum, pointRangeMaximum, pointRangeScale, pointRangeOffset));
else
proto.set("sphericalRange", FloatNode(imf_, 0., (data3DHeader.pointFields.pointRangeScaledInteger < 0.) ? E57_DOUBLE : E57_SINGLE,
data3DHeader.pointFields.pointRangeMinimum, data3DHeader.pointFields.pointRangeMaximum));
proto.set("sphericalRange",
FloatNode(imf_, 0., (data3DHeader.pointFields.pointRangeScaledInteger < 0.) ? FloatPrecision::E57_DOUBLE : FloatPrecision::E57_SINGLE,
data3DHeader.pointFields.pointRangeMinimum, data3DHeader.pointFields.pointRangeMaximum));
}
double angleScale = data3DHeader.pointFields.angleScaledInteger;
@@ -2189,8 +2193,9 @@ int32_t WriterImpl ::NewData3D(Data3D& data3DHeader,
if (data3DHeader.pointFields.angleScaledInteger > 0.)
proto.set("sphericalAzimuth", ScaledIntegerNode(imf_, 0, angleMinimum, angleMaximum, angleScale, angleOffset));
else
proto.set("sphericalAzimuth", FloatNode(imf_, 0., (data3DHeader.pointFields.angleScaledInteger < 0.) ? E57_DOUBLE : E57_SINGLE,
data3DHeader.pointFields.angleMinimum, data3DHeader.pointFields.angleMaximum));
proto.set("sphericalAzimuth",
FloatNode(imf_, 0., (data3DHeader.pointFields.angleScaledInteger < 0.) ? FloatPrecision::E57_DOUBLE : FloatPrecision::E57_SINGLE,
data3DHeader.pointFields.angleMinimum, data3DHeader.pointFields.angleMaximum));
}
if (data3DHeader.pointFields.sphericalElevationField)
@@ -2198,8 +2203,9 @@ int32_t WriterImpl ::NewData3D(Data3D& data3DHeader,
if (data3DHeader.pointFields.angleScaledInteger > 0.)
proto.set("sphericalElevation", ScaledIntegerNode(imf_, 0, angleMinimum, angleMaximum, angleScale, angleOffset));
else
proto.set("sphericalElevation", FloatNode(imf_, 0., (data3DHeader.pointFields.angleScaledInteger < 0.) ? E57_DOUBLE : E57_SINGLE,
data3DHeader.pointFields.angleMinimum, data3DHeader.pointFields.angleMaximum));
proto.set("sphericalElevation",
FloatNode(imf_, 0., (data3DHeader.pointFields.angleScaledInteger < 0.) ? FloatPrecision::E57_DOUBLE : FloatPrecision::E57_SINGLE,
data3DHeader.pointFields.angleMinimum, data3DHeader.pointFields.angleMaximum));
}
#ifdef TEST_EXTENSIONS
@@ -2217,7 +2223,8 @@ int32_t WriterImpl ::NewData3D(Data3D& data3DHeader,
proto.set("intensity", ScaledIntegerNode(imf_, 0, rawIntegerMinimum, rawIntegerMaximum, scale, offset));
}
else if (data3DHeader.pointFields.intensityScaledInteger == E57_NOT_SCALED_USE_FLOAT)
proto.set("intensity", FloatNode(imf_, 0., E57_SINGLE, data3DHeader.intensityLimits.intensityMinimum, data3DHeader.intensityLimits.intensityMaximum));
proto.set("intensity",
FloatNode(imf_, 0., FloatPrecision::E57_SINGLE, data3DHeader.intensityLimits.intensityMinimum, data3DHeader.intensityLimits.intensityMaximum));
else
proto.set("intensity",
IntegerNode(imf_, 0, (int64_t)data3DHeader.intensityLimits.intensityMinimum, (int64_t)data3DHeader.intensityLimits.intensityMaximum));
@@ -2253,9 +2260,9 @@ int32_t WriterImpl ::NewData3D(Data3D& data3DHeader,
else if (data3DHeader.pointFields.timeScaledInteger == E57_NOT_SCALED_USE_FLOAT)
{
if (data3DHeader.pointFields.timeMaximum == E57_FLOAT_MAX)
proto.set("timeStamp", FloatNode(imf_, 0., E57_SINGLE, E57_FLOAT_MIN, E57_FLOAT_MAX));
proto.set("timeStamp", FloatNode(imf_, 0., FloatPrecision::E57_SINGLE, E57_FLOAT_MIN, E57_FLOAT_MAX));
else if (data3DHeader.pointFields.timeMaximum == E57_DOUBLE_MAX)
proto.set("timeStamp", FloatNode(imf_, 0., E57_DOUBLE, E57_DOUBLE_MIN, E57_DOUBLE_MAX));
proto.set("timeStamp", FloatNode(imf_, 0., FloatPrecision::E57_DOUBLE, E57_DOUBLE_MIN, E57_DOUBLE_MAX));
}
else
proto.set("timeStamp", IntegerNode(imf_, 0, (int64_t)data3DHeader.pointFields.timeMinimum, (int64_t)data3DHeader.pointFields.timeMaximum));

View File

@@ -0,0 +1,847 @@
#include <cmath>
#include <ctime>
#include <iostream>
#include <openE57/impl/time_conversion.h>
#define ERROR_MESSAGE(msg) \
{ \
const char* themsg = msg; \
if (themsg != NULL) \
{ \
printf("\n%s,\n%s, %d,\n%s\n", __FILE__, __func__, __LINE__, themsg); \
} \
else \
{ \
printf("\n%s,\n%s, %d,\nUnknown Error\n", __FILE__, __func__, __LINE__); \
} \
}
// Julian Date Offsets
constexpr const double JULIAN_DATE_OFFSET_1980 = 2444244.5000; // Jan 06 1980 00:00:00.0
constexpr const double JULIAN_DATE_OFFSET_1981 = 2444786.5000; // Jul 01 1981 00:00:00.0
constexpr const double JULIAN_DATE_OFFSET_1982 = 2445151.5000; // Jul 01 1982 00:00:00.0
constexpr const double JULIAN_DATE_OFFSET_1983 = 2445516.5000; // Jul 01 1983 00:00:00.0
constexpr const double JULIAN_DATE_OFFSET_1985 = 2446247.5000; // Jul 01 1985 00:00:00.0
constexpr const double JULIAN_DATE_OFFSET_1988 = 2447161.5000; // Jan 01 1988 00:00:00.0
constexpr const double JULIAN_DATE_OFFSET_1990 = 2447892.5000; // Jan 01 1990 00:00:00.0
constexpr const double JULIAN_DATE_OFFSET_1991 = 2448257.5000; // Jan 01 1991 00:00:00.0
constexpr const double JULIAN_DATE_OFFSET_1992 = 2448804.5000; // Jul 01 1992 00:00:00.0
constexpr const double JULIAN_DATE_OFFSET_1993 = 2449169.5000; // Jul 01 1993 00:00:00.0
constexpr const double JULIAN_DATE_OFFSET_1994 = 2449534.5000; // Jul 01 1994 00:00:00.0
constexpr const double JULIAN_DATE_OFFSET_1996 = 2450083.5000; // Jan 01 1996 00:00:00.0
constexpr const double JULIAN_DATE_OFFSET_1997 = 2450630.5000; // Jul 01 1997 00:00:00.0
constexpr const double JULIAN_DATE_OFFSET_1999 = 2451179.5000; // Jan 01 1999 00:00:00.0
constexpr const double JULIAN_DATE_OFFSET_2006 = 2453736.5000; // Jan 01 2006 00:00:00.0
constexpr const double JULIAN_DATE_OFFSET_2009 = 2454832.5000; // Jan 01 2009 00:00:00.0
// Constants definition
constexpr const double JULIAN_DATE_START_OF_GPS_TIME = JULIAN_DATE_OFFSET_1980; // [days]
constexpr const double JULIAN_DATE_START_OF_PC_TIME = 2440587.5; // [days]
constexpr const int DAYS_IN_JAN = 31;
constexpr const int DAYS_IN_MAR = 31;
constexpr const int DAYS_IN_APR = 30;
constexpr const int DAYS_IN_MAY = 31;
constexpr const int DAYS_IN_JUN = 30;
constexpr const int DAYS_IN_JUL = 31;
constexpr const int DAYS_IN_AUG = 31;
constexpr const int DAYS_IN_SEP = 30;
constexpr const int DAYS_IN_OCT = 31;
constexpr const int DAYS_IN_NOV = 30;
constexpr const int DAYS_IN_DEC = 31;
[[nodiscard]] bool e57::utils::current_system_time(
unsigned short& utc_year, //!< Universal Time Coordinated [year]
unsigned char& utc_month, //!< Universal Time Coordinated [1-12 months]
unsigned char& utc_day, //!< Universal Time Coordinated [1-31 days]
unsigned char& utc_hour, //!< Universal Time Coordinated [hours]
unsigned char& utc_minute, //!< Universal Time Coordinated [minutes]
float& utc_seconds, //!< Universal Time Coordinated [s]
unsigned char& utc_offset, //!< Integer seconds that GPS is ahead of UTC time, always positive [s], obtained from a look up table
double& julian_date, //!< Number of days since noon Universal Time Jan 1, 4713 BCE (Julian calendar) [days]
unsigned short& gps_week, //!< GPS week (0-1024+) [week]
double& gps_tow //!< GPS time of week (0-604800.0) [s]
) noexcept
{
if (!e57::utils::current_julian_date(julian_date))
{
ERROR_MESSAGE("current_julian_date returned false.");
return false;
}
if (!e57::utils::determine_utc_offset(julian_date, utc_offset))
{
ERROR_MESSAGE("determine_utc_offset returned false.");
return false;
}
if (!e57::utils::gps_time_from_julian_date(julian_date, utc_offset, gps_week, gps_tow))
{
ERROR_MESSAGE("gps_time_from_julian_date returned false.");
return false;
}
if (!e57::utils::utc_time_from_julian_date(julian_date, utc_year, utc_month, utc_day, utc_hour, utc_minute, utc_seconds))
{
ERROR_MESSAGE("utc_time_from_julian_date returned false");
return false;
}
return true;
}
[[nodiscard]] bool e57::utils::current_julian_date(double& julian_date //!< Number of days since noon Universal Time Jan 1, 4713 BCE (Julian calendar) [days]
) noexcept
{
std::timespec time_spec;
if (std::timespec_get(&time_spec, TIME_UTC) == 0)
{
ERROR_MESSAGE("Could not retrieve timespec for TIME_UTC");
return false;
};
const double timebuffer_time_in_seconds = time_spec.tv_sec;
// timebuffer_time_in_seconds is the time in seconds since midnight (00:00:00), January 1, 1970,
// coordinated universal time (UTC). Julian date for (00:00:00), January 1, 1970 is: 2440587.5 [days]
// convert timebuffer.time from seconds to days
const double timebuffer_time_in_days = timebuffer_time_in_seconds / SECONDS_IN_A_DAY; // days since julian date 2440587.5000000 [days]
// convert to julian date
julian_date = JULIAN_DATE_START_OF_PC_TIME + timebuffer_time_in_days;
return true;
}
[[nodiscard]] bool e57::utils::current_gps_time(unsigned short& gps_week, //!< GPS week (0-1024+) [week]
double& gps_tow //!< GPS time of week (0-604800.0) [s]
) noexcept
{
double julian_date{};
unsigned char utc_offset{};
if (!e57::utils::current_julian_date(julian_date))
{
ERROR_MESSAGE("current_julian_date returned false.");
return false;
}
if (!e57::utils::determine_utc_offset(julian_date, utc_offset))
{
ERROR_MESSAGE("determine_utc_offset returned false.");
return false;
}
if (!e57::utils::gps_time_from_julian_date(julian_date, utc_offset, gps_week, gps_tow))
{
ERROR_MESSAGE("gps_time_from_julian_date returned false.");
return false;
}
return true;
}
[[nodiscard]] bool e57::utils::current_utc_time(unsigned short& utc_year, //!< Universal Time Coordinated [year]
unsigned char& utc_month, //!< Universal Time Coordinated [1-12 months]
unsigned char& utc_day, //!< Universal Time Coordinated [1-31 days]
unsigned char& utc_hour, //!< Universal Time Coordinated [hours]
unsigned char& utc_minute, //!< Universal Time Coordinated [minutes]
float& utc_seconds //!< Universal Time Coordinated [s]
) noexcept
{
double julian_date{};
if (!e57::utils::current_julian_date(julian_date))
{
ERROR_MESSAGE("current_julian_date returned false.");
return false;
}
if (!e57::utils::utc_time_from_julian_date(julian_date, utc_year, utc_month, utc_day, utc_hour, utc_minute, utc_seconds))
{
ERROR_MESSAGE("utc_time_from_julian_date returned false");
return false;
}
return true;
}
[[nodiscard]] bool e57::utils::day_of_week_from_julian_date(
const double julian_date, //!< Number of days since noon Universal Time Jan 1, 4713 BCE (Julian calendar) [days]
unsigned char& day_of_week //!< 0-Sunday, 1-Monday, 2-Tuesday, 3-Wednesday, 4-Thursday, 5-Friday, 6-Saturday [].
) noexcept
{
// "If the Julian date of noon is applied to the entire midnight-to-midnight civil
// day centered on that noon,[5] rounding Julian dates (fractional days) for the
// twelve hours before noon up while rounding those after noon down, then the remainder
// upon division by 7 represents the day of the week, with 0 representing Monday,
// 1 representing Tuesday, and so forth. Now at 17:48, Wednesday December 3 2008 (UTC)
// the nearest noon JDN is 2454804 yielding a remainder of 2." (http://en.wikipedia.org/wiki/Julian_day, 2008-12-03)
int64_t dow = 0;
int64_t jd = 0;
if (julian_date - floor(julian_date) > 0.5)
{
jd = static_cast<int64_t>(floor(julian_date + 0.5));
}
else
{
jd = static_cast<int64_t>(floor(julian_date));
}
dow = jd % 7; // 0 is monday, 1 is tuesday, etc
switch (dow)
{
case 0:
day_of_week = 1;
break;
case 1:
day_of_week = 2;
break;
case 2:
day_of_week = 3;
break;
case 3:
day_of_week = 4;
break;
case 4:
day_of_week = 5;
break;
case 5:
day_of_week = 6;
break;
case 6:
day_of_week = 0;
break;
default:
return false;
break;
}
return true;
}
[[nodiscard]] bool e57::utils::julian_date_from_gps_time(
const unsigned short gps_week, //!< GPS week (0-1024+) [week]
const double gps_tow, //!< GPS time of week (0-604800.0) [s]
const unsigned char utc_offset, //!< Integer seconds that GPS is ahead of UTC time, always positive [s]
double& julian_date //!< Number of days since noon Universal Time Jan 1, 4713 BCE (Julian calendar) [days]
) noexcept
{
if (gps_tow < 0.0 || gps_tow > SECONDS_IN_A_WEEK)
{
ERROR_MESSAGE("if( gps_tow < 0.0 || gps_tow > 604800.0 )");
return false;
}
// GPS time is ahead of UTC time and Julian time by the UTC offset
julian_date = (static_cast<double>(gps_week) + (gps_tow - static_cast<double>(utc_offset)) / SECONDS_IN_A_WEEK) * 7.0 + JULIAN_DATE_START_OF_GPS_TIME;
return true;
}
[[nodiscard]] bool e57::utils::julian_date_from_utc_time(
const unsigned short utc_year, //!< Universal Time Coordinated [year]
const unsigned char utc_month, //!< Universal Time Coordinated [1-12 months]
const unsigned char utc_day, //!< Universal Time Coordinated [1-31 days]
const unsigned char utc_hour, //!< Universal Time Coordinated [hours]
const unsigned char utc_minute, //!< Universal Time Coordinated [minutes]
const float utc_seconds, //!< Universal Time Coordinated [s]
double& julian_date //!< Number of days since noon Universal Time Jan 1, 4713 BCE (Julian calendar) [days]
) noexcept
{
double y{0.0}; // temp for year
double m{0.0}; // temp for month
// Check the input.
if (!e57::utils::is_utc_time_valid(utc_year, utc_month, utc_day, utc_hour, utc_minute, utc_seconds))
{
ERROR_MESSAGE("is_utc_time_valid returned false.");
return false;
}
if (utc_month <= 2)
{
y = utc_year - 1;
m = utc_month + 12;
}
else
{
y = utc_year;
m = utc_month;
}
julian_date = static_cast<int32_t>(365.25 * y) + static_cast<int32_t>(30.6001 * (m + 1.0)) + utc_day + utc_hour / 24.0 + utc_minute / 1440.0
+ utc_seconds / SECONDS_IN_A_DAY + 1720981.5;
return true;
}
[[nodiscard]] bool e57::utils::gps_time_from_julian_date(
const double julian_date, //!< Number of days since noon Universal Time Jan 1, 4713 BCE (Julian calendar) [days]
const unsigned char utc_offset, //!< Integer seconds that GPS is ahead of UTC time, always positive [s]
unsigned short& gps_week, //!< GPS week (0-1024+) [week]
double& gps_tow //!< GPS time of week [s]
) noexcept
{
// Check the input.
if (julian_date < 0.0)
{
ERROR_MESSAGE("julian_date is negative");
return false;
}
unsigned short week = static_cast<unsigned short>((julian_date - JULIAN_DATE_START_OF_GPS_TIME) / 7.0);
double tow = (julian_date - JULIAN_DATE_START_OF_GPS_TIME) * SECONDS_IN_A_DAY; // seconds since start of gps time [s]
tow -= (week)*SECONDS_IN_A_WEEK; // seconds into the current week [s]
// however, GPS time is ahead of utc time by the UTC offset (and thus the Julian date as well)
tow += utc_offset;
if (tow > SECONDS_IN_A_WEEK)
{
tow -= SECONDS_IN_A_WEEK;
week += 1;
}
gps_week = week;
gps_tow = tow;
return true;
}
[[nodiscard]] bool e57::utils::utc_time_from_julian_date(
const double julian_date, //!< Number of days since noon Universal Time Jan 1, 4713 BCE (Julian calendar) [days]
unsigned short& utc_year, //!< Universal Time Coordinated [year]
unsigned char& utc_month, //!< Universal Time Coordinated [1-12 months]
unsigned char& utc_day, //!< Universal Time Coordinated [1-31 days]
unsigned char& utc_hour, //!< Universal Time Coordinated [hours]
unsigned char& utc_minute, //!< Universal Time Coordinated [minutes]
float& utc_seconds //!< Universal Time Coordinated [s]
) noexcept
{
// Check the input.
if (julian_date < 0.0)
{
ERROR_MESSAGE("julian_date is negative");
return false;
}
unsigned char days_in_month = 0;
// temporary values
const int32_t a = static_cast<int32_t>(julian_date + 0.5);
const int32_t b = a + 1537;
const int32_t c = static_cast<int32_t>((static_cast<double>(b) - 122.1) / 365.25);
const int32_t d = static_cast<int32_t>(365.25 * c);
const int32_t e = static_cast<int32_t>((static_cast<double>(b - d)) / 30.6001);
double td = b - d - static_cast<int>(30.6001 * e) + fmod(julian_date + 0.5, 1.0); // [days]
unsigned char day = static_cast<unsigned char>(td);
// compute hours
td -= day;
td *= 24.0;
unsigned char hour = static_cast<unsigned char>(td);
// compute minutes
td -= hour;
td *= 60.0;
unsigned char minute = static_cast<unsigned char>(td);
// compute seconds
td -= minute;
td *= 60.0;
float seconds = td;
unsigned char month = static_cast<unsigned char>(e - 1 - 12 * static_cast<int>(e / 14));
unsigned short year = static_cast<unsigned short>(c - 4715 - static_cast<int>((7.0 + static_cast<double>(month)) / 10.0));
// check for rollover issues
if (seconds >= 60.0)
{
seconds -= 60.0;
minute++;
if (minute >= 60)
{
minute -= 60;
hour++;
if (hour >= 24)
{
hour -= 24;
day++;
if (!e57::utils::number_days_in_month(year, month, days_in_month))
{
ERROR_MESSAGE("number_days_in_month returned false.");
return false;
}
if (day > days_in_month)
{
day = 1;
month++;
if (month > 12)
{
month = 1;
year++;
}
}
}
}
}
utc_year = year;
utc_month = month;
utc_day = day;
utc_hour = hour;
utc_minute = minute;
utc_seconds = static_cast<float>(seconds);
return true;
}
[[nodiscard]] bool e57::utils::gps_time_from_utc_time(const unsigned short utc_year, //!< Universal Time Coordinated [year]
const unsigned char utc_month, //!< Universal Time Coordinated [1-12 months]
const unsigned char utc_day, //!< Universal Time Coordinated [1-31 days]
const unsigned char utc_hour, //!< Universal Time Coordinated [hours]
const unsigned char utc_minute, //!< Universal Time Coordinated [minutes]
const float utc_seconds, //!< Universal Time Coordinated [s]
unsigned short& gps_week, //!< GPS week (0-1024+) [week]
double& gps_tow //!< GPS time of week (0-604800.0) [s]
) noexcept
{
double julian_date{0.0};
unsigned char utc_offset{0};
// Check the input.
if (!e57::utils::is_utc_time_valid(utc_year, utc_month, utc_day, utc_hour, utc_minute, utc_seconds))
{
ERROR_MESSAGE("is_utc_time_valid returned false.");
return false;
}
if (!e57::utils::julian_date_from_utc_time(utc_year, utc_month, utc_day, utc_hour, utc_minute, utc_seconds, julian_date))
{
ERROR_MESSAGE("julian_date_from_utc_time returned false.");
return false;
}
if (!e57::utils::determine_utc_offset(julian_date, utc_offset))
{
ERROR_MESSAGE("determine_utc_offset returned false.");
return false;
}
if (!e57::utils::gps_time_from_julian_date(julian_date, utc_offset, gps_week, gps_tow))
{
ERROR_MESSAGE("gps_time_from_julian_date returned false.");
return false;
}
return true;
}
[[nodiscard]] bool e57::utils::gps_time_from_rinex_time(const unsigned short utc_year, //!< Universal Time Coordinated [year]
const unsigned char utc_month, //!< Universal Time Coordinated [1-12 months]
const unsigned char utc_day, //!< Universal Time Coordinated [1-31 days]
const unsigned char utc_hour, //!< Universal Time Coordinated [hours]
const unsigned char utc_minute, //!< Universal Time Coordinated [minutes]
const float utc_seconds, //!< Universal Time Coordinated [s]
unsigned short& gps_week, //!< GPS week (0-1024+) [week]
double& gps_tow //!< GPS time of week (0-604800.0) [s]
) noexcept
{
double julian_date{0.0};
unsigned char utc_offset{0};
// Check the input.
if (!e57::utils::is_utc_time_valid(utc_year, utc_month, utc_day, utc_hour, utc_minute, utc_seconds))
{
ERROR_MESSAGE("is_utc_time_valid returned false.");
return false;
}
if (!e57::utils::julian_date_from_utc_time(utc_year, utc_month, utc_day, utc_hour, utc_minute, utc_seconds, julian_date))
{
ERROR_MESSAGE("julian_date_from_utc_time returned false.");
return false;
}
if (!e57::utils::gps_time_from_julian_date(julian_date, utc_offset, gps_week, gps_tow))
{
ERROR_MESSAGE("GetGPSTimeFromJulianDate returned false.");
return false;
}
return true;
}
[[nodiscard]] bool e57::utils::utc_time_from_gps_time(const unsigned short gps_week, //!< GPS week (0-1024+) [week]
const double gps_tow, //!< GPS time of week (0-604800.0) [s]
unsigned short& utc_year, //!< Universal Time Coordinated [year]
unsigned char& utc_month, //!< Universal Time Coordinated [1-12 months]
unsigned char& utc_day, //!< Universal Time Coordinated [1-31 days]
unsigned char& utc_hour, //!< Universal Time Coordinated [hours]
unsigned char& utc_minute, //!< Universal Time Coordinated [minutes]
float& utc_seconds //!< Universal Time Coordinated [s]
) noexcept
{
double julian_date{0.0};
unsigned char utc_offset{0};
int i{0};
if (gps_tow < 0.0 || gps_tow > SECONDS_IN_A_WEEK)
{
ERROR_MESSAGE("if( gps_tow < 0.0 || gps_tow > 604800.0 )");
return false;
}
// iterate to get the right utc offset
for (i = 0; i < 4; i++)
{
if (!e57::utils::julian_date_from_gps_time(gps_week, gps_tow, utc_offset, julian_date))
{
ERROR_MESSAGE("julian_date_from_gps_time returned false.");
return false;
}
if (!e57::utils::determine_utc_offset(julian_date, utc_offset))
{
ERROR_MESSAGE("determine_utc_offset returned false.");
return false;
}
}
if (!e57::utils::utc_time_from_julian_date(julian_date, utc_year, utc_month, utc_day, utc_hour, utc_minute, utc_seconds))
{
ERROR_MESSAGE("utc_time_from_julian_date returned false.");
return false;
}
return true;
}
[[nodiscard]] bool e57::utils::determine_utc_offset(
const double julian_date, //!< Number of days since noon Universal Time Jan 1, 4713 BCE (Julian calendar) [days]
unsigned char& utc_offset //!< Integer seconds that GPS is ahead of UTC time, always positive [s], obtained from a look up table
) noexcept
{
if (julian_date < 0.0)
{
ERROR_MESSAGE("julian_date is negative");
return false;
}
if (julian_date < JULIAN_DATE_OFFSET_1981)
utc_offset = 0;
else if (julian_date < JULIAN_DATE_OFFSET_1982)
utc_offset = 1;
else if (julian_date < JULIAN_DATE_OFFSET_1983)
utc_offset = 2;
else if (julian_date < JULIAN_DATE_OFFSET_1985)
utc_offset = 3;
else if (julian_date < JULIAN_DATE_OFFSET_1988)
utc_offset = 4;
else if (julian_date < JULIAN_DATE_OFFSET_1990)
utc_offset = 5;
else if (julian_date < JULIAN_DATE_OFFSET_1991)
utc_offset = 6;
else if (julian_date < JULIAN_DATE_OFFSET_1992)
utc_offset = 7;
else if (julian_date < JULIAN_DATE_OFFSET_1993)
utc_offset = 8;
else if (julian_date < JULIAN_DATE_OFFSET_1994)
utc_offset = 9;
else if (julian_date < JULIAN_DATE_OFFSET_1996)
utc_offset = 10;
else if (julian_date < JULIAN_DATE_OFFSET_1997)
utc_offset = 11;
else if (julian_date < JULIAN_DATE_OFFSET_1999)
utc_offset = 12;
else if (julian_date < JULIAN_DATE_OFFSET_2006)
utc_offset = 13;
else if (julian_date < JULIAN_DATE_OFFSET_2009)
utc_offset = 14;
else
utc_offset = 15;
/*
* 12/Sep/2009 (KA): The following program will print out the required julian date for the next leap second (after editting year/month).
* #include <iostream>
* #include <iomanip>
* #include "time_conversion.h"
* void main() {
* double julianDate;
* if (GetJulianDateFromUTCTime(2008, 12, 31, 23, 59, 60.0, &julianDate))
* std::cout << "utc:2008-12-31 23:59:60 --> julian:" << std::setprecision(12) << julianDate << std::endl;
* }
*/
return true;
}
[[nodiscard]] bool e57::utils::number_days_in_month(const unsigned short year, //!< Universal Time Coordinated [year]
const unsigned char month, //!< Universal Time Coordinated [1-12 months]
unsigned char& days_in_month //!< Days in the specified month [1-28|29|30|31 days]
) noexcept
{
const bool is_a_leapyear = e57::utils::is_leap_year(year);
unsigned char utmp{0};
switch (month)
{
case 1:
utmp = DAYS_IN_JAN;
break;
case 2:
if (is_a_leapyear)
{
utmp = 29;
}
else
{
utmp = 28;
}
break;
case 3:
utmp = DAYS_IN_MAR;
break;
case 4:
utmp = DAYS_IN_APR;
break;
case 5:
utmp = DAYS_IN_MAY;
break;
case 6:
utmp = DAYS_IN_JUN;
break;
case 7:
utmp = DAYS_IN_JUL;
break;
case 8:
utmp = DAYS_IN_AUG;
break;
case 9:
utmp = DAYS_IN_SEP;
break;
case 10:
utmp = DAYS_IN_OCT;
break;
case 11:
utmp = DAYS_IN_NOV;
break;
case 12:
utmp = DAYS_IN_DEC;
break;
default: {
ERROR_MESSAGE("unexpected default case.");
return false;
break;
}
}
days_in_month = utmp;
return true;
}
[[nodiscard]] bool e57::utils::is_leap_year(const unsigned short year) noexcept
{
bool is_a_leap_year{false};
if ((year % 4) == 0)
{
is_a_leap_year = true;
if ((year % 100) == 0)
{
if ((year % 400) == 0)
{
is_a_leap_year = true;
}
else
{
is_a_leap_year = false;
}
}
}
if (is_a_leap_year)
{
return true;
}
return false;
}
[[nodiscard]] bool e57::utils::day_of_year(const unsigned short utc_year, // Universal Time Coordinated [year]
const unsigned char utc_month, // Universal Time Coordinated [1-12 months]
const unsigned char utc_day, // Universal Time Coordinated [1-31 days]
unsigned short& day_of_year // the day of the year (1-366) [days]
) noexcept
{
unsigned char days_in_feb{0};
if (!e57::utils::number_days_in_month(utc_year, 2, days_in_feb))
{
ERROR_MESSAGE("number_days_in_month returned false.");
return false;
}
switch (utc_month)
{
case 1:
day_of_year = utc_day;
break;
case 2:
day_of_year = (unsigned short)(DAYS_IN_JAN + utc_day);
break;
case 3:
day_of_year = (unsigned short)(DAYS_IN_JAN + days_in_feb + utc_day);
break;
case 4:
day_of_year = (unsigned short)(62 + days_in_feb + utc_day);
break;
case 5:
day_of_year = (unsigned short)(92 + days_in_feb + utc_day);
break;
case 6:
day_of_year = (unsigned short)(123 + days_in_feb + utc_day);
break;
case 7:
day_of_year = (unsigned short)(153 + days_in_feb + utc_day);
break;
case 8:
day_of_year = (unsigned short)(184 + days_in_feb + utc_day);
break;
case 9:
day_of_year = (unsigned short)(215 + days_in_feb + utc_day);
break;
case 10:
day_of_year = (unsigned short)(245 + days_in_feb + utc_day);
break;
case 11:
day_of_year = (unsigned short)(276 + days_in_feb + utc_day);
break;
case 12:
day_of_year = (unsigned short)(306 + days_in_feb + utc_day);
break;
default: {
ERROR_MESSAGE("unexpected default case.");
return false;
break;
}
}
return true;
}
[[nodiscard]] bool e57::utils::gps_time_from_year_and_day_of_year(const unsigned short year, // The year [year]
const unsigned short day_of_year, // The number of days into the year (1-366) [days]
unsigned short& gps_week, //!< GPS week (0-1024+) [week]
double& gps_tow //!< GPS time of week (0-604800.0) [s]
) noexcept
{
double julian_date{0.0};
unsigned char utc_offset{};
if (day_of_year < 1 || day_of_year > 366)
{
ERROR_MESSAGE("invalid date of year");
return false;
}
if (!e57::utils::julian_date_from_utc_time(year, 1, 1, 0, 0, 0, julian_date))
{
ERROR_MESSAGE("julian_date_from_utc_time returned false.");
return false;
}
if (!e57::utils::determine_utc_offset(julian_date, utc_offset))
{
ERROR_MESSAGE("determine_utc_offset returned false.");
return false;
}
julian_date += day_of_year - 1; // at the start of the day so -1.
if (!e57::utils::gps_time_from_julian_date(julian_date, utc_offset, gps_week, gps_tow))
{
ERROR_MESSAGE("gps_time_from_julian_date returned false.");
return false;
}
return true;
}
[[nodiscard]] bool e57::utils::is_utc_time_valid(const unsigned short utc_year, //!< Universal Time Coordinated [year]
const unsigned char utc_month, //!< Universal Time Coordinated [1-12 months]
const unsigned char utc_day, //!< Universal Time Coordinated [1-31 days]
const unsigned char utc_hour, //!< Universal Time Coordinated [hours]
const unsigned char utc_minute, //!< Universal Time Coordinated [minutes]
const float utc_seconds //!< Universal Time Coordinated [s]
) noexcept
{
unsigned char daysInMonth;
if (utc_month == 0 || utc_month > 12)
{
ERROR_MESSAGE("invalid utc_month value");
return false;
}
if (utc_hour > 23)
{
ERROR_MESSAGE("invalid utc_hour value");
return false;
}
if (utc_minute > 59)
{
ERROR_MESSAGE("invalid utc_minute value");
return false;
}
if (utc_seconds > 60)
{
ERROR_MESSAGE("invalid utc_seconds value");
return false;
}
if (!e57::utils::number_days_in_month(utc_year, utc_month, daysInMonth))
{
ERROR_MESSAGE("number_days_in_month returned false.");
return false;
}
if (utc_day == 0 || utc_day > daysInMonth)
{
ERROR_MESSAGE("if( utc_day == 0 || utc_day > daysInMonth )");
return false;
}
return true;
}
[[nodiscard]] bool e57::utils::gps_time_to_value(const unsigned short gps_week, //!< GPS week (0-1024+) [week]
const double gps_tow, //!< GPS time of week (0-604800.0) [s])
double& gps_time //!< GPS time expressed as a single double value)
) noexcept
{
if (gps_tow < 0.0 || gps_tow > SECONDS_IN_A_WEEK)
{
ERROR_MESSAGE("if( gps_tow < 0.0 || gps_tow > 604800.0 )");
return false;
}
gps_time = (gps_week * SECONDS_IN_A_WEEK) + gps_tow;
return true;
}
[[nodiscard]] bool e57::utils::gps_time_from_value(const double gps_time, //!< GPS time expressed as a single double value)
unsigned short& gps_week, //!< GPS week (0-1024+) [week]
double& gps_tow //!< GPS time of week (0-604800.0) [s])
) noexcept
{
if (gps_time <= 0.0)
{
ERROR_MESSAGE("if( gps_time <= 0.0");
return false;
}
gps_week = static_cast<int32_t>(floor(gps_time)) / SECONDS_IN_A_WEEK;
gps_tow = gps_time - gps_week * SECONDS_IN_A_WEEK;
return true;
}

View File

@@ -0,0 +1,33 @@
#define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN
#include <doctest/doctest.h>
#include <openE57/api.h>
using namespace e57;
TEST_SUITE("API Date/Time Tests")
{
TEST_CASE("Tests the creation of GpsTime from week and tow works successfully")
{
const core::GpsTime gps_time(2191, 15.0);
REQUIRE_EQ(1325116815.0, gps_time.time);
}
TEST_CASE("Tests the creation of GpsTime works from time works successfully")
{
const core::GpsTime gps_time(1325116815.0);
REQUIRE_EQ(2191, gps_time.week);
REQUIRE_EQ(15.0, gps_time.tow);
}
TEST_CASE("Tests the conversion to UTC Time from a given GPS Time")
{
const core::UtcTime utc_time = utils::utc_time_from_gps_time(core::GpsTime(2191, 15.0));
REQUIRE_EQ(2022, utc_time.year);
REQUIRE_EQ(1, utc_time.month);
REQUIRE_EQ(2, utc_time.day);
REQUIRE_EQ(0, utc_time.hour);
REQUIRE_EQ(0, utc_time.minute);
REQUIRE_EQ(0, utc_time.seconds);
}
}

View File

@@ -0,0 +1,204 @@
#define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN
#include <doctest/doctest.h>
#include <openE57/impl/time_conversion.h>
using namespace e57;
TEST_SUITE("Date/Time Conversion Tests")
{
TEST_CASE("Tests that current system time function works as expected")
{
unsigned short utc_year{};
unsigned char utc_month{};
unsigned char utc_day{};
unsigned char utc_hour{};
unsigned char utc_minute{};
float utc_seconds{};
unsigned char utc_offset{};
double julian_date{};
unsigned short gps_week{};
double gps_tow{};
REQUIRE_EQ(true, utils::current_system_time(utc_year, utc_month, utc_day, utc_hour, utc_minute, utc_seconds, utc_offset, julian_date, gps_week, gps_tow));
REQUIRE(utc_year >= 0);
REQUIRE(utc_month >= 1);
REQUIRE(utc_day >= 1);
REQUIRE(utc_hour >= 0);
REQUIRE(utc_minute >= 0);
REQUIRE(utc_seconds >= 0);
REQUIRE(utc_offset >= 0);
REQUIRE(julian_date >= 0);
REQUIRE(gps_week >= 0);
REQUIRE(gps_tow >= 0);
}
TEST_CASE("Tests that current system time as Julian Date function works as expected")
{
double julian_date{};
REQUIRE_EQ(true, utils::current_julian_date(julian_date));
REQUIRE(julian_date >= 0);
}
TEST_CASE("Tests that current system time as UTC time function works as expected")
{
unsigned short utc_year{};
unsigned char utc_month{};
unsigned char utc_day{};
unsigned char utc_hour{};
unsigned char utc_minute{};
float utc_seconds{};
REQUIRE_EQ(true, utils::current_utc_time(utc_year, utc_month, utc_day, utc_hour, utc_minute, utc_seconds));
REQUIRE(utc_year >= 0);
REQUIRE(utc_month >= 1);
REQUIRE(utc_day >= 1);
REQUIRE(utc_hour >= 0);
REQUIRE(utc_minute >= 0);
REQUIRE(utc_seconds >= 0);
}
TEST_CASE("Tests that current system time as GPS time function works as expected")
{
unsigned short gps_week{};
double gps_tow{};
REQUIRE_EQ(true, utils::current_gps_time(gps_week, gps_tow));
REQUIRE(gps_week >= 0);
REQUIRE(gps_tow >= 0);
}
TEST_CASE("Tests the conversion from UTC Time to Julian Date")
{
double julian_date{};
// This is the same as doing 2022-01-02 00:00:00
REQUIRE_EQ(true, utils::julian_date_from_utc_time(2022, 1, 1, 23, 59, 60, julian_date));
REQUIRE_EQ(2459581.5, julian_date);
}
TEST_CASE("Tests the conversion from UTC Time to GPS Time")
{
unsigned short gps_week{};
double gps_tow{};
// This is the same as doing 2022-01-02 00:00:00
REQUIRE_EQ(true, utils::gps_time_from_utc_time(2022, 1, 1, 23, 59, 60, gps_week, gps_tow));
REQUIRE_EQ(2191, gps_week);
REQUIRE_EQ(15.0, gps_tow);
}
TEST_CASE("Tests the conversion from Julian Date to UTC Time")
{
const double julian_date{2459581.5};
unsigned short utc_year{};
unsigned char utc_month{};
unsigned char utc_day{};
unsigned char utc_hour{};
unsigned char utc_minute{};
float utc_seconds{};
REQUIRE_EQ(true, utils::utc_time_from_julian_date(julian_date, utc_year, utc_month, utc_day, utc_hour, utc_minute, utc_seconds));
REQUIRE_EQ(2022, utc_year);
REQUIRE_EQ(1, utc_month);
REQUIRE_EQ(2, utc_day);
REQUIRE_EQ(0, utc_hour);
REQUIRE_EQ(0, utc_minute);
REQUIRE_EQ(0, utc_seconds);
}
TEST_CASE("Tests the conversion from Julian Date to GPS Time")
{
const double julian_date{2459581.5};
const unsigned char utc_offset{15};
unsigned short gps_week{};
double gps_tow{};
REQUIRE_EQ(true, utils::gps_time_from_julian_date(julian_date, utc_offset, gps_week, gps_tow));
REQUIRE_EQ(2191, gps_week);
REQUIRE_EQ(15.0, gps_tow);
}
TEST_CASE("Tests the conversion from GPS Time to Julian Date")
{
const unsigned short gps_week{2191};
const double gps_tow{15.0};
const unsigned char utc_offset{15};
double julian_date{};
REQUIRE_EQ(true, utils::julian_date_from_gps_time(gps_week, gps_tow, utc_offset, julian_date));
REQUIRE_EQ(2459581.5, julian_date);
}
TEST_CASE("Tests the conversion from GPS Time to UTC Time")
{
const unsigned short gps_week{2191};
const double gps_tow{15.0};
unsigned short utc_year{};
unsigned char utc_month{};
unsigned char utc_day{};
unsigned char utc_hour{};
unsigned char utc_minute{};
float utc_seconds{};
REQUIRE_EQ(true, utils::utc_time_from_gps_time(gps_week, gps_tow, utc_year, utc_month, utc_day, utc_hour, utc_minute, utc_seconds));
REQUIRE_EQ(2022, utc_year);
REQUIRE_EQ(1, utc_month);
REQUIRE_EQ(2, utc_day);
REQUIRE_EQ(0, utc_hour);
REQUIRE_EQ(0, utc_minute);
REQUIRE_EQ(0, utc_seconds);
}
TEST_CASE("Computes the UTC Offset from Julian Date")
{
const double julian_date{2459581.5};
unsigned char utc_offset{};
REQUIRE_EQ(true, utils::determine_utc_offset(julian_date, utc_offset));
REQUIRE_EQ(15, utc_offset);
}
TEST_CASE("Tests for Leap Year")
{
REQUIRE_EQ(false, utils::is_leap_year(2022));
REQUIRE_EQ(false, utils::is_leap_year(1399));
REQUIRE_EQ(true, utils::is_leap_year(2000));
REQUIRE_EQ(true, utils::is_leap_year(2004));
}
TEST_CASE("Tests for days in a month")
{
unsigned char days_in_month{};
REQUIRE_EQ(true, utils::number_days_in_month(2022, 2, days_in_month));
REQUIRE_EQ(28, days_in_month);
REQUIRE_EQ(true, utils::number_days_in_month(2000, 2, days_in_month));
REQUIRE_EQ(29, days_in_month);
}
TEST_CASE("Tests Number of Days in a Year")
{
unsigned short day_of_year{};
REQUIRE_EQ(true, utils::day_of_year(2022, 1, 1, day_of_year));
REQUIRE_EQ(1, day_of_year);
REQUIRE_EQ(true, utils::day_of_year(2022, 12, 31, day_of_year));
REQUIRE_EQ(365, day_of_year);
}
TEST_CASE("Tests the retrieval of GPS Time from Year and of Day of Year")
{
unsigned short gps_week{};
double gps_tow{};
REQUIRE_EQ(true, utils::gps_time_from_year_and_day_of_year(2022, 2, gps_week, gps_tow));
REQUIRE_EQ(2191, gps_week);
REQUIRE_EQ(15.0, gps_tow);
}
}

View File

@@ -1,35 +1,3 @@
#
# Time conversion utilities
#
add_library(time_conversion ${LIBRARY_TYPE}
${CMAKE_CURRENT_SOURCE_DIR}/time_conversion/time_conversion.c
${CMAKE_CURRENT_SOURCE_DIR}/time_conversion/time_conversion.h
${CMAKE_CURRENT_SOURCE_DIR}/time_conversion/basictypes.h
${CMAKE_CURRENT_SOURCE_DIR}/time_conversion/constants.h
${CMAKE_CURRENT_SOURCE_DIR}/time_conversion/gnss_error.h)
set_target_properties(time_conversion PROPERTIES
DEBUG_POSTFIX "-d"
MSVC_RUNTIME_LIBRARY "${CMAKE_MSVC_RUNTIME_LIBRARY}")
target_compile_options(time_conversion PUBLIC ${compiler_options})
target_compile_definitions(time_conversion PUBLIC ${compiler_definitions})
target_link_options(time_conversion PUBLIC ${linker_flags})
target_include_directories(time_conversion
PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/time_conversion
)
target_link_libraries(time_conversion
PUBLIC
${Boost_LIBRARY_DIRS}
${XML_LIBRARIES}
$<$<OR:$<C_COMPILER_ID:GNU>,$<C_COMPILER_ID:Clang>>:dl>
$<$<OR:$<C_COMPILER_ID:GNU>,$<C_COMPILER_ID:Clang>>:m>
$<$<OR:$<C_COMPILER_ID:GNU>,$<C_COMPILER_ID:Clang>>:c>
)
target_clangformat_setup(time_conversion)
#
# Build executables
#
@@ -91,7 +59,6 @@ target_link_libraries(las2e57
PRIVATE
${PROJECT_NAME}
${PROJECT_NAME}las
time_conversion
${XML_LIBRARIES}
${Boost_LIBRARIES}
${CMAKE_THREAD_LIBS_INIT}

View File

@@ -28,13 +28,12 @@
*/
#include <openE57/LAS/openE57las.h>
#include <openE57/openE57.h>
#include <time_conversion/time_conversion.h> // code from Essential GNSS Project
//#include <time_conversion/time_conversion.h> // code from Essential GNSS Project
#include <fstream> // std::ifstream
#include <iomanip>
#include <iostream>
#include <map>
#include <math.h>
#include <sstream>
#if 0
@@ -1119,9 +1118,9 @@ void copyPerScanData(CommandLineOptions& options, LASReader& lasf, ImageFile imf
unsigned short dayOfYear = static_cast<unsigned short>(hdr.fileCreationDayOfYear);
unsigned short gpsWeek = 0;
double gpsTOW = 0.0;
if (!TIMECONV_GetGPSTimeFromYearAndDayOfYear(year, dayOfYear, &gpsWeek, &gpsTOW))
if (!utils::gps_time_from_year_and_day_of_year(year, dayOfYear, gpsWeek, gpsTOW))
throw EXCEPTION("bad year,day");
double acquisitionStartGpsTime = gpsWeek * SECONDS_IN_WEEK + gpsTOW;
double acquisitionStartGpsTime = gpsWeek * utils::SECONDS_IN_A_WEEK + gpsTOW;
StructureNode dateTimeStruct = StructureNode(imf);
scan0.set("acquisitionStart", dateTimeStruct);
dateTimeStruct.set("dateTimeValue", FloatNode(imf, acquisitionStartGpsTime, E57_DOUBLE));
@@ -1448,8 +1447,8 @@ void copyPerPointData(CommandLineOptions& options, LASReader& lasf, ImageFile im
{
unsigned short gpsWeek = 0;
double gpsTOW = 0.0;
if (TIMECONV_GetGPSTimeFromYearAndDayOfYear(hdr.fileCreationYear, hdr.fileCreationDayOfYear, &gpsWeek, &gpsTOW))
lasTimeOffset = gpsWeek * SECONDS_IN_WEEK;
if (utils::gps_time_from_year_and_day_of_year(hdr.fileCreationYear, hdr.fileCreationDayOfYear, gpsWeek, gpsTOW))
lasTimeOffset = gpsWeek * utils::SECONDS_IN_A_WEEK;
else
lasTimeOffset = 0.0;
}
@@ -1620,9 +1619,9 @@ void copyPerFileData(CommandLineOptions& /*options*/, LASReader& /*lasf*/, Image
double julian_date; // Number of days since noon Universal Time Jan 1, 4713 BCE (Julian calendar) [days]
unsigned short gps_week; // GPS week (0-1024+) [week]
double gps_tow; // GPS time of week (0-604800.0) [s]
if (!TIMECONV_GetSystemTime(&utc_year, &utc_month, &utc_day, &utc_hour, &utc_minute, &utc_seconds, &utc_offset, &julian_date, &gps_week, &gps_tow))
throw EXCEPTION("get system time failed");
double gpsTime = gps_week * SECONDS_IN_WEEK + gps_tow;
if (!utils::current_system_time(utc_year, utc_month, utc_day, utc_hour, utc_minute, utc_seconds, utc_offset, julian_date, gps_week, gps_tow))
throw EXCEPTION("Failed to retrieve current system time");
double gpsTime = gps_week * utils::SECONDS_IN_A_WEEK + gps_tow;
StructureNode dateTimeStruct = StructureNode(imf);
root.set("creationDateTime", dateTimeStruct);
dateTimeStruct.set("dateTimeValue", FloatNode(imf, gpsTime, E57_DOUBLE));
@@ -1684,8 +1683,8 @@ ustring guidUnparse(uint32_t data1, uint16_t data2, uint16_t data3, uint8_t data
ustring gpsTimeUnparse(double gpsTime)
{
unsigned short gpsWeek = static_cast<unsigned short>(floor(gpsTime / SECONDS_IN_WEEK));
double gpsTOW = gpsTime - gpsWeek * SECONDS_IN_WEEK;
unsigned short gpsWeek = static_cast<unsigned short>(floor(gpsTime / utils::SECONDS_IN_A_WEEK));
double gpsTOW = gpsTime - gpsWeek * utils::SECONDS_IN_A_WEEK;
unsigned short utc_year; //!< Universal Time Coordinated [year]
unsigned char utc_month; //!< Universal Time Coordinated [1-12 months]
@@ -1694,7 +1693,8 @@ ustring gpsTimeUnparse(double gpsTime)
unsigned char utc_minute; //!< Universal Time Coordinated [minutes]
float utc_seconds; //!< Universal Time Coordinated [s]
ostringstream ss;
if (TIMECONV_GetUTCTimeFromGPSTime(gpsWeek, gpsTOW, &utc_year, &utc_month, &utc_day, &utc_hour, &utc_minute, &utc_seconds))
if (utils::utc_time_from_gps_time(gpsWeek, gpsTOW, utc_year, utc_month, utc_day, utc_hour, utc_minute, utc_seconds))
{
ss << utc_year << "-" << (unsigned)utc_month << "-" << (unsigned)utc_day << " " << (unsigned)utc_hour << ":" << (unsigned)utc_minute << ":" << utc_seconds;
return (ss.str());

View File

@@ -1,60 +0,0 @@
/**
\file basictypes.h
\brief GNSS core 'c' function library: basic types.
\author Glenn D. MacGougan (GDM)
\date 2007-11-29
\since 2006-11-10
\b "LICENSE INFORMATION" \n
Copyright (c) 2007, refer to 'author' doxygen tags \n
All rights reserved. \n
Redistribution and use in source and binary forms, with or without
modification, are permitted provided the following conditions are met: \n
- Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer. \n
- Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution. \n
- The name(s) of the contributor(s) may not be used to endorse or promote
products derived from this software without specific prior written
permission. \n
THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS ``AS IS'' AND ANY EXPRESS
OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
SUCH DAMAGE.
*/
#ifndef _C_BASICTYPES_H_
#define _C_BASICTYPES_H_
#ifdef __cplusplus
extern "C"
{
#endif
/// The 'c' boolean type is a define for (int). TRUE(0), FALSE(1).
typedef int BOOL;
#ifndef FALSE
# define FALSE (0)
#endif
#ifndef TRUE
# define TRUE (1)
#endif
#ifdef __cplusplus
}
#endif
#endif // _C_BASICTYPES_H_

View File

@@ -1,112 +0,0 @@
/**
\file constants.h
\brief GNSS core 'c' function library: Contains constants.
\author Glenn D. MacGougan (GDM)
\date 2007-11-29
\since 2005-07-30
\b "LICENSE INFORMATION" \n
Copyright (c) 2007, refer to 'author' doxygen tags \n
All rights reserved. \n
Redistribution and use in source and binary forms, with or without
modification, are permitted provided the following conditions are met: \n
- Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer. \n
- Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution. \n
- The name(s) of the contributor(s) may not be used to endorse or promote
products derived from this software without specific prior written
permission. \n
THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS ``AS IS'' AND ANY EXPRESS
OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
SUCH DAMAGE.
*/
#ifndef _C_CONSTANTS_H_
#define _C_CONSTANTS_H_
#ifdef __cplusplus
extern "C"
{
#endif
//#define PI (3.1415926535898) // value from GPS-ICD pp. 101 used in orbit curve fit calculations by the control segment
#ifndef PI
# define PI (3.1415926535897932384626433832795) //!< better value
#endif
#ifndef TWOPI
# define TWOPI (6.283185307179586476925286766559) //!< 2.0*PI
#endif
#ifndef HALFPI
# define HALFPI (1.5707963267948966192313216916398) //!< PI/2.0
#endif
#ifdef QUARTERPI
# define QUARTERPI (0.78539816339744830961566084581988) //!< PI/4.0
#endif
#ifndef DEG2RAD
# define DEG2RAD (0.017453292519943295769236907684886) //!< PI/180.0
#endif
#ifndef RAD2DEG
# define RAD2DEG (57.295779513082320876798154814105) //!< 180.0/PI
#endif
#ifndef SECONDS_IN_WEEK
# define SECONDS_IN_WEEK (604800.0) //!< [s]
#endif
#ifndef LIGHTSPEED
# define LIGHTSPEED (299792458.0) //!< light speed constant defined in ICD-GPS-200C p. 89 [m/s]
#endif
#ifndef ONE_MS_IN_M
# define ONE_MS_IN_M (299792.4580) //!< 1 millisecond * light speed constant defined in ICD-GPS-200C p. 89 [m/s]
#endif
#ifndef GPS_FREQUENCYL1
# define GPS_FREQUENCYL1 (1575.42e06) //!< [Hz]
#endif
#ifndef GPS_FREQUENCYL2
# define GPS_FREQUENCYL2 (1227.60e06) //!< [Hz]
#endif
#ifndef GPS_WAVELENGTHL1
# define GPS_WAVELENGTHL1 (0.19029367279836488047631742646405) //!< [m]
#endif
#ifndef GPS_WAVELENGTHL2
# define GPS_WAVELENGTHL2 (0.24421021342456825) //!< [m]
#endif
// not a constant but a very common type
#ifndef FALSE
# define FALSE (0)
#endif
#ifndef TRUE
# define TRUE (1)
#endif
#ifdef __cplusplus
}
#endif
#endif // _C_CONSTANTS_H_

View File

@@ -1,83 +0,0 @@
/**
\file gnss_error.h
\brief GNSS core 'c' function library: error and warning macros.
\author Glenn D. MacGougan (GDM)
\date 2008-03-19
\since 2008-03-19
\remarks
\b "LICENSE INFORMATION" \n
Copyright (c) 2008, refer to 'author' doxygen tags \n
All rights reserved. \n
Redistribution and use in source and binary forms, with or without
modification, are permitted provided the following conditions are met: \n
- Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer. \n
- Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution. \n
- The name(s) of the contributor(s) may not be used to endorse or promote
products derived from this software without specific prior written
permission. \n
THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS ``AS IS'' AND ANY EXPRESS
OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
SUCH DAMAGE.
*/
#ifndef _C_ERROR_H_
#define _C_ERROR_H_
#ifdef __cplusplus
extern "C"
{
#endif
#include <stdio.h>
/**
\brief Output an error message with the following format:\n
file, function, line number, msg\n
\code
char msg[128];
char fname[24];
sprintf( fname, "test.txt" );
sprintf( msg, "Unable to open %s", fname );
ERROR_MSG( msg );
\endcode
\author Glenn D. MacGougan (GDM)
\date 2008-03-19
\since 2008-03-19
*/
#define GNSS_ERROR_MSG(msg) \
{ \
const char* themsg = msg; \
if (themsg != NULL) \
{ \
printf("\n%s,\n%s, %d,\n%s\n", __FILE__, __func__, __LINE__, themsg); \
} \
else \
{ \
printf("\n%s,\n%s, %d,\nUnknown Error\n", __FILE__, __func__, __LINE__); \
} \
}
#ifdef __cplusplus
}
#endif
#endif // _C_ERROR_H_

View File

@@ -1,874 +0,0 @@
/**
\file time_conversion.c
\brief GNSS core 'c' function library: converting time information.
\author Glenn D. MacGougan (GDM)
\date 2007-11-29
\since 2005-07-30
\b REFERENCES \n
- Hofmann-Wellenhof, B., H. Lichtenegger, and J. Collins (1994). GPS Theory and
Practice, Third, revised edition. Springer-Verlag, Wien New York. pp. 38-42 \n
- http://aa.usno.navy.mil/data/docs/JulianDate.html - Julian Date Converter \n
- http://aa.usno.navy.mil/faq/docs/UT.html \n
- http://wwwmacho.mcmaster.ca/JAVA/JD.html \n
- Raquet, J. F. (2002), GPS Receiver Design Lecture Notes. Geomatics Engineering,
University of Calgary Graduate Course. \n
\b "LICENSE INFORMATION" \n
Copyright (c) 2007, refer to 'author' doxygen tags \n
All rights reserved. \n
Redistribution and use in source and binary forms, with or without
modification, are permitted provided the following conditions are met: \n
- Redistributions of source code must retain te above copyright
notice, this list of conditions and the following disclaimer. \n
- Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution. \n
- The name(s) of the contributor(s) may not be used to endorse or promote
products derived from this software without specific prior written
permission. \n
THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS ``AS IS'' AND ANY EXPRESS
OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
SUCH DAMAGE.
*/
#include <constants.h>
#include <gnss_error.h>
#include <math.h> /* for fmod() */
#include <sys/timeb.h>
#include <time.h>
#include <time_conversion.h>
#if 0
# ifndef WIN32
# define _CRT_SECURE_NO_DEPRECATE
# endif
#endif
#ifdef WIN32
# include <windows.h>
#endif
#define TIMECONV_JULIAN_DATE_START_OF_GPS_TIME (2444244.5) // [days]
#define TIMECONV_JULIAN_DATE_START_OF_PC_TIME (2440587.5) // [days]
#define TIMECONV_DAYS_IN_JAN 31
#define TIMECONV_DAYS_IN_MAR 31
#define TIMECONV_DAYS_IN_APR 30
#define TIMECONV_DAYS_IN_MAY 31
#define TIMECONV_DAYS_IN_JUN 30
#define TIMECONV_DAYS_IN_JUL 31
#define TIMECONV_DAYS_IN_AUG 31
#define TIMECONV_DAYS_IN_SEP 30
#define TIMECONV_DAYS_IN_OCT 31
#define TIMECONV_DAYS_IN_NOV 30
#define TIMECONV_DAYS_IN_DEC 31
// A static function to check if the utc input values are valid.
// \return TRUE if valid, FALSE otherwise.
static BOOL TIMECONV_IsUTCTimeValid(const unsigned short utc_year, //!< Universal Time Coordinated [year]
const unsigned char utc_month, //!< Universal Time Coordinated [1-12 months]
const unsigned char utc_day, //!< Universal Time Coordinated [1-31 days]
const unsigned char utc_hour, //!< Universal Time Coordinated [hours]
const unsigned char utc_minute, //!< Universal Time Coordinated [minutes]
const float utc_seconds //!< Universal Time Coordinated [s]
);
BOOL TIMECONV_IsUTCTimeValid(const unsigned short utc_year, //!< Universal Time Coordinated [year]
const unsigned char utc_month, //!< Universal Time Coordinated [1-12 months]
const unsigned char utc_day, //!< Universal Time Coordinated [1-31 days]
const unsigned char utc_hour, //!< Universal Time Coordinated [hours]
const unsigned char utc_minute, //!< Universal Time Coordinated [minutes]
const float utc_seconds //!< Universal Time Coordinated [s]
)
{
unsigned char daysInMonth;
BOOL result;
if (utc_month == 0 || utc_month > 12)
{
GNSS_ERROR_MSG("if( utc_month == 0 || utc_month > 12 )");
return FALSE;
}
result = TIMECONV_GetNumberOfDaysInMonth(utc_year, utc_month, &daysInMonth);
if (result == FALSE)
{
GNSS_ERROR_MSG("TIMECONV_GetNumberOfDaysInMonth returned FALSE.");
return FALSE;
}
if (utc_day == 0 || utc_day > daysInMonth)
{
GNSS_ERROR_MSG("if( utc_day == 0 || utc_day > daysInMonth )");
return FALSE;
}
if (utc_hour > 23)
{
GNSS_ERROR_MSG("if( utc_hour > 23 )");
return FALSE;
}
if (utc_minute > 59)
{
GNSS_ERROR_MSG("if( utc_minute > 59 )");
return FALSE;
}
if (utc_seconds > 60)
{
GNSS_ERROR_MSG("if( utc_seconds > 60 )");
return FALSE;
}
return TRUE;
}
BOOL TIMECONV_GetSystemTime(
unsigned short* utc_year, //!< Universal Time Coordinated [year]
unsigned char* utc_month, //!< Universal Time Coordinated [1-12 months]
unsigned char* utc_day, //!< Universal Time Coordinated [1-31 days]
unsigned char* utc_hour, //!< Universal Time Coordinated [hours]
unsigned char* utc_minute, //!< Universal Time Coordinated [minutes]
float* utc_seconds, //!< Universal Time Coordinated [s]
unsigned char* utc_offset, //!< Integer seconds that GPS is ahead of UTC time, always positive [s], obtained from a look up table
double* julian_date, //!< Number of days since noon Universal Time Jan 1, 4713 BCE (Julian calendar) [days]
unsigned short* gps_week, //!< GPS week (0-1024+) [week]
double* gps_tow //!< GPS time of week (0-604800.0) [s]
)
{
BOOL result;
#if defined(WIN32) && !defined(__GNUC__)
struct _timeb timebuffer; // found in <sys/timeb.h>
#else
struct timeb timebuffer;
#endif
double timebuffer_time_in_days;
double timebuffer_time_in_seconds;
// char *timeline; // for debugging
#ifdef _CRT_SECURE_NO_DEPRECATE
if (_ftime_s(&timebuffer) != 0)
{
GNSS_ERROR_MSG("if( _ftime_s( &timebuffer ) != 0 )");
return FALSE;
}
#else
# if defined(WIN32) && !defined(__GNUC__)
_ftime64_s(&timebuffer);
# else
ftime(&timebuffer);
# endif
#endif
// timeline = ctime( & ( timebuffer.time ) ); // for debugging
// printf( "%s\n", timeline ); // for debugging
timebuffer_time_in_seconds = timebuffer.time + timebuffer.millitm / 1000.0; // [s] with ms resolution
// timebuffer_time_in_seconds is the time in seconds since midnight (00:00:00), January 1, 1970,
// coordinated universal time (UTC). Julian date for (00:00:00), January 1, 1970 is: 2440587.5 [days]
// convert timebuffer.time from seconds to days
timebuffer_time_in_days = timebuffer_time_in_seconds / SECONDS_IN_DAY; // days since julian date 2440587.5000000 [days]
// convert to julian date
*julian_date = TIMECONV_JULIAN_DATE_START_OF_PC_TIME + timebuffer_time_in_days;
result = TIMECONV_DetermineUTCOffset(*julian_date, utc_offset);
if (result == FALSE)
{
GNSS_ERROR_MSG("TIMECONV_DetermineUTCOffset returned FALSE.");
return FALSE;
}
result = TIMECONV_GetGPSTimeFromJulianDate(*julian_date, *utc_offset, gps_week, gps_tow);
if (result == FALSE)
{
GNSS_ERROR_MSG("TIMECONV_GetGPSTimeFromJulianDate returned FALSE.");
return FALSE;
}
result = TIMECONV_GetUTCTimeFromJulianDate(*julian_date, utc_year, utc_month, utc_day, utc_hour, utc_minute, utc_seconds);
if (result == FALSE)
{
GNSS_ERROR_MSG("TIMECONV_GetUTCTimeFromJulianDate");
return FALSE;
}
return TRUE;
}
#ifdef WIN32
BOOL TIMECONV_SetSystemTime(const unsigned short utc_year, //!< Universal Time Coordinated [year]
const unsigned char utc_month, //!< Universal Time Coordinated [1-12 months]
const unsigned char utc_day, //!< Universal Time Coordinated [1-31 days]
const unsigned char utc_hour, //!< Universal Time Coordinated [hours]
const unsigned char utc_minute, //!< Universal Time Coordinated [minutes]
const float utc_seconds //!< Universal Time Coordinated [s]
)
{
BOOL result;
SYSTEMTIME t;
double julian_date = 0;
unsigned char day_of_week = 0;
result = TIMECONV_GetJulianDateFromUTCTime(utc_year, utc_month, utc_day, utc_hour, utc_minute, utc_seconds, &julian_date);
if (!result)
{
GNSS_ERROR_MSG("TIMECONV_GetJulianDateFromUTCTime returned FALSE.");
return FALSE;
}
result = TIMECONV_GetDayOfWeekFromJulianDate(julian_date, &day_of_week);
if (!result)
{
GNSS_ERROR_MSG("TIMECONV_GetDayOfWeekFromJulianDate returned FALSE.");
return FALSE;
}
t.wDayOfWeek = day_of_week;
t.wYear = utc_year;
t.wMonth = utc_month;
t.wDay = utc_day;
t.wHour = utc_hour;
t.wMinute = utc_minute;
t.wSecond = (WORD)(floor(utc_seconds));
t.wMilliseconds = (WORD)((utc_seconds - t.wSecond) * 1000);
// Set the PC system time.
result = SetSystemTime(&t);
return result;
}
#endif
BOOL TIMECONV_GetDayOfWeekFromJulianDate(const double julian_date, //!< Number of days since noon Universal Time Jan 1, 4713 BCE (Julian calendar) [days]
unsigned char* day_of_week //!< 0-Sunday, 1-Monday, 2-Tuesday, 3-Wednesday, 4-Thursday, 5-Friday, 6-Saturday [].
)
{
// "If the Julian date of noon is applied to the entire midnight-to-midnight civil
// day centered on that noon,[5] rounding Julian dates (fractional days) for the
// twelve hours before noon up while rounding those after noon down, then the remainder
// upon division by 7 represents the day of the week, with 0 representing Monday,
// 1 representing Tuesday, and so forth. Now at 17:48, Wednesday December 3 2008 (UTC)
// the nearest noon JDN is 2454804 yielding a remainder of 2." (http://en.wikipedia.org/wiki/Julian_day, 2008-12-03)
int dow = 0;
int jd = 0;
if (julian_date - floor(julian_date) > 0.5)
{
jd = (int)floor(julian_date + 0.5);
}
else
{
jd = (int)floor(julian_date);
}
dow = jd % 7; // 0 is monday, 1 is tuesday, etc
switch (dow)
{
case 0:
*day_of_week = 1;
break;
case 1:
*day_of_week = 2;
break;
case 2:
*day_of_week = 3;
break;
case 3:
*day_of_week = 4;
break;
case 4:
*day_of_week = 5;
break;
case 5:
*day_of_week = 6;
break;
case 6:
*day_of_week = 0;
break;
default:
return FALSE;
break;
}
return TRUE;
}
BOOL TIMECONV_GetJulianDateFromGPSTime(const unsigned short gps_week, //!< GPS week (0-1024+) [week]
const double gps_tow, //!< GPS time of week (0-604800.0) [s]
const unsigned char utc_offset, //!< Integer seconds that GPS is ahead of UTC time, always positive [s]
double* julian_date //!< Number of days since noon Universal Time Jan 1, 4713 BCE (Julian calendar) [days]
)
{
if (gps_tow < 0.0 || gps_tow > 604800.0)
{
GNSS_ERROR_MSG("if( gps_tow < 0.0 || gps_tow > 604800.0 )");
return FALSE;
}
// GPS time is ahead of UTC time and Julian time by the UTC offset
*julian_date = ((double)gps_week + (gps_tow - (double)utc_offset) / 604800.0) * 7.0 + TIMECONV_JULIAN_DATE_START_OF_GPS_TIME;
return TRUE;
}
BOOL TIMECONV_GetJulianDateFromUTCTime(const unsigned short utc_year, //!< Universal Time Coordinated [year]
const unsigned char utc_month, //!< Universal Time Coordinated [1-12 months]
const unsigned char utc_day, //!< Universal Time Coordinated [1-31 days]
const unsigned char utc_hour, //!< Universal Time Coordinated [hours]
const unsigned char utc_minute, //!< Universal Time Coordinated [minutes]
const float utc_seconds, //!< Universal Time Coordinated [s]
double* julian_date //!< Number of days since noon Universal Time Jan 1, 4713 BCE (Julian calendar) [days]
)
{
double y; // temp for year
double m; // temp for month
BOOL result;
// Check the input.
result = TIMECONV_IsUTCTimeValid(utc_year, utc_month, utc_day, utc_hour, utc_minute, utc_seconds);
if (result == FALSE)
{
GNSS_ERROR_MSG("TIMECONV_IsUTCTimeValid returned FALSE.");
return FALSE;
}
if (utc_month <= 2)
{
y = utc_year - 1;
m = utc_month + 12;
}
else
{
y = utc_year;
m = utc_month;
}
*julian_date = (int)(365.25 * y) + (int)(30.6001 * (m + 1.0)) + utc_day + utc_hour / 24.0 + utc_minute / 1440.0 + utc_seconds / 86400.0 + 1720981.5;
return TRUE;
}
BOOL TIMECONV_GetGPSTimeFromJulianDate(const double julian_date, //!< Number of days since noon Universal Time Jan 1, 4713 BCE (Julian calendar) [days]
const unsigned char utc_offset, //!< Integer seconds that GPS is ahead of UTC time, always positive [s]
unsigned short* gps_week, //!< GPS week (0-1024+) [week]
double* gps_tow //!< GPS time of week [s]
)
{
// Check the input.
if (julian_date < 0.0)
{
GNSS_ERROR_MSG("if( julian_date < 0.0 )");
return FALSE;
}
*gps_week = (unsigned short)((julian_date - TIMECONV_JULIAN_DATE_START_OF_GPS_TIME) / 7.0); //
*gps_tow = (julian_date - TIMECONV_JULIAN_DATE_START_OF_GPS_TIME) * SECONDS_IN_DAY; // seconds since start of gps time [s]
*gps_tow -= (*gps_week) * SECONDS_IN_WEEK; // seconds into the current week [s]
// however, GPS time is ahead of utc time by the UTC offset (and thus the Julian date as well)
*gps_tow += utc_offset;
if (*gps_tow > SECONDS_IN_WEEK)
{
*gps_tow -= SECONDS_IN_WEEK;
*gps_week += 1;
}
return TRUE;
}
BOOL TIMECONV_GetUTCTimeFromJulianDate(const double julian_date, //!< Number of days since noon Universal Time Jan 1, 4713 BCE (Julian calendar) [days]
unsigned short* utc_year, //!< Universal Time Coordinated [year]
unsigned char* utc_month, //!< Universal Time Coordinated [1-12 months]
unsigned char* utc_day, //!< Universal Time Coordinated [1-31 days]
unsigned char* utc_hour, //!< Universal Time Coordinated [hours]
unsigned char* utc_minute, //!< Universal Time Coordinated [minutes]
float* utc_seconds //!< Universal Time Coordinated [s]
)
{
int a, b, c, d, e; // temporary values
unsigned short year;
unsigned char month;
unsigned char day;
unsigned char hour;
unsigned char minute;
unsigned char days_in_month = 0;
double td; // temporary double
double seconds;
BOOL result;
// Check the input.
if (julian_date < 0.0)
{
GNSS_ERROR_MSG("if( julian_date < 0.0 )");
return FALSE;
}
a = (int)(julian_date + 0.5);
b = a + 1537;
c = (int)(((double)b - 122.1) / 365.25);
d = (int)(365.25 * c);
e = (int)(((double)(b - d)) / 30.6001);
td = b - d - (int)(30.6001 * e) + fmod(julian_date + 0.5, 1.0); // [days]
day = (unsigned char)td;
td -= day;
td *= 24.0; // [hours]
hour = (unsigned char)td;
td -= hour;
td *= 60.0; // [minutes]
minute = (unsigned char)td;
td -= minute;
td *= 60.0; // [s]
seconds = td;
month = (unsigned char)(e - 1 - 12 * (int)(e / 14));
year = (unsigned short)(c - 4715 - (int)((7.0 + (double)month) / 10.0));
// check for rollover issues
if (seconds >= 60.0)
{
seconds -= 60.0;
minute++;
if (minute >= 60)
{
minute -= 60;
hour++;
if (hour >= 24)
{
hour -= 24;
day++;
result = TIMECONV_GetNumberOfDaysInMonth(year, month, &days_in_month);
if (result == FALSE)
{
GNSS_ERROR_MSG("TIMECONV_GetNumberOfDaysInMonth returned FALSE.");
return FALSE;
}
if (day > days_in_month)
{
day = 1;
month++;
if (month > 12)
{
month = 1;
year++;
}
}
}
}
}
*utc_year = year;
*utc_month = month;
*utc_day = day;
*utc_hour = hour;
*utc_minute = minute;
*utc_seconds = (float)seconds;
return TRUE;
}
BOOL TIMECONV_GetGPSTimeFromUTCTime(unsigned short utc_year, //!< Universal Time Coordinated [year]
unsigned char utc_month, //!< Universal Time Coordinated [1-12 months]
unsigned char utc_day, //!< Universal Time Coordinated [1-31 days]
unsigned char utc_hour, //!< Universal Time Coordinated [hours]
unsigned char utc_minute, //!< Universal Time Coordinated [minutes]
float utc_seconds, //!< Universal Time Coordinated [s]
unsigned short* gps_week, //!< GPS week (0-1024+) [week]
double* gps_tow //!< GPS time of week (0-604800.0) [s]
)
{
double julian_date = 0.0;
unsigned char utc_offset = 0;
BOOL result;
// Check the input.
result = TIMECONV_IsUTCTimeValid(utc_year, utc_month, utc_day, utc_hour, utc_minute, utc_seconds);
if (result == FALSE)
{
GNSS_ERROR_MSG("TIMECONV_IsUTCTimeValid returned FALSE.");
return FALSE;
}
result = TIMECONV_GetJulianDateFromUTCTime(utc_year, utc_month, utc_day, utc_hour, utc_minute, utc_seconds, &julian_date);
if (result == FALSE)
{
GNSS_ERROR_MSG("TIMECONV_GetJulianDateFromUTCTime returned FALSE.");
return FALSE;
}
result = TIMECONV_DetermineUTCOffset(julian_date, &utc_offset);
if (result == FALSE)
{
GNSS_ERROR_MSG("TIMECONV_DetermineUTCOffset returned FALSE.");
return FALSE;
}
result = TIMECONV_GetGPSTimeFromJulianDate(julian_date, utc_offset, gps_week, gps_tow);
if (result == FALSE)
{
GNSS_ERROR_MSG("TIMECONV_GetGPSTimeFromJulianDate returned FALSE.");
return FALSE;
}
return TRUE;
}
BOOL TIMECONV_GetGPSTimeFromRinexTime(unsigned short utc_year, //!< Universal Time Coordinated [year]
unsigned char utc_month, //!< Universal Time Coordinated [1-12 months]
unsigned char utc_day, //!< Universal Time Coordinated [1-31 days]
unsigned char utc_hour, //!< Universal Time Coordinated [hours]
unsigned char utc_minute, //!< Universal Time Coordinated [minutes]
float utc_seconds, //!< Universal Time Coordinated [s]
unsigned short* gps_week, //!< GPS week (0-1024+) [week]
double* gps_tow //!< GPS time of week (0-604800.0) [s]
)
{
double julian_date = 0.0;
unsigned char utc_offset = 0;
BOOL result;
// Check the input.
result = TIMECONV_IsUTCTimeValid(utc_year, utc_month, utc_day, utc_hour, utc_minute, utc_seconds);
if (result == FALSE)
{
GNSS_ERROR_MSG("TIMECONV_IsUTCTimeValid returned FALSE.");
return FALSE;
}
result = TIMECONV_GetJulianDateFromUTCTime(utc_year, utc_month, utc_day, utc_hour, utc_minute, utc_seconds, &julian_date);
if (result == FALSE)
{
GNSS_ERROR_MSG("TIMECONV_GetJulianDateFromUTCTime returned FALSE.");
return FALSE;
}
result = TIMECONV_GetGPSTimeFromJulianDate(julian_date, utc_offset, gps_week, gps_tow);
if (result == FALSE)
{
GNSS_ERROR_MSG("TIMECONV_GetGPSTimeFromJulianDate returned FALSE.");
return FALSE;
}
return TRUE;
}
BOOL TIMECONV_GetUTCTimeFromGPSTime(unsigned short gps_week, //!< GPS week (0-1024+) [week]
double gps_tow, //!< GPS time of week (0-604800.0) [s]
unsigned short* utc_year, //!< Universal Time Coordinated [year]
unsigned char* utc_month, //!< Universal Time Coordinated [1-12 months]
unsigned char* utc_day, //!< Universal Time Coordinated [1-31 days]
unsigned char* utc_hour, //!< Universal Time Coordinated [hours]
unsigned char* utc_minute, //!< Universal Time Coordinated [minutes]
float* utc_seconds //!< Universal Time Coordinated [s]
)
{
double julian_date = 0.0;
unsigned char utc_offset = 0;
int i;
BOOL result;
if (gps_tow < 0.0 || gps_tow > 604800.0)
{
GNSS_ERROR_MSG("if( gps_tow < 0.0 || gps_tow > 604800.0 )");
return FALSE;
}
// iterate to get the right utc offset
for (i = 0; i < 4; i++)
{
result = TIMECONV_GetJulianDateFromGPSTime(gps_week, gps_tow, utc_offset, &julian_date);
if (result == FALSE)
{
GNSS_ERROR_MSG("TIMECONV_GetJulianDateFromGPSTime returned FALSE.");
return FALSE;
}
result = TIMECONV_DetermineUTCOffset(julian_date, &utc_offset);
if (result == FALSE)
{
GNSS_ERROR_MSG("TIMECONV_DetermineUTCOffset returned FALSE.");
return FALSE;
}
}
result = TIMECONV_GetUTCTimeFromJulianDate(julian_date, utc_year, utc_month, utc_day, utc_hour, utc_minute, utc_seconds);
if (result == FALSE)
{
GNSS_ERROR_MSG("TIMECONV_GetUTCTimeFromJulianDate returned FALSE.");
return FALSE;
}
return TRUE;
}
BOOL TIMECONV_DetermineUTCOffset(
double julian_date, //!< Number of days since noon Universal Time Jan 1, 4713 BCE (Julian calendar) [days]
unsigned char* utc_offset //!< Integer seconds that GPS is ahead of UTC time, always positive [s], obtained from a look up table
)
{
if (julian_date < 0.0)
{
GNSS_ERROR_MSG("if( julian_date < 0.0 )");
return FALSE;
}
if (julian_date < 2444786.5000)
*utc_offset = 0;
else if (julian_date < 2445151.5000)
*utc_offset = 1;
else if (julian_date < 2445516.5000)
*utc_offset = 2;
else if (julian_date < 2446247.5000)
*utc_offset = 3;
else if (julian_date < 2447161.5000)
*utc_offset = 4;
else if (julian_date < 2447892.5000)
*utc_offset = 5;
else if (julian_date < 2448257.5000)
*utc_offset = 6;
else if (julian_date < 2448804.5000)
*utc_offset = 7;
else if (julian_date < 2449169.5000)
*utc_offset = 8;
else if (julian_date < 2449534.5000)
*utc_offset = 9;
else if (julian_date < 2450083.5000)
*utc_offset = 10;
else if (julian_date < 2450630.5000)
*utc_offset = 11;
else if (julian_date < 2451179.5000)
*utc_offset = 12;
else if (julian_date < 2453736.5000)
*utc_offset = 13;
else if (julian_date < 2454832.5000)
*utc_offset = 14; // 12/Sep/2009 (KA): updated for leap second at 2008-12-31 23:59:60
else
*utc_offset = 15;
/*
* 12/Sep/2009 (KA): The following program will print out the required julian date for the next leap second (after editting year/month).
* #include <iostream>
* #include <iomanip>
* #include "time_conversion.h"
* void main() {
* double julianDate;
* if (TIMECONV_GetJulianDateFromUTCTime(2008, 12, 31, 23, 59, 60.0, &julianDate))
* std::cout << "utc:2008-12-31 23:59:60 --> julian:" << std::setprecision(12) << julianDate << std::endl;
* }
*/
return TRUE;
}
BOOL TIMECONV_GetNumberOfDaysInMonth(const unsigned short year, //!< Universal Time Coordinated [year]
const unsigned char month, //!< Universal Time Coordinated [1-12 months]
unsigned char* days_in_month //!< Days in the specified month [1-28|29|30|31 days]
)
{
BOOL is_a_leapyear;
unsigned char utmp = 0;
is_a_leapyear = TIMECONV_IsALeapYear(year);
switch (month)
{
case 1:
utmp = TIMECONV_DAYS_IN_JAN;
break;
case 2:
if (is_a_leapyear)
{
utmp = 29;
}
else
{
utmp = 28;
}
break;
case 3:
utmp = TIMECONV_DAYS_IN_MAR;
break;
case 4:
utmp = TIMECONV_DAYS_IN_APR;
break;
case 5:
utmp = TIMECONV_DAYS_IN_MAY;
break;
case 6:
utmp = TIMECONV_DAYS_IN_JUN;
break;
case 7:
utmp = TIMECONV_DAYS_IN_JUL;
break;
case 8:
utmp = TIMECONV_DAYS_IN_AUG;
break;
case 9:
utmp = TIMECONV_DAYS_IN_SEP;
break;
case 10:
utmp = TIMECONV_DAYS_IN_OCT;
break;
case 11:
utmp = TIMECONV_DAYS_IN_NOV;
break;
case 12:
utmp = TIMECONV_DAYS_IN_DEC;
break;
default: {
GNSS_ERROR_MSG("unexpected default case.");
return FALSE;
break;
}
}
*days_in_month = utmp;
return TRUE;
}
BOOL TIMECONV_IsALeapYear(const unsigned short year)
{
BOOL is_a_leap_year = FALSE;
if ((year % 4) == 0)
{
is_a_leap_year = TRUE;
if ((year % 100) == 0)
{
if ((year % 400) == 0)
{
is_a_leap_year = TRUE;
}
else
{
is_a_leap_year = FALSE;
}
}
}
if (is_a_leap_year)
{
return TRUE;
}
else
{
return FALSE;
}
}
BOOL TIMECONV_GetDayOfYear(const unsigned short utc_year, // Universal Time Coordinated [year]
const unsigned char utc_month, // Universal Time Coordinated [1-12 months]
const unsigned char utc_day, // Universal Time Coordinated [1-31 days]
unsigned short* dayofyear // number of days into the year (1-366) [days]
)
{
unsigned char days_in_feb = 0;
BOOL result;
result = TIMECONV_GetNumberOfDaysInMonth(utc_year, 2, &days_in_feb);
if (result == FALSE)
{
GNSS_ERROR_MSG("TIMECONV_GetNumberOfDaysInMonth returned FALSE.");
return FALSE;
}
switch (utc_month)
{
case 1:
*dayofyear = utc_day;
break;
case 2:
*dayofyear = (unsigned short)(TIMECONV_DAYS_IN_JAN + utc_day);
break;
case 3:
*dayofyear = (unsigned short)(TIMECONV_DAYS_IN_JAN + days_in_feb + utc_day);
break;
case 4:
*dayofyear = (unsigned short)(62 + days_in_feb + utc_day);
break;
case 5:
*dayofyear = (unsigned short)(92 + days_in_feb + utc_day);
break;
case 6:
*dayofyear = (unsigned short)(123 + days_in_feb + utc_day);
break;
case 7:
*dayofyear = (unsigned short)(153 + days_in_feb + utc_day);
break;
case 8:
*dayofyear = (unsigned short)(184 + days_in_feb + utc_day);
break;
case 9:
*dayofyear = (unsigned short)(215 + days_in_feb + utc_day);
break;
case 10:
*dayofyear = (unsigned short)(245 + days_in_feb + utc_day);
break;
case 11:
*dayofyear = (unsigned short)(276 + days_in_feb + utc_day);
break;
case 12:
*dayofyear = (unsigned short)(306 + days_in_feb + utc_day);
break;
default: {
GNSS_ERROR_MSG("unexpected default case.");
return FALSE;
break;
}
}
return TRUE;
}
BOOL TIMECONV_GetGPSTimeFromYearAndDayOfYear(const unsigned short year, // The year [year]
const unsigned short dayofyear, // The number of days into the year (1-366) [days]
unsigned short* gps_week, //!< GPS week (0-1024+) [week]
double* gps_tow //!< GPS time of week (0-604800.0) [s]
)
{
BOOL result;
double julian_date = 0;
if (gps_week == NULL)
{
GNSS_ERROR_MSG("if( gps_week == NULL )");
return FALSE;
}
if (gps_tow == NULL)
{
GNSS_ERROR_MSG("if( gps_tow == NULL )");
return FALSE;
}
if (dayofyear > 366)
{
GNSS_ERROR_MSG("if( dayofyear > 366 )");
return FALSE;
}
result = TIMECONV_GetJulianDateFromUTCTime(year, 1, 1, 0, 0, 0, &julian_date);
if (result == FALSE)
{
GNSS_ERROR_MSG("TIMECONV_GetJulianDateFromUTCTime returned FALSE.");
return FALSE;
}
julian_date += dayofyear - 1; // at the start of the day so -1.
result = TIMECONV_GetGPSTimeFromJulianDate(julian_date, 0, gps_week, gps_tow);
if (result == FALSE)
{
GNSS_ERROR_MSG("TIMECONV_GetGPSTimeFromJulianDate returned FALSE.");
return FALSE;
}
return TRUE;
}

View File

@@ -1,386 +0,0 @@
/**
\file time_conversion.h
\brief GNSS core 'c' function library: converting time information.
\author Glenn D. MacGougan (GDM)
\date 2007-11-29
\since 2005-07-30
\b REFERENCES \n
- Hofmann-Wellenhof, B., H. Lichtenegger, and J. Collins (1994). GPS Theory and
Practice, Third, revised edition. Springer-Verlag, Wien New York. pp. 38-42 \n
- http://aa.usno.navy.mil/data/docs/JulianDate.html - Julian Date Converter \n
- http://aa.usno.navy.mil/faq/docs/UT.html \n
- http://wwwmacho.mcmaster.ca/JAVA/JD.html \n
- Raquet, J. F. (2002), GPS Receiver Design Lecture Notes. Geomatics Engineering,
University of Calgary Graduate Course. \n
\b "LICENSE INFORMATION" \n
Copyright (c) 2007, refer to 'author' doxygen tags \n
All rights reserved. \n
Redistribution and use in source and binary forms, with or without
modification, are permitted provided the following conditions are met: \n
- Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer. \n
- Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution. \n
- The name(s) of the contributor(s) may not be used to endorse or promote
products derived from this software without specific prior written
permission. \n
THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS ``AS IS'' AND ANY EXPRESS
OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
SUCH DAMAGE.
*/
#ifndef _C_TIMECONV_H_
#define _C_TIMECONV_H_
#ifdef __cplusplus
extern "C"
{
#endif
#include "basictypes.h"
/*************************************************************************************************/
// preprocessor constant definitions, any related enumerations and descriptors
#ifndef SECONDS_IN_DAY
# define SECONDS_IN_DAY (86400.0)
#endif
#ifndef SECONDS_IN_WEEK
# define SECONDS_IN_WEEK (604800.0)
#endif
/**
\brief Obtains the UTC time, GPS time, and Julian date from PC system time.
\author Glenn D. MacGougan (GDM)
\date 2006-11-10
\since 2005-08-22
\return TRUE(1) if successful, FALSE(0) otherwise.
\remarks (1) Millisecond time is obtained
*/
BOOL TIMECONV_GetSystemTime(
unsigned short* utc_year, //!< Universal Time Coordinated [year]
unsigned char* utc_month, //!< Universal Time Coordinated [1-12 months]
unsigned char* utc_day, //!< Universal Time Coordinated [1-31 days]
unsigned char* utc_hour, //!< Universal Time Coordinated [hours]
unsigned char* utc_minute, //!< Universal Time Coordinated [minutes]
float* utc_seconds, //!< Universal Time Coordinated [s]
unsigned char* utc_offset, //!< Integer seconds that GPS is ahead of UTC time, always positive [s], obtained from a look up table
double* julian_date, //!< Number of days since noon Universal Time Jan 1, 4713 BCE (Julian calendar) [days]
unsigned short* gps_week, //!< GPS week (0-1024+) [week]
double* gps_tow //!< GPS time of week (0-604800.0) [s]
);
#ifdef WIN32
/**
\brief Sets the PC time to the UTC time provided.
\author Glenn D. MacGougan (GDM)
\date 2008-12-03
\since 2008-12-03
\return TRUE(1) if successful, FALSE(0) otherwise.
*/
BOOL TIMECONV_SetSystemTime(const unsigned short utc_year, //!< Universal Time Coordinated [year]
const unsigned char utc_month, //!< Universal Time Coordinated [1-12 months]
const unsigned char utc_day, //!< Universal Time Coordinated [1-31 days]
const unsigned char utc_hour, //!< Universal Time Coordinated [hours]
const unsigned char utc_minute, //!< Universal Time Coordinated [minutes]
const float utc_seconds //!< Universal Time Coordinated [s]
);
#endif
/**
\brief Computes the day of the week from the Julian date.
\author Glenn D. MacGougan (GDM)
\date 2008-12-03
\since 2008-12-03
\return TRUE(1) if successful, FALSE(0) otherwise.
\b REFERENCES \n
http://en.wikipedia.org/wiki/Julian_day
*/
BOOL TIMECONV_GetDayOfWeekFromJulianDate(const double julian_date, //!< Number of days since noon Universal Time Jan 1, 4713 BCE (Julian calendar) [days]
unsigned char* day_of_week //!< 0-Sunday, 1-Monday, 2-Tuesday, 3-Wednesday, 4-Thursday, 5-Friday, 6-Saturday [].
);
/**
\brief Computes the Julian date from GPS time
\author Glenn D. MacGougan (GDM)
\date 2007-11-29
\since 2005-08-22
\return TRUE(1) if successful, FALSE(0) otherwise.
\b REFERENCES \n
- Hofmann-Wellenhof, B., H. Lichtenegger, and J. Collins (1994). GPS Theory and
Practice, Third, revised edition. Springer-Verlag, Wien New York. pp. 38-42 \n
*/
BOOL TIMECONV_GetJulianDateFromGPSTime(const unsigned short gps_week, //!< GPS week (0-1024+) [week]
const double gps_tow, //!< GPS time of week (0-604800.0) [s]
const unsigned char utc_offset, //!< Integer seconds that GPS is ahead of UTC time, always positive [s]
double* julian_date //!< Number of days since noon Universal Time Jan 1, 4713 BCE (Julian calendar) [days]
);
/**
\brief Computes the Julian date from UTC time
\author Glenn D. MacGougan (GDM)
\date 2007-11-29
\since 2005-08-22
\return TRUE(1) if successful, FALSE(0) otherwise.
\remarks
- Verified calculation using http://aa.usno.navy.mil/data/docs/JulianDate.html,
a Julian Date Converter and http://wwwmacho.mcmaster.ca/JAVA/JD.html,
another online converter tool. \n
\b REFERENCES \n
- Hofmann-Wellenhof, B., H. Lichtenegger, and J. Collins (1994). GPS Theory and
Practice, Third, revised edition. Springer-Verlag, Wien New York. pp. 38-42 \n
*/
BOOL TIMECONV_GetJulianDateFromUTCTime(const unsigned short utc_year, //!< Universal Time Coordinated [year]
const unsigned char utc_month, //!< Universal Time Coordinated [1-12 months]
const unsigned char utc_day, //!< Universal Time Coordinated [1-31 days]
const unsigned char utc_hour, //!< Universal Time Coordinated [hours]
const unsigned char utc_minute, //!< Universal Time Coordinated [minutes]
const float utc_seconds, //!< Universal Time Coordinated [s]
double* julian_date //!< Number of days since noon Universal Time Jan 1, 4713 BCE (Julian calendar) [days]
);
/**
\brief Computes GPS time from the Julian date
\author Glenn D. MacGougan (GDM)
\date 2007-11-29
\since 2005-08-22
\return TRUE(1) if successful, FALSE(0) otherwise.
\b REFERENCES \n
- Hofmann-Wellenhof, B., H. Lichtenegger, and J. Collins (1994). GPS Theory and
Practice, Third, revised edition. Springer-Verlag, Wien New York. pp. 38-42 \n
*/
BOOL TIMECONV_GetGPSTimeFromJulianDate(const double julian_date, //!< Number of days since noon Universal Time Jan 1, 4713 BCE (Julian calendar) [days]
const unsigned char utc_offset, //!< Integer seconds that GPS is ahead of UTC time, always positive [s]
unsigned short* gps_week, //!< GPS week (0-1024+) [week]
double* gps_tow //!< GPS time of week [s]
);
/**
\brief Computes UTC time from the Julian date
\author Glenn D. MacGougan (GDM)
\date 2007-11-29
\since 2005-08-22
\return TRUE(1) if successful, FALSE(0) otherwise.
\b REFERENCES \n
- Hofmann-Wellenhof, B., H. Lichtenegger, and J. Collins (1994). GPS Theory and
Practice, Third, revised edition. Springer-Verlag, Wien New York. pp. 38-42 \n
*/
BOOL TIMECONV_GetUTCTimeFromJulianDate(const double julian_date, //!< Number of days since noon Universal Time Jan 1, 4713 BCE (Julian calendar) [days]
unsigned short* utc_year, //!< Universal Time Coordinated [year]
unsigned char* utc_month, //!< Universal Time Coordinated [1-12 months]
unsigned char* utc_day, //!< Universal Time Coordinated [1-31 days]
unsigned char* utc_hour, //!< Universal Time Coordinated [hours]
unsigned char* utc_minute, //!< Universal Time Coordinated [minutes]
float* utc_seconds //!< Universal Time Coordinated [s]
);
/**
\brief Computes GPS time from UTC time
\author Glenn D. MacGougan (GDM)
\date 2007-11-29
\since 2005-08-22
\return TRUE(1) if successful, FALSE(0) otherwise.
\remarks
(1) The utc offset is determined automatically from a look up table
\b REFERENCES \n
- Hofmann-Wellenhof, B., H. Lichtenegger, and J. Collins (1994). GPS Theory and
Practice, Third, revised edition. Springer-Verlag, Wien New York. pp. 38-42 \n
*/
BOOL TIMECONV_GetGPSTimeFromUTCTime(unsigned short utc_year, //!< Universal Time Coordinated [year]
unsigned char utc_month, //!< Universal Time Coordinated [1-12 months]
unsigned char utc_day, //!< Universal Time Coordinated [1-31 days]
unsigned char utc_hour, //!< Universal Time Coordinated [hours]
unsigned char utc_minute, //!< Universal Time Coordinated [minutes]
float utc_seconds, //!< Universal Time Coordinated [s]
unsigned short* gps_week, //!< GPS week (0-1024+) [week]
double* gps_tow //!< GPS time of week (0-604800.0) [s]
);
/**
\brief Computes GPS time from RINEX time. RINEX time looks like UTC
but it is GPS time in year, month, day, hours, minutes, seconds.
\author Glenn D. MacGougan (GDM)
\date 2007-12-07
\since 2007-12-07
\return TRUE(1) if successful, FALSE(0) otherwise.
\remarks
- There is no UTC offset to apply
- The RINEX time system must be the GPS Time system to use this function.
\b REFERENCES \n
- Hofmann-Wellenhof, B., H. Lichtenegger, and J. Collins (1994). GPS Theory and
Practice, Third, revised edition. Springer-Verlag, Wien New York. pp. 38-42 \n
- RINEX version 2.11, (http://www.aiub-download.unibe.ch/rinex/rinex211.txt)
*/
BOOL TIMECONV_GetGPSTimeFromRinexTime(unsigned short utc_year, //!< Universal Time Coordinated [year]
unsigned char utc_month, //!< Universal Time Coordinated [1-12 months]
unsigned char utc_day, //!< Universal Time Coordinated [1-31 days]
unsigned char utc_hour, //!< Universal Time Coordinated [hours]
unsigned char utc_minute, //!< Universal Time Coordinated [minutes]
float utc_seconds, //!< Universal Time Coordinated [s]
unsigned short* gps_week, //!< GPS week (0-1024+) [week]
double* gps_tow //!< GPS time of week (0-604800.0) [s]
);
/**
\brief Computes UTC time from GPS time
\author Glenn D. MacGougan (GDM)
\date 2007-11-29
\since 2005-08-22
\return TRUE(1) if successful, FALSE(0) otherwise.
\remarks
- The utc offset is determined automatically from a look up table
\b REFERENCES \n
- Hofmann-Wellenhof, B., H. Lichtenegger, and J. Collins (1994). GPS Theory and
Practice, Third, revised edition. Springer-Verlag, Wien New York. pp. 38-42 \n
*/
BOOL TIMECONV_GetUTCTimeFromGPSTime(unsigned short gps_week, //!< GPS week (0-1024+) [week]
double gps_tow, //!< GPS time of week (0-604800.0) [s]
unsigned short* utc_year, //!< Universal Time Coordinated [year]
unsigned char* utc_month, //!< Universal Time Coordinated [1-12 months]
unsigned char* utc_day, //!< Universal Time Coordinated [1-31 days]
unsigned char* utc_hour, //!< Universal Time Coordinated [hours]
unsigned char* utc_minute, //!< Universal Time Coordinated [minutes]
float* utc_seconds //!< Universal Time Coordinated [s]
);
/**
\brief This function is a look up table to determine the UTC offset from the Julian Date.
\author Glenn D. MacGougan (GDM)
\date 2007-11-29
\since 2005-08-22
\return TRUE(1) if successful, FALSE(0) otherwise.
\remarks
- This function must be updated when the next UTC *utc_offset step occurs. Current max is (13).
\b REFERENCES \n
- Raquet, J. F. (2002), GPS Receiver Design Lecture Notes. Geomatics Engineering,
University of Calgary Graduate Course. \n
\b "Offset Table" \n
UTCOffset, UTC Date, Julian Date [days] \n
0, Jan 06 1980 00:00:00.0, 2444244.5000 \n
1, Jul 01 1981 00:00:00.0, 2444786.5000 \n
2, Jul 01 1982 00:00:00.0, 2445151.5000 \n
3, Jul 01 1983 00:00:00.0, 2445516.5000 \n
4, Jul 01 1985 00:00:00.0, 2446247.5000 \n
5, Jan 01 1988 00:00:00.0, 2447161.5000 \n
6, Jan 01 1990 00:00:00.0, 2447892.5000 \n
7, Jan 01 1991 00:00:00.0, 2448257.5000 \n
8, Jul 01 1992 00:00:00.0, 2448804.5000 \n
9, Jul 01 1993 00:00:00.0, 2449169.5000 \n
10, Jul 01 1994 00:00:00.0, 2449534.5000 \n
11, Jan 01 1996 00:00:00.0, 2450083.5000 \n
12, Jul 01 1997 00:00:00.0, 2450630.5000 \n
13, Jan 01 1999 00:00:00.0, 2451179.5000 \n
14, Jan 01 2006 00:00:00.0, 2453736.5000 \n
*/
BOOL TIMECONV_DetermineUTCOffset(
double julian_date, //!< Number of days since noon Universal Time Jan 1, 4713 BCE (Julian calendar) [days]
unsigned char* utc_offset //!< Integer seconds that GPS is ahead of UTC time, always positive [s], obtained from a look up table
);
/**
\brief Determines the number of days in a month, given the month and year.
\author Glenn D. MacGougan (GDM)
\date 2007-11-29
\since 2005-08-22
\return TRUE(1) if successful, FALSE(0) otherwise.
\b REFERENCES \n
- Hofmann-Wellenhof, B., H. Lichtenegger, and J. Collins (1994). GPS Theory and
Practice, Third, revised edition. Springer-Verlag, Wien New York. pp. 38-42 \n
*/
BOOL TIMECONV_GetNumberOfDaysInMonth(const unsigned short year, //!< Universal Time Coordinated [year]
const unsigned char month, //!< Universal Time Coordinated [1-12 months]
unsigned char* days_in_month //!< Days in the specified month [1-28|29|30|31 days]
);
/**
\brief Determines if the given year is a leap year
\author Glenn D. MacGougan (GDM)
\date 2007-11-29
\since 2005-08-22
\returns TRUE(1) if the given year is a leap year, FALSE(0) otherwise
- Hofmann-Wellenhof, B., H. Lichtenegger, and J. Collins (1994). GPS Theory and
Practice, Third, revised edition. Springer-Verlag, Wien New York. pp. 38-42 \n
*/
BOOL TIMECONV_IsALeapYear(const unsigned short year);
/**
\brief Determines the day of year given the year, month, and day
\author Glenn D. MacGougan (GDM)
\date 2007-11-29
\since 2005-08-22
\return TRUE(1) if successful, FALSE(0) otherwise.
\remarks
(1) Performed independant comparison with http://www.mbari.org/staff/coletti/doytable.html
*/
BOOL TIMECONV_GetDayOfYear(const unsigned short utc_year, // Universal Time Coordinated [year]
const unsigned char utc_month, // Universal Time Coordinated [1-12 months]
const unsigned char utc_day, // Universal Time Coordinated [1-31 days]
unsigned short* dayofyear // number of days into the year (1-366) [days]
);
/**
\brief Determines the GPS time of the start of a day from the day of year and the year.
\author Glenn D. MacGougan (GDM)
\date 2007-12-07
\since 2007-12-07
\return TRUE(1) if successful, FALSE(0) otherwise.
*/
BOOL TIMECONV_GetGPSTimeFromYearAndDayOfYear(const unsigned short year, // The year [year]
const unsigned short dayofyear, // The number of days into the year (1-366) [days]
unsigned short* gps_week, //!< GPS week (0-1024+) [week]
double* gps_tow //!< GPS time of week (0-604800.0) [s]
);
#ifdef __cplusplus
}
#endif
#endif // _C_TIMECONV_H_