diff --git a/dbms/src/Dictionaries/PolygonDictionaryUtils.cpp b/dbms/src/Dictionaries/PolygonDictionaryUtils.cpp index d3c8ad9835d..008ab7df1ee 100644 --- a/dbms/src/Dictionaries/PolygonDictionaryUtils.cpp +++ b/dbms/src/Dictionaries/PolygonDictionaryUtils.cpp @@ -11,10 +11,9 @@ namespace DB { -Cell::Cell(std::vector polygon_ids_, const std::vector & polygons_, const Box & box_): +FinalCell::FinalCell(std::vector polygon_ids_, const std::vector & polygons_, const Box & box_): polygon_ids(std::move(polygon_ids_)) { - is_final = true; Polygon tmp_poly; bg::convert(box_, tmp_poly); std::transform(polygon_ids.begin(), polygon_ids.end(), std::back_inserter(is_covered_by), [&](const auto id) @@ -23,10 +22,15 @@ polygon_ids(std::move(polygon_ids_)) }); } -const Cell * Cell::find(Float64 x, Float64 y) const +const FinalCell * FinalCell::find(Float64, Float64) const +{ + return this; +} + +DividedCell::DividedCell(std::vector> children_): children(std::move(children_)) {} + +const FinalCell * DividedCell::find(Float64 x, Float64 y) const { - if (is_final) - return this; auto x_ratio = x * GridRoot::kSplit; auto y_ratio = y * GridRoot::kSplit; auto x_bin = static_cast(x_ratio); @@ -34,9 +38,6 @@ const Cell * Cell::find(Float64 x, Float64 y) const return children[y_bin + x_bin * GridRoot::kSplit]->find(x_ratio - x_bin, y_ratio - y_bin); } -Cell::Cell(std::vector> children_): children(std::move(children_)) {} - - GridRoot::GridRoot(const size_t min_intersections_, const size_t max_depth_, const std::vector & polygons_): kMinIntersections(min_intersections_), kMaxDepth(max_depth_), polygons(polygons_) { setBoundingBox(); @@ -45,7 +46,7 @@ kMinIntersections(min_intersections_), kMaxDepth(max_depth_), polygons(polygons_ root = makeCell(min_x, min_y, max_x, max_y, order); } -const Cell * GridRoot::find(Float64 x, Float64 y) const +const FinalCell * GridRoot::find(Float64 x, Float64 y) const { if (x < min_x || x >= max_x) return nullptr; @@ -54,7 +55,7 @@ const Cell * GridRoot::find(Float64 x, Float64 y) const return root->find((x - min_x) / (max_x - min_x), (y - min_y) / (max_y - min_y)); } -std::unique_ptr GridRoot::makeCell(Float64 current_min_x, Float64 current_min_y, Float64 current_max_x, Float64 current_max_y, std::vector possible_ids, size_t depth) +std::unique_ptr GridRoot::makeCell(Float64 current_min_x, Float64 current_min_y, Float64 current_max_x, Float64 current_max_y, std::vector possible_ids, size_t depth) { auto current_box = Box(Point(current_min_x, current_min_y), Point(current_max_x, current_max_y)); possible_ids.erase(std::remove_if(possible_ids.begin(), possible_ids.end(), [&](const auto id) @@ -62,10 +63,10 @@ std::unique_ptr GridRoot::makeCell(Float64 current_min_x, Float64 current_ return !bg::intersects(current_box, polygons[id]); }), possible_ids.end()); if (possible_ids.size() <= kMinIntersections || depth++ == kMaxDepth) - return std::make_unique(possible_ids, polygons, current_box); + return std::make_unique(possible_ids, polygons, current_box); auto x_shift = (current_max_x - current_min_x) / kSplit; auto y_shift = (current_max_y - current_min_y) / kSplit; - std::vector> children; + std::vector> children; children.resize(kSplit * kSplit); std::vector threads; for (size_t i = 0; i < kSplit; current_min_x += x_shift, ++i) @@ -84,7 +85,7 @@ std::unique_ptr GridRoot::makeCell(Float64 current_min_x, Float64 current_ } for (auto & thread : threads) thread.join(); - return std::make_unique(std::move(children)); + return std::make_unique(std::move(children)); } void GridRoot::setBoundingBox() diff --git a/dbms/src/Dictionaries/PolygonDictionaryUtils.h b/dbms/src/Dictionaries/PolygonDictionaryUtils.h index 02c1b375fbf..e100a020377 100644 --- a/dbms/src/Dictionaries/PolygonDictionaryUtils.h +++ b/dbms/src/Dictionaries/PolygonDictionaryUtils.h @@ -19,21 +19,34 @@ using Point = IPolygonDictionary::Point; using Polygon = IPolygonDictionary::Polygon; using Box = bg::model::box; -class Cell +class FinalCell; + +class ICell { public: - explicit Cell(std::vector polygon_ids_, const std::vector & polygons_, const Box & box_); + virtual ~ICell() = default; + [[nodiscard]] virtual const FinalCell * find(Float64 x, Float64 y) const = 0; +}; + +class DividedCell : public ICell +{ +public: + explicit DividedCell(std::vector> children_); + [[nodiscard]] const FinalCell * find(Float64 x, Float64 y) const override; + +private: + std::vector> children; +}; + +class FinalCell : public ICell +{ +public: + explicit FinalCell(std::vector polygon_ids_, const std::vector & polygons_, const Box & box_); std::vector polygon_ids; std::vector is_covered_by; - explicit Cell(std::vector> children_); - - [[nodiscard]] const Cell * find(Float64 x, Float64 y) const override; - private: - std::vector> children; - - bool is_final = false; + [[nodiscard]] const FinalCell * find(Float64 x, Float64 y) const override; }; /** A recursively built grid containing information about polygons intersecting each cell. @@ -43,21 +56,21 @@ private: * intersects a small enough number of polygons or the maximum allowed depth is exceeded. * Both of these parameters are set in the constructor. */ -class GridRoot +class GridRoot : public ICell { public: GridRoot(size_t min_intersections_, size_t max_depth_, const std::vector & polygons_); /** Retrieves the cell containing a given point. * A null pointer is returned when the point falls outside the grid. */ - [[nodiscard]] const Cell * find(Float64 x, Float64 y) const override; + [[nodiscard]] const FinalCell * find(Float64 x, Float64 y) const override; /** When a cell is split every side is split into kSplit pieces producing kSplit * kSplit equal smaller cells. */ static constexpr size_t kSplit = 4; static constexpr size_t kMultiProcessingDepth = 2; private: - std::unique_ptr root = nullptr; + std::unique_ptr root = nullptr; Float64 min_x = 0, min_y = 0; Float64 max_x = 0, max_y = 0; const size_t kMinIntersections; @@ -65,7 +78,7 @@ private: const std::vector & polygons; - std::unique_ptr makeCell(Float64 min_x, Float64 min_y, Float64 max_x, Float64 max_y, std::vector intersecting_ids, size_t depth = 0); + std::unique_ptr makeCell(Float64 min_x, Float64 min_y, Float64 max_x, Float64 max_y, std::vector intersecting_ids, size_t depth = 0); void setBoundingBox(); };