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:
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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};
|
||||
|
||||
Reference in New Issue
Block a user