From 48d71cc14d2fd4e78c6592aa3c37138f6987ec50 Mon Sep 17 00:00:00 2001 From: Dan Paulat Date: Fri, 21 Jul 2023 00:26:42 -0500 Subject: [PATCH] Placefile text statement support - Merged place and text - Todo: Custom fonts not yet supported - Todo: End statements sometimes appear after "Text" or other items - Todo: Support "Title" statement --- .../source/scwx/qt/map/placefile_layer.cpp | 39 ++++++------ wxdata/include/scwx/gr/placefile.hpp | 7 ++- wxdata/source/scwx/gr/placefile.cpp | 59 ++++++++++++++++++- 3 files changed, 80 insertions(+), 25 deletions(-) diff --git a/scwx-qt/source/scwx/qt/map/placefile_layer.cpp b/scwx-qt/source/scwx/qt/map/placefile_layer.cpp index 9db91381..09dbd2af 100644 --- a/scwx-qt/source/scwx/qt/map/placefile_layer.cpp +++ b/scwx-qt/source/scwx/qt/map/placefile_layer.cpp @@ -24,8 +24,9 @@ public: explicit Impl(std::shared_ptr context) {}; ~Impl() = default; - void RenderPlace(const QMapLibreGL::CustomLayerRenderParameters& params, - std::shared_ptr place); + void + RenderTextDrawItem(const QMapLibreGL::CustomLayerRenderParameters& params, + std::shared_ptr di); void RenderText(const QMapLibreGL::CustomLayerRenderParameters& params, const std::string& text, @@ -55,27 +56,26 @@ void PlacefileLayer::Initialize() DrawLayer::Initialize(); } -void PlacefileLayer::Impl::RenderPlace( +void PlacefileLayer::Impl::RenderTextDrawItem( const QMapLibreGL::CustomLayerRenderParameters& params, - std::shared_ptr place) + std::shared_ptr di) { auto distance = util::GeographicLib::GetDistance( - params.latitude, params.longitude, place->latitude_, place->longitude_); + params.latitude, params.longitude, di->latitude_, di->longitude_); - if (distance < place->threshold_) + if (distance < di->threshold_) { - const auto screenCoordinates = - (util::maplibre::LatLongToScreenCoordinate( - {place->latitude_, place->longitude_}) - - mapScreenCoordLocation_) * - mapScale_; + const auto screenCoordinates = (util::maplibre::LatLongToScreenCoordinate( + {di->latitude_, di->longitude_}) - + mapScreenCoordLocation_) * + mapScale_; RenderText(params, - place->text_, - "", - place->color_, - screenCoordinates.x + place->x_ + halfWidth_, - screenCoordinates.y + place->y_ + halfHeight_); + di->text_, + di->hoverText_, + di->color_, + screenCoordinates.x + di->x_ + halfWidth_, + screenCoordinates.y + di->y_ + halfHeight_); } } @@ -146,11 +146,10 @@ void PlacefileLayer::Render( { switch (drawItem->itemType_) { - case gr::Placefile::ItemType::Place: - p->RenderPlace( + case gr::Placefile::ItemType::Text: + p->RenderTextDrawItem( params, - std::static_pointer_cast( - drawItem)); + std::static_pointer_cast(drawItem)); break; } } diff --git a/wxdata/include/scwx/gr/placefile.hpp b/wxdata/include/scwx/gr/placefile.hpp index 91f8cb28..71f26cb3 100644 --- a/wxdata/include/scwx/gr/placefile.hpp +++ b/wxdata/include/scwx/gr/placefile.hpp @@ -37,7 +37,6 @@ public: enum class ItemType { - Place, Icon, Font, Text, @@ -54,16 +53,18 @@ public: boost::units::quantity threshold_ {}; }; - struct PlaceDrawItem : DrawItem + struct TextDrawItem : DrawItem { - PlaceDrawItem() { itemType_ = ItemType::Place; } + TextDrawItem() { itemType_ = ItemType::Text; } boost::gil::rgba8_pixel_t color_ {}; double latitude_ {}; double longitude_ {}; double x_ {}; double y_ {}; + std::size_t fontNumber_ {0u}; std::string text_ {}; + std::string hoverText_ {}; }; bool IsValid() const; diff --git a/wxdata/source/scwx/gr/placefile.cpp b/wxdata/source/scwx/gr/placefile.cpp index 2622f143..04dc0ae3 100644 --- a/wxdata/source/scwx/gr/placefile.cpp +++ b/wxdata/source/scwx/gr/placefile.cpp @@ -48,6 +48,8 @@ public: double& y); void ProcessLine(const std::string& line); + static void TrimQuotes(std::string& s); + std::chrono::seconds refresh_ {-1}; // Parsing state @@ -243,7 +245,7 @@ void Placefile::Impl::ProcessLine(const std::string& line) if (tokenList.size() >= 3) { - std::shared_ptr di = std::make_shared(); + std::shared_ptr di = std::make_shared(); di->threshold_ = threshold_; di->color_ = color_; @@ -255,6 +257,7 @@ void Placefile::Impl::ProcessLine(const std::string& line) di->x_, di->y_); + ProcessEscapeCharacters(tokenList[2]); di->text_.swap(tokenList[2]); drawItems_.emplace_back(std::move(di)); @@ -285,8 +288,46 @@ void Placefile::Impl::ProcessLine(const std::string& line) else if (boost::istarts_with(line, textKey_)) { // Text: lat, lon, fontNumber, "string", "hover" + std::vector tokenList = + util::ParseTokens(line, {",", ",", ",", ",", ","}, textKey_.size()); - // TODO + std::shared_ptr di = nullptr; + + if (tokenList.size() >= 4) + { + di = std::make_shared(); + + di->threshold_ = threshold_; + di->color_ = color_; + + ParseLocation(tokenList[0], + tokenList[1], + di->latitude_, + di->longitude_, + di->x_, + di->y_); + + di->fontNumber_ = std::stoul(tokenList[2]); + + ProcessEscapeCharacters(tokenList[3]); + TrimQuotes(tokenList[3]); + di->text_.swap(tokenList[3]); + } + if (tokenList.size() >= 5) + { + ProcessEscapeCharacters(tokenList[4]); + TrimQuotes(tokenList[4]); + di->hoverText_.swap(tokenList[4]); + } + + if (di != nullptr) + { + drawItems_.emplace_back(std::move(di)); + } + else + { + logger_->warn("Text statement malformed: {}", line); + } } else if (boost::istarts_with(line, objectKey_)) { @@ -409,5 +450,19 @@ void Placefile::Impl::ParseLocation(const std::string& latitudeToken, } } +void Placefile::Impl::ProcessEscapeCharacters(std::string& s) +{ + boost::replace_all(s, "\\n", "\n"); +} + +void Placefile::Impl::TrimQuotes(std::string& s) +{ + if (s.size() >= 2 && s.front() == '"' && s.back() == '"') + { + s.erase(s.size() - 1); + s.erase(0, 1); + } +} + } // namespace gr } // namespace scwx