#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace DB { template class FunctionPolygonsIntersection : public IFunction { public: static inline const char * name; explicit FunctionPolygonsIntersection() = default; static FunctionPtr create(const Context &) { return std::make_shared(); } String getName() const override { return name; } bool isVariadic() const override { return false; } size_t getNumberOfArguments() const override { return 2; } DataTypePtr getReturnTypeImpl(const DataTypes &) const override { /// Intersection of each with figure with each could be easily represent as MultiPolygon. return DataTypeCustomMultiPolygonSerialization::nestedDataType(); } ColumnPtr executeImpl(const ColumnsWithTypeAndName & arguments, const DataTypePtr & /*result_type*/, size_t input_rows_count) const override { auto first_parser = getConverterBasedOnType(arguments[0]); auto second_parser = getConverterBasedOnType(arguments[1]); MultiPolygonSerializer serializer; auto first = parseFigure(first_parser); auto second = parseFigure(second_parser); /// 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) { /// Orient the polygons correctly. boost::geometry::correct(first[i]); boost::geometry::correct(second[i]); MultiPolygon intersection{}; /// Main work here. boost::geometry::intersection(first[i], second[i], intersection); serializer.add(intersection); } return serializer.finalize(); } bool useDefaultImplementationForConstants() const override { return true; } }; template <> const char * FunctionPolygonsIntersection::name = "polygonsIntersectionCartesian"; template <> const char * FunctionPolygonsIntersection::name = "polygonsIntersectionGeographic"; void registerFunctionPolygonsIntersection(FunctionFactory & factory) { factory.registerFunction>(); factory.registerFunction>(); } }