polygonsSymDifference.cpp 3.5 KB
Newer Older
N
Nikita Mikhailov 已提交
1 2 3
#include <Functions/FunctionFactory.h>
#include <Functions/geometryConverters.h>

N
Nikita Mikhaylov 已提交
4 5 6
#include <boost/geometry.hpp>
#include <boost/geometry/geometries/point_xy.hpp>
#include <boost/geometry/geometries/polygon.hpp>
N
Nikita Mikhailov 已提交
7

N
Nikita Mikhaylov 已提交
8
#include <common/logger_useful.h>
N
better  
Nikita Mikhailov 已提交
9

N
Nikita Mikhaylov 已提交
10 11 12 13 14 15
#include <Columns/ColumnArray.h>
#include <Columns/ColumnTuple.h>
#include <Columns/ColumnConst.h>
#include <DataTypes/DataTypeArray.h>
#include <DataTypes/DataTypeTuple.h>
#include <DataTypes/DataTypeCustomGeo.h>
N
better  
Nikita Mikhailov 已提交
16

N
Nikita Mikhaylov 已提交
17 18
#include <memory>
#include <utility>
N
Nikita Mikhaylov 已提交
19

N
Nikita Mikhaylov 已提交
20
namespace DB
N
Nikita Mikhaylov 已提交
21 22
{

N
Nikita Mikhaylov 已提交
23
namespace ErrorCodes
N
Nikita Mikhaylov 已提交
24
{
N
Nikita Mikhaylov 已提交
25 26
    extern const int ILLEGAL_TYPE_OF_ARGUMENT;
}
N
Nikita Mikhaylov 已提交
27 28


N
Nikita Mikhaylov 已提交
29
template <typename Point>
N
Nikita Mikhailov 已提交
30 31 32
class FunctionPolygonsSymDifference : public IFunction
{
public:
N
Nikita Mikhaylov 已提交
33
    static const char * name;
N
Nikita Mikhailov 已提交
34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58

    explicit FunctionPolygonsSymDifference() = default;

    static FunctionPtr create(const Context &)
    {
        return std::make_shared<FunctionPolygonsSymDifference>();
    }

    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
    {
59
        return DataTypeFactory::instance().get("MultiPolygon");
N
Nikita Mikhailov 已提交
60 61 62 63 64 65 66 67 68 69 70 71 72 73
    }

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

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

            using LeftConverter = typename LeftConverterType::Type;
            using RightConverter = typename RightConverterType::Type;

N
Nikita Mikhailov 已提交
74
            if constexpr (std::is_same_v<ColumnToPointsConverter<Point>, LeftConverter> || std::is_same_v<ColumnToPointsConverter<Point>, RightConverter>)
N
better  
Nikita Mikhailov 已提交
75 76
                throw Exception(fmt::format("Any argument of function {} must not be Point", getName()), ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT);
            else
N
Nikita Mikhailov 已提交
77
            {
N
Nikita Mikhailov 已提交
78 79
                auto first = LeftConverter::convert(arguments[0].column->convertToFullColumnIfConst());
                auto second = RightConverter::convert(arguments[1].column->convertToFullColumnIfConst());
N
better  
Nikita Mikhailov 已提交
80 81 82 83 84 85

                /// NOLINTNEXTLINE(clang-analyzer-core.uninitialized.Assign)
                for (size_t i = 0; i < input_rows_count; i++)
                {
                    boost::geometry::correct(first[i]);
                    boost::geometry::correct(second[i]);
N
Nikita Mikhailov 已提交
86

N
better  
Nikita Mikhailov 已提交
87 88
                    MultiPolygon<Point> sym_difference{};
                    boost::geometry::sym_difference(first[i], second[i], sym_difference);
N
Nikita Mikhailov 已提交
89

N
better  
Nikita Mikhailov 已提交
90 91
                    serializer.add(sym_difference);
                }
N
Nikita Mikhailov 已提交
92 93 94 95 96 97 98 99 100 101 102 103
            }
        });

        return serializer.finalize();
    }

    bool useDefaultImplementationForConstants() const override
    {
        return true;
    }
};

N
Nikita Mikhaylov 已提交
104 105 106 107 108 109
template <>
const char * FunctionPolygonsSymDifference<CartesianPoint>::name = "polygonsSymDifferenceCartesian";

template <>
const char * FunctionPolygonsSymDifference<SphericalPoint>::name = "polygonsSymDifferenceSpherical";

N
Nikita Mikhailov 已提交
110 111
void registerFunctionPolygonsSymDifference(FunctionFactory & factory)
{
N
Nikita Mikhaylov 已提交
112 113
    factory.registerFunction<FunctionPolygonsSymDifference<CartesianPoint>>();
    factory.registerFunction<FunctionPolygonsSymDifference<SphericalPoint>>();
N
Nikita Mikhailov 已提交
114 115 116
}

}