mirror of
https://github.com/MaSzyna-EU07/maszyna.git
synced 2026-10-26 01:02:26 +01:00
Editor checkpoint: turnout domain service, web->editor rename, Id-1 templates
Checkpoint of the editor branch so work isn't carried loose across a branch switch. Builds. - maj0sted turnout geometry moved into the domain: domain::lay_turnout lays the diverging path (pre-blade lead, blade at beta, arc of alfa-beta, frog rail) and solve_junction is a thin adapter onto it. - the maj0sted web/ tree renamed to editor/ (namespace and paths) - there is no WASM here, it's plain native C++ the editor calls. - click places the switch at its start (początek rozjazdu); the branch's leaving straight is locked tangent to the frog; switches can be slid along the through track and flipped L/P. - Polish turnout templates carry catalogue length (Id-1-consistent lengths), plus blade-angle and pre-blade fields (left 0 until the catalogue figures are in). - TURNOUT_SPEC.md: the Bezier-based runtime/model contract. - also folds in other pending branch changes (scenery, tests) to leave a clean tree.
This commit is contained in:
@@ -136,11 +136,19 @@ bool http_get(std::string const &, std::vector<std::uint8_t> &, std::string &)
|
||||
|
||||
} // namespace
|
||||
|
||||
orthophoto_source::orthophoto_source()
|
||||
orthophoto_source::orthophoto_source(maj0sted::editor::WmsConfig Config, int const Gridzoom, std::string Cachesubdir)
|
||||
: m_service([&] {
|
||||
if (Gridzoom >= maj0sted::editor::TileGrid::kCellZoomMin)
|
||||
{
|
||||
Config.tile_pixels = 512; // coarse cells do not need orto's 1024 px
|
||||
}
|
||||
return std::move(Config);
|
||||
}()),
|
||||
m_gridzoom(Gridzoom), m_cachesubdir(std::move(Cachesubdir))
|
||||
{
|
||||
// the library asks for a URL and expects the answer whenever it arrives; the transfer is queued
|
||||
// here and handed back on the thread that drains it, so the service stays single threaded
|
||||
m_service.set_fetcher([this](std::string const &Url, maj0sted::web::TileService::DoneFn Done) {
|
||||
m_service.set_fetcher([this](std::string const &Url, maj0sted::editor::TileService::DoneFn Done) {
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(m_mutex);
|
||||
m_queued.push_back({Url, std::move(Done), false, {}, {}});
|
||||
@@ -210,7 +218,7 @@ void orthophoto_source::worker()
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<orthophoto_source::ready_tile> orthophoto_source::collect(maj0sted::web::TileBBox const &View, int const Maxtiles)
|
||||
std::vector<orthophoto_source::ready_tile> orthophoto_source::collect(maj0sted::editor::TileBBox const &View, int const Maxtiles)
|
||||
{
|
||||
// hand finished transfers to the library here, on the caller's thread
|
||||
std::deque<transfer> arrived;
|
||||
@@ -227,8 +235,10 @@ std::vector<orthophoto_source::ready_tile> orthophoto_source::collect(maj0sted::
|
||||
--m_inflight;
|
||||
}
|
||||
|
||||
std::vector<ready_tile> tiles;
|
||||
for (auto const &key : maj0sted::web::TileGrid::tiles_for_view(View, maj0sted::web::TileGrid::kLevel, Maxtiles))
|
||||
// fetch only what fits the budget for the current view. the window is recentred when the
|
||||
// view is larger than the cap, and zoom-to-cursor moves the camera, so the set of keys asked
|
||||
// for changes from frame to frame - that must not decide what is drawn
|
||||
for (auto const &key : maj0sted::editor::TileGrid::tiles_for_view(View, m_gridzoom, 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))
|
||||
@@ -237,33 +247,51 @@ std::vector<orthophoto_source::ready_tile> orthophoto_source::collect(maj0sted::
|
||||
}
|
||||
|
||||
auto const status = m_service.request(key);
|
||||
if (status == maj0sted::web::TileStatus::Failed)
|
||||
if (status == maj0sted::editor::TileStatus::Failed)
|
||||
{
|
||||
++m_failed;
|
||||
// counted once per tile, not once per frame it stays unavailable
|
||||
m_failedkeys.insert(key);
|
||||
continue;
|
||||
}
|
||||
if (status != maj0sted::web::TileStatus::Ready)
|
||||
if (status != maj0sted::editor::TileStatus::Ready)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
auto found = m_textures.find(key);
|
||||
if (found == m_textures.end())
|
||||
if (m_textures.find(key) == m_textures.end())
|
||||
{
|
||||
// the first time a tile is drawn is also the moment its bytes are known to be good
|
||||
// the first time a tile is ready is also the moment its bytes are known to be good
|
||||
save_to_disk(key);
|
||||
found = m_textures.emplace(key, upload(key)).first;
|
||||
m_textures.emplace(key, upload(key));
|
||||
}
|
||||
if (found->second != 0)
|
||||
}
|
||||
|
||||
// draw every texture we already hold that still covers the view. returning only the fetch
|
||||
// window made tiles blink out during zoom as soon as they fell outside the cap, then blink
|
||||
// back in once the window moved over them again
|
||||
auto const overlaps = [](maj0sted::editor::TileBBox const &Left, maj0sted::editor::TileBBox const &Right) {
|
||||
return Left.min_x < Right.max_x && Left.max_x > Right.min_x && Left.min_y < Right.max_y && Left.max_y > Right.min_y;
|
||||
};
|
||||
|
||||
std::vector<ready_tile> tiles;
|
||||
tiles.reserve(m_textures.size());
|
||||
for (auto const &[key, texture] : m_textures)
|
||||
{
|
||||
if (texture == 0)
|
||||
{
|
||||
tiles.push_back({maj0sted::web::TileGrid::bbox(key), found->second});
|
||||
continue;
|
||||
}
|
||||
auto const box = maj0sted::editor::TileGrid::bbox(key);
|
||||
if (overlaps(box, View))
|
||||
{
|
||||
tiles.push_back({box, texture});
|
||||
}
|
||||
}
|
||||
|
||||
return tiles;
|
||||
}
|
||||
|
||||
unsigned int orthophoto_source::upload(maj0sted::web::TileKey const &Key)
|
||||
unsigned int orthophoto_source::upload(maj0sted::editor::TileKey const &Key)
|
||||
{
|
||||
auto const *image = m_service.peek(Key);
|
||||
if (image == nullptr || image->bytes.empty())
|
||||
@@ -296,12 +324,12 @@ unsigned int orthophoto_source::upload(maj0sted::web::TileKey const &Key)
|
||||
return texture;
|
||||
}
|
||||
|
||||
std::string orthophoto_source::tile_path(maj0sted::web::TileKey const &Key)
|
||||
std::string orthophoto_source::tile_path(maj0sted::editor::TileKey const &Key) const
|
||||
{
|
||||
return "editor/cache/orto/" + std::to_string(Key.zoom) + "_" + std::to_string(Key.x) + "_" + std::to_string(Key.y) + ".img";
|
||||
return "editor/cache/" + m_cachesubdir + "/" + 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)
|
||||
bool orthophoto_source::load_from_disk(maj0sted::editor::TileKey const &Key)
|
||||
{
|
||||
std::ifstream file(tile_path(Key), std::ios::binary);
|
||||
if (false == file.is_open())
|
||||
@@ -320,7 +348,7 @@ bool orthophoto_source::load_from_disk(maj0sted::web::TileKey const &Key)
|
||||
return true;
|
||||
}
|
||||
|
||||
void orthophoto_source::save_to_disk(maj0sted::web::TileKey const &Key)
|
||||
void orthophoto_source::save_to_disk(maj0sted::editor::TileKey const &Key)
|
||||
{
|
||||
auto const *image = m_service.peek(Key);
|
||||
if (image == nullptr || image->bytes.empty())
|
||||
@@ -350,7 +378,7 @@ std::size_t orthophoto_source::pending() const
|
||||
|
||||
std::size_t orthophoto_source::failed() const
|
||||
{
|
||||
return m_failed;
|
||||
return m_failedkeys.size();
|
||||
}
|
||||
|
||||
namespace
|
||||
@@ -383,7 +411,7 @@ unsigned int upload_image(std::vector<std::uint8_t> const &Bytes)
|
||||
return texture;
|
||||
}
|
||||
|
||||
bool same_box(maj0sted::web::TileBBox const &Left, maj0sted::web::TileBBox const &Right)
|
||||
bool same_box(maj0sted::editor::TileBBox const &Left, maj0sted::editor::TileBBox const &Right)
|
||||
{
|
||||
auto const close = [](double const A, double const B) { return std::abs(A - B) < 1.0; };
|
||||
return close(Left.min_x, Right.min_x) && close(Left.min_y, Right.min_y) && close(Left.max_x, Right.max_x) && close(Left.max_y, Right.max_y);
|
||||
@@ -391,7 +419,7 @@ bool same_box(maj0sted::web::TileBBox const &Left, maj0sted::web::TileBBox const
|
||||
|
||||
} // namespace
|
||||
|
||||
wms_image::wms_image(maj0sted::web::WmsConfig Config) : m_config(std::move(Config))
|
||||
wms_image::wms_image(maj0sted::editor::WmsConfig Config) : m_config(std::move(Config))
|
||||
{
|
||||
m_worker = std::thread([this]() { worker(); });
|
||||
}
|
||||
@@ -446,7 +474,7 @@ void wms_image::worker()
|
||||
}
|
||||
}
|
||||
|
||||
unsigned int wms_image::texture_for(maj0sted::web::TileBBox const &Box, int const Pixels)
|
||||
unsigned int wms_image::texture_for(maj0sted::editor::TileBBox const &Box, int const Pixels)
|
||||
{
|
||||
// a finished download becomes the texture on this thread, where the graphics API is safe to touch
|
||||
{
|
||||
@@ -482,7 +510,7 @@ unsigned int wms_image::texture_for(maj0sted::web::TileBBox const &Box, int cons
|
||||
config.tile_pixels = Pixels;
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(m_mutex);
|
||||
m_url = maj0sted::web::wms_getmap_url(config, Box);
|
||||
m_url = maj0sted::editor::wms_getmap_url(config, Box);
|
||||
m_haswork = true;
|
||||
}
|
||||
m_loading = true;
|
||||
|
||||
Reference in New Issue
Block a user