-
Notifications
You must be signed in to change notification settings - Fork 311
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Refactor sampled orbit and orientation classes
- Store sample times and rotations in separate vectors to reduce padding - Do not permit out-of-order timestamps in sample files - Do not permit empty sampled trajectories or rotations - Pre-rotate the sampled trajectory positions and velocities - Consolidate loader code Deduplicate the loader code Deduplicate the index code Revise includes
- Loading branch information
Showing
6 changed files
with
697 additions
and
692 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,139 @@ | ||
// sampfile.cpp | ||
// | ||
// Utility functions for sampled orbit and rotation files. | ||
// | ||
// Copyright (C) 2023, Celestia Development Team | ||
// | ||
// Extracted from samporbit.cpp/samporient.cpp | ||
// Copyright (C) 2008, Celestia Development Team | ||
// Initial implementation by Chris Laurel <[email protected]> | ||
// | ||
// This program is free software; you can redistribute it and/or | ||
// modify it under the terms of the GNU General Public License | ||
// as published by the Free Software Foundation; either version 2 | ||
// of the License, or (at your option) any later version. | ||
|
||
#include "sampfile.h" | ||
|
||
#include <algorithm> | ||
#include <cctype> | ||
|
||
#include <celutil/gettext.h> | ||
#include <celutil/logger.h> | ||
|
||
using celestia::util::GetLogger; | ||
|
||
namespace celestia::ephem | ||
{ | ||
|
||
namespace detail | ||
{ | ||
|
||
bool | ||
checkSampleOrdering(double tdb, | ||
double& lastSampleTime, | ||
bool& hasOutOfOrderSamples, | ||
const fs::path& filename) | ||
{ | ||
if (tdb > lastSampleTime) | ||
{ | ||
lastSampleTime = tdb; | ||
return true; | ||
} | ||
|
||
if (!hasOutOfOrderSamples) | ||
{ | ||
GetLogger()->warn(_("Skipping out-of-order samples in {}."), filename); | ||
hasOutOfOrderSamples = true; | ||
} | ||
|
||
return false; | ||
} | ||
|
||
|
||
bool | ||
logIfNoSamples(bool hasSamples, const fs::path& filename) | ||
{ | ||
if (!hasSamples) | ||
GetLogger()->error(_("No samples found in sample file {}.\n"), filename); | ||
|
||
return hasSamples; | ||
} | ||
|
||
|
||
void | ||
logReadError(const fs::path& filename) | ||
{ | ||
GetLogger()->error(_("Error reading sample file {}.\n"), filename); | ||
} | ||
|
||
|
||
void | ||
logOpenAsciiFail(const fs::path& filename) | ||
{ | ||
GetLogger()->error(_("Error opening ASCII sample file {}.\n"), filename); | ||
} | ||
|
||
|
||
void | ||
logSkipCommentsFail(const fs::path& filename) | ||
{ | ||
GetLogger()->error(_("Error finding data in ASCII sample file {}.\n"), filename); | ||
} | ||
|
||
|
||
// Scan past comments. A comment begins with the # character and ends | ||
// with a newline. Return true if the stream state is good. The stream | ||
// position will be at the first non-comment, non-whitespace character. | ||
bool skipComments(std::istream& in) | ||
{ | ||
bool inComment = false; | ||
for (;;) | ||
{ | ||
int c = in.get(); | ||
if (!in.good()) | ||
return false; | ||
|
||
if (inComment) | ||
{ | ||
if (c == '\n') | ||
inComment = false; | ||
} | ||
else | ||
{ | ||
if (c == '#') | ||
{ | ||
inComment = true; | ||
} | ||
else if (!std::isspace(static_cast<unsigned char>(c))) | ||
{ | ||
in.unget(); | ||
return in.good(); | ||
} | ||
} | ||
} | ||
} | ||
|
||
} // end namespace celestia::ephem::detail | ||
|
||
// Do a binary search to find the samples that define the orientation | ||
// at the current time. Cache the previous sample used and avoid | ||
// the search if it covers the requested time. | ||
std::uint32_t | ||
GetSampleIndex(double jd, | ||
std::uint32_t& lastSample, | ||
celestia::util::array_view<double> sampleTimes) | ||
{ | ||
std::uint32_t n = lastSample; | ||
const auto maxSample = static_cast<std::uint32_t>(sampleTimes.size()); | ||
if (n < 1 || n >= maxSample || jd < sampleTimes[n - 1] || jd > sampleTimes[n]) | ||
{ | ||
auto iter = std::lower_bound(sampleTimes.begin(), sampleTimes.end(), jd); | ||
n = static_cast<std::uint32_t>(iter - sampleTimes.begin()); | ||
lastSample = n; | ||
} | ||
|
||
return n; | ||
} | ||
|
||
} // end namespace celestia::ephem |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,109 @@ | ||
// sampfile.h | ||
// | ||
// Utility functions for sampled orbit and rotation files. | ||
// | ||
// Copyright (C) 2023, Celestia Development Team | ||
// | ||
// Extracted from samporbit.h/samporient.h | ||
// Copyright (C) 2008, Celestia Development Team | ||
// Initial implementation by Chris Laurel <[email protected]> | ||
// | ||
// This program is free software; you can redistribute it and/or | ||
// modify it under the terms of the GNU General Public License | ||
// as published by the Free Software Foundation; either version 2 | ||
// of the License, or (at your option) any later version. | ||
|
||
#include <cstdint> | ||
#include <fstream> | ||
#include <istream> | ||
#include <limits> | ||
#include <utility> | ||
#include <vector> | ||
|
||
#include <celcompat/filesystem.h> | ||
#include <celutil/array_view.h> | ||
|
||
namespace celestia::ephem | ||
{ | ||
|
||
namespace detail | ||
{ | ||
|
||
bool checkSampleOrdering(double tdb, | ||
double& lastSampleTime, | ||
bool& hasOutOfOrderSamples, | ||
const fs::path& filename); | ||
|
||
bool logIfNoSamples(bool, const fs::path&); | ||
void logReadError(const fs::path&); | ||
void logOpenAsciiFail(const fs::path&); | ||
void logSkipCommentsFail(const fs::path&); | ||
|
||
bool skipComments(std::istream& in); | ||
|
||
} | ||
|
||
|
||
std::uint32_t GetSampleIndex(double jd, | ||
std::uint32_t& lastSample, | ||
celestia::util::array_view<double> sampleTimes); | ||
|
||
|
||
template<typename T, typename F> | ||
bool | ||
LoadSamples(std::istream& in, | ||
const fs::path& filename, | ||
std::vector<double>& sampleTimes, | ||
std::vector<T>& samples, | ||
F readSample) | ||
{ | ||
double lastSampleTime = -std::numeric_limits<double>::infinity(); | ||
bool hasOutOfOrderSamples = false; | ||
for (;;) | ||
{ | ||
double tdb; | ||
T sample; | ||
if (!readSample(in, tdb, sample)) | ||
{ | ||
if (in.eof()) | ||
return detail::logIfNoSamples(!sampleTimes.empty(), filename); | ||
|
||
detail::logReadError(filename); | ||
return false; | ||
} | ||
|
||
// Skip samples with duplicate or out-of-order times; such trajectories | ||
// are invalid, but are unfortunately used in some existing add-ons. | ||
if (!detail::checkSampleOrdering(tdb, lastSampleTime, hasOutOfOrderSamples, filename)) | ||
continue; | ||
|
||
sampleTimes.push_back(tdb); | ||
samples.push_back(std::move(sample)); | ||
} | ||
} | ||
|
||
|
||
template<typename T, typename F> | ||
bool | ||
LoadAsciiSamples(const fs::path& filename, | ||
std::vector<double>& sampleTimes, | ||
std::vector<T>& samples, | ||
F readSample) | ||
{ | ||
std::ifstream in(filename); | ||
if (!in.good()) | ||
{ | ||
detail::logOpenAsciiFail(filename); | ||
return false; | ||
} | ||
|
||
if (!detail::skipComments(in)) | ||
{ | ||
detail::logSkipCommentsFail(filename); | ||
return false; | ||
} | ||
|
||
return LoadSamples(in, filename, sampleTimes, samples, readSample); | ||
} | ||
|
||
} // end namespace celestia::ephem |
Oops, something went wrong.