This commit is contained in:
Nikita Mikhailov 2021-01-19 02:51:34 +03:00 committed by Nikita Mikhaylov
parent 373b429e61
commit 0425d566d3
21 changed files with 481 additions and 346 deletions

View File

@ -28,14 +28,6 @@ namespace ErrorCodes
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
{
public:
@ -68,17 +60,17 @@ public:
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 =
checkAndGetColumn<ColumnConst>(block.getByPosition(arguments[i]).column.get());
checkAndGetColumn<ColumnConst>(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]))};
return std::pair<bool, CartesianGeometryFromColumnParser>{is_const, is_const ?
makeCartesianGeometryFromColumnParser(ColumnWithTypeAndName(const_col->getDataColumnPtr(), arguments[i].type, arguments[i].name)) :
makeCartesianGeometryFromColumnParser(arguments[i])};
};
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 second_container = createContainer(second_parser);
Float64MultiPolygonSerializer serializer;
CartesianMultiPolygonSerializer serializer;
for (size_t i = 0; i < input_rows_count; i++)
{
@ -96,19 +88,19 @@ public:
if (!is_second_polygon_const || i == 0)
get(second_parser, second_container, i);
Float64Geometry polygons_union = Float64MultiPolygon({{{{}}}});
CartesianGeometry polygons_union = CartesianMultiPolygon({{{{}}}});
boost::geometry::union_(
boost::get<Float64MultiPolygon>(first_container),
boost::get<Float64MultiPolygon>(second_container),
boost::get<Float64MultiPolygon>(polygons_union));
boost::get<CartesianMultiPolygon>(first_container),
boost::get<CartesianMultiPolygon>(second_container),
boost::get<CartesianMultiPolygon>(polygons_union));
boost::get<Float64MultiPolygon>(polygons_union).erase(
boost::get<Float64MultiPolygon>(polygons_union).begin());
boost::get<CartesianMultiPolygon>(polygons_union).erase(
boost::get<CartesianMultiPolygon>(polygons_union).begin());
serializer.add(polygons_union);
}
block.getByPosition(result).column = std::move(serializer.finalize());
return serializer.finalize();
}
bool useDefaultImplementationForConstants() const override

View File

@ -9,32 +9,32 @@ namespace {
size_t getArrayDepth(DataTypePtr data_type, size_t max_depth)
{
LOG_FATAL(&Poco::Logger::get("geoconv"), "getting depth");
size_t depth = 0;
while (data_type && isArray(data_type) && depth != max_depth + 1)
{
depth++;
data_type = static_cast<const DataTypeArray &>(*data_type).getNestedType();
}
LOG_FATAL(&Poco::Logger::get("geoconv"), "got depth");
return depth;
}
class ContainerCreator : public boost::static_visitor<Float64Geometry>
template <typename Geometry>
class ContainerCreator : public boost::static_visitor<Geometry>
{
public:
template <class T>
Float64Geometry operator()(const T & parser) const
Geometry operator()(const T & parser) const
{
return parser.createContainer();
}
};
template <typename Geometry>
class Getter : public boost::static_visitor<void>
{
public:
constexpr Getter(Float64Geometry & container_, size_t i_)
constexpr Getter(Geometry & container_, size_t i_)
: container(container_)
, i(i_)
{}
@ -46,7 +46,7 @@ public:
}
private:
Float64Geometry & container;
Geometry & container;
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)) {
case 0: return makeParser<DataTypeCustomPointSerialization, Float64PointFromColumnParser>(col);
case 1: return makeParser<DataTypeCustomRingSerialization, Float64RingFromColumnParser>(col);
case 2: return makeParser<DataTypeCustomPolygonSerialization, Float64PolygonFromColumnParser>(col);
case 3: return makeParser<DataTypeCustomMultiPolygonSerialization, Float64MultiPolygonFromColumnParser>(col);
switch (getArrayDepth(col.type, 3))
{
case 0: return makeParser<DataTypeCustomPointSerialization, PointFromColumnParser<CartesianPoint>>(col);
case 1: return makeParser<DataTypeCustomRingSerialization, CartesianRingFromColumnParser>(col);
case 2: return makeParser<DataTypeCustomPolygonSerialization, CartesianPolygonFromColumnParser>(col);
case 3: return makeParser<DataTypeCustomMultiPolygonSerialization, CartesianMultiPolygonFromColumnParser>(col);
default: throw Exception("Cannot parse geometry from column with type " + col.type->getName()
+ ", 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);
}
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);
}

