mirror of
https://github.com/ClickHouse/ClickHouse.git
synced 2024-11-27 01:51:59 +00:00
better
This commit is contained in:
parent
373b429e61
commit
0425d566d3
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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>;
|
||||
|
||||
}
|
||||
|
@ -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>();
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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>();
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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>();
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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";
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -1,2 +1,4 @@
|
||||
0
|
||||
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 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;
|
||||
|
@ -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
|
||||
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