mirror of
https://github.com/ClickHouse/ClickHouse.git
synced 2024-11-23 08:02:02 +00:00
better
This commit is contained in:
parent
373b429e61
commit
0425d566d3
@ -28,14 +28,6 @@ namespace ErrorCodes
|
|||||||
extern const int ILLEGAL_COLUMN;
|
extern const int ILLEGAL_COLUMN;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
using CoordinateType = Float64;
|
|
||||||
using Point = boost::geometry::model::d2::point_xy<CoordinateType>;
|
|
||||||
using Polygon = boost::geometry::model::polygon<Point, false>;
|
|
||||||
using MultiPolygon = boost::geometry::model::multi_polygon<Float64Polygon>;
|
|
||||||
using Box = boost::geometry::model::box<Point>;
|
|
||||||
|
|
||||||
|
|
||||||
class FunctionPolygonsUnion : public IFunction
|
class FunctionPolygonsUnion : public IFunction
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@ -68,17 +60,17 @@ public:
|
|||||||
return DataTypeCustomMultiPolygonSerialization::nestedDataType();
|
return DataTypeCustomMultiPolygonSerialization::nestedDataType();
|
||||||
}
|
}
|
||||||
|
|
||||||
void executeImpl(Block & block, const ColumnNumbers & arguments, size_t result, size_t input_rows_count) override
|
ColumnPtr executeImpl(const ColumnsWithTypeAndName & arguments, const DataTypePtr & /*result_type*/, size_t input_rows_count) const override
|
||||||
{
|
{
|
||||||
auto get_parser = [&block, &arguments] (size_t i) {
|
auto get_parser = [&arguments] (size_t i) {
|
||||||
const auto * const_col =
|
const auto * const_col =
|
||||||
checkAndGetColumn<ColumnConst>(block.getByPosition(arguments[i]).column.get());
|
checkAndGetColumn<ColumnConst>(arguments[i].column.get());
|
||||||
|
|
||||||
bool is_const = static_cast<bool>(const_col);
|
bool is_const = static_cast<bool>(const_col);
|
||||||
|
|
||||||
return std::pair<bool, GeometryFromColumnParser>{is_const, is_const ?
|
return std::pair<bool, CartesianGeometryFromColumnParser>{is_const, is_const ?
|
||||||
makeGeometryFromColumnParser(ColumnWithTypeAndName(const_col->getDataColumnPtr(), block.getByPosition(arguments[i]).type, block.getByPosition(arguments[i]).name)) :
|
makeCartesianGeometryFromColumnParser(ColumnWithTypeAndName(const_col->getDataColumnPtr(), arguments[i].type, arguments[i].name)) :
|
||||||
makeGeometryFromColumnParser(block.getByPosition(arguments[i]))};
|
makeCartesianGeometryFromColumnParser(arguments[i])};
|
||||||
};
|
};
|
||||||
|
|
||||||
auto [is_first_polygon_const, first_parser] = get_parser(0);
|
auto [is_first_polygon_const, first_parser] = get_parser(0);
|
||||||
@ -87,7 +79,7 @@ public:
|
|||||||
auto [is_second_polygon_const, second_parser] = get_parser(1);
|
auto [is_second_polygon_const, second_parser] = get_parser(1);
|
||||||
auto second_container = createContainer(second_parser);
|
auto second_container = createContainer(second_parser);
|
||||||
|
|
||||||
Float64MultiPolygonSerializer serializer;
|
CartesianMultiPolygonSerializer serializer;
|
||||||
|
|
||||||
for (size_t i = 0; i < input_rows_count; i++)
|
for (size_t i = 0; i < input_rows_count; i++)
|
||||||
{
|
{
|
||||||
@ -96,19 +88,19 @@ public:
|
|||||||
if (!is_second_polygon_const || i == 0)
|
if (!is_second_polygon_const || i == 0)
|
||||||
get(second_parser, second_container, i);
|
get(second_parser, second_container, i);
|
||||||
|
|
||||||
Float64Geometry polygons_union = Float64MultiPolygon({{{{}}}});
|
CartesianGeometry polygons_union = CartesianMultiPolygon({{{{}}}});
|
||||||
boost::geometry::union_(
|
boost::geometry::union_(
|
||||||
boost::get<Float64MultiPolygon>(first_container),
|
boost::get<CartesianMultiPolygon>(first_container),
|
||||||
boost::get<Float64MultiPolygon>(second_container),
|
boost::get<CartesianMultiPolygon>(second_container),
|
||||||
boost::get<Float64MultiPolygon>(polygons_union));
|
boost::get<CartesianMultiPolygon>(polygons_union));
|
||||||
|
|
||||||
boost::get<Float64MultiPolygon>(polygons_union).erase(
|
boost::get<CartesianMultiPolygon>(polygons_union).erase(
|
||||||
boost::get<Float64MultiPolygon>(polygons_union).begin());
|
boost::get<CartesianMultiPolygon>(polygons_union).begin());
|
||||||
|
|
||||||
serializer.add(polygons_union);
|
serializer.add(polygons_union);
|
||||||
}
|
}
|
||||||
|
|
||||||
block.getByPosition(result).column = std::move(serializer.finalize());
|
return serializer.finalize();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool useDefaultImplementationForConstants() const override
|
bool useDefaultImplementationForConstants() const override
|
||||||
|
@ -9,32 +9,32 @@ namespace {
|
|||||||
|
|
||||||
size_t getArrayDepth(DataTypePtr data_type, size_t max_depth)
|
size_t getArrayDepth(DataTypePtr data_type, size_t max_depth)
|
||||||
{
|
{
|
||||||
LOG_FATAL(&Poco::Logger::get("geoconv"), "getting depth");
|
|
||||||
size_t depth = 0;
|
size_t depth = 0;
|
||||||
while (data_type && isArray(data_type) && depth != max_depth + 1)
|
while (data_type && isArray(data_type) && depth != max_depth + 1)
|
||||||
{
|
{
|
||||||
depth++;
|
depth++;
|
||||||
data_type = static_cast<const DataTypeArray &>(*data_type).getNestedType();
|
data_type = static_cast<const DataTypeArray &>(*data_type).getNestedType();
|
||||||
}
|
}
|
||||||
LOG_FATAL(&Poco::Logger::get("geoconv"), "got depth");
|
|
||||||
|
|
||||||
return depth;
|
return depth;
|
||||||
}
|
}
|
||||||
|
|
||||||
class ContainerCreator : public boost::static_visitor<Float64Geometry>
|
template <typename Geometry>
|
||||||
|
class ContainerCreator : public boost::static_visitor<Geometry>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
template <class T>
|
template <class T>
|
||||||
Float64Geometry operator()(const T & parser) const
|
Geometry operator()(const T & parser) const
|
||||||
{
|
{
|
||||||
return parser.createContainer();
|
return parser.createContainer();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template <typename Geometry>
|
||||||
class Getter : public boost::static_visitor<void>
|
class Getter : public boost::static_visitor<void>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
constexpr Getter(Float64Geometry & container_, size_t i_)
|
constexpr Getter(Geometry & container_, size_t i_)
|
||||||
: container(container_)
|
: container(container_)
|
||||||
, i(i_)
|
, i(i_)
|
||||||
{}
|
{}
|
||||||
@ -46,7 +46,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Float64Geometry & container;
|
Geometry & container;
|
||||||
size_t i;
|
size_t i;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -64,26 +64,50 @@ Parser makeParser(const ColumnWithTypeAndName & col)
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
GeometryFromColumnParser makeGeometryFromColumnParser(const ColumnWithTypeAndName & col)
|
CartesianGeometryFromColumnParser makeCartesianGeometryFromColumnParser(const ColumnWithTypeAndName & col)
|
||||||
{
|
{
|
||||||
LOG_FATAL(&Poco::Logger::get("geoconv"), "Fine");
|
switch (getArrayDepth(col.type, 3))
|
||||||
switch (getArrayDepth(col.type, 3)) {
|
{
|
||||||
case 0: return makeParser<DataTypeCustomPointSerialization, Float64PointFromColumnParser>(col);
|
case 0: return makeParser<DataTypeCustomPointSerialization, PointFromColumnParser<CartesianPoint>>(col);
|
||||||
case 1: return makeParser<DataTypeCustomRingSerialization, Float64RingFromColumnParser>(col);
|
case 1: return makeParser<DataTypeCustomRingSerialization, CartesianRingFromColumnParser>(col);
|
||||||
case 2: return makeParser<DataTypeCustomPolygonSerialization, Float64PolygonFromColumnParser>(col);
|
case 2: return makeParser<DataTypeCustomPolygonSerialization, CartesianPolygonFromColumnParser>(col);
|
||||||
case 3: return makeParser<DataTypeCustomMultiPolygonSerialization, Float64MultiPolygonFromColumnParser>(col);
|
case 3: return makeParser<DataTypeCustomMultiPolygonSerialization, CartesianMultiPolygonFromColumnParser>(col);
|
||||||
default: throw Exception("Cannot parse geometry from column with type " + col.type->getName()
|
default: throw Exception("Cannot parse geometry from column with type " + col.type->getName()
|
||||||
+ ", array depth is too big", ErrorCodes::ILLEGAL_COLUMN);
|
+ ", array depth is too big", ErrorCodes::ILLEGAL_COLUMN);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Float64Geometry createContainer(const GeometryFromColumnParser & parser)
|
CartesianGeometry createContainer(const CartesianGeometryFromColumnParser & parser)
|
||||||
{
|
{
|
||||||
static ContainerCreator creator;
|
static ContainerCreator<CartesianGeometry> creator;
|
||||||
return boost::apply_visitor(creator, parser);
|
return boost::apply_visitor(creator, parser);
|
||||||
}
|
}
|
||||||
|
|
||||||
void get(const GeometryFromColumnParser & parser, Float64Geometry & container, size_t i)
|
void get(const CartesianGeometryFromColumnParser & parser, CartesianGeometry & container, size_t i)
|
||||||
|
{
|
||||||
|
boost::apply_visitor(Getter(container, i), parser);
|
||||||
|
}
|
||||||
|
|
||||||
|
GeographicGeometryFromColumnParser makeGeographicGeometryFromColumnParser(const ColumnWithTypeAndName & col)
|
||||||
|
{
|
||||||
|
switch (getArrayDepth(col.type, 3))
|
||||||
|
{
|
||||||
|
case 0: return makeParser<DataTypeCustomPointSerialization, PointFromColumnParser<GeographicPoint>>(col);
|
||||||
|
case 1: return makeParser<DataTypeCustomRingSerialization, GeographicRingFromColumnParser>(col);
|
||||||
|
case 2: return makeParser<DataTypeCustomPolygonSerialization, GeographicPolygonFromColumnParser>(col);
|
||||||
|
case 3: return makeParser<DataTypeCustomMultiPolygonSerialization, GeographicMultiPolygonFromColumnParser>(col);
|
||||||
|
default: throw Exception("Cannot parse geometry from column with type " + col.type->getName()
|
||||||
|
+ ", array depth is too big", ErrorCodes::ILLEGAL_COLUMN);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
GeographicGeometry createContainer(const GeographicGeometryFromColumnParser & parser)
|
||||||
|
{
|
||||||
|
static ContainerCreator<GeographicGeometry> creator;
|
||||||
|
return boost::apply_visitor(creator, parser);
|
||||||
|
}
|
||||||
|
|
||||||
|
void get(const GeographicGeometryFromColumnParser & parser, GeographicGeometry & container, size_t i)
|
||||||
{
|
{
|
||||||
boost::apply_visitor(Getter(container, i), parser);
|
boost::apply_visitor(Getter(container, i), parser);
|
||||||
}
|
}
|
||||||
|
@ -26,49 +26,89 @@ namespace ErrorCodes
|
|||||||
extern const int BAD_ARGUMENTS;
|
extern const int BAD_ARGUMENTS;
|
||||||
}
|
}
|
||||||
|
|
||||||
using Float64Point = boost::geometry::model::d2::point_xy<Float64>;
|
namespace bg = boost::geometry;
|
||||||
using Float64Ring = boost::geometry::model::ring<Float64Point>;
|
using CartesianPoint = bg::model::d2::point_xy<Float64>;
|
||||||
using Float64Polygon = boost::geometry::model::polygon<Float64Point>;
|
using CartesianRing = bg::model::ring<CartesianPoint>;
|
||||||
using Float64MultiPolygon = boost::geometry::model::multi_polygon<Float64Polygon>;
|
using CartesianPolygon = bg::model::polygon<CartesianPoint>;
|
||||||
using Float64Geometry = boost::variant<Float64Point, Float64Ring, Float64Polygon, Float64MultiPolygon>;
|
using CartesianMultiPolygon = bg::model::multi_polygon<CartesianPolygon>;
|
||||||
|
using CartesianGeometry = boost::variant<CartesianPoint, CartesianRing, CartesianPolygon, CartesianMultiPolygon>;
|
||||||
|
|
||||||
class Float64PointFromColumnParser
|
using GeographicPoint = bg::model::point<Float64, 2, bg::cs::geographic<bg::degree>>;
|
||||||
|
using GeographicRing = bg::model::ring<GeographicPoint>;
|
||||||
|
using GeographicPolygon = bg::model::polygon<GeographicPoint>;
|
||||||
|
using GeographicMultiPolygon = bg::model::multi_polygon<GeographicPolygon>;
|
||||||
|
using GeographicGeometry = boost::variant<GeographicPoint, GeographicRing, GeographicPolygon, GeographicMultiPolygon>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class which takes some boost type and returns a pair of numbers.
|
||||||
|
* They are (x,y) in case of cartesian coordinated and (lon,lat) in case of geographic.
|
||||||
|
*/
|
||||||
|
template <typename PointType>
|
||||||
|
class PointFromColumnParser
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Float64PointFromColumnParser(ColumnPtr col_)
|
PointFromColumnParser(ColumnPtr col_) : col(col_)
|
||||||
: col(col_)
|
|
||||||
{
|
{
|
||||||
const auto & tuple = static_cast<const ColumnTuple &>(*col_);
|
const auto & tuple = static_cast<const ColumnTuple &>(*col_);
|
||||||
const auto & tuple_columns = tuple.getColumns();
|
const auto & tuple_columns = tuple.getColumns();
|
||||||
|
|
||||||
|
#ifndef NDEBUG
|
||||||
|
size = tuple.size();
|
||||||
|
#endif
|
||||||
const auto & x_data = static_cast<const ColumnFloat64 &>(*tuple_columns[0]);
|
const auto & x_data = static_cast<const ColumnFloat64 &>(*tuple_columns[0]);
|
||||||
x = x_data.getData().data();
|
first = x_data.getData().data();
|
||||||
|
|
||||||
const auto & y_data = static_cast<const ColumnFloat64 &>(*tuple_columns[1]);
|
const auto & y_data = static_cast<const ColumnFloat64 &>(*tuple_columns[1]);
|
||||||
y = y_data.getData().data();
|
second = y_data.getData().data();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<class Q = PointType>
|
||||||
Float64Geometry createContainer() const
|
typename std::enable_if_t<std::is_same_v<Q, CartesianPoint>, CartesianGeometry> createContainer() const
|
||||||
{
|
{
|
||||||
return Float64Point();
|
return CartesianPoint();
|
||||||
}
|
}
|
||||||
|
|
||||||
void get(Float64Geometry & container, size_t i) const
|
template<class Q = PointType>
|
||||||
|
typename std::enable_if_t<std::is_same_v<Q, GeographicPoint>, GeographicGeometry> createContainer() const
|
||||||
{
|
{
|
||||||
get(boost::get<Float64Point>(container), i);
|
return GeographicPoint();
|
||||||
}
|
}
|
||||||
|
|
||||||
void get(Float64Point & container, size_t i) const
|
template<class Q = PointType>
|
||||||
|
void get(std::enable_if_t<std::is_same_v<Q, CartesianPoint>, CartesianGeometry> & container, size_t i) const
|
||||||
{
|
{
|
||||||
boost::geometry::set<0>(container, x[i]);
|
#ifndef NDEBUG
|
||||||
boost::geometry::set<1>(container, y[i]);
|
assert(i < size);
|
||||||
|
#endif
|
||||||
|
get(boost::get<PointType>(container), i);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<class Q = PointType>
|
||||||
|
void get(std::enable_if_t<std::is_same_v<Q, GeographicPoint>, GeographicGeometry> & container, size_t i) const
|
||||||
|
{
|
||||||
|
#ifndef NDEBUG
|
||||||
|
assert(i < size);
|
||||||
|
#endif
|
||||||
|
get(boost::get<PointType>(container), i);
|
||||||
|
}
|
||||||
|
|
||||||
|
void get(PointType & container, size_t i) const
|
||||||
|
{
|
||||||
|
#ifndef NDEBUG
|
||||||
|
assert(i < size);
|
||||||
|
#endif
|
||||||
|
boost::geometry::set<0>(container, first[i]);
|
||||||
|
boost::geometry::set<1>(container, second[i]);
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
/// Note, this is needed to prevent use-after-free.
|
||||||
ColumnPtr col;
|
ColumnPtr col;
|
||||||
|
#ifndef NDEBUG
|
||||||
const Float64 * x;
|
size_t size;
|
||||||
const Float64 * y;
|
#endif
|
||||||
|
const Float64 * first;
|
||||||
|
const Float64 * second;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<class Geometry, class RingType, class PointParser>
|
template<class Geometry, class RingType, class PointParser>
|
||||||
@ -142,8 +182,6 @@ public:
|
|||||||
|
|
||||||
ringParser.get(container.outer(), l);
|
ringParser.get(container.outer(), l);
|
||||||
|
|
||||||
LOG_FATAL(&Poco::Logger::get("geoconv"), "polygon: l = {}, r = {}", l, r);
|
|
||||||
|
|
||||||
container.inners().resize(r - l - 1);
|
container.inners().resize(r - l - 1);
|
||||||
for (size_t j = l + 1; j < r; j++)
|
for (size_t j = l + 1; j < r; j++)
|
||||||
{
|
{
|
||||||
@ -176,8 +214,6 @@ public:
|
|||||||
size_t l = offsets[i - 1];
|
size_t l = offsets[i - 1];
|
||||||
size_t r = offsets[i];
|
size_t r = offsets[i];
|
||||||
|
|
||||||
LOG_FATAL(&Poco::Logger::get("geoconv"), "multipolygon: l = {}, r = {}", l, r);
|
|
||||||
|
|
||||||
multi_polygon.resize(r - l);
|
multi_polygon.resize(r - l);
|
||||||
for (size_t j = l; j < r; j++)
|
for (size_t j = l; j < r; j++)
|
||||||
{
|
{
|
||||||
@ -190,43 +226,65 @@ private:
|
|||||||
const PolygonParser polygonParser;
|
const PolygonParser polygonParser;
|
||||||
};
|
};
|
||||||
|
|
||||||
using Float64RingFromColumnParser = RingFromColumnParser<Float64Geometry, Float64Ring, Float64PointFromColumnParser>;
|
/// Cartesian coordinates
|
||||||
using Float64PolygonFromColumnParser = PolygonFromColumnParser<Float64Geometry, Float64Polygon, Float64RingFromColumnParser>;
|
|
||||||
using Float64MultiPolygonFromColumnParser = MultiPolygonFromColumnParser<Float64Geometry, Float64MultiPolygon, Float64PolygonFromColumnParser>;
|
|
||||||
|
|
||||||
using GeometryFromColumnParser = boost::variant<
|
using CartesianRingFromColumnParser = RingFromColumnParser<CartesianGeometry, CartesianRing, PointFromColumnParser<CartesianPoint>>;
|
||||||
Float64PointFromColumnParser,
|
using CartesianPolygonFromColumnParser = PolygonFromColumnParser<CartesianGeometry, CartesianPolygon, CartesianRingFromColumnParser>;
|
||||||
Float64RingFromColumnParser,
|
using CartesianMultiPolygonFromColumnParser = MultiPolygonFromColumnParser<CartesianGeometry, CartesianMultiPolygon, CartesianPolygonFromColumnParser>;
|
||||||
Float64PolygonFromColumnParser,
|
|
||||||
Float64MultiPolygonFromColumnParser
|
using CartesianGeometryFromColumnParser = boost::variant<
|
||||||
|
PointFromColumnParser<CartesianPoint>,
|
||||||
|
CartesianRingFromColumnParser,
|
||||||
|
CartesianPolygonFromColumnParser,
|
||||||
|
CartesianMultiPolygonFromColumnParser
|
||||||
>;
|
>;
|
||||||
|
|
||||||
Float64Geometry createContainer(const GeometryFromColumnParser & parser);
|
CartesianGeometry createContainer(const CartesianGeometryFromColumnParser & parser);
|
||||||
|
|
||||||
void get(const GeometryFromColumnParser & parser, Float64Geometry & container, size_t i);
|
void get(const CartesianGeometryFromColumnParser & parser, CartesianGeometry & container, size_t i);
|
||||||
|
|
||||||
GeometryFromColumnParser makeGeometryFromColumnParser(const ColumnWithTypeAndName & col);
|
CartesianGeometryFromColumnParser makeCartesianGeometryFromColumnParser(const ColumnWithTypeAndName & col);
|
||||||
|
|
||||||
class Float64PointSerializerVisitor : public boost::static_visitor<void>
|
/// Geographic coordinates
|
||||||
|
|
||||||
|
using GeographicRingFromColumnParser = RingFromColumnParser<GeographicGeometry, GeographicRing, PointFromColumnParser<GeographicPoint>>;
|
||||||
|
using GeographicPolygonFromColumnParser = PolygonFromColumnParser<GeographicGeometry, GeographicPolygon, GeographicRingFromColumnParser>;
|
||||||
|
using GeographicMultiPolygonFromColumnParser = MultiPolygonFromColumnParser<GeographicGeometry, GeographicMultiPolygon, GeographicPolygonFromColumnParser>;
|
||||||
|
|
||||||
|
using GeographicGeometryFromColumnParser = boost::variant<
|
||||||
|
PointFromColumnParser<GeographicPoint>,
|
||||||
|
GeographicRingFromColumnParser,
|
||||||
|
GeographicPolygonFromColumnParser,
|
||||||
|
GeographicMultiPolygonFromColumnParser
|
||||||
|
>;
|
||||||
|
|
||||||
|
GeographicGeometry createContainer(const GeographicGeometryFromColumnParser & parser);
|
||||||
|
|
||||||
|
void get(const GeographicGeometryFromColumnParser & parser, GeographicGeometry & container, size_t i);
|
||||||
|
|
||||||
|
GeographicGeometryFromColumnParser makeGeographicGeometryFromColumnParser(const ColumnWithTypeAndName & col);
|
||||||
|
|
||||||
|
|
||||||
|
class CartesianPointSerializerVisitor : public boost::static_visitor<void>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Float64PointSerializerVisitor()
|
CartesianPointSerializerVisitor()
|
||||||
: x(ColumnFloat64::create())
|
: x(ColumnFloat64::create())
|
||||||
, y(ColumnFloat64::create())
|
, y(ColumnFloat64::create())
|
||||||
{}
|
{}
|
||||||
|
|
||||||
Float64PointSerializerVisitor(size_t n)
|
CartesianPointSerializerVisitor(size_t n)
|
||||||
: x(ColumnFloat64::create(n))
|
: x(ColumnFloat64::create(n))
|
||||||
, y(ColumnFloat64::create(n))
|
, y(ColumnFloat64::create(n))
|
||||||
{}
|
{}
|
||||||
|
|
||||||
void operator()(const Float64Point & point)
|
void operator()(const CartesianPoint & point)
|
||||||
{
|
{
|
||||||
x->insertValue(point.x());
|
x->insertValue(point.get<0>());
|
||||||
y->insertValue(point.y());
|
y->insertValue(point.get<0>());
|
||||||
}
|
}
|
||||||
|
|
||||||
void operator()(const Float64Ring & ring)
|
void operator()(const CartesianRing & ring)
|
||||||
{
|
{
|
||||||
if (ring.size() != 1) {
|
if (ring.size() != 1) {
|
||||||
throw Exception("Unable to write ring of size " + toString(ring.size()) + " != 1 to point column", ErrorCodes::BAD_ARGUMENTS);
|
throw Exception("Unable to write ring of size " + toString(ring.size()) + " != 1 to point column", ErrorCodes::BAD_ARGUMENTS);
|
||||||
@ -234,7 +292,7 @@ public:
|
|||||||
(*this)(ring[0]);
|
(*this)(ring[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
void operator()(const Float64Polygon & polygon)
|
void operator()(const CartesianPolygon & polygon)
|
||||||
{
|
{
|
||||||
if (polygon.inners().size() != 0) {
|
if (polygon.inners().size() != 0) {
|
||||||
throw Exception("Unable to write polygon with holes to point column", ErrorCodes::BAD_ARGUMENTS);
|
throw Exception("Unable to write polygon with holes to point column", ErrorCodes::BAD_ARGUMENTS);
|
||||||
@ -242,7 +300,7 @@ public:
|
|||||||
(*this)(polygon.outer());
|
(*this)(polygon.outer());
|
||||||
}
|
}
|
||||||
|
|
||||||
void operator()(const Float64MultiPolygon & multi_polygon)
|
void operator()(const CartesianMultiPolygon & multi_polygon)
|
||||||
{
|
{
|
||||||
if (multi_polygon.size() != 1) {
|
if (multi_polygon.size() != 1) {
|
||||||
throw Exception("Unable to write multi-polygon of size " + toString(multi_polygon.size()) + " != 1 to point column", ErrorCodes::BAD_ARGUMENTS);
|
throw Exception("Unable to write multi-polygon of size " + toString(multi_polygon.size()) + " != 1 to point column", ErrorCodes::BAD_ARGUMENTS);
|
||||||
@ -264,18 +322,18 @@ private:
|
|||||||
ColumnFloat64::MutablePtr y;
|
ColumnFloat64::MutablePtr y;
|
||||||
};
|
};
|
||||||
|
|
||||||
class Float64RingSerializerVisitor : public boost::static_visitor<void>
|
class CartesianRingSerializerVisitor : public boost::static_visitor<void>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Float64RingSerializerVisitor()
|
CartesianRingSerializerVisitor()
|
||||||
: offsets(ColumnUInt64::create())
|
: offsets(ColumnUInt64::create())
|
||||||
{}
|
{}
|
||||||
|
|
||||||
Float64RingSerializerVisitor(size_t n)
|
CartesianRingSerializerVisitor(size_t n)
|
||||||
: offsets(ColumnUInt64::create(n))
|
: offsets(ColumnUInt64::create(n))
|
||||||
{}
|
{}
|
||||||
|
|
||||||
void operator()(const Float64Point & point)
|
void operator()(const CartesianPoint & point)
|
||||||
{
|
{
|
||||||
size++;
|
size++;
|
||||||
offsets->insertValue(size);
|
offsets->insertValue(size);
|
||||||
@ -283,7 +341,7 @@ public:
|
|||||||
pointSerializer(point);
|
pointSerializer(point);
|
||||||
}
|
}
|
||||||
|
|
||||||
void operator()(const Float64Ring & ring)
|
void operator()(const CartesianRing & ring)
|
||||||
{
|
{
|
||||||
size += ring.size();
|
size += ring.size();
|
||||||
offsets->insertValue(size);
|
offsets->insertValue(size);
|
||||||
@ -293,7 +351,7 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void operator()(const Float64Polygon & polygon)
|
void operator()(const CartesianPolygon & polygon)
|
||||||
{
|
{
|
||||||
if (polygon.inners().size() != 0) {
|
if (polygon.inners().size() != 0) {
|
||||||
throw Exception("Unable to write polygon with holes to ring column", ErrorCodes::BAD_ARGUMENTS);
|
throw Exception("Unable to write polygon with holes to ring column", ErrorCodes::BAD_ARGUMENTS);
|
||||||
@ -301,7 +359,7 @@ public:
|
|||||||
(*this)(polygon.outer());
|
(*this)(polygon.outer());
|
||||||
}
|
}
|
||||||
|
|
||||||
void operator()(const Float64MultiPolygon & multi_polygon)
|
void operator()(const CartesianMultiPolygon & multi_polygon)
|
||||||
{
|
{
|
||||||
if (multi_polygon.size() != 1) {
|
if (multi_polygon.size() != 1) {
|
||||||
throw Exception("Unable to write multi-polygon of size " + toString(multi_polygon.size()) + " != 1 to ring column", ErrorCodes::BAD_ARGUMENTS);
|
throw Exception("Unable to write multi-polygon of size " + toString(multi_polygon.size()) + " != 1 to ring column", ErrorCodes::BAD_ARGUMENTS);
|
||||||
@ -316,36 +374,36 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
size_t size = 0;
|
size_t size = 0;
|
||||||
Float64PointSerializerVisitor pointSerializer;
|
CartesianPointSerializerVisitor pointSerializer;
|
||||||
ColumnUInt64::MutablePtr offsets;
|
ColumnUInt64::MutablePtr offsets;
|
||||||
};
|
};
|
||||||
|
|
||||||
class Float64PolygonSerializerVisitor : public boost::static_visitor<void>
|
class CartesianPolygonSerializerVisitor : public boost::static_visitor<void>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Float64PolygonSerializerVisitor()
|
CartesianPolygonSerializerVisitor()
|
||||||
: offsets(ColumnUInt64::create())
|
: offsets(ColumnUInt64::create())
|
||||||
{}
|
{}
|
||||||
|
|
||||||
Float64PolygonSerializerVisitor(size_t n)
|
CartesianPolygonSerializerVisitor(size_t n)
|
||||||
: offsets(ColumnUInt64::create(n))
|
: offsets(ColumnUInt64::create(n))
|
||||||
{}
|
{}
|
||||||
|
|
||||||
void operator()(const Float64Point & point)
|
void operator()(const CartesianPoint & point)
|
||||||
{
|
{
|
||||||
size++;
|
size++;
|
||||||
offsets->insertValue(size);
|
offsets->insertValue(size);
|
||||||
ringSerializer(point);
|
ringSerializer(point);
|
||||||
}
|
}
|
||||||
|
|
||||||
void operator()(const Float64Ring & ring)
|
void operator()(const CartesianRing & ring)
|
||||||
{
|
{
|
||||||
size++;
|
size++;
|
||||||
offsets->insertValue(size);
|
offsets->insertValue(size);
|
||||||
ringSerializer(ring);
|
ringSerializer(ring);
|
||||||
}
|
}
|
||||||
|
|
||||||
void operator()(const Float64Polygon & polygon)
|
void operator()(const CartesianPolygon & polygon)
|
||||||
{
|
{
|
||||||
size += 1 + polygon.inners().size();
|
size += 1 + polygon.inners().size();
|
||||||
offsets->insertValue(size);
|
offsets->insertValue(size);
|
||||||
@ -356,7 +414,7 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void operator()(const Float64MultiPolygon & multi_polygon)
|
void operator()(const CartesianMultiPolygon & multi_polygon)
|
||||||
{
|
{
|
||||||
if (multi_polygon.size() != 1) {
|
if (multi_polygon.size() != 1) {
|
||||||
throw Exception("Unable to write multi-polygon of size " + toString(multi_polygon.size()) + " != 1 to polygon column", ErrorCodes::BAD_ARGUMENTS);
|
throw Exception("Unable to write multi-polygon of size " + toString(multi_polygon.size()) + " != 1 to polygon column", ErrorCodes::BAD_ARGUMENTS);
|
||||||
@ -371,43 +429,43 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
size_t size = 0;
|
size_t size = 0;
|
||||||
Float64RingSerializerVisitor ringSerializer;
|
CartesianRingSerializerVisitor ringSerializer;
|
||||||
ColumnUInt64::MutablePtr offsets;
|
ColumnUInt64::MutablePtr offsets;
|
||||||
};
|
};
|
||||||
|
|
||||||
class Float64MultiPolygonSerializerVisitor : public boost::static_visitor<void>
|
class CartesianMultiPolygonSerializerVisitor : public boost::static_visitor<void>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Float64MultiPolygonSerializerVisitor()
|
CartesianMultiPolygonSerializerVisitor()
|
||||||
: offsets(ColumnUInt64::create())
|
: offsets(ColumnUInt64::create())
|
||||||
{}
|
{}
|
||||||
|
|
||||||
Float64MultiPolygonSerializerVisitor(size_t n)
|
CartesianMultiPolygonSerializerVisitor(size_t n)
|
||||||
: offsets(ColumnUInt64::create(n))
|
: offsets(ColumnUInt64::create(n))
|
||||||
{}
|
{}
|
||||||
|
|
||||||
void operator()(const Float64Point & point)
|
void operator()(const CartesianPoint & point)
|
||||||
{
|
{
|
||||||
size++;
|
size++;
|
||||||
offsets->insertValue(size);
|
offsets->insertValue(size);
|
||||||
polygonSerializer(point);
|
polygonSerializer(point);
|
||||||
}
|
}
|
||||||
|
|
||||||
void operator()(const Float64Ring & ring)
|
void operator()(const CartesianRing & ring)
|
||||||
{
|
{
|
||||||
size++;
|
size++;
|
||||||
offsets->insertValue(size);
|
offsets->insertValue(size);
|
||||||
polygonSerializer(ring);
|
polygonSerializer(ring);
|
||||||
}
|
}
|
||||||
|
|
||||||
void operator()(const Float64Polygon & polygon)
|
void operator()(const CartesianPolygon & polygon)
|
||||||
{
|
{
|
||||||
size++;
|
size++;
|
||||||
offsets->insertValue(size);
|
offsets->insertValue(size);
|
||||||
polygonSerializer(polygon);
|
polygonSerializer(polygon);
|
||||||
}
|
}
|
||||||
|
|
||||||
void operator()(const Float64MultiPolygon & multi_polygon)
|
void operator()(const CartesianMultiPolygon & multi_polygon)
|
||||||
{
|
{
|
||||||
size += multi_polygon.size();
|
size += multi_polygon.size();
|
||||||
offsets->insertValue(size);
|
offsets->insertValue(size);
|
||||||
@ -424,7 +482,7 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
size_t size = 0;
|
size_t size = 0;
|
||||||
Float64PolygonSerializerVisitor polygonSerializer;
|
CartesianPolygonSerializerVisitor polygonSerializer;
|
||||||
ColumnUInt64::MutablePtr offsets;
|
ColumnUInt64::MutablePtr offsets;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -445,9 +503,9 @@ private:
|
|||||||
Visitor visitor;
|
Visitor visitor;
|
||||||
};
|
};
|
||||||
|
|
||||||
using Float64PointSerializer = GeometrySerializer<Float64Geometry, Float64PointSerializerVisitor>;
|
using CartesianPointSerializer = GeometrySerializer<CartesianGeometry, CartesianPointSerializerVisitor>;
|
||||||
using Float64RingSerializer = GeometrySerializer<Float64Geometry, Float64RingSerializerVisitor>;
|
using CartesianRingSerializer = GeometrySerializer<CartesianGeometry, CartesianRingSerializerVisitor>;
|
||||||
using Float64PolygonSerializer = GeometrySerializer<Float64Geometry, Float64PolygonSerializerVisitor>;
|
using CartesianPolygonSerializer = GeometrySerializer<CartesianGeometry, CartesianPolygonSerializerVisitor>;
|
||||||
using Float64MultiPolygonSerializer = GeometrySerializer<Float64Geometry, Float64MultiPolygonSerializerVisitor>;
|
using CartesianMultiPolygonSerializer = GeometrySerializer<CartesianGeometry, CartesianMultiPolygonSerializerVisitor>;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -28,24 +28,17 @@ namespace ErrorCodes
|
|||||||
extern const int ILLEGAL_COLUMN;
|
extern const int ILLEGAL_COLUMN;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename Derived>
|
||||||
using CoordinateType = Float64;
|
class FunctionPolygonAreaBase : public IFunction
|
||||||
using Point = boost::geometry::model::d2::point_xy<CoordinateType>;
|
|
||||||
using Polygon = boost::geometry::model::polygon<Point, false>;
|
|
||||||
using MultiPolygon = boost::geometry::model::multi_polygon<Float64Polygon>;
|
|
||||||
using Box = boost::geometry::model::box<Point>;
|
|
||||||
|
|
||||||
|
|
||||||
class FunctionPolygonArea : public IFunction
|
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
static inline const char * name = "polygonArea";
|
static inline const char * name = Derived::name;
|
||||||
|
|
||||||
explicit FunctionPolygonArea() = default;
|
explicit FunctionPolygonAreaBase() = default;
|
||||||
|
|
||||||
static FunctionPtr create(const Context &)
|
static FunctionPtr create(const Context &)
|
||||||
{
|
{
|
||||||
return std::make_shared<FunctionPolygonArea>();
|
return std::make_shared<FunctionPolygonAreaBase>();
|
||||||
}
|
}
|
||||||
|
|
||||||
String getName() const override
|
String getName() const override
|
||||||
@ -68,29 +61,9 @@ public:
|
|||||||
return std::make_shared<DataTypeFloat64>();
|
return std::make_shared<DataTypeFloat64>();
|
||||||
}
|
}
|
||||||
|
|
||||||
void executeImpl(Block & block, const ColumnNumbers & arguments, size_t result, size_t input_rows_count) override
|
ColumnPtr executeImpl(const ColumnsWithTypeAndName & arguments, const DataTypePtr & result_type, size_t input_rows_count) const override
|
||||||
{
|
{
|
||||||
auto get_parser = [&block, &arguments] (size_t i) {
|
return static_cast<const Derived*>(this)->executeImplementation(arguments, result_type, input_rows_count);
|
||||||
const ColumnWithTypeAndName polygon = block.getByPosition(arguments[i]);
|
|
||||||
return makeGeometryFromColumnParser(polygon);
|
|
||||||
};
|
|
||||||
|
|
||||||
auto parser = get_parser(0);
|
|
||||||
auto container = createContainer(parser);
|
|
||||||
|
|
||||||
auto res_column = ColumnFloat64::create();
|
|
||||||
|
|
||||||
for (size_t i = 0; i < input_rows_count; i++)
|
|
||||||
{
|
|
||||||
get(parser, container, i);
|
|
||||||
|
|
||||||
Float64 area = boost::geometry::area(
|
|
||||||
boost::get<Float64MultiPolygon>(container));
|
|
||||||
|
|
||||||
res_column->insertValue(area);
|
|
||||||
}
|
|
||||||
|
|
||||||
block.getByPosition(result).column = std::move(res_column);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool useDefaultImplementationForConstants() const override
|
bool useDefaultImplementationForConstants() const override
|
||||||
@ -100,9 +73,67 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
void registerFunctionPolygonArea(FunctionFactory & factory)
|
class FunctionPolygonAreaCartesian : public FunctionPolygonAreaBase<FunctionPolygonAreaCartesian>
|
||||||
{
|
{
|
||||||
factory.registerFunction<FunctionPolygonArea>();
|
public:
|
||||||
|
static inline const char * name = "polygonAreaCartesian";
|
||||||
|
|
||||||
|
ColumnPtr executeImplementation(const ColumnsWithTypeAndName & arguments, const DataTypePtr & /*result_type*/, size_t input_rows_count) const
|
||||||
|
{
|
||||||
|
auto parser = makeCartesianGeometryFromColumnParser(arguments[0]);
|
||||||
|
auto container = createContainer(parser);
|
||||||
|
|
||||||
|
auto res_column = ColumnFloat64::create();
|
||||||
|
|
||||||
|
for (size_t i = 0; i < input_rows_count; i++)
|
||||||
|
{
|
||||||
|
get(parser, container, i);
|
||||||
|
|
||||||
|
Float64 area = boost::geometry::area(
|
||||||
|
boost::get<CartesianMultiPolygon>(container));
|
||||||
|
|
||||||
|
res_column->insertValue(area);
|
||||||
|
}
|
||||||
|
|
||||||
|
return res_column;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class FunctionPolygonAreaGeographic : public FunctionPolygonAreaBase<FunctionPolygonAreaGeographic>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static inline const char * name = "polygonAreaGeographic";
|
||||||
|
|
||||||
|
ColumnPtr executeImplementation(const ColumnsWithTypeAndName & arguments, const DataTypePtr & /*result_type*/, size_t input_rows_count) const
|
||||||
|
{
|
||||||
|
auto parser = makeGeographicGeometryFromColumnParser(arguments[0]);
|
||||||
|
auto container = createContainer(parser);
|
||||||
|
|
||||||
|
auto res_column = ColumnFloat64::create();
|
||||||
|
|
||||||
|
for (size_t i = 0; i < input_rows_count; i++)
|
||||||
|
{
|
||||||
|
get(parser, container, i);
|
||||||
|
|
||||||
|
Float64 area = boost::geometry::area(
|
||||||
|
boost::get<GeographicMultiPolygon>(container));
|
||||||
|
|
||||||
|
res_column->insertValue(area);
|
||||||
|
}
|
||||||
|
|
||||||
|
return res_column;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
void registerFunctionPolygonAreaCartesian(FunctionFactory & factory)
|
||||||
|
{
|
||||||
|
factory.registerFunction<FunctionPolygonAreaCartesian>();
|
||||||
|
}
|
||||||
|
|
||||||
|
void registerFunctionPolygonAreaGeographic(FunctionFactory & factory)
|
||||||
|
{
|
||||||
|
factory.registerFunction<FunctionPolygonAreaGeographic>();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -28,14 +28,6 @@ namespace ErrorCodes
|
|||||||
extern const int ILLEGAL_COLUMN;
|
extern const int ILLEGAL_COLUMN;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
using CoordinateType = Float64;
|
|
||||||
using Point = boost::geometry::model::d2::point_xy<CoordinateType>;
|
|
||||||
using Polygon = boost::geometry::model::polygon<Point, false>;
|
|
||||||
using MultiPolygon = boost::geometry::model::multi_polygon<Float64Polygon>;
|
|
||||||
using Box = boost::geometry::model::box<Point>;
|
|
||||||
|
|
||||||
|
|
||||||
class FunctionPolygonConvexHull : public IFunction
|
class FunctionPolygonConvexHull : public IFunction
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@ -68,34 +60,34 @@ public:
|
|||||||
return DataTypeCustomPolygonSerialization::nestedDataType();
|
return DataTypeCustomPolygonSerialization::nestedDataType();
|
||||||
}
|
}
|
||||||
|
|
||||||
void executeImpl(Block & block, const ColumnNumbers & arguments, size_t result, size_t input_rows_count) override
|
ColumnPtr executeImpl(const ColumnsWithTypeAndName & arguments, const DataTypePtr & /*result_type*/, size_t input_rows_count) const override
|
||||||
{
|
{
|
||||||
auto get_parser = [&block, &arguments] (size_t i) {
|
auto get_parser = [&arguments] (size_t i) {
|
||||||
const ColumnWithTypeAndName polygon = block.getByPosition(arguments[i]);
|
const ColumnWithTypeAndName polygon = arguments[i];
|
||||||
return makeGeometryFromColumnParser(polygon);
|
return makeCartesianGeometryFromColumnParser(polygon);
|
||||||
};
|
};
|
||||||
|
|
||||||
auto parser = get_parser(0);
|
auto parser = get_parser(0);
|
||||||
auto container = createContainer(parser);
|
auto container = createContainer(parser);
|
||||||
|
|
||||||
Float64PolygonSerializer serializer;
|
CartesianPolygonSerializer serializer;
|
||||||
|
|
||||||
for (size_t i = 0; i < input_rows_count; i++)
|
for (size_t i = 0; i < input_rows_count; i++)
|
||||||
{
|
{
|
||||||
get(parser, container, i);
|
get(parser, container, i);
|
||||||
|
|
||||||
Float64Geometry convex_hull = Float64Polygon({{{}}});
|
CartesianGeometry convex_hull = CartesianPolygon({{{}}});
|
||||||
boost::geometry::convex_hull(
|
boost::geometry::convex_hull(
|
||||||
boost::get<Float64MultiPolygon>(container),
|
boost::get<CartesianMultiPolygon>(container),
|
||||||
boost::get<Float64Polygon>(convex_hull));
|
boost::get<CartesianPolygon>(convex_hull));
|
||||||
|
|
||||||
boost::get<Float64Polygon>(convex_hull).outer().erase(
|
boost::get<CartesianPolygon>(convex_hull).outer().erase(
|
||||||
boost::get<Float64Polygon>(convex_hull).outer().begin());
|
boost::get<CartesianPolygon>(convex_hull).outer().begin());
|
||||||
|
|
||||||
serializer.add(convex_hull);
|
serializer.add(convex_hull);
|
||||||
}
|
}
|
||||||
|
|
||||||
block.getByPosition(result).column = std::move(serializer.finalize());
|
return serializer.finalize();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool useDefaultImplementationForConstants() const override
|
bool useDefaultImplementationForConstants() const override
|
||||||
|
@ -28,24 +28,17 @@ namespace ErrorCodes
|
|||||||
extern const int ILLEGAL_COLUMN;
|
extern const int ILLEGAL_COLUMN;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename Derived>
|
||||||
using CoordinateType = Float64;
|
class FunctionPolygonPerimeterBase : public IFunction
|
||||||
using Point = boost::geometry::model::d2::point_xy<CoordinateType>;
|
|
||||||
using Polygon = boost::geometry::model::polygon<Point, false>;
|
|
||||||
using MultiPolygon = boost::geometry::model::multi_polygon<Float64Polygon>;
|
|
||||||
using Box = boost::geometry::model::box<Point>;
|
|
||||||
|
|
||||||
|
|
||||||
class FunctionPolygonPerimeter : public IFunction
|
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
static inline const char * name = "polygonPerimeter";
|
static inline const char * name = Derived::name;
|
||||||
|
|
||||||
explicit FunctionPolygonPerimeter() = default;
|
explicit FunctionPolygonPerimeterBase() = default;
|
||||||
|
|
||||||
static FunctionPtr create(const Context &)
|
static FunctionPtr create(const Context &)
|
||||||
{
|
{
|
||||||
return std::make_shared<FunctionPolygonPerimeter>();
|
return std::make_shared<FunctionPolygonPerimeterBase>();
|
||||||
}
|
}
|
||||||
|
|
||||||
String getName() const override
|
String getName() const override
|
||||||
@ -68,14 +61,25 @@ public:
|
|||||||
return std::make_shared<DataTypeFloat64>();
|
return std::make_shared<DataTypeFloat64>();
|
||||||
}
|
}
|
||||||
|
|
||||||
void executeImpl(Block & block, const ColumnNumbers & arguments, size_t result, size_t input_rows_count) override
|
ColumnPtr executeImpl(const ColumnsWithTypeAndName & arguments, const DataTypePtr & result_type, size_t input_rows_count) const override
|
||||||
{
|
{
|
||||||
auto get_parser = [&block, &arguments] (size_t i) {
|
return static_cast<const Derived*>(this)->executeImplementation(arguments, result_type, input_rows_count);
|
||||||
const ColumnWithTypeAndName polygon = block.getByPosition(arguments[i]);
|
}
|
||||||
return makeGeometryFromColumnParser(polygon);
|
|
||||||
};
|
|
||||||
|
|
||||||
auto parser = get_parser(0);
|
bool useDefaultImplementationForConstants() const override
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class FunctionPolygonPerimeterCartesian : public FunctionPolygonPerimeterBase<FunctionPolygonPerimeterCartesian>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static inline const char * name = "polygonPerimeterCartesian";
|
||||||
|
|
||||||
|
ColumnPtr executeImplementation(const ColumnsWithTypeAndName & arguments, const DataTypePtr & /*result_type*/, size_t input_rows_count) const
|
||||||
|
{
|
||||||
|
auto parser = makeCartesianGeometryFromColumnParser(arguments[0]);
|
||||||
auto container = createContainer(parser);
|
auto container = createContainer(parser);
|
||||||
|
|
||||||
auto res_column = ColumnFloat64::create();
|
auto res_column = ColumnFloat64::create();
|
||||||
@ -85,24 +89,52 @@ public:
|
|||||||
get(parser, container, i);
|
get(parser, container, i);
|
||||||
|
|
||||||
Float64 perimeter = boost::geometry::perimeter(
|
Float64 perimeter = boost::geometry::perimeter(
|
||||||
boost::get<Float64MultiPolygon>(container));
|
boost::get<CartesianMultiPolygon>(container));
|
||||||
|
|
||||||
res_column->insertValue(perimeter);
|
res_column->insertValue(perimeter);
|
||||||
}
|
}
|
||||||
|
|
||||||
block.getByPosition(result).column = std::move(res_column);
|
return res_column;
|
||||||
}
|
|
||||||
|
|
||||||
bool useDefaultImplementationForConstants() const override
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
void registerFunctionPolygonPerimeter(FunctionFactory & factory)
|
class FunctionPolygonPerimeterGeographic : public FunctionPolygonPerimeterBase<FunctionPolygonPerimeterGeographic>
|
||||||
{
|
{
|
||||||
factory.registerFunction<FunctionPolygonPerimeter>();
|
public:
|
||||||
|
static inline const char * name = "polygonPerimeterGeographic";
|
||||||
|
|
||||||
|
ColumnPtr executeImplementation(const ColumnsWithTypeAndName & arguments, const DataTypePtr & /*result_type*/, size_t input_rows_count) const
|
||||||
|
{
|
||||||
|
auto parser = makeGeographicGeometryFromColumnParser(arguments[0]);
|
||||||
|
auto container = createContainer(parser);
|
||||||
|
|
||||||
|
auto res_column = ColumnFloat64::create();
|
||||||
|
|
||||||
|
for (size_t i = 0; i < input_rows_count; i++)
|
||||||
|
{
|
||||||
|
get(parser, container, i);
|
||||||
|
|
||||||
|
Float64 perimeter = boost::geometry::perimeter(
|
||||||
|
boost::get<GeographicMultiPolygon>(container));
|
||||||
|
|
||||||
|
res_column->insertValue(perimeter);
|
||||||
|
}
|
||||||
|
|
||||||
|
return res_column;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void registerFunctionPolygonPerimeterCartesian(FunctionFactory & factory)
|
||||||
|
{
|
||||||
|
factory.registerFunction<FunctionPolygonPerimeterCartesian>();
|
||||||
|
}
|
||||||
|
|
||||||
|
void registerFunctionPolygonPerimeterGeographic(FunctionFactory & factory)
|
||||||
|
{
|
||||||
|
factory.registerFunction<FunctionPolygonPerimeterGeographic>();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -30,24 +30,17 @@ namespace ErrorCodes
|
|||||||
extern const int ILLEGAL_COLUMN;
|
extern const int ILLEGAL_COLUMN;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename Derived>
|
||||||
using CoordinateType = Float64;
|
class FunctionPolygonsDistanceBase : public IFunction
|
||||||
using Point = boost::geometry::model::d2::point_xy<CoordinateType>;
|
|
||||||
using Polygon = boost::geometry::model::polygon<Point, false>;
|
|
||||||
using MultiPolygon = boost::geometry::model::multi_polygon<Float64Polygon>;
|
|
||||||
using Box = boost::geometry::model::box<Point>;
|
|
||||||
|
|
||||||
|
|
||||||
class FunctionPolygonsDistance : public IFunction
|
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
static inline const char * name = "polygonsDistance";
|
static inline const char * name = Derived::name;
|
||||||
|
|
||||||
explicit FunctionPolygonsDistance() = default;
|
explicit FunctionPolygonsDistanceBase() = default;
|
||||||
|
|
||||||
static FunctionPtr create(const Context &)
|
static FunctionPtr create(const Context &)
|
||||||
{
|
{
|
||||||
return std::make_shared<FunctionPolygonsDistance>();
|
return std::make_shared<FunctionPolygonsDistanceBase>();
|
||||||
}
|
}
|
||||||
|
|
||||||
String getName() const override
|
String getName() const override
|
||||||
@ -70,42 +63,9 @@ public:
|
|||||||
return std::make_shared<DataTypeFloat64>();
|
return std::make_shared<DataTypeFloat64>();
|
||||||
}
|
}
|
||||||
|
|
||||||
void executeImpl(Block & block, const ColumnNumbers & arguments, size_t result, size_t input_rows_count) override
|
ColumnPtr executeImpl(const ColumnsWithTypeAndName & arguments, const DataTypePtr & result_type, size_t input_rows_count) const override
|
||||||
{
|
{
|
||||||
auto get_parser = [&block, &arguments] (size_t i) {
|
return static_cast<const Derived*>(this)->executeImplementation(arguments, result_type, input_rows_count);
|
||||||
const auto * const_col =
|
|
||||||
checkAndGetColumn<ColumnConst>(block.getByPosition(arguments[i]).column.get());
|
|
||||||
|
|
||||||
bool is_const = static_cast<bool>(const_col);
|
|
||||||
|
|
||||||
return std::pair<bool, GeometryFromColumnParser>{is_const, is_const ?
|
|
||||||
makeGeometryFromColumnParser(ColumnWithTypeAndName(const_col->getDataColumnPtr(), block.getByPosition(arguments[i]).type, block.getByPosition(arguments[i]).name)) :
|
|
||||||
makeGeometryFromColumnParser(block.getByPosition(arguments[i]))};
|
|
||||||
};
|
|
||||||
|
|
||||||
auto [is_first_polygon_const, first_parser] = get_parser(0);
|
|
||||||
auto first_container = createContainer(first_parser);
|
|
||||||
|
|
||||||
auto [is_second_polygon_const, second_parser] = get_parser(1);
|
|
||||||
auto second_container = createContainer(second_parser);
|
|
||||||
|
|
||||||
auto res_column = ColumnFloat64::create();
|
|
||||||
|
|
||||||
for (size_t i = 0; i < input_rows_count; i++)
|
|
||||||
{
|
|
||||||
if (!is_first_polygon_const || i == 0)
|
|
||||||
get(first_parser, first_container, i);
|
|
||||||
if (!is_second_polygon_const || i == 0)
|
|
||||||
get(second_parser, second_container, i);
|
|
||||||
|
|
||||||
Float64 distance = boost::geometry::distance(
|
|
||||||
boost::get<Float64MultiPolygon>(first_container),
|
|
||||||
boost::get<Float64MultiPolygon>(second_container));
|
|
||||||
|
|
||||||
res_column->insertValue(distance);
|
|
||||||
}
|
|
||||||
|
|
||||||
block.getByPosition(result).column = std::move(res_column);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool useDefaultImplementationForConstants() const override
|
bool useDefaultImplementationForConstants() const override
|
||||||
@ -115,9 +75,72 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
void registerFunctionPolygonsDistance(FunctionFactory & factory)
|
class FunctionPolygonsDistanceCartesian : public FunctionPolygonsDistanceBase<FunctionPolygonsDistanceCartesian>
|
||||||
{
|
{
|
||||||
factory.registerFunction<FunctionPolygonsDistance>();
|
public:
|
||||||
|
static inline const char * name = "polygonsDistanceCartesian";
|
||||||
|
|
||||||
|
ColumnPtr executeImplementation(const ColumnsWithTypeAndName & arguments, const DataTypePtr & /*result_type*/, size_t input_rows_count) const
|
||||||
|
{
|
||||||
|
auto first_parser = makeCartesianGeometryFromColumnParser(arguments[0]);
|
||||||
|
auto first_container = createContainer(first_parser);
|
||||||
|
|
||||||
|
auto second_parser = makeCartesianGeometryFromColumnParser(arguments[1]);
|
||||||
|
auto second_container = createContainer(second_parser);
|
||||||
|
|
||||||
|
auto res_column = ColumnFloat64::create();
|
||||||
|
|
||||||
|
for (size_t i = 0; i < input_rows_count; i++)
|
||||||
|
{
|
||||||
|
Float64 distance = boost::geometry::distance(
|
||||||
|
boost::get<CartesianMultiPolygon>(first_container),
|
||||||
|
boost::get<CartesianMultiPolygon>(second_container));
|
||||||
|
|
||||||
|
res_column->insertValue(distance);
|
||||||
|
}
|
||||||
|
|
||||||
|
return res_column;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class FunctionPolygonsDistanceGeographic : public FunctionPolygonsDistanceBase<FunctionPolygonsDistanceGeographic>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static inline const char * name = "polygonsDistanceGeographic";
|
||||||
|
|
||||||
|
ColumnPtr executeImplementation(const ColumnsWithTypeAndName & arguments, const DataTypePtr & /*result_type*/, size_t input_rows_count) const
|
||||||
|
{
|
||||||
|
auto first_parser = makeGeographicGeometryFromColumnParser(arguments[0]);
|
||||||
|
auto first_container = createContainer(first_parser);
|
||||||
|
|
||||||
|
auto second_parser = makeGeographicGeometryFromColumnParser(arguments[1]);
|
||||||
|
auto second_container = createContainer(second_parser);
|
||||||
|
|
||||||
|
auto res_column = ColumnFloat64::create();
|
||||||
|
|
||||||
|
for (size_t i = 0; i < input_rows_count; i++)
|
||||||
|
{
|
||||||
|
Float64 distance = boost::geometry::distance(
|
||||||
|
boost::get<GeographicMultiPolygon>(first_container),
|
||||||
|
boost::get<GeographicMultiPolygon>(second_container));
|
||||||
|
|
||||||
|
res_column->insertValue(distance);
|
||||||
|
}
|
||||||
|
|
||||||
|
return res_column;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
void registerFunctionPolygonsDistanceCartesian(FunctionFactory & factory)
|
||||||
|
{
|
||||||
|
factory.registerFunction<FunctionPolygonsDistanceCartesian>();
|
||||||
|
}
|
||||||
|
|
||||||
|
void registerFunctionPolygonsDistanceGeographic(FunctionFactory & factory)
|
||||||
|
{
|
||||||
|
factory.registerFunction<FunctionPolygonsDistanceGeographic>();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -30,14 +30,6 @@ namespace ErrorCodes
|
|||||||
extern const int ILLEGAL_COLUMN;
|
extern const int ILLEGAL_COLUMN;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
using CoordinateType = Float64;
|
|
||||||
using Point = boost::geometry::model::d2::point_xy<CoordinateType>;
|
|
||||||
using Polygon = boost::geometry::model::polygon<Point, false>;
|
|
||||||
using MultiPolygon = boost::geometry::model::multi_polygon<Float64Polygon>;
|
|
||||||
using Box = boost::geometry::model::box<Point>;
|
|
||||||
|
|
||||||
|
|
||||||
class FunctionPolygonsEquals : public IFunction
|
class FunctionPolygonsEquals : public IFunction
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@ -70,17 +62,17 @@ public:
|
|||||||
return std::make_shared<DataTypeUInt8>();
|
return std::make_shared<DataTypeUInt8>();
|
||||||
}
|
}
|
||||||
|
|
||||||
void executeImpl(Block & block, const ColumnNumbers & arguments, size_t result, size_t input_rows_count) override
|
ColumnPtr executeImpl(const ColumnsWithTypeAndName & arguments, const DataTypePtr & /*result_type*/, size_t input_rows_count) const override
|
||||||
{
|
{
|
||||||
auto get_parser = [&block, &arguments] (size_t i) {
|
auto get_parser = [&arguments] (size_t i) {
|
||||||
const auto * const_col =
|
const auto * const_col =
|
||||||
checkAndGetColumn<ColumnConst>(block.getByPosition(arguments[i]).column.get());
|
checkAndGetColumn<ColumnConst>(arguments[i].column.get());
|
||||||
|
|
||||||
bool is_const = static_cast<bool>(const_col);
|
bool is_const = static_cast<bool>(const_col);
|
||||||
|
|
||||||
return std::pair<bool, GeometryFromColumnParser>{is_const, is_const ?
|
return std::pair<bool, CartesianGeometryFromColumnParser>{is_const, is_const ?
|
||||||
makeGeometryFromColumnParser(ColumnWithTypeAndName(const_col->getDataColumnPtr(), block.getByPosition(arguments[i]).type, block.getByPosition(arguments[i]).name)) :
|
makeCartesianGeometryFromColumnParser(ColumnWithTypeAndName(const_col->getDataColumnPtr(), arguments[i].type, arguments[i].name)) :
|
||||||
makeGeometryFromColumnParser(block.getByPosition(arguments[i]))};
|
makeCartesianGeometryFromColumnParser(arguments[i])};
|
||||||
};
|
};
|
||||||
|
|
||||||
auto [is_first_polygon_const, first_parser] = get_parser(0);
|
auto [is_first_polygon_const, first_parser] = get_parser(0);
|
||||||
@ -99,13 +91,13 @@ public:
|
|||||||
get(second_parser, second_container, i);
|
get(second_parser, second_container, i);
|
||||||
|
|
||||||
bool equals = boost::geometry::equals(
|
bool equals = boost::geometry::equals(
|
||||||
boost::get<Float64MultiPolygon>(first_container),
|
boost::get<CartesianMultiPolygon>(first_container),
|
||||||
boost::get<Float64MultiPolygon>(second_container));
|
boost::get<CartesianMultiPolygon>(second_container));
|
||||||
|
|
||||||
res_column->insertValue(equals);
|
res_column->insertValue(equals);
|
||||||
}
|
}
|
||||||
|
|
||||||
block.getByPosition(result).column = std::move(res_column);
|
return res_column;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool useDefaultImplementationForConstants() const override
|
bool useDefaultImplementationForConstants() const override
|
||||||
|
@ -29,13 +29,6 @@ namespace ErrorCodes
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
using CoordinateType = Float64;
|
|
||||||
using Point = boost::geometry::model::d2::point_xy<CoordinateType>;
|
|
||||||
using Polygon = boost::geometry::model::polygon<Point, false>;
|
|
||||||
using MultiPolygon = boost::geometry::model::multi_polygon<Float64Polygon>;
|
|
||||||
using Box = boost::geometry::model::box<Point>;
|
|
||||||
|
|
||||||
|
|
||||||
class FunctionPolygonsIntersection : public IFunction
|
class FunctionPolygonsIntersection : public IFunction
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@ -68,17 +61,17 @@ public:
|
|||||||
return DataTypeCustomMultiPolygonSerialization::nestedDataType();
|
return DataTypeCustomMultiPolygonSerialization::nestedDataType();
|
||||||
}
|
}
|
||||||
|
|
||||||
void executeImpl(Block & block, const ColumnNumbers & arguments, size_t result, size_t input_rows_count) override
|
ColumnPtr executeImpl(const ColumnsWithTypeAndName & arguments, const DataTypePtr & /*result_type*/, size_t input_rows_count) const override
|
||||||
{
|
{
|
||||||
auto get_parser = [&block, &arguments] (size_t i) {
|
auto get_parser = [&arguments] (size_t i) {
|
||||||
const auto * const_col =
|
const auto * const_col =
|
||||||
checkAndGetColumn<ColumnConst>(block.getByPosition(arguments[i]).column.get());
|
checkAndGetColumn<ColumnConst>(arguments[i].column.get());
|
||||||
|
|
||||||
bool is_const = static_cast<bool>(const_col);
|
bool is_const = static_cast<bool>(const_col);
|
||||||
|
|
||||||
return std::pair<bool, GeometryFromColumnParser>{is_const, is_const ?
|
return std::pair<bool, CartesianGeometryFromColumnParser>{is_const, is_const ?
|
||||||
makeGeometryFromColumnParser(ColumnWithTypeAndName(const_col->getDataColumnPtr(), block.getByPosition(arguments[i]).type, block.getByPosition(arguments[i]).name)) :
|
makeCartesianGeometryFromColumnParser(ColumnWithTypeAndName(const_col->getDataColumnPtr(), arguments[i].type, arguments[i].name)) :
|
||||||
makeGeometryFromColumnParser(block.getByPosition(arguments[i]))};
|
makeCartesianGeometryFromColumnParser(arguments[i])};
|
||||||
};
|
};
|
||||||
|
|
||||||
auto [is_first_polygon_const, first_parser] = get_parser(0);
|
auto [is_first_polygon_const, first_parser] = get_parser(0);
|
||||||
@ -87,7 +80,7 @@ public:
|
|||||||
auto [is_second_polygon_const, second_parser] = get_parser(1);
|
auto [is_second_polygon_const, second_parser] = get_parser(1);
|
||||||
auto second_container = createContainer(second_parser);
|
auto second_container = createContainer(second_parser);
|
||||||
|
|
||||||
Float64MultiPolygonSerializer serializer;
|
CartesianMultiPolygonSerializer serializer;
|
||||||
|
|
||||||
for (size_t i = 0; i < input_rows_count; i++)
|
for (size_t i = 0; i < input_rows_count; i++)
|
||||||
{
|
{
|
||||||
@ -96,19 +89,19 @@ public:
|
|||||||
if (!is_second_polygon_const || i == 0)
|
if (!is_second_polygon_const || i == 0)
|
||||||
get(second_parser, second_container, i);
|
get(second_parser, second_container, i);
|
||||||
|
|
||||||
Float64Geometry intersection = Float64MultiPolygon({{{{}}}});
|
CartesianGeometry intersection = CartesianMultiPolygon({{{{}}}});
|
||||||
boost::geometry::intersection(
|
boost::geometry::intersection(
|
||||||
boost::get<Float64MultiPolygon>(first_container),
|
boost::get<CartesianMultiPolygon>(first_container),
|
||||||
boost::get<Float64MultiPolygon>(second_container),
|
boost::get<CartesianMultiPolygon>(second_container),
|
||||||
boost::get<Float64MultiPolygon>(intersection));
|
boost::get<CartesianMultiPolygon>(intersection));
|
||||||
|
|
||||||
boost::get<Float64MultiPolygon>(intersection).erase(
|
boost::get<CartesianMultiPolygon>(intersection).erase(
|
||||||
boost::get<Float64MultiPolygon>(intersection).begin());
|
boost::get<CartesianMultiPolygon>(intersection).begin());
|
||||||
|
|
||||||
serializer.add(intersection);
|
serializer.add(intersection);
|
||||||
}
|
}
|
||||||
|
|
||||||
block.getByPosition(result).column = std::move(serializer.finalize());
|
return serializer.finalize();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool useDefaultImplementationForConstants() const override
|
bool useDefaultImplementationForConstants() const override
|
||||||
|
@ -28,14 +28,6 @@ namespace ErrorCodes
|
|||||||
extern const int ILLEGAL_COLUMN;
|
extern const int ILLEGAL_COLUMN;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
using CoordinateType = Float64;
|
|
||||||
using Point = boost::geometry::model::d2::point_xy<CoordinateType>;
|
|
||||||
using Polygon = boost::geometry::model::polygon<Point, false>;
|
|
||||||
using MultiPolygon = boost::geometry::model::multi_polygon<Float64Polygon>;
|
|
||||||
using Box = boost::geometry::model::box<Point>;
|
|
||||||
|
|
||||||
|
|
||||||
class FunctionPolygonsSymDifference : public IFunction
|
class FunctionPolygonsSymDifference : public IFunction
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@ -68,17 +60,17 @@ public:
|
|||||||
return DataTypeCustomMultiPolygonSerialization::nestedDataType();
|
return DataTypeCustomMultiPolygonSerialization::nestedDataType();
|
||||||
}
|
}
|
||||||
|
|
||||||
void executeImpl(Block & block, const ColumnNumbers & arguments, size_t result, size_t input_rows_count) override
|
ColumnPtr executeImpl(const ColumnsWithTypeAndName & arguments, const DataTypePtr & /*result_type*/, size_t input_rows_count) const override
|
||||||
{
|
{
|
||||||
auto get_parser = [&block, &arguments] (size_t i) {
|
auto get_parser = [&arguments] (size_t i) {
|
||||||
const auto * const_col =
|
const auto * const_col =
|
||||||
checkAndGetColumn<ColumnConst>(block.getByPosition(arguments[i]).column.get());
|
checkAndGetColumn<ColumnConst>(arguments[i].column.get());
|
||||||
|
|
||||||
bool is_const = static_cast<bool>(const_col);
|
bool is_const = static_cast<bool>(const_col);
|
||||||
|
|
||||||
return std::pair<bool, GeometryFromColumnParser>{is_const, is_const ?
|
return std::pair<bool, CartesianGeometryFromColumnParser>{is_const, is_const ?
|
||||||
makeGeometryFromColumnParser(ColumnWithTypeAndName(const_col->getDataColumnPtr(), block.getByPosition(arguments[i]).type, block.getByPosition(arguments[i]).name)) :
|
makeCartesianGeometryFromColumnParser(ColumnWithTypeAndName(const_col->getDataColumnPtr(), arguments[i].type, arguments[i].name)) :
|
||||||
makeGeometryFromColumnParser(block.getByPosition(arguments[i]))};
|
makeCartesianGeometryFromColumnParser(arguments[i])};
|
||||||
};
|
};
|
||||||
|
|
||||||
auto [is_first_polygon_const, first_parser] = get_parser(0);
|
auto [is_first_polygon_const, first_parser] = get_parser(0);
|
||||||
@ -87,7 +79,7 @@ public:
|
|||||||
auto [is_second_polygon_const, second_parser] = get_parser(1);
|
auto [is_second_polygon_const, second_parser] = get_parser(1);
|
||||||
auto second_container = createContainer(second_parser);
|
auto second_container = createContainer(second_parser);
|
||||||
|
|
||||||
Float64MultiPolygonSerializer serializer;
|
CartesianMultiPolygonSerializer serializer;
|
||||||
|
|
||||||
for (size_t i = 0; i < input_rows_count; i++)
|
for (size_t i = 0; i < input_rows_count; i++)
|
||||||
{
|
{
|
||||||
@ -96,19 +88,19 @@ public:
|
|||||||
if (!is_second_polygon_const || i == 0)
|
if (!is_second_polygon_const || i == 0)
|
||||||
get(second_parser, second_container, i);
|
get(second_parser, second_container, i);
|
||||||
|
|
||||||
Float64Geometry sym_difference = Float64MultiPolygon({{{{}}}});
|
CartesianGeometry sym_difference = CartesianMultiPolygon({{{{}}}});
|
||||||
boost::geometry::sym_difference(
|
boost::geometry::sym_difference(
|
||||||
boost::get<Float64MultiPolygon>(first_container),
|
boost::get<CartesianMultiPolygon>(first_container),
|
||||||
boost::get<Float64MultiPolygon>(second_container),
|
boost::get<CartesianMultiPolygon>(second_container),
|
||||||
boost::get<Float64MultiPolygon>(sym_difference));
|
boost::get<CartesianMultiPolygon>(sym_difference));
|
||||||
|
|
||||||
boost::get<Float64MultiPolygon>(sym_difference).erase(
|
boost::get<CartesianMultiPolygon>(sym_difference).erase(
|
||||||
boost::get<Float64MultiPolygon>(sym_difference).begin());
|
boost::get<CartesianMultiPolygon>(sym_difference).begin());
|
||||||
|
|
||||||
serializer.add(sym_difference);
|
serializer.add(sym_difference);
|
||||||
}
|
}
|
||||||
|
|
||||||
block.getByPosition(result).column = std::move(serializer.finalize());
|
return serializer.finalize();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool useDefaultImplementationForConstants() const override
|
bool useDefaultImplementationForConstants() const override
|
||||||
|
@ -30,14 +30,6 @@ namespace ErrorCodes
|
|||||||
extern const int ILLEGAL_COLUMN;
|
extern const int ILLEGAL_COLUMN;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
using CoordinateType = Float64;
|
|
||||||
using Point = boost::geometry::model::d2::point_xy<CoordinateType>;
|
|
||||||
using Polygon = boost::geometry::model::polygon<Point, false>;
|
|
||||||
using MultiPolygon = boost::geometry::model::multi_polygon<Float64Polygon>;
|
|
||||||
using Box = boost::geometry::model::box<Point>;
|
|
||||||
|
|
||||||
|
|
||||||
class FunctionPolygonsWithin : public IFunction
|
class FunctionPolygonsWithin : public IFunction
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@ -70,17 +62,17 @@ public:
|
|||||||
return std::make_shared<DataTypeUInt8>();
|
return std::make_shared<DataTypeUInt8>();
|
||||||
}
|
}
|
||||||
|
|
||||||
void executeImpl(Block & block, const ColumnNumbers & arguments, size_t result, size_t input_rows_count) override
|
ColumnPtr executeImpl(const ColumnsWithTypeAndName & arguments, const DataTypePtr & /*result_type*/, size_t input_rows_count) const override
|
||||||
{
|
{
|
||||||
auto get_parser = [&block, &arguments] (size_t i) {
|
auto get_parser = [&arguments] (size_t i) {
|
||||||
const auto * const_col =
|
const auto * const_col =
|
||||||
checkAndGetColumn<ColumnConst>(block.getByPosition(arguments[i]).column.get());
|
checkAndGetColumn<ColumnConst>(arguments[i].column.get());
|
||||||
|
|
||||||
bool is_const = static_cast<bool>(const_col);
|
bool is_const = static_cast<bool>(const_col);
|
||||||
|
|
||||||
return std::pair<bool, GeometryFromColumnParser>{is_const, is_const ?
|
return std::pair<bool, CartesianGeometryFromColumnParser>{is_const, is_const ?
|
||||||
makeGeometryFromColumnParser(ColumnWithTypeAndName(const_col->getDataColumnPtr(), block.getByPosition(arguments[i]).type, block.getByPosition(arguments[i]).name)) :
|
makeCartesianGeometryFromColumnParser(ColumnWithTypeAndName(const_col->getDataColumnPtr(), arguments[i].type, arguments[i].name)) :
|
||||||
makeGeometryFromColumnParser(block.getByPosition(arguments[i]))};
|
makeCartesianGeometryFromColumnParser(arguments[i])};
|
||||||
};
|
};
|
||||||
|
|
||||||
auto [is_first_polygon_const, first_parser] = get_parser(0);
|
auto [is_first_polygon_const, first_parser] = get_parser(0);
|
||||||
@ -99,13 +91,13 @@ public:
|
|||||||
get(second_parser, second_container, i);
|
get(second_parser, second_container, i);
|
||||||
|
|
||||||
bool within = boost::geometry::within(
|
bool within = boost::geometry::within(
|
||||||
boost::get<Float64MultiPolygon>(first_container),
|
boost::get<CartesianMultiPolygon>(first_container),
|
||||||
boost::get<Float64MultiPolygon>(second_container));
|
boost::get<CartesianMultiPolygon>(second_container));
|
||||||
|
|
||||||
res_column->insertValue(within);
|
res_column->insertValue(within);
|
||||||
}
|
}
|
||||||
|
|
||||||
block.getByPosition(result).column = std::move(res_column);
|
return res_column;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool useDefaultImplementationForConstants() const override
|
bool useDefaultImplementationForConstants() const override
|
||||||
|
@ -39,9 +39,9 @@ public:
|
|||||||
return DataType::nestedDataType();
|
return DataType::nestedDataType();
|
||||||
}
|
}
|
||||||
|
|
||||||
void executeImpl(Block & block, const ColumnNumbers & arguments, size_t result, size_t input_rows_count) override
|
ColumnPtr executeImpl(const ColumnsWithTypeAndName & arguments, const DataTypePtr & /*result_type*/, size_t input_rows_count) const override
|
||||||
{
|
{
|
||||||
auto column_string = checkAndGetColumn<ColumnString>(block.getByPosition(arguments[0]).column.get());
|
auto column_string = checkAndGetColumn<ColumnString>(arguments[0].column.get());
|
||||||
|
|
||||||
Serializer serializer;
|
Serializer serializer;
|
||||||
Geometry geometry;
|
Geometry geometry;
|
||||||
@ -53,7 +53,7 @@ public:
|
|||||||
serializer.add(geometry);
|
serializer.add(geometry);
|
||||||
}
|
}
|
||||||
|
|
||||||
block.getByPosition(result).column = serializer.finalize();
|
return serializer.finalize();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool useDefaultImplementationForConstants() const override
|
bool useDefaultImplementationForConstants() const override
|
||||||
@ -62,7 +62,7 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class FunctionReadWktPoint : public FunctionReadWkt<DataTypeCustomPointSerialization, Float64Point, Float64PointSerializer>
|
class FunctionReadWktPoint : public FunctionReadWkt<DataTypeCustomPointSerialization, CartesianPoint, CartesianPointSerializer>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
static inline const char * name = "readWktPoint";
|
static inline const char * name = "readWktPoint";
|
||||||
@ -76,7 +76,7 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class FunctionReadWktPolygon : public FunctionReadWkt<DataTypeCustomPolygonSerialization, Float64Polygon, Float64PolygonSerializer>
|
class FunctionReadWktPolygon : public FunctionReadWkt<DataTypeCustomPolygonSerialization, CartesianPolygon, CartesianPolygonSerializer>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
static inline const char * name = "readWktPolygon";
|
static inline const char * name = "readWktPolygon";
|
||||||
@ -90,7 +90,7 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class FunctionReadWktMultiPolygon : public FunctionReadWkt<DataTypeCustomMultiPolygonSerialization, Float64MultiPolygon, Float64MultiPolygonSerializer>
|
class FunctionReadWktMultiPolygon : public FunctionReadWkt<DataTypeCustomMultiPolygonSerialization, CartesianMultiPolygon, CartesianMultiPolygonSerializer>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
static inline const char * name = "readWktMultiPolygon";
|
static inline const char * name = "readWktMultiPolygon";
|
||||||
|
@ -12,13 +12,16 @@ void registerFunctionPointInEllipses(FunctionFactory & factory);
|
|||||||
void registerFunctionPointInPolygon(FunctionFactory & factory);
|
void registerFunctionPointInPolygon(FunctionFactory & factory);
|
||||||
void registerFunctionPolygonsIntersection(FunctionFactory & factory);
|
void registerFunctionPolygonsIntersection(FunctionFactory & factory);
|
||||||
void registerFunctionPolygonsUnion(FunctionFactory & factory);
|
void registerFunctionPolygonsUnion(FunctionFactory & factory);
|
||||||
void registerFunctionPolygonArea(FunctionFactory & factory);
|
void registerFunctionPolygonAreaCartesian(FunctionFactory & factory);
|
||||||
|
void registerFunctionPolygonAreaGeographic (FunctionFactory & factory);
|
||||||
void registerFunctionPolygonConvexHull(FunctionFactory & factory);
|
void registerFunctionPolygonConvexHull(FunctionFactory & factory);
|
||||||
void registerFunctionPolygonsSymDifference(FunctionFactory & factory);
|
void registerFunctionPolygonsSymDifference(FunctionFactory & factory);
|
||||||
void registerFunctionPolygonsEquals(FunctionFactory & factory);
|
void registerFunctionPolygonsEquals(FunctionFactory & factory);
|
||||||
void registerFunctionPolygonsDistance(FunctionFactory & factory);
|
void registerFunctionPolygonsDistanceCartesian(FunctionFactory & factory);
|
||||||
|
void registerFunctionPolygonsDistanceGeographic(FunctionFactory & factory);
|
||||||
void registerFunctionPolygonsWithin(FunctionFactory & factory);
|
void registerFunctionPolygonsWithin(FunctionFactory & factory);
|
||||||
void registerFunctionPolygonPerimeter(FunctionFactory & factory);
|
void registerFunctionPolygonPerimeterCartesian(FunctionFactory & factory);
|
||||||
|
void registerFunctionPolygonPerimeterGeographic(FunctionFactory & factory);
|
||||||
void registerFunctionGeohashEncode(FunctionFactory & factory);
|
void registerFunctionGeohashEncode(FunctionFactory & factory);
|
||||||
void registerFunctionGeohashDecode(FunctionFactory & factory);
|
void registerFunctionGeohashDecode(FunctionFactory & factory);
|
||||||
void registerFunctionGeohashesInBox(FunctionFactory & factory);
|
void registerFunctionGeohashesInBox(FunctionFactory & factory);
|
||||||
@ -50,13 +53,16 @@ void registerFunctionsGeo(FunctionFactory & factory)
|
|||||||
registerFunctionPointInPolygon(factory);
|
registerFunctionPointInPolygon(factory);
|
||||||
registerFunctionPolygonsIntersection(factory);
|
registerFunctionPolygonsIntersection(factory);
|
||||||
registerFunctionPolygonsUnion(factory);
|
registerFunctionPolygonsUnion(factory);
|
||||||
registerFunctionPolygonArea(factory);
|
registerFunctionPolygonAreaCartesian(factory);
|
||||||
|
registerFunctionPolygonAreaGeographic(factory);
|
||||||
registerFunctionPolygonConvexHull(factory);
|
registerFunctionPolygonConvexHull(factory);
|
||||||
registerFunctionPolygonsSymDifference(factory);
|
registerFunctionPolygonsSymDifference(factory);
|
||||||
registerFunctionPolygonsEquals(factory);
|
registerFunctionPolygonsEquals(factory);
|
||||||
registerFunctionPolygonsDistance(factory);
|
registerFunctionPolygonsDistanceCartesian(factory);
|
||||||
|
registerFunctionPolygonsDistanceGeographic(factory);
|
||||||
registerFunctionPolygonsWithin(factory);
|
registerFunctionPolygonsWithin(factory);
|
||||||
registerFunctionPolygonPerimeter(factory);
|
registerFunctionPolygonPerimeterCartesian(factory);
|
||||||
|
registerFunctionPolygonPerimeterGeographic(factory);
|
||||||
registerFunctionGeohashEncode(factory);
|
registerFunctionGeohashEncode(factory);
|
||||||
registerFunctionGeohashDecode(factory);
|
registerFunctionGeohashDecode(factory);
|
||||||
registerFunctionGeohashesInBox(factory);
|
registerFunctionGeohashesInBox(factory);
|
||||||
|
@ -60,13 +60,13 @@ public:
|
|||||||
return std::make_shared<DataTypeString>();
|
return std::make_shared<DataTypeString>();
|
||||||
}
|
}
|
||||||
|
|
||||||
void executeImpl(Block & block, const ColumnNumbers & arguments, size_t result, size_t input_rows_count) override
|
ColumnPtr executeImpl(const ColumnsWithTypeAndName & arguments, const DataTypePtr & /*result_type*/, size_t input_rows_count) const override
|
||||||
{
|
{
|
||||||
const auto * const_col = checkAndGetColumn<ColumnConst>(block.getByPosition(arguments[0]).column.get());
|
const auto * const_col = checkAndGetColumn<ColumnConst>(arguments[0].column.get());
|
||||||
|
|
||||||
auto parser = const_col ?
|
auto parser = const_col ?
|
||||||
makeGeometryFromColumnParser(ColumnWithTypeAndName(const_col->getDataColumnPtr(), block.getByPosition(arguments[0]).type, block.getByPosition(arguments[0]).name)) :
|
makeCartesianGeometryFromColumnParser(ColumnWithTypeAndName(const_col->getDataColumnPtr(), arguments[0].type, arguments[0].name)) :
|
||||||
makeGeometryFromColumnParser(block.getByPosition(arguments[0]));
|
makeCartesianGeometryFromColumnParser(arguments[0]);
|
||||||
|
|
||||||
bool geo_column_is_const = static_cast<bool>(const_col);
|
bool geo_column_is_const = static_cast<bool>(const_col);
|
||||||
|
|
||||||
@ -76,7 +76,7 @@ public:
|
|||||||
bool has_style = arguments.size() > 1;
|
bool has_style = arguments.size() > 1;
|
||||||
ColumnPtr style;
|
ColumnPtr style;
|
||||||
if (has_style) {
|
if (has_style) {
|
||||||
style = block.getByPosition(arguments[1]).column;
|
style = arguments[1].column;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (size_t i = 0; i < input_rows_count; i++)
|
for (size_t i = 0; i < input_rows_count; i++)
|
||||||
@ -90,7 +90,7 @@ public:
|
|||||||
res_column->insertData(serialized.c_str(), serialized.size());
|
res_column->insertData(serialized.c_str(), serialized.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
block.getByPosition(result).column = std::move(res_column);
|
return res_column;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool useDefaultImplementationForConstants() const override
|
bool useDefaultImplementationForConstants() const override
|
||||||
|
@ -36,9 +36,9 @@ public:
|
|||||||
return std::make_shared<DataTypeString>();
|
return std::make_shared<DataTypeString>();
|
||||||
}
|
}
|
||||||
|
|
||||||
void executeImpl(Block & block, const ColumnNumbers & arguments, size_t result, size_t input_rows_count) override
|
ColumnPtr executeImpl(const ColumnsWithTypeAndName & arguments, const DataTypePtr & /*result_type*/, size_t input_rows_count) const override
|
||||||
{
|
{
|
||||||
auto parser = makeGeometryFromColumnParser(block.getByPosition(arguments[0]));
|
auto parser = makeCartesianGeometryFromColumnParser(arguments[0]);
|
||||||
auto res_column = ColumnString::create();
|
auto res_column = ColumnString::create();
|
||||||
|
|
||||||
auto container = createContainer(parser);
|
auto container = createContainer(parser);
|
||||||
@ -52,7 +52,7 @@ public:
|
|||||||
res_column->insertData(serialized.c_str(), serialized.size());
|
res_column->insertData(serialized.c_str(), serialized.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
block.getByPosition(result).column = std::move(res_column);
|
return res_column;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool useDefaultImplementationForConstants() const override
|
bool useDefaultImplementationForConstants() const override
|
||||||
|
@ -1,2 +1,4 @@
|
|||||||
0
|
0
|
||||||
1.2727922061357855
|
1.2727922061357855
|
||||||
|
2088389.0786590837
|
||||||
|
2088389.0786590837
|
||||||
|
@ -1,3 +1,7 @@
|
|||||||
select polygonsDistance([[[(0, 0),(0, 3),(1, 2.9),(2, 2.6),(2.6, 2),(2.9, 1),(3, 0),(0, 0)]]], [[[(1, 1),(1, 4),(4, 4),(4, 1),(1, 1)]]]);
|
select polygonsDistanceCartesian([[[(0, 0),(0, 3),(1, 2.9),(2, 2.6),(2.6, 2),(2.9, 1),(3, 0),(0, 0)]]], [[[(1, 1),(1, 4),(4, 4),(4, 1),(1, 1)]]]);
|
||||||
|
select polygonsDistanceCartesian([[[(0, 0), (0, 0.1), (0.1, 0.1), (0.1, 0)]]], [[[(1, 1),(1, 4),(4, 4),(4, 1),(1, 1)]]]);
|
||||||
select polygonsDistance([[[(0, 0), (0, 0.1), (0.1, 0.1), (0.1, 0)]]], [[[(1, 1),(1, 4),(4, 4),(4, 1),(1, 1)]]])
|
select polygonsDistanceGeographic([[[(23.725750, 37.971536)]]], [[[(4.3826169, 50.8119483)]]]);
|
||||||
|
drop table if exists polygon_01302
|
||||||
|
create table polygon_01302 (x Array(Array(Array(Tuple(Float64, Float64)))), y Array(Array(Array(Tuple(Float64, Float64))))) engine=Memory();
|
||||||
|
insert into polygon_01302 values ([[[(23.725750, 37.971536)]]], [[[(4.3826169, 50.8119483)]]]);
|
||||||
|
select polygonsDistanceGeographic(x, y) from polygon;
|
||||||
|
@ -1 +1 @@
|
|||||||
select polygonPerimeter([[[(0, 0), (0., 5), (5, 5), (5., 0)]]])
|
select polygonPerimeterCartesian([[[(0, 0), (0., 5), (5, 5), (5., 0)]]]);
|
@ -1 +1,2 @@
|
|||||||
25
|
25
|
||||||
|
3848183.73456666
|
||||||
|
@ -1 +1,2 @@
|
|||||||
select polygonArea([[[(0, 0), (0., 5), (5, 5), (5., 0)]]])
|
select polygonAreaCartesian([[[(0, 0), (0., 5), (5, 5), (5., 0)]]]);
|
||||||
|
select polygonAreaGeographic([[[(4.346693, 50.858306), (4.367945, 50.852455), (4.366227, 50.840809), (4.344961, 50.833264), (4.338074, 50.848677), (4.346693, 50.858306)]]]);
|
Loading…
Reference in New Issue
Block a user