From d9a53ea8d7baa5109b3fe3f352ebce81d5a6d2ee Mon Sep 17 00:00:00 2001 From: Dan Paulat Date: Mon, 7 Aug 2023 23:52:29 -0500 Subject: [PATCH] Add placefile parsing for Triangles and Polygon --- wxdata/include/scwx/gr/placefile.hpp | 39 ++++++++ wxdata/source/scwx/gr/placefile.cpp | 135 ++++++++++++++++++++++++++- 2 files changed, 172 insertions(+), 2 deletions(-) diff --git a/wxdata/include/scwx/gr/placefile.hpp b/wxdata/include/scwx/gr/placefile.hpp index 816471dd..0da773a5 100644 --- a/wxdata/include/scwx/gr/placefile.hpp +++ b/wxdata/include/scwx/gr/placefile.hpp @@ -2,6 +2,7 @@ #include #include +#include #include #include @@ -120,6 +121,44 @@ public: std::vector elements_ {}; }; + struct TrianglesDrawItem : DrawItem + { + TrianglesDrawItem() { itemType_ = ItemType::Triangles; } + + boost::gil::rgba8_pixel_t color_ {}; + + struct Element + { + double latitude_ {}; + double longitude_ {}; + double x_ {}; + double y_ {}; + + std::optional color_ {}; + }; + + std::vector elements_ {}; + }; + + struct PolygonDrawItem : DrawItem + { + PolygonDrawItem() { itemType_ = ItemType::Polygon; } + + boost::gil::rgba8_pixel_t color_ {}; + + struct Element + { + double latitude_ {}; + double longitude_ {}; + double x_ {}; + double y_ {}; + + std::optional color_ {}; + }; + + std::vector> contours_ {}; + }; + bool IsValid() const; /** diff --git a/wxdata/source/scwx/gr/placefile.cpp b/wxdata/source/scwx/gr/placefile.cpp index 8bd0277b..fa98a6a5 100644 --- a/wxdata/source/scwx/gr/placefile.cpp +++ b/wxdata/source/scwx/gr/placefile.cpp @@ -47,6 +47,7 @@ public: double& x, double& y); void ProcessElement(const std::string& line); + void ProcessElementEnd(); void ProcessLine(const std::string& line); static void ProcessEscapeCharacters(std::string& s); @@ -64,6 +65,7 @@ public: std::vector objectStack_ {}; DrawingStatement currentStatement_ {DrawingStatement::Standard}; std::shared_ptr currentDrawItem_ {nullptr}; + std::vector currentPolygonContour_ {}; // References std::unordered_map> iconFiles_ {}; @@ -180,6 +182,8 @@ std::shared_ptr Placefile::Load(const std::string& name, case DrawingStatement::Polygon: if (boost::istarts_with(line, "End:")) { + placefile->p->ProcessElementEnd(); + placefile->p->currentStatement_ = DrawingStatement::Standard; placefile->p->currentDrawItem_ = nullptr; } @@ -551,7 +555,14 @@ void Placefile::Impl::ProcessLine(const std::string& line) // End: currentStatement_ = DrawingStatement::Triangles; - // TODO + std::shared_ptr di = + std::make_shared(); + + di->threshold_ = threshold_; + di->color_ = color_; + + currentDrawItem_ = di; + drawItems_.emplace_back(std::move(di)); } else if (boost::istarts_with(line, imageKey_)) { @@ -577,7 +588,13 @@ void Placefile::Impl::ProcessLine(const std::string& line) // End: currentStatement_ = DrawingStatement::Polygon; - // TODO + std::shared_ptr di = std::make_shared(); + + di->threshold_ = threshold_; + di->color_ = color_; + + currentDrawItem_ = di; + drawItems_.emplace_back(std::move(di)); } else { @@ -609,6 +626,120 @@ void Placefile::Impl::ProcessElement(const std::string& line) std::static_pointer_cast(currentDrawItem_) ->elements_.emplace_back(std::move(element)); } + else + { + logger_->warn("Line sub-statement malformed: {}", line); + } + } + else if (currentStatement_ == DrawingStatement::Triangles) + { + // Triangles: + // lat, lon [, r, g, b [,a]] + // ... + // End: + std::vector tokenList = + util::ParseTokens(line, {",", ",", ",", ",", ",", ","}); + + TrianglesDrawItem::Element element; + + if (tokenList.size() >= 5) + { + element.color_ = ParseColor(tokenList, 2, colorMode_); + } + + if (tokenList.size() >= 2) + { + ParseLocation(tokenList[0], + tokenList[1], + element.latitude_, + element.longitude_, + element.x_, + element.y_); + + std::static_pointer_cast(currentDrawItem_) + ->elements_.emplace_back(std::move(element)); + } + else + { + logger_->warn("Triangles sub-statement malformed: {}", line); + } + } + else if (currentStatement_ == DrawingStatement::Polygon) + { + // Polygon: + // lat1, lon1 [, r, g, b [,a]] ; start of the first contour + // ... + // lat1, lon1 ; repeating the first point closes the + // ; contour + // + // lat2, lon2 ; next point starts a new contour + // ... + // lat2, lon2 ; and repeating it ends the contour + // End: + std::vector tokenList = + util::ParseTokens(line, {",", ",", ",", ",", ",", ","}); + + PolygonDrawItem::Element element; + + if (tokenList.size() >= 5) + { + element.color_ = ParseColor(tokenList, 2, colorMode_); + } + + if (tokenList.size() >= 2) + { + ParseLocation(tokenList[0], + tokenList[1], + element.latitude_, + element.longitude_, + element.x_, + element.y_); + + currentPolygonContour_.emplace_back(std::move(element)); + + if (currentPolygonContour_.size() >= 2) + { + auto& first = currentPolygonContour_.front(); + auto& last = currentPolygonContour_.back(); + + // Repeating the first point closes the contour + if (first.latitude_ == last.latitude_ && + first.longitude_ == last.longitude_ && // + first.x_ == last.x_ && // + first.y_ == last.y_) + { + auto& contours = + std::static_pointer_cast(currentDrawItem_) + ->contours_; + + auto& newContour = contours.emplace_back( + std::vector {}); + newContour.swap(currentPolygonContour_); + } + } + } + else + { + logger_->warn("Polygon sub-statement malformed: {}", line); + } + } +} + +void Placefile::Impl::ProcessElementEnd() +{ + if (currentStatement_ == DrawingStatement::Polygon) + { + // Complete the current contour when ending the Polygon statement + if (!currentPolygonContour_.empty()) + { + auto& contours = + std::static_pointer_cast(currentDrawItem_) + ->contours_; + + auto& newContour = + contours.emplace_back(std::vector {}); + newContour.swap(currentPolygonContour_); + } } }