From 05cf1b5bc5026731e17df81ab78b9d99e06d5222 Mon Sep 17 00:00:00 2001 From: Nikita Mikhailov Date: Mon, 15 Feb 2021 22:22:13 +0300 Subject: [PATCH] better --- src/DataTypes/DataTypeCustomGeo.cpp | 11 ++-- src/Functions/geometryConverters.cpp | 26 +++++++++ src/Functions/geometryConverters.h | 25 +++++---- src/Functions/polygonArea.cpp | 37 ++----------- src/Functions/polygonConvexHull.cpp | 40 +++----------- src/Functions/polygonPerimeter.cpp | 35 ++---------- src/Functions/polygonsDistance.cpp | 49 ++++------------- src/Functions/polygonsEquals.cpp | 50 ++++------------- src/Functions/polygonsIntersection.cpp | 54 +++++-------------- src/Functions/polygonsSymDifference.cpp | 53 +++++------------- src/Functions/polygonsUnion.cpp | 51 +++++------------- src/Functions/polygonsWithin.cpp | 50 ++++------------- .../0_stateless/01300_polygon_convex_hull.sql | 2 +- .../0_stateless/01301_polygons_within.sql | 4 +- .../0_stateless/01302_polygons_distance.sql | 4 +- .../0_stateless/01303_polygons_equals.sql | 4 +- .../01304_polygons_sym_difference.sql | 2 +- .../0_stateless/01305_polygons_union.sql | 2 +- .../01306_polygons_intersection.sql | 4 +- .../0_stateless/01307_polygon_perimeter.sql | 2 +- .../0_stateless/01308_polygon_area.sql | 2 +- 21 files changed, 147 insertions(+), 360 deletions(-) diff --git a/src/DataTypes/DataTypeCustomGeo.cpp b/src/DataTypes/DataTypeCustomGeo.cpp index 9f30ba4223a..60fe6f3450c 100644 --- a/src/DataTypes/DataTypeCustomGeo.cpp +++ b/src/DataTypes/DataTypeCustomGeo.cpp @@ -26,8 +26,9 @@ void DataTypeCustomPointSerialization::deserializeText( DataTypePtr DataTypeCustomPointSerialization::nestedDataType() { - static auto data_type = DataTypePtr(std::make_unique( - DataTypes({std::make_unique(), std::make_unique()}))); + static const auto data_type = std::make_shared( + DataTypes{std::make_shared(), std::make_shared()} + ); return data_type; } @@ -45,7 +46,7 @@ void DataTypeCustomRingSerialization::deserializeText( DataTypePtr DataTypeCustomRingSerialization::nestedDataType() { - static auto data_type = DataTypePtr(std::make_unique(DataTypeCustomPointSerialization::nestedDataType())); + static auto data_type = std::make_shared(DataTypeCustomPointSerialization::nestedDataType()); return data_type; } @@ -63,7 +64,7 @@ void DataTypeCustomPolygonSerialization::deserializeText( DataTypePtr DataTypeCustomPolygonSerialization::nestedDataType() { - static auto data_type = DataTypePtr(std::make_unique(DataTypeCustomRingSerialization::nestedDataType())); + static auto data_type = std::make_shared(DataTypeCustomRingSerialization::nestedDataType()); return data_type; } @@ -81,7 +82,7 @@ void DataTypeCustomMultiPolygonSerialization::deserializeText( DataTypePtr DataTypeCustomMultiPolygonSerialization::nestedDataType() { - static auto data_type = DataTypePtr(std::make_unique(DataTypeCustomPolygonSerialization::nestedDataType())); + static auto data_type = std::make_shared(DataTypeCustomPolygonSerialization::nestedDataType()); return data_type; } diff --git a/src/Functions/geometryConverters.cpp b/src/Functions/geometryConverters.cpp index def1f3b8fde..8665fbb1771 100644 --- a/src/Functions/geometryConverters.cpp +++ b/src/Functions/geometryConverters.cpp @@ -9,6 +9,8 @@ namespace DB namespace ErrorCodes { extern const int ILLEGAL_COLUMN; + extern const int BAD_ARGUMENTS; + extern const int LOGICAL_ERROR; } namespace @@ -108,4 +110,28 @@ template GeometryFromColumnParser makeGeometryFromColumnParser(c template GeometryFromColumnParser makeGeometryFromColumnParser(const ColumnWithTypeAndName & col); +template typename Desired> +void checkColumnTypeOrThrow(const ColumnWithTypeAndName & column) +{ + DataTypePtr desired_type; + if constexpr (std::is_same_v, Ring>) + desired_type = DataTypeCustomRingSerialization::nestedDataType(); + else if constexpr (std::is_same_v, Polygon>) + desired_type = DataTypeCustomPolygonSerialization::nestedDataType(); + else if constexpr (std::is_same_v, MultiPolygon>) + desired_type = DataTypeCustomMultiPolygonSerialization::nestedDataType(); + else + throw Exception("Unexpected Desired type.", ErrorCodes::LOGICAL_ERROR); + + if (!desired_type->equals(*column.type)) + throw Exception(fmt::format("Expected type {} (MultiPolygon), but got {}", desired_type->getName(), column.type->getName()), ErrorCodes::BAD_ARGUMENTS); +} + +template void checkColumnTypeOrThrow(const ColumnWithTypeAndName &); +template void checkColumnTypeOrThrow(const ColumnWithTypeAndName &); +template void checkColumnTypeOrThrow(const ColumnWithTypeAndName &); +template void checkColumnTypeOrThrow(const ColumnWithTypeAndName &); +template void checkColumnTypeOrThrow(const ColumnWithTypeAndName &); +template void checkColumnTypeOrThrow(const ColumnWithTypeAndName &); + } diff --git a/src/Functions/geometryConverters.h b/src/Functions/geometryConverters.h index 7a5ce1ae6f2..7938e5ca775 100644 --- a/src/Functions/geometryConverters.h +++ b/src/Functions/geometryConverters.h @@ -233,14 +233,18 @@ public: void get(Geometry & container, size_t i) const { - auto & multi_polygon = boost::get>(container); + get(boost::get>(container), i); + } + + void get(MultiPolygon & container, size_t i) const + { size_t l = offsets[i - 1]; size_t r = offsets[i]; - multi_polygon.resize(r - l); + container.resize(r - l); for (size_t j = l; j < r; j++) { - polygon_parser.get(multi_polygon[j - l], j); + polygon_parser.get(container[j - l], j); } } @@ -262,18 +266,17 @@ using GeometryFromColumnParser = boost::variant< template Geometry createContainer(const GeometryFromColumnParser & parser); -extern template Geometry createContainer(const GeometryFromColumnParser & parser); -extern template Geometry createContainer(const GeometryFromColumnParser & parser); - template void get(const GeometryFromColumnParser & parser, Geometry & container, size_t i); -extern template void get(const GeometryFromColumnParser & parser, Geometry & container, size_t i); -extern template void get(const GeometryFromColumnParser & parser, Geometry & container, size_t i); - template GeometryFromColumnParser makeGeometryFromColumnParser(const ColumnWithTypeAndName & col); + +extern template Geometry createContainer(const GeometryFromColumnParser & parser); +extern template Geometry createContainer(const GeometryFromColumnParser & parser); +extern template void get(const GeometryFromColumnParser & parser, Geometry & container, size_t i); +extern template void get(const GeometryFromColumnParser & parser, Geometry & container, size_t i); extern template GeometryFromColumnParser makeGeometryFromColumnParser(const ColumnWithTypeAndName & col); extern template GeometryFromColumnParser makeGeometryFromColumnParser(const ColumnWithTypeAndName & col); @@ -532,4 +535,8 @@ using PolygonSerializer = GeometrySerializer, PolygonSerializerV template using MultiPolygonSerializer = GeometrySerializer, MultiPolygonSerializerVisitor>; + +template typename Desired> +void checkColumnTypeOrThrow(const ColumnWithTypeAndName & column); + } diff --git a/src/Functions/polygonArea.cpp b/src/Functions/polygonArea.cpp index 44687ae183e..e3ecc9d6fac 100644 --- a/src/Functions/polygonArea.cpp +++ b/src/Functions/polygonArea.cpp @@ -20,11 +20,6 @@ namespace DB { -namespace ErrorCodes -{ - extern const int BAD_ARGUMENTS; -} - template class FunctionPolygonArea : public IFunction { @@ -58,40 +53,18 @@ public: return std::make_shared(); } - void checkInputType(const ColumnsWithTypeAndName & arguments) const - { - /// Array(Array(Array(Tuple(Float64, Float64)))) - auto desired = std::make_shared( - std::make_shared( - std::make_shared( - std::make_shared( - DataTypes{std::make_shared(), std::make_shared()} - ) - ) - ) - ); - if (!desired->equals(*arguments[0].type)) - throw Exception(fmt::format("The type of first argument of function {} must be Array(Array(Array(Tuple(Float64, Float64))))", name), ErrorCodes::BAD_ARGUMENTS); - } - ColumnPtr executeImpl(const ColumnsWithTypeAndName & arguments, const DataTypePtr & /*result_type*/, size_t input_rows_count) const override { - checkInputType(arguments); - auto parser = makeGeometryFromColumnParser(arguments[0]); - - std::cout << arguments[0].type->getName() << std::endl; - auto container = createContainer(parser); + checkColumnTypeOrThrow(arguments[0]); + auto parser = MultiPolygonFromColumnParser(std::move(arguments[0].column->convertToFullColumnIfConst())); + MultiPolygon container; auto res_column = ColumnFloat64::create(); for (size_t i = 0; i < input_rows_count; i++) { - get(parser, container, i); - - Float64 area = boost::geometry::area( - boost::get>(container)); - - res_column->insertValue(area); + parser.get(container, i); + res_column->insertValue(boost::geometry::area(container)); } return res_column; diff --git a/src/Functions/polygonConvexHull.cpp b/src/Functions/polygonConvexHull.cpp index 26e37dc335b..3bc4cd1cf2d 100644 --- a/src/Functions/polygonConvexHull.cpp +++ b/src/Functions/polygonConvexHull.cpp @@ -20,11 +20,6 @@ namespace DB { -namespace ErrorCodes -{ - extern const int BAD_ARGUMENTS; -} - template class FunctionPolygonConvexHull : public IFunction { @@ -58,42 +53,19 @@ public: return DataTypeCustomPolygonSerialization::nestedDataType(); } - void checkInputType(const ColumnsWithTypeAndName & arguments) const - { - /// Array(Array(Array(Tuple(Float64, Float64)))) - auto desired = std::make_shared( - std::make_shared( - std::make_shared( - std::make_shared( - DataTypes{std::make_shared(), std::make_shared()} - ) - ) - ) - ); - if (!desired->equals(*arguments[0].type)) - throw Exception(fmt::format("The type of the argument of function {} must be Array(Array(Array(Tuple(Float64, Float64))))", name), ErrorCodes::BAD_ARGUMENTS); - } - ColumnPtr executeImpl(const ColumnsWithTypeAndName & arguments, const DataTypePtr & /*result_type*/, size_t input_rows_count) const override { - checkInputType(arguments); - auto parser = makeGeometryFromColumnParser(arguments[0]); - auto container = createContainer(parser); + checkColumnTypeOrThrow(arguments[0]); + auto parser = MultiPolygonFromColumnParser(std::move(arguments[0].column->convertToFullColumnIfConst())); + MultiPolygon container; PolygonSerializer serializer; + Polygon convex_hull{}; for (size_t i = 0; i < input_rows_count; i++) { - get(parser, container, i); - - auto convex_hull = Polygon({{{}}}); - - boost::geometry::convex_hull( - boost::get>(container), - convex_hull); - - convex_hull.outer().erase(convex_hull.outer().begin()); - + parser.get(container, i); + boost::geometry::convex_hull(container, convex_hull); serializer.add(convex_hull); } diff --git a/src/Functions/polygonPerimeter.cpp b/src/Functions/polygonPerimeter.cpp index 6c45c45b99a..2f277af7fd5 100644 --- a/src/Functions/polygonPerimeter.cpp +++ b/src/Functions/polygonPerimeter.cpp @@ -20,11 +20,6 @@ namespace DB { -namespace ErrorCodes -{ - extern const int BAD_ARGUMENTS; -} - template class FunctionPolygonPerimeter : public IFunction { @@ -58,38 +53,18 @@ public: return std::make_shared(); } - void checkInputType(const ColumnsWithTypeAndName & arguments) const - { - /// Array(Array(Array(Tuple(Float64, Float64)))) - auto desired = std::make_shared( - std::make_shared( - std::make_shared( - std::make_shared( - DataTypes{std::make_shared(), std::make_shared()} - ) - ) - ) - ); - if (!desired->equals(*arguments[0].type)) - throw Exception(fmt::format("The type of the argument of function {} must be Array(Array(Array(Tuple(Float64, Float64))))", name), ErrorCodes::BAD_ARGUMENTS); - } - ColumnPtr executeImpl(const ColumnsWithTypeAndName & arguments, const DataTypePtr & /*result_type*/, size_t input_rows_count) const override { - checkInputType(arguments); - auto parser = makeGeometryFromColumnParser(arguments[0]); - auto container = createContainer(parser); + checkColumnTypeOrThrow(arguments[0]); + auto parser = MultiPolygonFromColumnParser(std::move(arguments[0].column->convertToFullColumnIfConst())); + MultiPolygon container; auto res_column = ColumnFloat64::create(); for (size_t i = 0; i < input_rows_count; i++) { - get(parser, container, i); - - Float64 perimeter = boost::geometry::perimeter( - boost::get>(container)); - - res_column->insertValue(perimeter); + parser.get(container, i); + res_column->insertValue(boost::geometry::perimeter(container)); } return res_column; diff --git a/src/Functions/polygonsDistance.cpp b/src/Functions/polygonsDistance.cpp index eb795860f6c..dea7ffcce70 100644 --- a/src/Functions/polygonsDistance.cpp +++ b/src/Functions/polygonsDistance.cpp @@ -22,11 +22,6 @@ namespace DB { -namespace ErrorCodes -{ - extern const int BAD_ARGUMENTS; -} - template class FunctionPolygonsDistance : public IFunction { @@ -60,49 +55,27 @@ public: return std::make_shared(); } - void checkInputType(const ColumnsWithTypeAndName & arguments) const - { - /// Array(Array(Array(Tuple(Float64, Float64)))) - auto desired = std::make_shared( - std::make_shared( - std::make_shared( - std::make_shared( - DataTypes{std::make_shared(), std::make_shared()} - ) - ) - ) - ); - if (!desired->equals(*arguments[0].type)) - throw Exception(fmt::format("The type of the first argument of function {} must be Array(Array(Array(Tuple(Float64, Float64))))", name), ErrorCodes::BAD_ARGUMENTS); - - if (!desired->equals(*arguments[1].type)) - throw Exception(fmt::format("The type of the second argument of function {} must be Array(Array(Array(Tuple(Float64, Float64))))", name), ErrorCodes::BAD_ARGUMENTS); - } - ColumnPtr executeImpl(const ColumnsWithTypeAndName & arguments, const DataTypePtr & /*result_type*/, size_t input_rows_count) const override { - auto first_parser = makeGeometryFromColumnParser(arguments[0]); - auto first_container = createContainer(first_parser); + checkColumnTypeOrThrow(arguments[0]); + auto first_parser = MultiPolygonFromColumnParser(std::move(arguments[0].column->convertToFullColumnIfConst())); + MultiPolygon first_container; - auto second_parser = makeGeometryFromColumnParser(arguments[1]); - auto second_container = createContainer(second_parser); + checkColumnTypeOrThrow(arguments[1]); + auto second_parser = MultiPolygonFromColumnParser(std::move(arguments[1].column->convertToFullColumnIfConst())); + MultiPolygon second_container; auto res_column = ColumnFloat64::create(); for (size_t i = 0; i < input_rows_count; i++) { - get(first_parser, first_container, i); - get(second_parser, second_container, i); + first_parser.get(first_container, i); + second_parser.get(second_container, i); - auto first = boost::get>(first_container); - auto second = boost::get>(second_container); + boost::geometry::correct(first_container); + boost::geometry::correct(second_container); - boost::geometry::correct(first); - boost::geometry::correct(second); - - Float64 distance = boost::geometry::distance(first, second); - - res_column->insertValue(distance); + res_column->insertValue(boost::geometry::distance(first_container, second_container)); } return res_column; diff --git a/src/Functions/polygonsEquals.cpp b/src/Functions/polygonsEquals.cpp index dc056b78815..4ab81597b70 100644 --- a/src/Functions/polygonsEquals.cpp +++ b/src/Functions/polygonsEquals.cpp @@ -22,11 +22,6 @@ namespace DB { -namespace ErrorCodes -{ - extern const int BAD_ARGUMENTS; -} - template class FunctionPolygonsEquals : public IFunction { @@ -60,50 +55,27 @@ public: return std::make_shared(); } - void checkInputType(const ColumnsWithTypeAndName & arguments) const - { - /// Array(Array(Array(Tuple(Float64, Float64)))) - auto desired = std::make_shared( - std::make_shared( - std::make_shared( - std::make_shared( - DataTypes{std::make_shared(), std::make_shared()} - ) - ) - ) - ); - if (!desired->equals(*arguments[0].type)) - throw Exception(fmt::format("The type of the first argument of function {} must be Array(Array(Array(Tuple(Float64, Float64))))", name), ErrorCodes::BAD_ARGUMENTS); - - if (!desired->equals(*arguments[1].type)) - throw Exception(fmt::format("The type of the second argument of function {} must be Array(Array(Array(Tuple(Float64, Float64))))", name), ErrorCodes::BAD_ARGUMENTS); - } - ColumnPtr executeImpl(const ColumnsWithTypeAndName & arguments, const DataTypePtr & /*result_type*/, size_t input_rows_count) const override { - checkInputType(arguments); - auto first_parser = makeGeometryFromColumnParser(arguments[0]); - auto first_container = createContainer(first_parser); + checkColumnTypeOrThrow(arguments[0]); + auto first_parser = MultiPolygonFromColumnParser(std::move(arguments[0].column->convertToFullColumnIfConst())); + MultiPolygon first_container; - auto second_parser = makeGeometryFromColumnParser(arguments[1]); - auto second_container = createContainer(second_parser); + checkColumnTypeOrThrow(arguments[1]); + auto second_parser = MultiPolygonFromColumnParser(std::move(arguments[1].column->convertToFullColumnIfConst())); + MultiPolygon second_container; auto res_column = ColumnUInt8::create(); for (size_t i = 0; i < input_rows_count; i++) { - get(first_parser, first_container, i); - get(second_parser, second_container, i); + first_parser.get(first_container, i); + second_parser.get(second_container, i); - auto first = boost::get>(first_container); - auto second = boost::get>(second_container); + boost::geometry::correct(first_container); + boost::geometry::correct(second_container); - boost::geometry::correct(first); - boost::geometry::correct(second); - - bool equals = boost::geometry::equals(first, second); - - res_column->insertValue(equals); + res_column->insertValue(boost::geometry::equals(first_container, second_container)); } return res_column; diff --git a/src/Functions/polygonsIntersection.cpp b/src/Functions/polygonsIntersection.cpp index ef99caf57a2..78e7396e082 100644 --- a/src/Functions/polygonsIntersection.cpp +++ b/src/Functions/polygonsIntersection.cpp @@ -20,11 +20,6 @@ namespace DB { -namespace ErrorCodes -{ - extern const int BAD_ARGUMENTS; -} - template class FunctionPolygonsIntersection : public IFunction { @@ -58,55 +53,32 @@ public: return DataTypeCustomMultiPolygonSerialization::nestedDataType(); } - void checkInputType(const ColumnsWithTypeAndName & arguments) const - { - /// Array(Array(Array(Tuple(Float64, Float64)))) - auto desired = std::make_shared( - std::make_shared( - std::make_shared( - std::make_shared( - DataTypes{std::make_shared(), std::make_shared()} - ) - ) - ) - ); - if (!desired->equals(*arguments[0].type)) - throw Exception(fmt::format("The type of the first argument of function {} must be Array(Array(Array(Tuple(Float64, Float64))))", name), ErrorCodes::BAD_ARGUMENTS); - - if (!desired->equals(*arguments[1].type)) - throw Exception(fmt::format("The type of the second argument of function {} must be Array(Array(Array(Tuple(Float64, Float64))))", name), ErrorCodes::BAD_ARGUMENTS); - } - ColumnPtr executeImpl(const ColumnsWithTypeAndName & arguments, const DataTypePtr & /*result_type*/, size_t input_rows_count) const override { - checkInputType(arguments); - auto first_parser = makeGeometryFromColumnParser(arguments[0]); - auto first_container = createContainer(first_parser); + checkColumnTypeOrThrow(arguments[0]); + auto first_parser = MultiPolygonFromColumnParser(std::move(arguments[0].column->convertToFullColumnIfConst())); + MultiPolygon first_container; - auto second_parser = makeGeometryFromColumnParser(arguments[1]); - auto second_container = createContainer(second_parser); + checkColumnTypeOrThrow(arguments[1]); + auto second_parser = MultiPolygonFromColumnParser(std::move(arguments[1].column->convertToFullColumnIfConst())); + MultiPolygon second_container; MultiPolygonSerializer serializer; + MultiPolygon intersection{}; /// We are not interested in some pitfalls in third-party libraries /// NOLINTNEXTLINE(clang-analyzer-core.uninitialized.Assign) - for (size_t i = 0; i < input_rows_count; i++) + for (size_t i = 0; i < input_rows_count; ++i) { - get(first_parser, first_container, i); - get(second_parser, second_container, i); - - auto intersection = MultiPolygon({{{{}}}}); - auto first = boost::get>(first_container); - auto second = boost::get>(second_container); + first_parser.get(first_container, i); + second_parser.get(second_container, i); /// Orient the polygons correctly. - boost::geometry::correct(first); - boost::geometry::correct(second); + boost::geometry::correct(first_container); + boost::geometry::correct(second_container); /// Main work here. - boost::geometry::intersection(first, second, intersection); - - intersection.erase(intersection.begin()); + boost::geometry::intersection(first_container, second_container, intersection); serializer.add(intersection); } diff --git a/src/Functions/polygonsSymDifference.cpp b/src/Functions/polygonsSymDifference.cpp index 53abadf3c4c..f8660de815d 100644 --- a/src/Functions/polygonsSymDifference.cpp +++ b/src/Functions/polygonsSymDifference.cpp @@ -20,11 +20,6 @@ namespace DB { -namespace ErrorCodes -{ - extern const int BAD_ARGUMENTS; -} - template class FunctionPolygonsSymDifference : public IFunction { @@ -58,53 +53,29 @@ public: return DataTypeCustomMultiPolygonSerialization::nestedDataType(); } - void checkInputType(const ColumnsWithTypeAndName & arguments) const - { - /// Array(Array(Array(Tuple(Float64, Float64)))) - auto desired = std::make_shared( - std::make_shared( - std::make_shared( - std::make_shared( - DataTypes{std::make_shared(), std::make_shared()} - ) - ) - ) - ); - if (!desired->equals(*arguments[0].type)) - throw Exception(fmt::format("The type of the first argument of function {} must be Array(Array(Array(Tuple(Float64, Float64))))", name), ErrorCodes::BAD_ARGUMENTS); - - if (!desired->equals(*arguments[1].type)) - throw Exception(fmt::format("The type of the second argument of function {} must be Array(Array(Array(Tuple(Float64, Float64))))", name), ErrorCodes::BAD_ARGUMENTS); - } - ColumnPtr executeImpl(const ColumnsWithTypeAndName & arguments, const DataTypePtr & /*result_type*/, size_t input_rows_count) const override { - checkInputType(arguments); - auto first_parser = makeGeometryFromColumnParser(arguments[0]); - auto first_container = createContainer(first_parser); + checkColumnTypeOrThrow(arguments[0]); + auto first_parser = MultiPolygonFromColumnParser(std::move(arguments[0].column->convertToFullColumnIfConst())); + MultiPolygon first_container; - auto second_parser = makeGeometryFromColumnParser(arguments[1]); - auto second_container = createContainer(second_parser); + checkColumnTypeOrThrow(arguments[1]); + auto second_parser = MultiPolygonFromColumnParser(std::move(arguments[1].column->convertToFullColumnIfConst())); + MultiPolygon second_container; MultiPolygonSerializer serializer; + MultiPolygon sym_difference{}; /// NOLINTNEXTLINE(clang-analyzer-core.uninitialized.Assign) for (size_t i = 0; i < input_rows_count; i++) { - get(first_parser, first_container, i); - get(second_parser, second_container, i); + first_parser.get(first_container, i); + second_parser.get(second_container, i); - auto sym_difference = MultiPolygon({{{{}}}}); + boost::geometry::correct(first_container); + boost::geometry::correct(second_container); - auto first = boost::get>(first_container); - auto second = boost::get>(second_container); - - boost::geometry::correct(first); - boost::geometry::correct(second); - - boost::geometry::sym_difference(first, second, sym_difference); - - sym_difference.erase(sym_difference.begin()); + boost::geometry::sym_difference(first_container, second_container, sym_difference); serializer.add(sym_difference); } diff --git a/src/Functions/polygonsUnion.cpp b/src/Functions/polygonsUnion.cpp index 7198e5b4959..f86706ad4c6 100644 --- a/src/Functions/polygonsUnion.cpp +++ b/src/Functions/polygonsUnion.cpp @@ -19,10 +19,6 @@ namespace DB { -namespace ErrorCodes -{ - extern const int BAD_ARGUMENTS; -} template class FunctionPolygonsUnion : public IFunction @@ -57,55 +53,32 @@ public: return DataTypeCustomMultiPolygonSerialization::nestedDataType(); } - void checkInputType(const ColumnsWithTypeAndName & arguments) const - { - /// Array(Array(Array(Tuple(Float64, Float64)))) - auto desired = std::make_shared( - std::make_shared( - std::make_shared( - std::make_shared( - DataTypes{std::make_shared(), std::make_shared()} - ) - ) - ) - ); - if (!desired->equals(*arguments[0].type)) - throw Exception(fmt::format("The type of the first argument of function {} must be Array(Array(Array(Tuple(Float64, Float64))))", name), ErrorCodes::BAD_ARGUMENTS); - - if (!desired->equals(*arguments[1].type)) - throw Exception(fmt::format("The type of the second argument of function {} must be Array(Array(Array(Tuple(Float64, Float64))))", name), ErrorCodes::BAD_ARGUMENTS); - } - ColumnPtr executeImpl(const ColumnsWithTypeAndName & arguments, const DataTypePtr & /*result_type*/, size_t input_rows_count) const override { - checkInputType(arguments); - auto first_parser = makeGeometryFromColumnParser(arguments[0]); - auto first_container = createContainer(first_parser); + checkColumnTypeOrThrow(arguments[0]); + auto first_parser = MultiPolygonFromColumnParser(std::move(arguments[0].column->convertToFullColumnIfConst())); + MultiPolygon first_container; - auto second_parser = makeGeometryFromColumnParser(arguments[1]); - auto second_container = createContainer(second_parser); + checkColumnTypeOrThrow(arguments[1]); + auto second_parser = MultiPolygonFromColumnParser(std::move(arguments[1].column->convertToFullColumnIfConst())); + MultiPolygon second_container; MultiPolygonSerializer serializer; + MultiPolygon polygons_union{}; /// We are not interested in some pitfalls in third-party libraries /// NOLINTNEXTLINE(clang-analyzer-core.uninitialized.Assign) for (size_t i = 0; i < input_rows_count; i++) { - get(first_parser, first_container, i); - get(second_parser, second_container, i); - - auto first = boost::get>(first_container); - auto second = boost::get>(second_container); - auto polygons_union = MultiPolygon({{{{}}}}); + first_parser.get(first_container, i); + second_parser.get(second_container, i); /// Orient the polygons correctly. - boost::geometry::correct(first); - boost::geometry::correct(second); + boost::geometry::correct(first_container); + boost::geometry::correct(second_container); /// Main work here. - boost::geometry::union_(first, second, polygons_union); - - polygons_union.erase(polygons_union.begin()); + boost::geometry::union_(first_container, second_container, polygons_union); serializer.add(polygons_union); } diff --git a/src/Functions/polygonsWithin.cpp b/src/Functions/polygonsWithin.cpp index 5e13adefffa..f483d68dc0d 100644 --- a/src/Functions/polygonsWithin.cpp +++ b/src/Functions/polygonsWithin.cpp @@ -22,11 +22,6 @@ namespace DB { -namespace ErrorCodes -{ - extern const int BAD_ARGUMENTS; -} - template class FunctionPolygonsWithin : public IFunction { @@ -60,51 +55,28 @@ public: return std::make_shared(); } - void checkInputType(const ColumnsWithTypeAndName & arguments) const - { - /// Array(Array(Array(Tuple(Float64, Float64)))) - auto desired = std::make_shared( - std::make_shared( - std::make_shared( - std::make_shared( - DataTypes{std::make_shared(), std::make_shared()} - ) - ) - ) - ); - if (!desired->equals(*arguments[0].type)) - throw Exception(fmt::format("The type of the first argument of function {} must be Array(Array(Array(Tuple(Float64, Float64))))", name), ErrorCodes::BAD_ARGUMENTS); - - if (!desired->equals(*arguments[1].type)) - throw Exception(fmt::format("The type of the second argument of function {} must be Array(Array(Array(Tuple(Float64, Float64))))", name), ErrorCodes::BAD_ARGUMENTS); - } - ColumnPtr executeImpl(const ColumnsWithTypeAndName & arguments, const DataTypePtr & /*result_type*/, size_t input_rows_count) const override { - checkInputType(arguments); - auto first_parser = makeGeometryFromColumnParser(arguments[0]); - auto first_container = createContainer(first_parser); + checkColumnTypeOrThrow(arguments[0]); + auto first_parser = MultiPolygonFromColumnParser(std::move(arguments[0].column->convertToFullColumnIfConst())); + MultiPolygon first_container; - auto second_parser = makeGeometryFromColumnParser(arguments[1]); - auto second_container = createContainer(second_parser); + checkColumnTypeOrThrow(arguments[1]); + auto second_parser = MultiPolygonFromColumnParser(std::move(arguments[1].column->convertToFullColumnIfConst())); + MultiPolygon second_container; auto res_column = ColumnUInt8::create(); /// NOLINTNEXTLINE(clang-analyzer-core.uninitialized.Assign) for (size_t i = 0; i < input_rows_count; i++) { - get(first_parser, first_container, i); - get(second_parser, second_container, i); + first_parser.get(first_container, i); + second_parser.get(second_container, i); - auto first = boost::get>(first_container); - auto second = boost::get>(second_container); + boost::geometry::correct(first_container); + boost::geometry::correct(second_container); - boost::geometry::correct(first); - boost::geometry::correct(second); - - bool within = boost::geometry::within(first, second); - - res_column->insertValue(within); + res_column->insertValue(boost::geometry::within(first_container, second_container)); } return res_column; diff --git a/tests/queries/0_stateless/01300_polygon_convex_hull.sql b/tests/queries/0_stateless/01300_polygon_convex_hull.sql index 125d10f3afc..4a4aa66bbfb 100644 --- a/tests/queries/0_stateless/01300_polygon_convex_hull.sql +++ b/tests/queries/0_stateless/01300_polygon_convex_hull.sql @@ -1 +1 @@ -select polygonConvexHullCartesian([[[(0, 0), (0, 5), (5, 5), (5, 0), (2, 3)]]]); +select polygonConvexHullCartesian([[[(0., 0.), (0., 5.), (5., 5.), (5., 0.), (2., 3.)]]]); diff --git a/tests/queries/0_stateless/01301_polygons_within.sql b/tests/queries/0_stateless/01301_polygons_within.sql index f3697803f23..5bfa586da79 100644 --- a/tests/queries/0_stateless/01301_polygons_within.sql +++ b/tests/queries/0_stateless/01301_polygons_within.sql @@ -1,5 +1,5 @@ -select polygonsWithinCartesian([[[(0, 0),(0, 3),(1, 2.9),(2, 2.6),(2.6, 2),(2.9, 1),(3, 0),(0, 0)]]], [[[(1, 1),(1, 4),(4, 4),(4, 1),(1, 1)]]]); -select polygonsWithinCartesian([[[(2, 2), (2, 3), (3, 3), (3, 2)]]], [[[(1, 1),(1, 4),(4, 4),(4, 1),(1, 1)]]]); +select polygonsWithinCartesian([[[(0, 0),(0, 3),(1, 2.9),(2, 2.6),(2.6, 2),(2.9, 1),(3, 0),(0, 0)]]], [[[(1., 1.),(1., 4.),(4., 4.),(4., 1.),(1., 1.)]]]); +select polygonsWithinCartesian([[[(2., 2.), (2., 3.), (3., 3.), (3., 2.)]]], [[[(1., 1.),(1., 4.),(4., 4.),(4., 1.),(1., 1.)]]]); select polygonsWithinGeographic([[[(4.3613577, 50.8651821), (4.349556, 50.8535879), (4.3602419, 50.8435626), (4.3830299, 50.8428851), (4.3904543, 50.8564867), (4.3613148, 50.8651279)]]], [[[(4.346693, 50.858306), (4.367945, 50.852455), (4.366227, 50.840809), (4.344961, 50.833264), (4.338074, 50.848677), (4.346693, 50.858306)]]]); select polygonsWithinGeographic([[[(4.3501568, 50.8518269), (4.3444920, 50.8439961), (4.3565941, 50.8443213), (4.3501568, 50.8518269)]]], [[[(4.3679450, 50.8524550),(4.3466930, 50.8583060),(4.3380740, 50.8486770),(4.3449610, 50.8332640),(4.3662270, 50.8408090),(4.3679450, 50.8524550)]]]); diff --git a/tests/queries/0_stateless/01302_polygons_distance.sql b/tests/queries/0_stateless/01302_polygons_distance.sql index a4c769ad8cb..0051578ea7c 100644 --- a/tests/queries/0_stateless/01302_polygons_distance.sql +++ b/tests/queries/0_stateless/01302_polygons_distance.sql @@ -1,5 +1,5 @@ -select polygonsDistanceCartesian([[[(0, 0),(0, 3),(1, 2.9),(2, 2.6),(2.6, 2),(2.9, 1),(3, 0),(0, 0)]]], [[[(1, 1),(1, 4),(4, 4),(4, 1),(1, 1)]]]); -select polygonsDistanceCartesian([[[(0, 0), (0, 0.1), (0.1, 0.1), (0.1, 0)]]], [[[(1, 1),(1, 4),(4, 4),(4, 1),(1, 1)]]]); +select polygonsDistanceCartesian([[[(0, 0),(0, 3),(1, 2.9),(2, 2.6),(2.6, 2),(2.9, 1),(3, 0),(0, 0)]]], [[[(1., 1.),(1., 4.),(4., 4.),(4., 1.),(1., 1.)]]]); +select polygonsDistanceCartesian([[[(0, 0), (0, 0.1), (0.1, 0.1), (0.1, 0)]]], [[[(1., 1.),(1., 4.),(4., 4.),(4., 1.),(1., 1.)]]]); select polygonsDistanceGeographic([[[(23.725750, 37.971536)]]], [[[(4.3826169, 50.8119483)]]]); drop table if exists polygon_01302; diff --git a/tests/queries/0_stateless/01303_polygons_equals.sql b/tests/queries/0_stateless/01303_polygons_equals.sql index b3a4d8f12b3..1d608ce45fa 100644 --- a/tests/queries/0_stateless/01303_polygons_equals.sql +++ b/tests/queries/0_stateless/01303_polygons_equals.sql @@ -1,2 +1,2 @@ -select polygonsEqualsCartesian([[[(0, 0),(0, 3),(1, 2.9),(2, 2.6),(2.6, 2),(2.9, 1),(3, 0),(0, 0)]]], [[[(1, 1),(1, 4),(4, 4),(4, 1),(1, 1)]]]); -select polygonsEqualsCartesian([[[(1, 1),(1, 4),(4, 4),(4, 1)]]], [[[(1, 1),(1, 4),(4, 4),(4, 1),(1, 1)]]]); \ No newline at end of file +select polygonsEqualsCartesian([[[(0, 0),(0, 3),(1, 2.9),(2, 2.6),(2.6, 2),(2.9, 1),(3, 0),(0, 0)]]], [[[(1., 1.),(1., 4.),(4., 4.),(4., 1.),(1., 1.)]]]); +select polygonsEqualsCartesian([[[(1., 1.),(1., 4.),(4., 4.),(4., 1.)]]], [[[(1., 1.),(1., 4.),(4., 4.),(4., 1.),(1., 1.)]]]); \ No newline at end of file diff --git a/tests/queries/0_stateless/01304_polygons_sym_difference.sql b/tests/queries/0_stateless/01304_polygons_sym_difference.sql index 1d839fa80b3..f81300172d3 100644 --- a/tests/queries/0_stateless/01304_polygons_sym_difference.sql +++ b/tests/queries/0_stateless/01304_polygons_sym_difference.sql @@ -1,2 +1,2 @@ -select polygonsSymDifferenceCartesian([[[(0, 0),(0, 3),(1, 2.9),(2, 2.6),(2.6, 2),(2.9, 1),(3, 0),(0, 0)]]], [[[(1, 1),(1, 4),(4, 4),(4, 1),(1, 1)]]]) +select polygonsSymDifferenceCartesian([[[(0, 0),(0, 3),(1, 2.9),(2, 2.6),(2.6, 2),(2.9, 1),(3, 0),(0, 0)]]], [[[(1., 1.),(1., 4.),(4., 4.),(4., 1.),(1., 1.)]]]) diff --git a/tests/queries/0_stateless/01305_polygons_union.sql b/tests/queries/0_stateless/01305_polygons_union.sql index 42b869e850a..67d1c3c95bb 100644 --- a/tests/queries/0_stateless/01305_polygons_union.sql +++ b/tests/queries/0_stateless/01305_polygons_union.sql @@ -1,3 +1,3 @@ -select polygonsUnionCartesian([[[(0, 0),(0, 3),(1, 2.9),(2, 2.6),(2.6, 2),(2.9, 1),(3, 0),(0, 0)]]], [[[(1, 1),(1, 4),(4, 4),(4, 1),(1, 1)]]]); +select polygonsUnionCartesian([[[(0., 0.),(0., 3.),(1., 2.9),(2., 2.6),(2.6, 2.),(2.9, 1),(3., 0.),(0., 0.)]]], [[[(1., 1.),(1., 4.),(4., 4.),(4., 1.),(1., 1.)]]]); select polygonsUnionGeographic([[[(4.3613577, 50.8651821), (4.349556, 50.8535879), (4.3602419, 50.8435626), (4.3830299, 50.8428851), (4.3904543, 50.8564867), (4.3613148, 50.8651279)]]], [[[(4.346693, 50.858306), (4.367945, 50.852455), (4.366227, 50.840809), (4.344961, 50.833264), (4.338074, 50.848677), (4.346693, 50.858306)]]]); diff --git a/tests/queries/0_stateless/01306_polygons_intersection.sql b/tests/queries/0_stateless/01306_polygons_intersection.sql index 0901f20fee5..15962c43648 100644 --- a/tests/queries/0_stateless/01306_polygons_intersection.sql +++ b/tests/queries/0_stateless/01306_polygons_intersection.sql @@ -1,5 +1,5 @@ -select polygonsIntersectionCartesian([[[(0, 0),(0, 3),(1, 2.9),(2, 2.6),(2.6, 2),(2.9, 1),(3, 0),(0, 0)]]], [[[(1, 1),(1, 4),(4, 4),(4, 1),(1, 1)]]]); -select polygonsIntersectionCartesian([[[(0, 0),(0, 3),(1, 2.9),(2, 2.6),(2.6, 2),(2.9, 1),(3, 0),(0, 0)]]], [[[(3, 3),(3, 4),(4, 4),(4, 3),(3, 3)]]]); +select polygonsIntersectionCartesian([[[(0., 0.),(0., 3.),(1., 2.9),(2., 2.6),(2.6, 2.),(2.9, 1.),(3., 0.),(0., 0.)]]], [[[(1., 1.),(1., 4.),(4., 4.),(4., 1.),(1., 1.)]]]); +select polygonsIntersectionCartesian([[[(0., 0.),(0., 3.),(1., 2.9),(2., 2.6),(2.6, 2.),(2.9, 1.),(3., 0.),(0., 0.)]]], [[[(3., 3.),(3., 4.),(4., 4.),(4., 3.),(3., 3.)]]]); select polygonsIntersectionGeographic([[[(4.346693, 50.858306), (4.367945, 50.852455), (4.366227, 50.840809), (4.344961, 50.833264), (4.338074, 50.848677), (4.346693, 50.858306)]]], [[[(25.0010, 136.9987), (17.7500, 142.5000), (11.3733, 142.5917)]]]); select polygonsIntersectionGeographic([[[(4.3613577, 50.8651821), (4.349556, 50.8535879), (4.3602419, 50.8435626), (4.3830299, 50.8428851), (4.3904543, 50.8564867), (4.3613148, 50.8651279)]]], [[[(4.346693, 50.858306), (4.367945, 50.852455), (4.366227, 50.840809), (4.344961, 50.833264), (4.338074, 50.848677), (4.346693, 50.858306)]]]); \ No newline at end of file diff --git a/tests/queries/0_stateless/01307_polygon_perimeter.sql b/tests/queries/0_stateless/01307_polygon_perimeter.sql index 7e12d032d83..1cbbf41a201 100644 --- a/tests/queries/0_stateless/01307_polygon_perimeter.sql +++ b/tests/queries/0_stateless/01307_polygon_perimeter.sql @@ -1 +1 @@ -select polygonPerimeterCartesian([[[(0, 0), (0., 5), (5, 5), (5., 0)]]]); \ No newline at end of file +select polygonPerimeterCartesian([[[(0., 0.), (0., 5.), (5., 5.), (5., 0.)]]]); \ No newline at end of file diff --git a/tests/queries/0_stateless/01308_polygon_area.sql b/tests/queries/0_stateless/01308_polygon_area.sql index 700cf661b48..03f87874139 100644 --- a/tests/queries/0_stateless/01308_polygon_area.sql +++ b/tests/queries/0_stateless/01308_polygon_area.sql @@ -1,3 +1,3 @@ -select polygonAreaCartesian([[[(0, 0), (0., 5), (5, 5), (5., 0)]]]); +select polygonAreaCartesian([[[(0., 0.), (0., 5.), (5., 5.), (5., 0.)]]]); select polygonAreaGeographic([[[(4.346693, 50.858306), (4.367945, 50.852455), (4.366227, 50.840809), (4.344961, 50.833264), (4.338074, 50.848677), (4.346693, 50.858306)]]]); SELECT polygonAreaCartesian([]); -- { serverError 36 } \ No newline at end of file