17
0
mirror of https://github.com/MaSzyna-EU07/maszyna.git synced 2026-10-26 11:23:08 +01:00

feat(editor): the terrain model asks again for what it didn't get, can be stopped and says when the place is outside Poland

This commit is contained in:
maj00r
2026-10-21 13:20:20 +02:00
parent da18883558
commit 6f25290eee
2 changed files with 80 additions and 8 deletions

View File

@@ -15,6 +15,7 @@ http://mozilla.org/MPL/2.0/.
#include <algorithm>
#include <cctype>
#include <chrono>
#include <cmath>
#include <cstring>
#include <filesystem>
@@ -33,6 +34,12 @@ char const *const cache_folder{"editor/cache/nmt/grid1/"};
int constexpr worker_count{2}; // the service is quick, but isn't to be hammered
int constexpr border{1}; // pixels of the neighbouring squares fetched around a square, so the heights interpolate across its edges
float constexpr no_data{-1000.f}; // the model gives far lower values outside of the country
double constexpr retry_after{15.0}; // s, a square the service didn't give is asked for again
double seconds()
{
return std::chrono::duration<double>(std::chrono::steady_clock::now().time_since_epoch()).count();
}
// the name of the model among the names the capabilities of the service list: the first which says it's a terrain model
std::string coverage_of(std::string const &Capabilities)
@@ -231,12 +238,17 @@ bool editor_nmt::request(glm::dvec2 const &Min, glm::dvec2 const &Max)
auto const low{key_of(m_east - Max.x, m_north + Min.y)};
auto const high{key_of(m_east - Min.x, m_north + Max.y)};
auto const middle{key_of(m_east - 0.5 * (Min.x + Max.x), m_north + 0.5 * (Min.y + Max.y))};
auto const now{seconds()};
for (auto e = low.first; e <= high.first; ++e)
for (auto n = low.second; n <= high.second; ++n)
{
key const square{e, n};
if (m_squares.contains(square))
continue;
if (auto const found{m_squares.find(square)}; found != m_squares.end())
{
if (false == found->second->failed || found->second->outside || now - found->second->failed_at < retry_after)
continue;
m_squares.erase(found);
}
all = false;
if (false == m_queued.contains(square))
wanted.push_back(square);
@@ -265,10 +277,52 @@ std::size_t editor_nmt::waiting() const
return m_queued.size();
}
std::string editor_nmt::error() const
bool editor_nmt::retrying(glm::dvec2 const &Min, glm::dvec2 const &Max) const
{
std::lock_guard<std::mutex> lock{m_mutex};
return m_error;
auto const low{key_of(m_east - Max.x, m_north + Min.y)};
auto const high{key_of(m_east - Min.x, m_north + Max.y)};
for (auto e = low.first; e <= high.first; ++e)
for (auto n = low.second; n <= high.second; ++n)
if (auto const found{m_squares.find({e, n})}; found != m_squares.end() && found->second->failed && false == found->second->outside)
return true;
return false;
}
void editor_nmt::retry()
{
std::lock_guard<std::mutex> lock{m_mutex};
std::erase_if(m_squares, [](auto const &Square) { return Square.second->failed && false == Square.second->outside; });
}
void editor_nmt::cancel()
{
std::lock_guard<std::mutex> lock{m_mutex};
for (auto const &square : m_queue)
m_queued.erase(square);
m_queue.clear();
}
std::string editor_nmt::error(bool *Again) const
{
std::lock_guard<std::mutex> lock{m_mutex};
std::string result;
bool outside{false};
if (Again != nullptr)
*Again = false;
for (auto const &[key, square] : m_squares)
{
if (false == square->failed)
continue;
if (Again != nullptr && false == square->outside)
*Again = true;
if (result.empty() || (square->outside && false == outside))
{
result = square->error;
outside = square->outside;
}
}
return result;
}
void editor_nmt::clear()
@@ -300,7 +354,6 @@ void editor_nmt::work()
continue; // cleared meanwhile
m_queued.erase(square);
m_squares[square] = std::move(fetched);
m_error = error;
}
}
}
@@ -324,6 +377,8 @@ std::shared_ptr<editor_nmt::square const> editor_nmt::fetch(key const &Key, std:
{
Error = STRN("This build can't fetch from the internet");
result->failed = true;
result->outside = true;
result->error = Error;
return result;
}
editor_http::client client;
@@ -365,10 +420,18 @@ std::shared_ptr<editor_nmt::square const> editor_nmt::fetch(key const &Key, std:
}
if (stop())
break;
if (std::string const text(data.begin(), data.end()); text.find("outside requested coverage") != std::string::npos)
{
Error = STRN("The place lies outside of the terrain model of Poland: check the location of the scenery");
result->outside = true;
break;
}
if (Error.empty())
Error = STRN("The service gave no terrain model");
}
WriteLog("Editor: NMT square " + std::to_string(Key.first) + "," + std::to_string(Key.second) + " not fetched: " + Error, logtype::generic);
result->failed = true;
result->error = Error;
result->failed_at = seconds();
return result;
}

View File

@@ -46,8 +46,15 @@ class editor_nmt
bool request(glm::dvec2 const &Min, glm::dvec2 const &Max);
// squares asked for and not in yet
std::size_t waiting() const;
// what the last fetch said went wrong, empty when it went right
std::string error() const;
// a square under the rectangle the service didn't give, which is asked for again after a while
bool retrying(glm::dvec2 const &Min, glm::dvec2 const &Max) const;
// the squares the service didn't give asked for again at once
void retry();
// the squares waiting aren't fetched; those in stay
void cancel();
// why squares in memory have no data, empty when all came; a place outside of the model is told first. Again: whether
// some of them are asked for again
std::string error(bool *Again = nullptr) const;
// the squares dropped from the memory, and those waiting; the files on the disk stay
void clear();
// whether this build can fetch from the service at all
@@ -67,6 +74,9 @@ class editor_nmt
int height{0};
std::vector<float> heights; // rows from the north, columns from the west
bool failed{false}; // the service gave nothing usable: the square has no data
bool outside{false}; // failed for it lies outside of the model: asked again, it gives nothing either
double failed_at{0.0}; // s
std::string error;
};
key key_of(double const East, double const North) const;
@@ -80,7 +90,6 @@ class editor_nmt
std::set<key> m_queued;
std::map<key, std::shared_ptr<square const>> m_squares;
std::string m_coverage; // the name of the model in the service, read from its capabilities once
std::string m_error;
double m_north{0.0};
double m_east{0.0};
bool m_stop{false};