#pragma once #include "indexer/city_boundary.hpp" #include "indexer/feature_decl.hpp" #include "geometry/point2d.hpp" #include "geometry/rect2d.hpp" #include #include #include #include #include #include class DataSource; namespace feature { struct FeatureID; } namespace search { class CitiesBoundariesTable { friend void GetCityBoundariesInRectForTesting(CitiesBoundariesTable const &, m2::RectD const & rect, std::vector & featureIds); public: class Boundaries { public: Boundaries() = default; Boundaries(std::vector const & boundaries, double eps) : m_boundaries(boundaries), m_eps(eps) { } Boundaries(std::vector && boundaries, double eps) : m_boundaries(std::move(boundaries)), m_eps(eps) { } // Returns true iff |p| is inside any of the regions bounded by // |*this|. bool HasPoint(m2::PointD const & p) const; m2::RectD GetLimitRect() const { m2::RectD rect; for (auto const & boundary : m_boundaries) { rect.Add(boundary.m_bbox.Min()); rect.Add(boundary.m_bbox.Max()); } return rect; } std::vector const & GetBoundariesForTesting() const { return m_boundaries; } friend std::string DebugPrint(Boundaries const & boundaries) { std::ostringstream os; os << "Boundaries ["; os << ::DebugPrint(boundaries.m_boundaries) << ", "; os << "eps: " << boundaries.m_eps; os << "]"; return os.str(); } private: std::vector m_boundaries; double m_eps = 0.0; }; explicit CitiesBoundariesTable(DataSource const & dataSource) : m_dataSource(dataSource) {} bool Load(); bool Has(FeatureID const & fid) const { return fid.m_mwmId == m_mwmId && Has(fid.m_index); } bool Has(uint32_t fid) const { return m_table.find(fid) != m_table.end(); } bool Get(FeatureID const & fid, Boundaries & bs) const; bool Get(uint32_t fid, Boundaries & bs) const; size_t GetSize() const { return m_table.size(); } private: DataSource const & m_dataSource; MwmSet::MwmId m_mwmId; std::unordered_map> m_table; double m_eps = 0.0; }; /// \brief Fills |featureIds| with feature ids of city boundaries if bounding rect of /// the city boundary crosses |rect|. /// \note This method is inefficient and is written for debug and test purposes only. void GetCityBoundariesInRectForTesting(CitiesBoundariesTable const &, m2::RectD const & rect, std::vector & featureIds); } // namespace search