ClickHouse

Форк
0
/
polygonsUnion.cpp 
120 строк · 3.5 Кб
1
#include <Functions/FunctionFactory.h>
2
#include <Functions/geometryConverters.h>
3

4
#include <boost/geometry.hpp>
5
#include <boost/geometry/geometries/point_xy.hpp>
6

7
#include <Common/logger_useful.h>
8

9
#include <Columns/ColumnTuple.h>
10
#include <DataTypes/DataTypeTuple.h>
11

12
#include <memory>
13

14

15
namespace DB
16
{
17

18
namespace ErrorCodes
19
{
20
    extern const int ILLEGAL_TYPE_OF_ARGUMENT;
21
}
22

23
namespace
24
{
25

26
template <typename Point>
27
class FunctionPolygonsUnion : public IFunction
28
{
29
public:
30
    static inline const char * name;
31

32
    explicit FunctionPolygonsUnion() = default;
33

34
    static FunctionPtr create(ContextPtr)
35
    {
36
        return std::make_shared<FunctionPolygonsUnion>();
37
    }
38

39
    String getName() const override
40
    {
41
        return name;
42
    }
43

44
    bool isVariadic() const override
45
    {
46
        return false;
47
    }
48

49
    size_t getNumberOfArguments() const override
50
    {
51
        return 2;
52
    }
53

54
    DataTypePtr getReturnTypeImpl(const DataTypes &) const override
55
    {
56
        return DataTypeFactory::instance().get("MultiPolygon");
57
    }
58

59
    bool isSuitableForShortCircuitArgumentsExecution(const DataTypesWithConstInfo & /*arguments*/) const override { return true; }
60

61
    ColumnPtr executeImpl(const ColumnsWithTypeAndName & arguments, const DataTypePtr & /*result_type*/, size_t input_rows_count) const override
62
    {
63
        MultiPolygonSerializer<Point> serializer;
64

65
        callOnTwoGeometryDataTypes<Point>(arguments[0].type, arguments[1].type, [&](const auto & left_type, const auto & right_type)
66
        {
67
            using LeftConverterType = std::decay_t<decltype(left_type)>;
68
            using RightConverterType = std::decay_t<decltype(right_type)>;
69

70
            using LeftConverter = typename LeftConverterType::Type;
71
            using RightConverter = typename RightConverterType::Type;
72

73
            if constexpr (std::is_same_v<ColumnToPointsConverter<Point>, LeftConverter> || std::is_same_v<ColumnToPointsConverter<Point>, RightConverter>)
74
                throw Exception(ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT, "Any argument of function {} must not be Point", getName());
75
            else
76
            {
77
                auto first = LeftConverter::convert(arguments[0].column->convertToFullColumnIfConst());
78
                auto second = RightConverter::convert(arguments[1].column->convertToFullColumnIfConst());
79

80
                /// We are not interested in some pitfalls in third-party libraries
81
                /// NOLINTNEXTLINE(clang-analyzer-core.uninitialized.Assign)
82
                for (size_t i = 0; i < input_rows_count; ++i)
83
                {
84
                    /// Orient the polygons correctly.
85
                    boost::geometry::correct(first[i]);
86
                    boost::geometry::correct(second[i]);
87

88
                    MultiPolygon<Point> polygons_union{};
89
                    /// Main work here.
90
                    boost::geometry::union_(first[i], second[i], polygons_union);
91

92
                    serializer.add(polygons_union);
93
                }
94
            }
95
        });
96

97
        return serializer.finalize();
98
    }
99

100
    bool useDefaultImplementationForConstants() const override
101
    {
102
        return true;
103
    }
104
};
105

106
template <>
107
const char * FunctionPolygonsUnion<CartesianPoint>::name = "polygonsUnionCartesian";
108

109
template <>
110
const char * FunctionPolygonsUnion<SphericalPoint>::name = "polygonsUnionSpherical";
111

112
}
113

114
REGISTER_FUNCTION(PolygonsUnion)
115
{
116
    factory.registerFunction<FunctionPolygonsUnion<CartesianPoint>>();
117
    factory.registerFunction<FunctionPolygonsUnion<SphericalPoint>>();
118
}
119

120
}
121

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.