ClickHouse
153 строки · 5.1 Кб
1#include "config.h"2
3#if USE_H34
5#include <Columns/ColumnsNumber.h>6#include <DataTypes/DataTypesNumber.h>7#include <DataTypes/DataTypeTuple.h>8#include <Functions/FunctionFactory.h>9#include <Functions/IFunction.h>10#include <IO/WriteHelpers.h>11#include <Common/typeid_cast.h>12#include <base/range.h>13
14#include <constants.h>15#include <h3api.h>16
17
18namespace DB19{
20namespace ErrorCodes21{
22extern const int ILLEGAL_TYPE_OF_ARGUMENT;23extern const int ILLEGAL_COLUMN;24}
25
26namespace
27{
28template <class Impl>29class FunctionH3PointDist final : public IFunction30{
31public:32static constexpr auto name = Impl::name;33static constexpr auto function = Impl::function;34
35static FunctionPtr create(ContextPtr) { return std::make_shared<FunctionH3PointDist>(); }36
37std::string getName() const override { return name; }38
39size_t getNumberOfArguments() const override { return 4; }40bool useDefaultImplementationForConstants() const override { return true; }41bool isSuitableForShortCircuitArgumentsExecution(const DataTypesWithConstInfo & /*arguments*/) const override { return false; }42
43DataTypePtr getReturnTypeImpl(const DataTypes & arguments) const override44{45for (size_t i = 0; i < getNumberOfArguments(); ++i)46{47const auto * arg = arguments[i].get();48if (!WhichDataType(arg).isFloat64())49throw Exception(50ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT,51"Illegal type {} of argument {} of function {}. Must be Float64",52arg->getName(), i, getName());53}54return std::make_shared<DataTypeFloat64>();55}56
57ColumnPtr executeImpl(const ColumnsWithTypeAndName & arguments, const DataTypePtr &, size_t input_rows_count) const override58{59auto non_const_arguments = arguments;60for (auto & argument : non_const_arguments)61argument.column = argument.column->convertToFullColumnIfConst();62
63const auto * col_lat1 = checkAndGetColumn<ColumnFloat64>(non_const_arguments[0].column.get());64if (!col_lat1)65throw Exception(66ErrorCodes::ILLEGAL_COLUMN,67"Illegal type {} of argument {} of function {}. Must be Float64",68arguments[0].type->getName(),691,70getName());71const auto & data_lat1 = col_lat1->getData();72
73const auto * col_lon1 = checkAndGetColumn<ColumnFloat64>(non_const_arguments[1].column.get());74if (!col_lon1)75throw Exception(76ErrorCodes::ILLEGAL_COLUMN,77"Illegal type {} of argument {} of function {}. Must be Float64",78arguments[1].type->getName(),792,80getName());81const auto & data_lon1 = col_lon1->getData();82
83const auto * col_lat2 = checkAndGetColumn<ColumnFloat64>(non_const_arguments[2].column.get());84if (!col_lat2)85throw Exception(86ErrorCodes::ILLEGAL_COLUMN,87"Illegal type {} of argument {} of function {}. Must be Float64",88arguments[2].type->getName(),893,90getName());91const auto & data_lat2 = col_lat2->getData();92
93const auto * col_lon2 = checkAndGetColumn<ColumnFloat64>(non_const_arguments[3].column.get());94if (!col_lon2)95throw Exception(96ErrorCodes::ILLEGAL_COLUMN,97"Illegal type {} of argument {} of function {}. Must be Float64",98arguments[3].type->getName(),994,100getName());101const auto & data_lon2 = col_lon2->getData();102
103auto dst = ColumnVector<Float64>::create();104auto & dst_data = dst->getData();105dst_data.resize(input_rows_count);106
107for (size_t row = 0; row < input_rows_count; ++row)108{109const double lat1 = data_lat1[row];110const double lon1 = data_lon1[row];111const auto lat2 = data_lat2[row];112const auto lon2 = data_lon2[row];113
114LatLng point1 = {degsToRads(lat1), degsToRads(lon1)};115LatLng point2 = {degsToRads(lat2), degsToRads(lon2)};116
117// function will be equivalent to distanceM or distanceKm or distanceRads118Float64 res = function(&point1, &point2);119dst_data[row] = res;120}121
122return dst;123}124};125
126}
127
128struct H3PointDistM129{
130static constexpr auto name = "h3PointDistM";131static constexpr auto function = distanceM;132};133
134struct H3PointDistKm135{
136static constexpr auto name = "h3PointDistKm";137static constexpr auto function = distanceKm;138};139
140struct H3PointDistRads141{
142static constexpr auto name = "h3PointDistRads";143static constexpr auto function = distanceRads;144};145
146
147REGISTER_FUNCTION(H3PointDistM) { factory.registerFunction<FunctionH3PointDist<H3PointDistM>>(); }148REGISTER_FUNCTION(H3PointDistKm) { factory.registerFunction<FunctionH3PointDist<H3PointDistKm>>(); }149REGISTER_FUNCTION(H3PointDistRads) { factory.registerFunction<FunctionH3PointDist<H3PointDistRads>>(); }150
151}
152
153#endif154