diff --git a/contrib/base64 b/contrib/base64 index 5257626d2be..95ba56a9b04 160000 --- a/contrib/base64 +++ b/contrib/base64 @@ -1 +1 @@ -Subproject commit 5257626d2be17a3eb23f79be17fe55ebba394ad2 +Subproject commit 95ba56a9b041f9933f5cd2bbb2ee4e083468c20a diff --git a/contrib/poco b/contrib/poco index 1f3e4638f25..860574c9398 160000 --- a/contrib/poco +++ b/contrib/poco @@ -1 +1 @@ -Subproject commit 1f3e4638f250ad4d028a2499af20d4185463e07d +Subproject commit 860574c93980d887a89df141edd9ca2fb0024fa3 diff --git a/dbms/src/Dictionaries/PolygonDictionaryUtils.cpp b/dbms/src/Dictionaries/PolygonDictionaryUtils.cpp index 841bf417f30..4e257a7cfe4 100644 --- a/dbms/src/Dictionaries/PolygonDictionaryUtils.cpp +++ b/dbms/src/Dictionaries/PolygonDictionaryUtils.cpp @@ -326,6 +326,18 @@ bool BucketsPolygonIndex::Edge::compare2(const Edge & a, const Edge & b) return a.polygon_id < b.polygon_id; } +namespace +{ + inline void update_result(bool & found, size_t & id, const size_t & new_id) + { + if (!found || new_id < id) + { + found = true; + id = new_id; + } + } +} + bool BucketsPolygonIndex::find(const Point & point, size_t & id) const { /** TODO: maybe we should check for vertical line? */ @@ -342,13 +354,15 @@ bool BucketsPolygonIndex::find(const Point & point, size_t & id) const return false; } + bool found = false; + /** point is considired inside when ray down from point crosses odd number of edges */ - std::map is_inside; - std::map on_the_edge; + std::vector intersections; + intersections.reserve(10); size_t pos = std::upper_bound(this->sorted_x.begin() + 1, this->sorted_x.end() - 1, x) - this->sorted_x.begin() - 1; - /** pos += n */ + /** Here we doing: pos += n */ pos += this->edges_index_tree.size() / 2; do { @@ -366,7 +380,8 @@ bool BucketsPolygonIndex::find(const Point & point, size_t & id) const { if (l.x() == x && y >= l.y() && y <= r.y()) { - on_the_edge[polygon_id] = true; + /** point is on the edge */ + update_result(found, id, polygon_id); } continue; } @@ -384,29 +399,22 @@ bool BucketsPolygonIndex::find(const Point & point, size_t & id) const } if (edge_y == y) { - on_the_edge[polygon_id] = true; + /** point is on the edge */ + update_result(found, id, polygon_id); } - is_inside[polygon_id] ^= true; + intersections.emplace_back(polygon_id); } pos >>= 1; } while (pos != 0); - bool found = false; - for (auto & [polygon_id, inside] : is_inside) + std::sort(intersections.begin(), intersections.end()); + for (size_t i = 0; i < intersections.size(); i += 2) { - if (inside) + if (i + 1 == intersections.size() || intersections[i] != intersections[i + 1]) { - found = true; - id = polygon_id; - } - } - for (auto & [polygon_id, is_edge] : on_the_edge) - { - if (is_edge) - { - found = true; - id = polygon_id; + update_result(found, id, intersections[i]); + break; } }