Program Listing for File GeoidUndulationSource.hpp
↰ Return to documentation for file (src/navtk/geospatial/sources/GeoidUndulationSource.hpp)
#pragma once
#include <fstream>
#include <memory>
#include <navtk/factory.hpp>
#include <navtk/geospatial/sources/SpatialMapDataSource.hpp>
#include <navtk/tensors.hpp>
namespace navtk {
namespace geospatial {
class GeoidUndulationSource : public SpatialMapDataSource {
public:
static std::shared_ptr<GeoidUndulationSource> get_shared(
const std::string& path = "WW15MGH.GRD");
std::pair<bool, double> lookup_datum(double latitude, double longitude) const override;
void set_chunk_size(Size size);
Size get_chunk_size() const;
private:
// private constructor because global instance is implemented via `get_shared()`.
GeoidUndulationSource(const std::string& path);
GeoidUndulationSource(const GeoidUndulationSource&) = delete;
GeoidUndulationSource& operator=(const GeoidUndulationSource&) = delete;
GeoidUndulationSource(const GeoidUndulationSource&&) = delete;
GeoidUndulationSource& operator=(const GeoidUndulationSource&&) = delete;
// Check if either latitude/longitude pair are outside of the current chunk of undulation
// values read into memory.
bool is_outside_cache_bounds(double lat, double lon) const;
// Moves file pointer to the start of a new chunk of data and reads the chunk into memory.
void init_coverage(double lat, double lon) const;
// Set the bounds for a new square chunk to be pulled into memory. This chunk will be centered
// around (lat, lon). Will set internal variables lat_coverage_min, lat_coverage_max,
// lon_coverage_min, and lat_coverage_max to reflect the range of latitudes and longitudes that
// the Matrix available_undulations contains undulation values for.
void set_coverage_bounds(double lat, double lon) const;
// Read in a 'box' of undulation data into memory.
void read_chunk() const;
// Skip a section of the file equivalent to a given number of records. This is called after
// resetting the file pointer to the start of the file to move the pointer to the start of the
// first record within the coverage bounds.
void skip_records(size_t num) const;
// Reads one double value from the file and returns it.
double read_value() const;
// Reads the value from a line in the file with a single element (such as occurs at the end of
// each record). Required that the file pointer at the end of block 9 (the last block) in a
// given record. This value is the same as the first value in a record, so no need to store it.
void ignore_value() const;
// Read an entire record (1440 values) starting at the current location of the file pointer. A
// record consists of 9 blocks containing 20 lines with 8 values per line (for a total of 160
// values per block). Each block is preceded by an empty line. A record is followed by an empty
// line and an additional single value on its own line.
void read_record(Size min_lon_idx, Size max_lon_idx, size_t row_idx) const;
// Get the record number of a given latitude. Ex: latitude 90 is the first record in the file,
// so return 0; latitude 80 is the 40th record, so return 40.
size_t get_lat_idx(double lat) const;
// Get the element in the available_undulations Matrix corresponding to the given lat and lon.
// Assumes lat and lon will be multiples of 0.25 and that the corresponding point will be found
// in memory.
double get_value(double lat, double lon) const;
mutable std::shared_ptr<std::ifstream> infile;
/* 'WW15MGH.GRD' file attributes */
const double min_lat, max_lat, min_lon, max_lon, lat_step, lon_step;
/* Chunk attributes */
// chunk_size is the length of a "side" of a chunk square (i.e. the number of latitude points or
// the number of longitude points to cover). The latitude or longitude range that a
// available_undulations spans in chunk_size/4. Ex: A chunk_size of 40 includes 41x41
// latitude/longitude points and spans 10 degrees of latitude and 10 degrees of longitude.
Size chunk_size = 40; // total number of bytes = (chunk_size + 1)^2 * (# of bytes/value)
// latitude coverage range is [lat_coverage_min, lat_coverage_max]
mutable double lat_coverage_min = -100;
mutable double lat_coverage_max = -100;
// longitude coverage range is [lon_coverage_min, lon_coverage_max]
mutable double lon_coverage_min = -1;
mutable double lon_coverage_max = -1;
// The chunk of read data stored in memory
// NOTE: using xt::xtensor instead of navtk::Matrix as the latter will heap-allocate a
// xt::pytensor object when using the python module. This is undesirable as the
// GeoidUndulationSource singleton won't be cleaned up until after the python interpreter has
// completely shut down, which will trigger a segfault.
mutable xt::xtensor<navtk::Scalar, 2> available_undulations;
};
} // namespace geospatial
} // namespace navtk