View File

@ -26,49 +26,89 @@ namespace ErrorCodes
extern const int BAD_ARGUMENTS;
}
using Float64Point = boost::geometry::model::d2::point_xy<Float64>;
using Float64Ring = boost::geometry::model::ring<Float64Point>;
using Float64Polygon = boost::geometry::model::polygon<Float64Point>;
using Float64MultiPolygon = boost::geometry::model::multi_polygon<Float64Polygon>;
using Float64Geometry = boost::variant<Float64Point, Float64Ring, Float64Polygon, Float64MultiPolygon>;
namespace bg = boost::geometry;
using CartesianPoint = bg::model::d2::point_xy<Float64>;
using CartesianRing = bg::model::ring<CartesianPoint>;
using CartesianPolygon = bg::model::polygon<CartesianPoint>;
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:
Float64PointFromColumnParser(ColumnPtr col_)
: col(col_)
PointFromColumnParser(ColumnPtr col_) : col(col_)
{
const auto & tuple = static_cast<const ColumnTuple &>(*col_);
const auto & tuple_columns = tuple.getColumns();
#ifndef NDEBUG
size = tuple.size();
#endif
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]);
y = y_data.getData().data();
second = y_data.getData().data();
}
Float64Geometry createContainer() const
template<class Q = PointType>
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]);
boost::geometry::set<1>(container, y[i]);
#ifndef NDEBUG
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:
/// Note, this is needed to prevent use-after-free.
ColumnPtr col;
const Float64 * x;
const Float64 * y;
#ifndef NDEBUG
size_t size;
#endif
const Float64 * first;
const Float64 * second;
};
template<class Geometry, class RingType, class PointParser>
@ -142,8 +182,6 @@ public:
ringParser.get(container.outer(), l);
LOG_FATAL(&Poco::Logger::get("geoconv"), "polygon: l = {}, r = {}", l, r);
container.inners().resize(r - l - 1);
for (size_t j = l + 1; j < r; j++)
{
@ -176,8 +214,6 @@ public:
size_t l = offsets[i - 1];
size_t r = offsets[i];
LOG_FATAL(&Poco::Logger::get("geoconv"), "multipolygon: l = {}, r = {}", l, r);
multi_polygon.resize(r - l);
for (size_t j = l; j < r; j++)
{
@ -190,43 +226,65 @@ private:
const PolygonParser polygonParser;
};
using Float64RingFromColumnParser = RingFromColumnParser<Float64Geometry, Float64Ring, Float64PointFromColumnParser>;
using Float64PolygonFromColumnParser = PolygonFromColumnParser<Float64Geometry, Float64Polygon, Float64RingFromColumnParser>;
using Float64MultiPolygonFromColumnParser = MultiPolygonFromColumnParser<Float64Geometry, Float64MultiPolygon, Float64PolygonFromColumnParser>;
/// Cartesian coordinates
using GeometryFromColumnParser = boost::variant<
Float64PointFromColumnParser,
Float64RingFromColumnParser,
Float64PolygonFromColumnParser,
Float64MultiPolygonFromColumnParser
using CartesianRingFromColumnParser = RingFromColumnParser<CartesianGeometry, CartesianRing, PointFromColumnParser<CartesianPoint>>;
using CartesianPolygonFromColumnParser = PolygonFromColumnParser<CartesianGeometry, CartesianPolygon, CartesianRingFromColumnParser>;
using CartesianMultiPolygonFromColumnParser = MultiPolygonFromColumnParser<CartesianGeometry, CartesianMultiPolygon, CartesianPolygonFromColumnParser>;
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:
Float64PointSerializerVisitor()
CartesianPointSerializerVisitor()
: x(ColumnFloat64::create())
, y(ColumnFloat64::create())
{}
Float64PointSerializerVisitor(size_t n)
CartesianPointSerializerVisitor(size_t n)
: x(ColumnFloat64::create(n))
, y(ColumnFloat64::create(n))
{}
void operator()(const Float64Point & point)
void operator()(const CartesianPoint & point)
{
x->insertValue(point.x());
y->insertValue(point.y());
x->insertValue(point.get<0>());
y->insertValue(point.get<0>());
}
void operator()(const Float64Ring & ring)
void operator()(const CartesianRing & ring)
{
if (ring.size() != 1) {
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]);
}
void operator()(const Float64Polygon & polygon)
void operator()(const CartesianPolygon & polygon)
{
if (polygon.inners().size() != 0) {
throw Exception("Unable to write polygon with holes to point column", ErrorCodes::BAD_ARGUMENTS);
@ -242,7 +300,7 @@ public:
(*this)(polygon.outer());
}
void operator()(const Float64MultiPolygon & multi_polygon)
void operator()(const CartesianMultiPolygon & multi_polygon)
{
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);
@ -264,18 +322,18 @@ private:
ColumnFloat64::MutablePtr y;
};
class Float64RingSerializerVisitor : public boost::static_visitor<void>
class CartesianRingSerializerVisitor : public boost::static_visitor<void>
{
public:
Float64RingSerializerVisitor()
CartesianRingSerializerVisitor()
: offsets(ColumnUInt64::create())
{}
Float64RingSerializerVisitor(size_t n)
CartesianRingSerializerVisitor(size_t n)
: offsets(ColumnUInt64::create(n))
{}
void operator()(const Float64Point & point)
void operator()(const CartesianPoint & point)
{
size++;
offsets->insertValue(size);
@ -283,7 +341,7 @@ public:
pointSerializer(point);
}
void operator()(const Float64Ring & ring)
void operator()(const CartesianRing & ring)
{
size += ring.size();
offsets->insertValue(size);
@ -293,7 +351,7 @@ public:
}
}
void operator()(const Float64Polygon & polygon)
void operator()(const CartesianPolygon & polygon)
{
if (polygon.inners().size() != 0) {
throw Exception("Unable to write polygon with holes to ring column", ErrorCodes::BAD_ARGUMENTS);
@ -301,7 +359,7 @@ public:
(*this)(polygon.outer());
}
void operator()(const Float64MultiPolygon & multi_polygon)
void operator()(const CartesianMultiPolygon & multi_polygon)
{
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);
@ -316,36 +374,36 @@ public:
private:
size_t size = 0;
Float64PointSerializerVisitor pointSerializer;
CartesianPointSerializerVisitor pointSerializer;
ColumnUInt64::MutablePtr offsets;
};
class Float64PolygonSerializerVisitor : public boost::static_visitor<void>
class CartesianPolygonSerializerVisitor : public boost::static_visitor<void>
{
public:
Float64PolygonSerializerVisitor()
CartesianPolygonSerializerVisitor()
: offsets(ColumnUInt64::create())
{}
Float64PolygonSerializerVisitor(size_t n)
CartesianPolygonSerializerVisitor(size_t n)
: offsets(ColumnUInt64::create(n))
{}
void operator()(const Float64Point & point)
void operator()(const CartesianPoint & point)
{
size++;
offsets->insertValue(size);
ringSerializer(point);
}
void operator()(const Float64Ring & ring)
void operator()(const CartesianRing & ring)
{
size++;
offsets->insertValue(size);
ringSerializer(ring);
}
void operator()(const Float64Polygon & polygon)
void operator()(const CartesianPolygon & polygon)
{
size += 1 + polygon.inners().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) {
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:
size_t size = 0;
Float64RingSerializerVisitor ringSerializer;
CartesianRingSerializerVisitor ringSerializer;
ColumnUInt64::MutablePtr offsets;
};
class Float64MultiPolygonSerializerVisitor : public boost::static_visitor<void>
class CartesianMultiPolygonSerializerVisitor : public boost::static_visitor<void>
{
public:
Float64MultiPolygonSerializerVisitor()
CartesianMultiPolygonSerializerVisitor()
: offsets(ColumnUInt64::create())
{}
Float64MultiPolygonSerializerVisitor(size_t n)
CartesianMultiPolygonSerializerVisitor(size_t n)
: offsets(ColumnUInt64::create(n))
{}
void operator()(const Float64Point & point)
void operator()(const CartesianPoint & point)
{
size++;
offsets->insertValue(size);
polygonSerializer(point);
}
void operator()(const Float64Ring & ring)
void operator()(const CartesianRing & ring)
{
size++;
offsets->insertValue(size);
polygonSerializer(ring);
}
void operator()(const Float64Polygon & polygon)
void operator()(const CartesianPolygon & polygon)
{
size++;
offsets->insertValue(size);
polygonSerializer(polygon);
}
void operator()(const Float64MultiPolygon & multi_polygon)
void operator()(const CartesianMultiPolygon & multi_polygon)
{
size += multi_polygon.size();
offsets->insertValue(size);
@ -424,7 +482,7 @@ public:
private:
size_t size = 0;
Float64PolygonSerializerVisitor polygonSerializer;
CartesianPolygonSerializerVisitor polygonSerializer;
ColumnUInt64::MutablePtr offsets;
};
@ -445,9 +503,9 @@ private:
Visitor visitor;
};
using Float64PointSerializer = GeometrySerializer<Float64Geometry, Float64PointSerializerVisitor>;
using Float64RingSerializer = GeometrySerializer<Float64Geometry, Float64RingSerializerVisitor>;
using Float64PolygonSerializer = GeometrySerializer<Float64Geometry, Float64PolygonSerializerVisitor>;
using Float64MultiPolygonSerializer = GeometrySerializer<Float64Geometry, Float64MultiPolygonSerializerVisitor>;
using CartesianPointSerializer = GeometrySerializer<CartesianGeometry, CartesianPointSerializerVisitor>;
using CartesianRingSerializer = GeometrySerializer<CartesianGeometry, CartesianRingSerializerVisitor>;
using CartesianPolygonSerializer = GeometrySerializer<CartesianGeometry, CartesianPolygonSerializerVisitor>;
using CartesianMultiPolygonSerializer = GeometrySerializer<CartesianGeometry, CartesianMultiPolygonSerializerVisitor>;
}

