Merge-in all updates from master

This commit is contained in:
Gene Payne
2024-03-25 18:35:57 -06:00
634 changed files with 13476 additions and 9937 deletions

View File

@@ -28,8 +28,7 @@
#include <ghoul/filesystem/filesystem.h>
#include <ghoul/logging/logmanager.h>
#include <ghoul/misc/stringhelper.h>
#include <scn/scn.h>
#include <scn/tuple_return.h>
#include <scn/scan.h>
#include <fstream>
#include <optional>
#include <sstream>
@@ -127,7 +126,7 @@ namespace {
LeapSecond { .year = 2017, .dayOfYear = 1 }
};
// Get the position of the last leap second before the desired date
LeapSecond date{ year, dayOfYear };
const LeapSecond date = { year, dayOfYear };
const auto it = std::lower_bound(LeapSeconds.begin(), LeapSeconds.end(), date);
// Get the position of the Epoch
@@ -209,10 +208,13 @@ namespace {
if (e.find('.') == std::string::npos) {
e += ".0";
}
auto [res, year, daysInYear] = scn::scan_tuple<int, double>(e, "{:2}{}");
// @TODO(abock) The 'd' suffix can be removed when
// https://github.com/eliaskosunen/scnlib/issues/104 is fixed
auto res = scn::scan<int, double>(e, "{:2d}{}");
if (!res) {
throw ghoul::RuntimeError(fmt::format("Error parsing epoch '{}'", epoch));
throw ghoul::RuntimeError(std::format("Error parsing epoch '{}'", epoch));
}
auto [year, daysInYear] = res->values();
year += year > 57 ? 1900 : 2000;
const int daysSince2000 = countDays(year);
@@ -259,20 +261,20 @@ namespace {
e += ".0";
}
// 1, 2
size_t nDashes = std::count_if(
const size_t nDashes = std::count_if(
epoch.begin(),
epoch.end(),
[](char c) { return c == '-'; }
);
std::string formatString = (nDashes == 2) ? "{:4}-{:2}-{:2}{}" : "{:4}{:2}{:2}{}";
auto [res, year, monthNum, dayOfMonthNum, fractionOfDay] =
scn::scan_tuple<int, int, int, double>(e, formatString);
const std::string format = (nDashes == 2) ? "{:4}-{:2}-{:2}{}" : "{:4}{:2}{:2}{}";
auto res = scn::scan<int, int, int, double>(e, scn::runtime_format(format));
if (!res) {
throw ghoul::RuntimeError(fmt::format("Error parsing epoch '{}'", epoch));
throw ghoul::RuntimeError(std::format("Error parsing epoch '{}'", epoch));
}
auto [year, monthNum, dayOfMonthNum, fractionOfDay] = res->values();
const int daysSince2000 = countDays(year);
int wholeDaysInto = daysIntoGivenYear(year, monthNum, dayOfMonthNum);
double daysInYear = static_cast<double>(wholeDaysInto) + fractionOfDay;
const int wholeDaysInto = daysIntoGivenYear(year, monthNum, dayOfMonthNum);
const double daysInYear = static_cast<double>(wholeDaysInto) + fractionOfDay;
// 3
using namespace std::chrono;
@@ -328,30 +330,37 @@ namespace {
const size_t pos = epoch.find('T');
if (pos == 10) {
// We have the first form
int month;
int days;
auto res = scn::scan(
epoch, "{:4}-{:2}-{:2}T{:2}:{:2}:{}",
date.year, month, days, date.hours, date.minutes, date.seconds
int month = 0;
int days = 0;
// @TODO(abock) The 'd' suffix can be removed when
// https://github.com/eliaskosunen/scnlib/issues/104 is fixed
auto res = scn::scan<int, int, int, int, int, double>(
epoch, "{:4d}-{:2d}-{:2d}T{:2d}:{:2d}:{}"
);
if (!res) {
throw ghoul::RuntimeError(fmt::format("Error parsing epoch '{}'", epoch));
throw ghoul::RuntimeError(std::format("Error parsing epoch '{}'", epoch));
}
std::tie(date.year, month, days, date.hours, date.minutes, date.seconds) =
res->values();
date.nDays = daysIntoGivenYear(date.year, month, days);
}
else if (pos == 8) {
// We have the second form
auto res = scn::scan(
epoch, "{:4}-{:3}T{:2}:{:2}:{}",
date.year, date.nDays, date.hours, date.minutes, date.seconds
// @TODO(abock) The 'd' suffix can be removed when
// https://github.com/eliaskosunen/scnlib/issues/104 is fixed
auto res = scn::scan<int, int, int, int, double>(
epoch, "{:4d}-{:3d}T{:2d}:{:2d}:{}"
//date.year, date.nDays, date.hours, date.minutes, date.seconds
);
if (!res) {
throw ghoul::RuntimeError(fmt::format("Error parsing epoch '{}'", epoch));
throw ghoul::RuntimeError(std::format("Error parsing epoch '{}'", epoch));
}
std::tie(date.year, date.nDays, date.hours, date.minutes, date.seconds) =
res->values();
}
else {
throw ghoul::RuntimeError(fmt::format("Malformed epoch string '{}'", epoch));
throw ghoul::RuntimeError(std::format("Malformed epoch string '{}'", epoch));
}
const int daysSince2000 = countDays(date.year);
@@ -385,7 +394,7 @@ namespace {
namespace openspace::kepler {
std::vector<Parameters> readTleFile(std::filesystem::path file) {
std::vector<Parameters> readTleFile(const std::filesystem::path& file) {
ghoul_assert(std::filesystem::is_regular_file(file), "File must exist");
std::vector<Parameters> result;
@@ -421,19 +430,19 @@ std::vector<Parameters> readTleFile(std::filesystem::path file) {
std::string firstLine;
ghoul::getline(f, firstLine);
if (f.bad() || firstLine[0] != '1') {
throw ghoul::RuntimeError(fmt::format(
throw ghoul::RuntimeError(std::format(
"Malformed TLE file '{}' at line {}", file, lineNum + 1
));
}
// The id only contains the last two digits of the launch year, so we have to
// patch it to the full year
{
std::string id = firstLine.substr(9, 6);
std::string prefix = [y = id.substr(0, 2)](){
int year = std::atoi(y.c_str());
const std::string id = firstLine.substr(9, 6);
const std::string prefix = [y = id.substr(0, 2)](){
const int year = std::atoi(y.c_str());
return year >= 57 ? "19" : "20";
}();
p.id = fmt::format("{}{}-{}", prefix, id.substr(0, 2), id.substr(3));
p.id = std::format("{}{}-{}", prefix, id.substr(0, 2), id.substr(3));
}
p.epoch = epochFromSubstring(firstLine.substr(18, 14)); // should be 13?
@@ -453,7 +462,7 @@ std::vector<Parameters> readTleFile(std::filesystem::path file) {
std::string secondLine;
ghoul::getline(f, secondLine);
if (f.bad() || secondLine[0] != '2') {
throw ghoul::RuntimeError(fmt::format(
throw ghoul::RuntimeError(std::format(
"Malformed TLE file '{}' at line {}", file, lineNum + 1
));
}
@@ -488,7 +497,7 @@ std::vector<Parameters> readTleFile(std::filesystem::path file) {
// Get mean motion
stream.str(secondLine.substr(52, 11));
float meanMotion;
float meanMotion = 0.f;
stream >> meanMotion;
p.semiMajorAxis = calculateSemiMajorAxis(meanMotion);
@@ -502,7 +511,7 @@ std::vector<Parameters> readTleFile(std::filesystem::path file) {
return result;
}
std::vector<Parameters> readOmmFile(std::filesystem::path file) {
std::vector<Parameters> readOmmFile(const std::filesystem::path& file) {
ghoul_assert(std::filesystem::is_regular_file(file), "File must exist");
std::vector<Parameters> result;
@@ -525,7 +534,7 @@ std::vector<Parameters> readOmmFile(std::filesystem::path file) {
}
if (parts.size() != 2) {
throw ghoul::RuntimeError(fmt::format(
throw ghoul::RuntimeError(std::format(
"Malformed line '{}' at {}", line, lineNum
));
}
@@ -534,7 +543,7 @@ std::vector<Parameters> readOmmFile(std::filesystem::path file) {
if (parts[1] != "2.0") {
LWARNINGC(
"OMM",
fmt::format(
std::format(
"Only version 2.0 is currently supported but found {}. "
"Parsing might fail",
parts[1]
@@ -563,7 +572,7 @@ std::vector<Parameters> readOmmFile(std::filesystem::path file) {
current->epoch = epochFromOmmString(parts[1]);
}
else if (parts[0] == "MEAN_MOTION") {
float mm = std::stof(parts[1]);
const float mm = std::stof(parts[1]);
current->semiMajorAxis = calculateSemiMajorAxis(mm);
current->period = std::chrono::seconds(std::chrono::hours(24)).count() / mm;
}
@@ -594,7 +603,7 @@ std::vector<Parameters> readOmmFile(std::filesystem::path file) {
return result;
}
std::vector<Parameters> readSbdbFile(std::filesystem::path file) {
std::vector<Parameters> readSbdbFile(const std::filesystem::path& file) {
constexpr int NDataFields = 9;
constexpr std::string_view ExpectedHeader = "full_name,epoch_cal,e,a,i,om,w,ma,per";
@@ -608,7 +617,7 @@ std::vector<Parameters> readSbdbFile(std::filesystem::path file) {
// Newer versions downloaded from the JPL SBDB website have " around variables
line.erase(remove(line.begin(), line.end(), '\"'), line.end());
if (line != ExpectedHeader) {
throw ghoul::RuntimeError(fmt::format(
throw ghoul::RuntimeError(std::format(
"Expected JPL SBDB file to start with '{}' but found '{}' instead",
ExpectedHeader, line.substr(0, 100)
));
@@ -620,7 +629,7 @@ std::vector<Parameters> readSbdbFile(std::filesystem::path file) {
std::vector<std::string> parts = ghoul::tokenizeString(line, ',');
if (parts.size() != NDataFields) {
throw ghoul::RuntimeError(fmt::format(
throw ghoul::RuntimeError(std::format(
"Malformed line {}, expected 8 data fields, got {}", line, parts.size()
));
}
@@ -658,7 +667,7 @@ std::vector<Parameters> readSbdbFile(std::filesystem::path file) {
return result;
}
void saveCache(const std::vector<Parameters>& params, std::filesystem::path file) {
void saveCache(const std::vector<Parameters>& params, const std::filesystem::path& file) {
std::ofstream stream(file, std::ofstream::binary);
stream.write(reinterpret_cast<const char*>(&CurrentCacheVersion), sizeof(int8_t));
@@ -688,7 +697,7 @@ void saveCache(const std::vector<Parameters>& params, std::filesystem::path file
}
}
std::optional<std::vector<Parameters>> loadCache(std::filesystem::path file) {
std::optional<std::vector<Parameters>> loadCache(const std::filesystem::path& file) {
std::ifstream stream(file, std::ifstream::binary);
int8_t version = 0;
@@ -733,8 +742,8 @@ std::optional<std::vector<Parameters>> loadCache(std::filesystem::path file) {
std::vector<Parameters> readFile(std::filesystem::path file, Format format) {
std::filesystem::path cachedFile = FileSys.cacheManager()->cachedFilename(file);
if (std::filesystem::is_regular_file(cachedFile)) {
LINFO(fmt::format(
"Cached file {} used for Kepler file {}", cachedFile, file
LINFO(std::format(
"Cached file '{}' used for Kepler file '{}'", cachedFile, file
));
std::optional<std::vector<Parameters>> res = loadCache(cachedFile);
@@ -758,7 +767,7 @@ std::vector<Parameters> readFile(std::filesystem::path file, Format format) {
break;
}
LINFO(fmt::format("Saving cache {} for Kepler file {}", cachedFile, file));
LINFO(std::format("Saving cache '{}' for Kepler file '{}'", cachedFile, file));
saveCache(res, cachedFile);
return res;
}