Skip to content

Commit

Permalink
WIP: Compress elevation data
Browse files Browse the repository at this point in the history
  • Loading branch information
MichaelKutzner committed Dec 17, 2024
1 parent aed7f0d commit 5a0ecb3
Show file tree
Hide file tree
Showing 2 changed files with 68 additions and 54 deletions.
17 changes: 11 additions & 6 deletions include/osr/elevation_storage.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,6 @@

#include "cista/mmap.h"

#include "utl/progress_tracker.h"

#include "osr/types.h"
#include "osr/ways.h"

Expand All @@ -24,18 +22,25 @@ struct elevation_storage {
elevation_t up_;
elevation_t down_;
};
// TODO Rename
struct compressed_elevation {
using coding = std::uint8_t;
static coding encode(elevation_t const);
static elevation_t decode(coding const);
bool is_flat() const;
coding up_ : 4;
coding down_ : 4;
};
elevation_storage(std::filesystem::path const&,
cista::mmap::protection const mode);
static std::unique_ptr<elevation_storage> try_open(
std::filesystem::path const&);
void set_elevations(ways&,
preprocessing::elevation::provider const&);
void set_elevations(ways&, preprocessing::elevation::provider const&);
elevation get_elevations(way_idx_t const way,
std::uint16_t const from,
std::uint16_t const to) const;

mm_vecvec<way_idx_t, elevation_t> elevations_up_;
mm_vecvec<way_idx_t, elevation_t> elevations_down_;
mm_vecvec<way_idx_t, compressed_elevation> elevations_;
};