View File

@ -28,24 +28,17 @@ namespace ErrorCodes
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 FunctionPolygonArea : public IFunction
template <typename Derived>
class FunctionPolygonAreaBase : public IFunction
{
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 &)
{
return std::make_shared<FunctionPolygonArea>();
return std::make_shared<FunctionPolygonAreaBase>();
}
String getName() const override
@ -68,29 +61,9 @@ public:
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) {
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);
return static_cast<const Derived*>(this)->executeImplementation(arguments, result_type, input_rows_count);
}
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>();
}
}

View File

@ -28,14 +28,6 @@ namespace ErrorCodes
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
{
public:
@ -68,34 +60,34 @@ public:
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) {
const ColumnWithTypeAndName polygon = block.getByPosition(arguments[i]);
return makeGeometryFromColumnParser(polygon);
auto get_parser = [&arguments] (size_t i) {
const ColumnWithTypeAndName polygon = arguments[i];
return makeCartesianGeometryFromColumnParser(polygon);
};
auto parser = get_parser(0);
auto container = createContainer(parser);
Float64PolygonSerializer serializer;
CartesianPolygonSerializer serializer;
for (size_t i = 0; i < input_rows_count; i++)
{
get(parser, container, i);
Float64Geometry convex_hull = Float64Polygon({{{}}});
CartesianGeometry convex_hull = CartesianPolygon({{{}}});
boost::geometry::convex_hull(
boost::get<Float64MultiPolygon>(container),
boost::get<Float64Polygon>(convex_hull));
boost::get<CartesianMultiPolygon>(container),
boost::get<CartesianPolygon>(convex_hull));
boost::get<Float64Polygon>(convex_hull).outer().erase(
boost::get<Float64Polygon>(convex_hull).outer().begin());
boost::get<CartesianPolygon>(convex_hull).outer().erase(
boost::get<CartesianPolygon>(convex_hull).outer().begin());
serializer.add(convex_hull);
}
block.getByPosition(result).column = std::move(serializer.finalize());
return serializer.finalize();
}
bool useDefaultImplementationForConstants() const override

