ClickHouse
110 строк · 2.7 Кб
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#include <boost/geometry/geometries/polygon.hpp>
7
8#include <Common/logger_useful.h>
9
10#include <Columns/ColumnArray.h>
11#include <Columns/ColumnTuple.h>
12#include <Columns/ColumnsNumber.h>
13#include <DataTypes/DataTypeArray.h>
14#include <DataTypes/DataTypeTuple.h>
15#include <DataTypes/DataTypeCustomGeo.h>
16
17#include <memory>
18#include <string>
19
20namespace DB
21{
22
23namespace ErrorCodes
24{
25extern const int BAD_ARGUMENTS;
26}
27
28namespace
29{
30
31template <typename Point>
32class FunctionPolygonConvexHull : public IFunction
33{
34public:
35static const char * name;
36
37explicit FunctionPolygonConvexHull() = default;
38
39static FunctionPtr create(ContextPtr)
40{
41return std::make_shared<FunctionPolygonConvexHull>();
42}
43
44String getName() const override
45{
46return name;
47}
48
49bool isVariadic() const override
50{
51return false;
52}
53
54bool isSuitableForShortCircuitArgumentsExecution(const DataTypesWithConstInfo & /*arguments*/) const override { return true; }
55
56size_t getNumberOfArguments() const override
57{
58return 1;
59}
60
61DataTypePtr getReturnTypeImpl(const DataTypes &) const override
62{
63return DataTypeFactory::instance().get("Polygon");
64}
65
66ColumnPtr executeImpl(const ColumnsWithTypeAndName & arguments, const DataTypePtr & /*result_type*/, size_t input_rows_count) const override
67{
68PolygonSerializer<Point> serializer;
69
70callOnGeometryDataType<Point>(arguments[0].type, [&] (const auto & type)
71{
72using TypeConverter = std::decay_t<decltype(type)>;
73using Converter = typename TypeConverter::Type;
74
75if constexpr (std::is_same_v<Converter, ColumnToPointsConverter<Point>>)
76throw Exception(ErrorCodes::BAD_ARGUMENTS, "The argument of function {} must not be a Point", getName());
77else
78{
79auto geometries = Converter::convert(arguments[0].column->convertToFullColumnIfConst());
80
81for (size_t i = 0; i < input_rows_count; ++i)
82{
83Polygon<Point> convex_hull{};
84boost::geometry::convex_hull(geometries[i], convex_hull);
85serializer.add(convex_hull);
86}
87}
88}
89);
90
91return serializer.finalize();
92}
93
94bool useDefaultImplementationForConstants() const override
95{
96return true;
97}
98};
99
100template <>
101const char * FunctionPolygonConvexHull<CartesianPoint>::name = "polygonConvexHullCartesian";
102
103}
104
105REGISTER_FUNCTION(PolygonConvexHull)
106{
107factory.registerFunction<FunctionPolygonConvexHull<CartesianPoint>>();
108}
109
110}
111