elevation_storage::elevation get_elevations(elevation_storage const*,
Expand Down
105 changes: 57 additions & 48 deletions src/elevation_storage.cc
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
#include "osr/elevation_storage.h"

#include <algorithm>
#include <array>

#include "utl/helpers/algorithm.h"
#include "utl/pairwise.h"
#include "utl/progress_tracker.h"

#include "osr/point.h"
#include "osr/preprocessing/elevation/provider.h"
Expand All @@ -18,36 +20,28 @@ cista::mmap mm(std::filesystem::path const& p,
}

namespace elevation_files {
constexpr auto const kUpDataName = "elevation_up_data.bin";
constexpr auto const kUpIndexName = "elevation_up_idx.bin";
constexpr auto const kDownDataName = "elevation_down_data.bin";
constexpr auto const kDownIndexName = "elevation_down_idx.bin";
constexpr auto const kDataName = "elevation_data.bin";
constexpr auto const kIndexName = "elevation_idx.bin";
}; // namespace elevation_files

elevation_storage::elevation_storage(std::filesystem::path const& p,
cista::mmap::protection const mode)
: elevations_up_{mm_vec<elevation_t>{
mm(p, elevation_files::kUpDataName, mode)},
mm_vec<unsigned>(
mm(p, elevation_files::kUpIndexName, mode))},
elevations_down_{
mm_vec<elevation_t>{mm(p, elevation_files::kDownDataName, mode)},
mm_vec<unsigned>(mm(p, elevation_files::kDownIndexName, mode))} {}
: elevations_{
mm_vec<compressed_elevation>{mm(p, elevation_files::kDataName, mode)},
mm_vec<unsigned>(mm(p, elevation_files::kIndexName, mode))} {}

std::unique_ptr<elevation_storage> elevation_storage::try_open(
std::filesystem::path const& path) {
if (utl::all_of(std::array{elevation_files::kUpDataName,
elevation_files::kUpIndexName,
elevation_files::kDownDataName,
elevation_files::kDownIndexName},
[&](char const* const filename) {
auto const full_path = path / filename;
auto const exists = std::filesystem::exists(full_path);
if (!exists) {
std::cout << full_path << " does not exist\n";
}
return exists;
})) {
if (utl::all_of(
std::array{elevation_files::kDataName, elevation_files::kIndexName},
[&](char const* const filename) {
auto const full_path = path / filename;
auto const exists = std::filesystem::exists(full_path);
if (!exists) {
std::cout << full_path << " does not exist\n";
}
return exists;
})) {
return std::make_unique<elevation_storage>(path,
cista::mmap::protection::READ);
}
Expand Down Expand Up @@ -102,52 +96,46 @@ void elevation_storage::set_elevations(
auto pt = utl::get_active_progress_tracker_or_activate("osr");
pt->status("Load elevation data").out_bounds(85, 90).in_high(w.n_ways());
auto const max_step_size = dem.get_step_size();
auto elevations_up = std::vector<elevation_t>{};
auto elevations_down = std::vector<elevation_t>{};
auto elevations = std::vector<compressed_elevation>{};
auto points = std::vector<point>{};
for (auto nodes : w.r_->way_nodes_) {
elevations_up.clear();
elevations_down.clear();
elevations.clear();
points.clear();
for (auto const& node : nodes) {
points.emplace_back(w.get_node_pos(node));
}
auto idx = std::size_t{0U};
for (auto const [from, to] : utl::pairwise(points)) {
auto const elevation = get_way_elevation(dem, from, to, max_step_size);
if (elevation.up_ > elevation_t{0}) {
elevations_up.resize(idx);
elevations_up.push_back(elevation.up_);
}
if (elevation.down_ > elevation_t{0}) {
elevations_down.resize(idx);
elevations_down.push_back(elevation.down_);
auto const segment_elevation = compressed_elevation{
.up_ = compressed_elevation::encode(elevation.up_),
.down_ = compressed_elevation::encode(elevation.down_),
};
if (!segment_elevation.is_flat()) {
elevations.resize(idx);
elevations.push_back(segment_elevation);
}
++idx;
}
elevations_up_.emplace_back(elevations_up);
elevations_down_.emplace_back(elevations_down);
elevations_.emplace_back(elevations);

pt->increment();
}
}

elevation_t elevation_at(mm_vecvec<way_idx_t, elevation_t> const& elevations,
way_idx_t const way_idx,
std::uint16_t const idx) {
return way_idx < elevations.size() && idx < elevations[way_idx].size()
? elevations[way_idx].at(idx)
: elevation_t{0};
}

elevation_storage::elevation elevation_storage::get_elevations(
way_idx_t const way,
std::uint16_t const from,
std::uint16_t const to) const {
return (from < to) ? elevation{elevation_at(elevations_up_, way, from),
elevation_at(elevations_down_, way, from)}
: elevation{elevation_at(elevations_down_, way, to),
elevation_at(elevations_up_, way, to)};
auto const idx = (from < to) ? from : to;
auto const elev = (way < elevations_.size() && idx < elevations_[way].size())
? elevations_[way][idx]
: compressed_elevation{0U, 0U};
return (from < to)
? elevation{.up_ = compressed_elevation::decode(elev.up_),
.down_ = compressed_elevation::decode(elev.down_)}
: elevation{.up_ = compressed_elevation::decode(elev.down_),
.down_ = compressed_elevation::decode(elev.up_)};
}

elevation_storage::elevation get_elevations(elevation_storage const* elevations,
Expand All @@ -159,4 +147,25 @@ elevation_storage::elevation get_elevations(elevation_storage const* elevations,
: elevations->get_elevations(way, from, to);
}

constexpr auto const kCompressedValues = std::array<elevation_t, 16>{
// 0, 1, 2, 4, 6, 8, 11, 14, 17, 21, 25, 29, 34, 38, 43, 48};
0, 1, 2, 3, 4, 5, 6, 7, 17, 21, 25, 29, 34, 38, 43, 48};

elevation_storage::compressed_elevation::coding
elevation_storage::compressed_elevation::encode(elevation_t const e) {
auto const c = std::ranges::lower_bound(kCompressedValues, e);
return (c == end(kCompressedValues))
? kCompressedValues.size() - 1
: static_cast<coding>(c - begin(kCompressedValues));
}

elevation_t elevation_storage::compressed_elevation::decode(coding const c) {
assert(c < kCompressedValues.size());
return kCompressedValues.at(c);
}

bool elevation_storage::compressed_elevation::is_flat() const {
return up_ == 0U && down_ == 0U;
}

} // namespace osr

0 comments on commit 5a0ecb3

Please sign in to comment.