View File

@ -28,24 +28,17 @@ namespace ErrorCodes
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 FunctionPolygonPerimeter : public IFunction
template <typename Derived>
class FunctionPolygonPerimeterBase : public IFunction
{
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 &)
{
return std::make_shared<FunctionPolygonPerimeter>();
return std::make_shared<FunctionPolygonPerimeterBase>();
}
String getName() const override
@ -68,14 +61,25 @@ public:
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) {
const ColumnWithTypeAndName polygon = block.getByPosition(arguments[i]);
return makeGeometryFromColumnParser(polygon);
};
return static_cast<const Derived*>(this)->executeImplementation(arguments, result_type, input_rows_count);
}
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 res_column = ColumnFloat64::create();
@ -85,24 +89,52 @@ public:
get(parser, container, i);
Float64 perimeter = boost::geometry::perimeter(
boost::get<Float64MultiPolygon>(container));
boost::get<CartesianMultiPolygon>(container));
res_column->insertValue(perimeter);
}
block.getByPosition(result).column = std::move(res_column);
}
bool useDefaultImplementationForConstants() const override
{
return true;
return res_column;
}
};
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>();
}
}

View File

@ -30,24 +30,17 @@ namespace ErrorCodes
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 FunctionPolygonsDistance : public IFunction
template <typename Derived>
class FunctionPolygonsDistanceBase : public IFunction
{
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 &)
{
return std::make_shared<FunctionPolygonsDistance>();
return std::make_shared<FunctionPolygonsDistanceBase>();
}
String getName() const override
@ -70,42 +63,9 @@ public:
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) {
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);
return static_cast<const Derived*>(this)->executeImplementation(arguments, result_type, input_rows_count);
}
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>();
}
}

