diff --git a/include/osr/elevation_storage.h b/include/osr/elevation_storage.h index 0b0e5d7..4ddfa78 100644 --- a/include/osr/elevation_storage.h +++ b/include/osr/elevation_storage.h @@ -19,17 +19,18 @@ struct provider; struct elevation_storage { struct elevation { + elevation swap() const; elevation_t up_; elevation_t down_; }; - // TODO Rename - struct compressed_elevation { + struct encoding { 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; + explicit encoding(elevation const&); + encoding() = default; + elevation decode() const; + explicit operator bool() const; + coding up_ : 4 {}; + coding down_ : 4 {}; }; elevation_storage(std::filesystem::path const&, cista::mmap::protection const mode); @@ -40,7 +41,7 @@ struct elevation_storage { std::uint16_t const from, std::uint16_t const to) const; - mm_vecvec elevations_; + mm_vecvec elevations_; }; elevation_storage::elevation get_elevations(elevation_storage const*, diff --git a/src/elevation_storage.cc b/src/elevation_storage.cc index 13207a3..5e25a77 100644 --- a/src/elevation_storage.cc +++ b/src/elevation_storage.cc @@ -26,9 +26,8 @@ constexpr auto const kIndexName = "elevation_idx.bin"; elevation_storage::elevation_storage(std::filesystem::path const& p, cista::mmap::protection const mode) - : elevations_{ - mm_vec{mm(p, elevation_files::kDataName, mode)}, - mm_vec(mm(p, elevation_files::kIndexName, mode))} {} + : elevations_{mm_vec{mm(p, elevation_files::kDataName, mode)}, + mm_vec(mm(p, elevation_files::kIndexName, mode))} {} std::unique_ptr elevation_storage::try_open( std::filesystem::path const& path) { @@ -96,7 +95,7 @@ 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 = std::vector{}; + auto elevations = std::vector{}; auto points = std::vector{}; for (auto nodes : w.r_->way_nodes_) { elevations.clear(); @@ -106,14 +105,11 @@ void elevation_storage::set_elevations( } 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); - auto const segment_elevation = compressed_elevation{ - .up_ = compressed_elevation::encode(elevation.up_), - .down_ = compressed_elevation::encode(elevation.down_), - }; - if (!segment_elevation.is_flat()) { + auto const elevation = + encoding{get_way_elevation(dem, from, to, max_step_size)}; + if (elevation) { elevations.resize(idx); - elevations.push_back(segment_elevation); + elevations.push_back(elevation); } ++idx; } @@ -129,12 +125,9 @@ elevation_storage::elevation elevation_storage::get_elevations( std::uint16_t const to) const { auto const idx = (from < to) ? from : to; auto const e = (way < elevations_.size() && idx < elevations_[way].size()) - ? elevations_[way][idx] - : compressed_elevation{0U, 0U}; - return (from < to) ? elevation{.up_ = compressed_elevation::decode(e.up_), - .down_ = compressed_elevation::decode(e.down_)} - : elevation{.up_ = compressed_elevation::decode(e.down_), - .down_ = compressed_elevation::decode(e.up_)}; + ? elevations_[way][idx].decode() + : elevation{0U, 0U}; + return (from < to) ? e : e.swap(); } elevation_storage::elevation get_elevations(elevation_storage const* elevations, @@ -146,24 +139,41 @@ elevation_storage::elevation get_elevations(elevation_storage const* elevations, : elevations->get_elevations(way, from, to); } +elevation_storage::elevation elevation_storage::elevation::swap() const { + return { + .up_ = down_, + .down_ = up_, + }; +} + constexpr auto const kCompressedValues = std::array{ 0, 1, 2, 4, 6, 8, 11, 14, 17, 21, 25, 29, 34, 38, 43, 48}; -elevation_storage::compressed_elevation::coding -elevation_storage::compressed_elevation::encode(elevation_t const e) { +elevation_storage::encoding::coding encode(elevation_t const e) { auto const c = std::ranges::lower_bound(kCompressedValues, e); return (c == end(kCompressedValues)) ? kCompressedValues.size() - 1 - : static_cast(c - begin(kCompressedValues)); + : static_cast( + c - begin(kCompressedValues)); } -elevation_t elevation_storage::compressed_elevation::decode(coding const c) { +elevation_t decode_helper(elevation_storage::encoding::coding const c) { assert(c < kCompressedValues.size()); return kCompressedValues.at(c); } -bool elevation_storage::compressed_elevation::is_flat() const { - return up_ == 0U && down_ == 0U; +elevation_storage::encoding::encoding(elevation const& e) + : up_{encode(e.up_)}, down_{encode(e.down_)} {} + +elevation_storage::elevation elevation_storage::encoding::decode() const { + return { + .up_ = decode_helper(up_), + .down_ = decode_helper(down_), + }; +} + +elevation_storage::encoding::operator bool() const { + return up_ != 0U || down_ != 0U; } } // namespace osr