mirror of
https://github.com/MaSzyna-EU07/maszyna.git
synced 2026-11-02 10:29:13 +01:00
Keep tiles on disk, add basket curves, undo the image flip
The flip was my mistake. Measured against the service instead of guessed: fetching a box and its northern half shows the half matching the top of the whole, so the images arrive with their first row at the north edge and the default texture coordinates were right all along. Both the base map and the orthophoto go back to them. Imagery of a given piece of ground does not change, so a fetched tile is now kept under editor/cache/orto and the next session starts from it. Until now the cache lived only in memory, which meant going back to a slow and flaky service for ground that had already been fetched once. Gaps can be fitted with a basket curve as well: the library's compound mode, with clothoids at both ends and a chain of arcs between them. Arcs can be added and removed; the closing one takes whatever deflection the earlier ones leave, so its length is not offered for editing.
This commit is contained in:
@@ -230,6 +230,12 @@ std::vector<orthophoto_source::ready_tile> orthophoto_source::collect(maj0sted::
|
||||
std::vector<ready_tile> tiles;
|
||||
for (auto const &key : maj0sted::web::TileGrid::tiles_for_view(View, maj0sted::web::TileGrid::kLevel, Maxtiles))
|
||||
{
|
||||
// a tile kept from an earlier session seeds the cache, so no request goes out for it at all
|
||||
if (false == m_service.has(key))
|
||||
{
|
||||
load_from_disk(key);
|
||||
}
|
||||
|
||||
auto const status = m_service.request(key);
|
||||
if (status == maj0sted::web::TileStatus::Failed)
|
||||
{
|
||||
@@ -244,6 +250,8 @@ std::vector<orthophoto_source::ready_tile> orthophoto_source::collect(maj0sted::
|
||||
auto found = m_textures.find(key);
|
||||
if (found == m_textures.end())
|
||||
{
|
||||
// the first time a tile is drawn is also the moment its bytes are known to be good
|
||||
save_to_disk(key);
|
||||
found = m_textures.emplace(key, upload(key)).first;
|
||||
}
|
||||
if (found->second != 0)
|
||||
@@ -288,6 +296,53 @@ unsigned int orthophoto_source::upload(maj0sted::web::TileKey const &Key)
|
||||
return texture;
|
||||
}
|
||||
|
||||
std::string orthophoto_source::tile_path(maj0sted::web::TileKey const &Key)
|
||||
{
|
||||
return "editor/cache/orto/" + std::to_string(Key.zoom) + "_" + std::to_string(Key.x) + "_" + std::to_string(Key.y) + ".img";
|
||||
}
|
||||
|
||||
bool orthophoto_source::load_from_disk(maj0sted::web::TileKey const &Key)
|
||||
{
|
||||
std::ifstream file(tile_path(Key), std::ios::binary);
|
||||
if (false == file.is_open())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
std::vector<std::uint8_t> bytes{std::istreambuf_iterator<char>(file), std::istreambuf_iterator<char>()};
|
||||
if (bytes.empty())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
m_service.store(Key, std::move(bytes));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void orthophoto_source::save_to_disk(maj0sted::web::TileKey const &Key)
|
||||
{
|
||||
auto const *image = m_service.peek(Key);
|
||||
if (image == nullptr || image->bytes.empty())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
auto const path = tile_path(Key);
|
||||
std::error_code error;
|
||||
std::filesystem::create_directories(std::filesystem::path(path).parent_path(), error);
|
||||
if (std::filesystem::exists(path, error))
|
||||
{
|
||||
return; // came from the disk in the first place
|
||||
}
|
||||
|
||||
std::ofstream file(path, std::ios::binary);
|
||||
if (file.is_open())
|
||||
{
|
||||
file.write(reinterpret_cast<char const *>(image->bytes.data()), static_cast<std::streamsize>(image->bytes.size()));
|
||||
}
|
||||
}
|
||||
|
||||
std::size_t orthophoto_source::pending() const
|
||||
{
|
||||
return m_inflight.load();
|
||||
|
||||
@@ -68,6 +68,11 @@ class orthophoto_source
|
||||
void worker();
|
||||
// decodes the cached bytes of a tile and uploads them; returns 0 when the image is unusable
|
||||
unsigned int upload(maj0sted::web::TileKey const &Key);
|
||||
// imagery of a given piece of ground never changes, so a fetched tile is kept on disk and the
|
||||
// next session starts with it instead of going back to a service that is slow and flaky
|
||||
static std::string tile_path(maj0sted::web::TileKey const &Key);
|
||||
bool load_from_disk(maj0sted::web::TileKey const &Key);
|
||||
void save_to_disk(maj0sted::web::TileKey const &Key);
|
||||
// members
|
||||
maj0sted::web::TileService m_service;
|
||||
std::unordered_map<maj0sted::web::TileKey, unsigned int, maj0sted::web::TileKeyHash> m_textures;
|
||||
|
||||
Reference in New Issue
Block a user