View File

@ -30,14 +30,6 @@ namespace ErrorCodes
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
{
public:
@ -70,17 +62,17 @@ public:
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 =
checkAndGetColumn<ColumnConst>(block.getByPosition(arguments[i]).column.get());
checkAndGetColumn<ColumnConst>(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]))};
return std::pair<bool, CartesianGeometryFromColumnParser>{is_const, is_const ?
makeCartesianGeometryFromColumnParser(ColumnWithTypeAndName(const_col->getDataColumnPtr(), arguments[i].type, arguments[i].name)) :
makeCartesianGeometryFromColumnParser(arguments[i])};
};
auto [is_first_polygon_const, first_parser] = get_parser(0);
@ -99,13 +91,13 @@ public:
get(second_parser, second_container, i);
bool equals = boost::geometry::equals(
boost::get<Float64MultiPolygon>(first_container),
boost::get<Float64MultiPolygon>(second_container));
boost::get<CartesianMultiPolygon>(first_container),
boost::get<CartesianMultiPolygon>(second_container));
res_column->insertValue(equals);
}
block.getByPosition(result).column = std::move(res_column);
return res_column;
}
bool useDefaultImplementationForConstants() const override

View File

@ -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
{
public:
@ -68,17 +61,17 @@ public:
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 =
checkAndGetColumn<ColumnConst>(block.getByPosition(arguments[i]).column.get());
checkAndGetColumn<ColumnConst>(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]))};
return std::pair<bool, CartesianGeometryFromColumnParser>{is_const, is_const ?
makeCartesianGeometryFromColumnParser(ColumnWithTypeAndName(const_col->getDataColumnPtr(), arguments[i].type, arguments[i].name)) :
makeCartesianGeometryFromColumnParser(arguments[i])};
};
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 second_container = createContainer(second_parser);
Float64MultiPolygonSerializer serializer;
CartesianMultiPolygonSerializer serializer;
for (size_t i = 0; i < input_rows_count; i++)
{
@ -96,19 +89,19 @@ public:
if (!is_second_polygon_const || i == 0)
get(second_parser, second_container, i);
Float64Geometry intersection = Float64MultiPolygon({{{{}}}});
CartesianGeometry intersection = CartesianMultiPolygon({{{{}}}});
boost::geometry::intersection(
boost::get<Float64MultiPolygon>(first_container),
boost::get<Float64MultiPolygon>(second_container),
boost::get<Float64MultiPolygon>(intersection));
boost::get<CartesianMultiPolygon>(first_container),
boost::get<CartesianMultiPolygon>(second_container),
boost::get<CartesianMultiPolygon>(intersection));
boost::get<Float64MultiPolygon>(intersection).erase(
boost::get<Float64MultiPolygon>(intersection).begin());
boost::get<CartesianMultiPolygon>(intersection).erase(
boost::get<CartesianMultiPolygon>(intersection).begin());
serializer.add(intersection);
}
block.getByPosition(result).column = std::move(serializer.finalize());
return serializer.finalize();
}
bool useDefaultImplementationForConstants() const override

View File

