Skip to content

Commit

Permalink
Merge pull request #28952 from fuzzERot/h3-functions
Browse files Browse the repository at this point in the history
Implementation of h3ToGeoBoundary
  • Loading branch information
alexey-milovidov committed Sep 18, 2021
2 parents ae808b8 + d4ac1fd commit 3eed1f0
Show file tree
Hide file tree
Showing 6 changed files with 184 additions and 0 deletions.
36 changes: 36 additions & 0 deletions docs/en/sql-reference/functions/geo/h3.md
Original file line number Diff line number Diff line change
Expand Up @@ -229,6 +229,42 @@ Result:
└───────────────────────────────────────┘
```

## h3ToGeoBoundary {#h3togeoboundary}

Returns array of pairs `(lon, lat)`, which corresponds to the boundary of the provided H3 index.

**Syntax**

``` sql
h3ToGeoBoundary(h3Index)
```

**Arguments**

- `h3Index` — H3 Index. Type: [UInt64](../../../sql-reference/data-types/int-uint.md).

**Returned values**

- Array of pairs '(lon, lat)'.
Type: [Array](../../../sql-reference/data-types/array.md)([Float64](../../../sql-reference/data-types/float.md), [Float64](../../../sql-reference/data-types/float.md)).


**Example**

Query:

``` sql
SELECT h3ToGeoBoundary(644325524701193974) AS coordinates;
```

Result:

``` text
┌─h3ToGeoBoundary(599686042433355775)────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
│ [(37.2713558667319,-121.91508032705622),(37.353926450852256,-121.8622232890249),(37.42834118609435,-121.92354999630156),(37.42012867767779,-122.03773496427027),(37.33755608435299,-122.090428929044),(37.26319797461824,-122.02910130919001)] │
└────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
```

## h3kRing {#h3kring}

Lists all the [H3](#h3index) hexagons in the raduis of `k` from the given hexagon in random order.
Expand Down
6 changes: 6 additions & 0 deletions src/DataTypes/IDataType.h
Original file line number Diff line number Diff line change
Expand Up @@ -387,6 +387,12 @@ inline bool isUInt8(const T & data_type)
return WhichDataType(data_type).isUInt8();
}

template <typename T>
inline bool isUInt64(const T & data_type)
{
return WhichDataType(data_type).isUInt64();
}

template <typename T>
inline bool isUnsignedInteger(const T & data_type)
{
Expand Down
96 changes: 96 additions & 0 deletions src/Functions/h3ToGeoBoundary.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
#if !defined(ARCADIA_BUILD)
# include "config_functions.h"
#endif

#if USE_H3

#include <Columns/ColumnArray.h>
#include <Columns/ColumnTuple.h>
#include <Columns/ColumnsNumber.h>
#include <Functions/FunctionFactory.h>
#include <Functions/IFunction.h>
#include <DataTypes/DataTypeArray.h>
#include <DataTypes/DataTypeTuple.h>
#include <DataTypes/DataTypesNumber.h>

#include <h3api.h>


namespace DB
{
namespace ErrorCodes
{
extern const int ILLEGAL_TYPE_OF_ARGUMENT;
extern const int INCORRECT_DATA;
}

class FunctionH3ToGeoBoundary : public IFunction
{
public:
static constexpr auto name = "h3ToGeoBoundary";
String getName() const override { return name; }
static FunctionPtr create(ContextPtr) { return std::make_shared<FunctionH3ToGeoBoundary>(); }

size_t getNumberOfArguments() const override { return 1; }
bool useDefaultImplementationForConstants() const override { return true; }
bool isSuitableForShortCircuitArgumentsExecution(const DataTypesWithConstInfo & /*arguments*/) const override { return false; }

DataTypePtr getReturnTypeImpl(const DataTypes & arguments) const override
{
const auto & arg = arguments[0];
if (!isUInt64(arg))
{
throw Exception(
ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT,
"Illegal type {} of argument {} of function {}. Must be UInt64",
arg->getName(), 1, getName());
}

return std::make_shared<DataTypeArray>(
std::make_shared<DataTypeTuple>(
DataTypes{std::make_shared<DataTypeFloat64>(), std::make_shared<DataTypeFloat64>()}));
}

ColumnPtr executeImpl(const ColumnsWithTypeAndName & arguments, const DataTypePtr &, size_t input_rows_count) const override
{
const auto * col_hindex = arguments[0].column.get();

auto latitude = ColumnFloat64::create();
auto longitude = ColumnFloat64::create();
auto offsets = DataTypeNumber<IColumn::Offset>().createColumn();
offsets->reserve(input_rows_count);
IColumn::Offset current_offset = 0;

for (size_t row = 0; row < input_rows_count; ++row)
{
H3Index h3index = col_hindex->getUInt(row);
CellBoundary boundary{};

auto err = cellToBoundary(h3index, &boundary);
if (err)
throw Exception(ErrorCodes::INCORRECT_DATA, "Incorrect H3 index: {}, error: {}", h3index, err);

for (int vert = 0; vert < boundary.numVerts; ++vert)
{
latitude->insert(radsToDegs(boundary.verts[vert].lat));
longitude->insert(radsToDegs(boundary.verts[vert].lng));
}

current_offset += boundary.numVerts;
offsets->insert(current_offset);
}

return ColumnArray::create(
ColumnTuple::create(Columns{std::move(latitude), std::move(longitude)}),
std::move(offsets));
}
};

void registerFunctionH3ToGeoBoundary(FunctionFactory & factory)
{
factory.registerFunction<FunctionH3ToGeoBoundary>();
}

}

#endif
2 changes: 2 additions & 0 deletions src/Functions/registerFunctionsGeo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ void registerFunctionSvg(FunctionFactory & factory);
#if USE_H3
void registerFunctionGeoToH3(FunctionFactory &);
void registerFunctionH3ToGeo(FunctionFactory &);
void registerFunctionH3ToGeoBoundary(FunctionFactory &);
void registerFunctionH3EdgeAngle(FunctionFactory &);
void registerFunctionH3EdgeLengthM(FunctionFactory &);
void registerFunctionH3GetResolution(FunctionFactory &);
Expand Down Expand Up @@ -81,6 +82,7 @@ void registerFunctionsGeo(FunctionFactory & factory)
#if USE_H3
registerFunctionGeoToH3(factory);
registerFunctionH3ToGeo(factory);
registerFunctionH3ToGeoBoundary(factory);
registerFunctionH3EdgeAngle(factory);
registerFunctionH3EdgeLengthM(factory);
registerFunctionH3GetResolution(factory);
Expand Down
16 changes: 16 additions & 0 deletions tests/queries/0_stateless/02006_h3_to_geo_boundary.reference
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
[(-25.60370257696877,-170.61932339479839),(-16.505947603561054,-161.6348206171839),(-5.762860491436932,-165.41674992858833),(-3.968796976609588,-176.05696384421356),(-11.54529597541476,175.98600155652952),(-22.19754138630238,177.51613498805204)]
[(57.15637211465772,51.15131422930827),(53.74532256646542,56.28611799875301),(54.25756495131088,64.15861768734945),(58.31910366055611,68.25632325438265),(62.114389785017146,63.44462184184533),(61.440920615681854,53.98254701603947)]
[(-82.24829137508873,167.18203088800593),(-83.41761096812805,158.00531624510785),(-84.94207431820979,162.09183616506846),(-85.00324300064887,-178.60454506450245),(-83.46691212211444,-172.41232929697492),(-82.25118471750908,179.4928586395771)]
[(-69.70201806837188,-95.63006768303532),(-69.78121889088241,-93.8329499937899),(-69.26603652285242,-92.70414199751751),(-68.6908704290193,-93.35479180342097),(-68.62037380778602,-95.0614247833063),(-69.11663254992226,-96.20491957306085)]
[(-55.64960804791368,-8.350548718066527),(-55.828830219010115,-8.612333853721543),(-56.03525612929049,-8.450494689408638),(-56.06193617137633,-8.024722968315496),(-55.88205068143165,-7.7639036247878686),(-55.67615021200244,-7.927868022867216)]
[(47.4047230189944,77.11372810022105),(47.31523866865899,77.16981222471887),(47.30324229614998,77.31177114774472),(47.380675190840634,77.39807294060385),(47.47025252565847,77.34232219743376),(47.482304118992815,77.19993524307596)]
[(36.59082706214739,135.1447773494689),(36.623412749699106,135.14466572237862),(36.640360586702336,135.11335418763244),(36.62472012921161,135.0821822076476),(36.592149268586866,135.08232217250773),(36.575204036900494,135.1136057921021)]
[(49.072491410488254,39.26829772479248),(49.06434071502539,39.28264806614126),(49.068946849412825,39.29969935764574),(49.08170687750978,39.30240475320644),(49.08985976852211,39.288050003564216),(49.0852504352169,39.27099426655672)]
[(-27.484668731117956,124.71456214331452),(-27.480255804296018,124.7164671069391),(-27.476759420067374,124.71353974495929),(-27.477675754654342,124.70870779388683),(-27.48208829554146,124.706802674375),(-27.485584887763263,124.70972966178107)]
[(76.73422062536704,-147.4905412849195),(76.73289074232657,-147.4965026703208),(76.73104961876471,-147.49472931389167),(76.730538300536,-147.48699643238956),(76.73186795003895,-147.4810352654388),(76.73370915128375,-147.4828067613433)]
[(-25.52488377871919,86.63224601066914),(-25.525614626072162,86.63222807640663),(-25.525993697439322,86.63290113101664),(-25.5256419200276,86.6335921124905),(-25.524911076278325,86.63361003835355),(-25.524532006337036,86.63293699114213)]
[(13.126242531761285,23.27727960465014),(13.125977729043674,23.277268554217677),(13.125836559860176,23.277506856149834),(13.125960192636454,23.27775620899515),(13.12622499528112,23.27776726055665),(13.126366165222441,23.277528958143787)]
[(-63.12570930185924,-70.40176049055108),(-63.12571366261393,-70.4015366058905),(-63.1256297288591,-70.40140848801948),(-63.125541434726955,-70.4015042543287),(-63.125537074078174,-70.40172813751032),(-63.125621007455614,-70.40185625586165)]
[(40.28583119436284,15.642383240826787),(40.2857926151193,15.642384471654026),(40.28577492591182,15.642429586343791),(40.28579581594201,15.642473470233714),(40.2858343951909,15.642472239444253),(40.28585208440421,15.642427124727082)]
[(54.55605961596273,-76.53410754061841),(54.556055751776405,-76.53413299495058),(54.5560411051761,-76.53413993412053),(54.55603032276505,-76.53412141897394),(54.55603418694863,-76.53409596465765),(54.556048833546,-76.53408902547206)]
[(67.69370622234305,8.199070817163335),(67.69370970389446,8.199075597443361),(67.69371314705361,8.199068130094206),(67.69371310866035,8.199055882463448),(67.69370962710823,8.19905110218645),(67.69370618395016,8.199058569537081)]
28 changes: 28 additions & 0 deletions tests/queries/0_stateless/02006_h3_to_geo_boundary.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
-- Tags: no-unbundled, no-fasttest

DROP TABLE IF EXISTS h3_indexes;

CREATE TABLE h3_indexes (h3_index UInt64) ENGINE = Memory;

-- Coordinates from h3ToGeo test.

INSERT INTO h3_indexes VALUES (579205133326352383);
INSERT INTO h3_indexes VALUES (581263419093549055);
INSERT INTO h3_indexes VALUES (589753847883235327);
INSERT INTO h3_indexes VALUES (594082350283882495);
INSERT INTO h3_indexes VALUES (598372386957426687);
INSERT INTO h3_indexes VALUES (599542359671177215);
INSERT INTO h3_indexes VALUES (604296355086598143);
INSERT INTO h3_indexes VALUES (608785214872748031);
INSERT INTO h3_indexes VALUES (615732192485572607);
INSERT INTO h3_indexes VALUES (617056794467368959);
INSERT INTO h3_indexes VALUES (624586477873168383);
INSERT INTO h3_indexes VALUES (627882919484481535);
INSERT INTO h3_indexes VALUES (634600058503392255);
INSERT INTO h3_indexes VALUES (635544851677385791);
INSERT INTO h3_indexes VALUES (639763125756281263);
INSERT INTO h3_indexes VALUES (644178757620501158);

SELECT h3ToGeoBoundary(h3_index) FROM h3_indexes ORDER BY h3_index;

DROP TABLE h3_indexes;

0 comments on commit 3eed1f0

Please sign in to comment.