@ -28,14 +28,6 @@ namespace ErrorCodes
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
{
public:
@ -68,17 +60,17 @@ public:
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 =
checkAndGetColumn<ColumnConst>(block.getByPosition(arguments[i]).column.get());
checkAndGetColumn<ColumnConst>(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]))};
return std::pair<bool, CartesianGeometryFromColumnParser>{is_const, is_const ?
makeCartesianGeometryFromColumnParser(ColumnWithTypeAndName(const_col->getDataColumnPtr(), arguments[i].type, arguments[i].name)) :
makeCartesianGeometryFromColumnParser(arguments[i])};
};
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 second_container = createContainer(second_parser);
Float64MultiPolygonSerializer serializer;
CartesianMultiPolygonSerializer serializer;
for (size_t i = 0; i < input_rows_count; i++)
{
@ -96,19 +88,19 @@ public:
if (!is_second_polygon_const || i == 0)
get(second_parser, second_container, i);
Float64Geometry sym_difference = Float64MultiPolygon({{{{}}}});
CartesianGeometry sym_difference = CartesianMultiPolygon({{{{}}}});
boost::geometry::sym_difference(
boost::get<Float64MultiPolygon>(first_container),
boost::get<Float64MultiPolygon>(second_container),
boost::get<Float64MultiPolygon>(sym_difference));
boost::get<CartesianMultiPolygon>(first_container),
boost::get<CartesianMultiPolygon>(second_container),
boost::get<CartesianMultiPolygon>(sym_difference));
boost::get<Float64MultiPolygon>(sym_difference).erase(
boost::get<Float64MultiPolygon>(sym_difference).begin());
boost::get<CartesianMultiPolygon>(sym_difference).erase(
boost::get<CartesianMultiPolygon>(sym_difference).begin());
serializer.add(sym_difference);
}
block.getByPosition(result).column = std::move(serializer.finalize());
return serializer.finalize();
}
bool useDefaultImplementationForConstants() const override

View File

@ -30,14 +30,6 @@ namespace ErrorCodes
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
{
public:
@ -70,17 +62,17 @@ public:
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 =
checkAndGetColumn<ColumnConst>(block.getByPosition(arguments[i]).column.get());
checkAndGetColumn<ColumnConst>(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]))};
return std::pair<bool, CartesianGeometryFromColumnParser>{is_const, is_const ?
makeCartesianGeometryFromColumnParser(ColumnWithTypeAndName(const_col->getDataColumnPtr(), arguments[i].type, arguments[i].name)) :
makeCartesianGeometryFromColumnParser(arguments[i])};
};
auto [is_first_polygon_const, first_parser] = get_parser(0);
@ -99,13 +91,13 @@ public:
get(second_parser, second_container, i);
bool within = boost::geometry::within(
boost::get<Float64MultiPolygon>(first_container),
boost::get<Float64MultiPolygon>(second_container));
boost::get<CartesianMultiPolygon>(first_container),
boost::get<CartesianMultiPolygon>(second_container));
res_column->insertValue(within);
}
block.getByPosition(result).column = std::move(res_column);
return res_column;
}
bool useDefaultImplementationForConstants() const override

View File

@ -39,9 +39,9 @@ public:
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;
Geometry geometry;
@ -53,7 +53,7 @@ public:
serializer.add(geometry);
}
block.getByPosition(result).column = serializer.finalize();
return serializer.finalize();
}
bool useDefaultImplementationForConstants() const override
@ -62,7 +62,7 @@ public:
}
};
class FunctionReadWktPoint : public FunctionReadWkt<DataTypeCustomPointSerialization, Float64Point, Float64PointSerializer>
class FunctionReadWktPoint : public FunctionReadWkt<DataTypeCustomPointSerialization, CartesianPoint, CartesianPointSerializer>
{
public:
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:
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:
static inline const char * name = "readWktMultiPolygon";

View File

@ -12,13 +12,16 @@ void registerFunctionPointInEllipses(FunctionFactory & factory);
void registerFunctionPointInPolygon(FunctionFactory & factory);
void registerFunctionPolygonsIntersection(FunctionFactory & factory);
void registerFunctionPolygonsUnion(FunctionFactory & factory);
void registerFunctionPolygonArea(FunctionFactory & factory);
void registerFunctionPolygonAreaCartesian(FunctionFactory & factory);
void registerFunctionPolygonAreaGeographic (FunctionFactory & factory);
void registerFunctionPolygonConvexHull(FunctionFactory & factory);
void registerFunctionPolygonsSymDifference(FunctionFactory & factory);
void registerFunctionPolygonsEquals(FunctionFactory & factory);
void registerFunctionPolygonsDistance(FunctionFactory & factory);
void registerFunctionPolygonsDistanceCartesian(FunctionFactory & factory);
void registerFunctionPolygonsDistanceGeographic(FunctionFactory & factory);
void registerFunctionPolygonsWithin(FunctionFactory & factory);
void registerFunctionPolygonPerimeter(FunctionFactory & factory);
void registerFunctionPolygonPerimeterCartesian(FunctionFactory & factory);
void registerFunctionPolygonPerimeterGeographic(FunctionFactory & factory);
void registerFunctionGeohashEncode(FunctionFactory & factory);
void registerFunctionGeohashDecode(FunctionFactory & factory);
void registerFunctionGeohashesInBox(FunctionFactory & factory);
@ -50,13 +53,16 @@ void registerFunctionsGeo(FunctionFactory & factory)
registerFunctionPointInPolygon(factory);
registerFunctionPolygonsIntersection(factory);
registerFunctionPolygonsUnion(factory);
registerFunctionPolygonArea(factory);
registerFunctionPolygonAreaCartesian(factory);
registerFunctionPolygonAreaGeographic(factory);
registerFunctionPolygonConvexHull(factory);
registerFunctionPolygonsSymDifference(factory);
registerFunctionPolygonsEquals(factory);
registerFunctionPolygonsDistance(factory);
registerFunctionPolygonsDistanceCartesian(factory);
registerFunctionPolygonsDistanceGeographic(factory);
registerFunctionPolygonsWithin(factory);
registerFunctionPolygonPerimeter(factory);
registerFunctionPolygonPerimeterCartesian(factory);
registerFunctionPolygonPerimeterGeographic(factory);
registerFunctionGeohashEncode(factory);
registerFunctionGeohashDecode(factory);
registerFunctionGeohashesInBox(factory);

View File

@ -60,13 +60,13 @@ public:
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 ?
makeGeometryFromColumnParser(ColumnWithTypeAndName(const_col->getDataColumnPtr(), block.getByPosition(arguments[0]).type, block.getByPosition(arguments[0]).name)) :
makeGeometryFromColumnParser(block.getByPosition(arguments[0]));
makeCartesianGeometryFromColumnParser(ColumnWithTypeAndName(const_col->getDataColumnPtr(), arguments[0].type, arguments[0].name)) :
makeCartesianGeometryFromColumnParser(arguments[0]);
bool geo_column_is_const = static_cast<bool>(const_col);
@ -76,7 +76,7 @@ public:
bool has_style = arguments.size() > 1;
ColumnPtr style;
if (has_style) {
style = block.getByPosition(arguments[1]).column;
style = arguments[1].column;
}
for (size_t i = 0; i < input_rows_count; i++)
@ -90,7 +90,7 @@ public:
res_column->insertData(serialized.c_str(), serialized.size());
}
block.getByPosition(result).column = std::move(res_column);
return res_column;
}
bool useDefaultImplementationForConstants() const override

View File

@ -36,9 +36,9 @@ public:
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 container = createContainer(parser);
@ -52,7 +52,7 @@ public:
res_column->insertData(serialized.c_str(), serialized.size());
}
block.getByPosition(result).column = std::move(res_column);
return res_column;
}
bool useDefaultImplementationForConstants() const override

View File

@ -1 +1 @@
[[(0,0),(0,5),(5,5),(5,0),(0,0)]]
[[(0,0),(0,5),(5,5),(5,0),(0,0)]]

View File

@ -1,2 +1,4 @@
0
1.2727922061357855
2088389.0786590837
2088389.0786590837

View File

@ -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 polygonsDistance([[[(0, 0), (0, 0.1), (0.1, 0.1), (0.1, 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 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;

View File

@ -1 +1 @@
select polygonPerimeter([[[(0, 0), (0., 5), (5, 5), (5., 0)]]])
select polygonPerimeterCartesian([[[(0, 0), (0., 5), (5, 5), (5., 0)]]]);

View File

@ -1 +1,2 @@
25
3848183.73456666

View File

@ -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)]]]);