mirror of
https://github.com/ClickHouse/ClickHouse.git
synced 2024-11-25 00:52:02 +00:00
better
This commit is contained in:
parent
3e36fae3df
commit
cfee417ce0
@ -62,33 +62,20 @@ public:
|
||||
|
||||
ColumnPtr executeImpl(const ColumnsWithTypeAndName & arguments, const DataTypePtr & /*result_type*/, size_t input_rows_count) const override
|
||||
{
|
||||
auto get_parser = [&arguments] (size_t i) {
|
||||
const auto * const_col =
|
||||
checkAndGetColumn<ColumnConst>(arguments[i].column.get());
|
||||
|
||||
bool is_const = static_cast<bool>(const_col);
|
||||
|
||||
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);
|
||||
auto first_parser = makeGeometryFromColumnParser<CartesianPoint>(arguments[0]);
|
||||
auto first_container = createContainer(first_parser);
|
||||
|
||||
auto [is_second_polygon_const, second_parser] = get_parser(1);
|
||||
auto second_parser = makeGeometryFromColumnParser<CartesianPoint>(arguments[1]);
|
||||
auto second_container = createContainer(second_parser);
|
||||
|
||||
CartesianMultiPolygonSerializer serializer;
|
||||
MultiPolygonSerializer<CartesianPoint> serializer;
|
||||
|
||||
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);
|
||||
get<CartesianPoint>(first_parser, first_container, i);
|
||||
get<CartesianPoint>(second_parser, second_container, i);
|
||||
|
||||
CartesianGeometry polygons_union = CartesianMultiPolygon({{{{}}}});
|
||||
Geometry<CartesianPoint> polygons_union = CartesianMultiPolygon({{{{}}}});
|
||||
boost::geometry::union_(
|
||||
boost::get<CartesianMultiPolygon>(first_container),
|
||||
boost::get<CartesianMultiPolygon>(second_container),
|
||||
|
@ -30,11 +30,11 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Geometry>
|
||||
template <typename Point>
|
||||
class Getter : public boost::static_visitor<void>
|
||||
{
|
||||
public:
|
||||
constexpr Getter(Geometry & container_, size_t i_)
|
||||
constexpr Getter(Geometry<Point> & container_, size_t i_)
|
||||
: container(container_)
|
||||
, i(i_)
|
||||
{}
|
||||
@ -46,7 +46,7 @@ public:
|
||||
}
|
||||
|
||||
private:
|
||||
Geometry & container;
|
||||
Geometry<Point> & container;
|
||||
size_t i;
|
||||
};
|
||||
|
||||
@ -64,52 +64,41 @@ Parser makeParser(const ColumnWithTypeAndName & col)
|
||||
|
||||
}
|
||||
|
||||
CartesianGeometryFromColumnParser makeCartesianGeometryFromColumnParser(const ColumnWithTypeAndName & col)
|
||||
template <typename Point>
|
||||
Geometry<Point> createContainer(const GeometryFromColumnParser<Point> & parser)
|
||||
{
|
||||
static ContainerCreator<Geometry<Point>> creator;
|
||||
return boost::apply_visitor(creator, parser);
|
||||
}
|
||||
|
||||
template <typename Point>
|
||||
void get(const GeometryFromColumnParser<Point> & parser, Geometry<Point> & container, size_t i)
|
||||
{
|
||||
boost::apply_visitor(Getter<Point>(container, i), parser);
|
||||
}
|
||||
|
||||
template <typename Point>
|
||||
GeometryFromColumnParser<Point> makeGeometryFromColumnParser(const ColumnWithTypeAndName & 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);
|
||||
case 0: return makeParser<DataTypeCustomPointSerialization, PointFromColumnParser<Point>>(col);
|
||||
case 1: return makeParser<DataTypeCustomRingSerialization, RingFromColumnParser<Point>>(col);
|
||||
case 2: return makeParser<DataTypeCustomPolygonSerialization, PolygonFromColumnParser<Point>>(col);
|
||||
case 3: return makeParser<DataTypeCustomMultiPolygonSerialization, MultiPolygonFromColumnParser<Point>>(col);
|
||||
default: throw Exception("Cannot parse geometry from column with type " + col.type->getName()
|
||||
+ ", array depth is too big", ErrorCodes::ILLEGAL_COLUMN);
|
||||
}
|
||||
}
|
||||
|
||||
CartesianGeometry createContainer(const CartesianGeometryFromColumnParser & parser)
|
||||
{
|
||||
static ContainerCreator<CartesianGeometry> creator;
|
||||
return boost::apply_visitor(creator, parser);
|
||||
}
|
||||
/// Explicit instantiations to avoid linker errors.
|
||||
|
||||
void get(const CartesianGeometryFromColumnParser & parser, CartesianGeometry & container, size_t i)
|
||||
{
|
||||
boost::apply_visitor(Getter(container, i), parser);
|
||||
}
|
||||
template Geometry<CartesianPoint> createContainer(const GeometryFromColumnParser<CartesianPoint> &);
|
||||
template Geometry<GeographicPoint> createContainer(const GeometryFromColumnParser<GeographicPoint> &);
|
||||
template void get(const GeometryFromColumnParser<CartesianPoint> & parser, Geometry<CartesianPoint> & container, size_t i);
|
||||
template void get(const GeometryFromColumnParser<GeographicPoint> & parser, Geometry<GeographicPoint> & container, size_t i);
|
||||
template GeometryFromColumnParser<CartesianPoint> makeGeometryFromColumnParser(const ColumnWithTypeAndName & col);
|
||||
template GeometryFromColumnParser<GeographicPoint> makeGeometryFromColumnParser(const ColumnWithTypeAndName & col);
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -27,17 +27,31 @@ namespace ErrorCodes
|
||||
}
|
||||
|
||||
namespace bg = boost::geometry;
|
||||
|
||||
template <typename Point>
|
||||
using Ring = bg::model::ring<Point>;
|
||||
|
||||
template <typename Point>
|
||||
using Polygon = bg::model::polygon<Point>;
|
||||
|
||||
template <typename Point>
|
||||
using MultiPolygon = bg::model::multi_polygon<Polygon<Point>>;
|
||||
|
||||
template <typename Point>
|
||||
using Geometry = boost::variant<Point, Ring<Point>, Polygon<Point>, MultiPolygon<Point>>;
|
||||
|
||||
|
||||
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>;
|
||||
using CartesianRing = Ring<CartesianPoint>;
|
||||
using CartesianPolygon = Polygon<CartesianPoint>;
|
||||
using CartesianMultiPolygon = MultiPolygon<CartesianPoint>;
|
||||
using CartesianGeometry = Geometry<CartesianPoint>;
|
||||
|
||||
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>;
|
||||
using GeographicRing = Ring<GeographicPoint>;
|
||||
using GeographicPolygon = Polygon<GeographicPoint>;
|
||||
using GeographicMultiPolygon = MultiPolygon<GeographicPoint>;
|
||||
using GeographicGeometry = Geometry<GeographicPoint>;
|
||||
|
||||
/**
|
||||
* Class which takes some boost type and returns a pair of numbers.
|
||||
@ -111,27 +125,27 @@ private:
|
||||
const Float64 * second;
|
||||
};
|
||||
|
||||
template<class Geometry, class RingType, class PointParser>
|
||||
template<class Point>
|
||||
class RingFromColumnParser
|
||||
{
|
||||
public:
|
||||
RingFromColumnParser(ColumnPtr col_)
|
||||
: offsets(static_cast<const ColumnArray &>(*col_).getOffsets())
|
||||
, pointParser(static_cast<const ColumnArray &>(*col_).getDataPtr())
|
||||
, point_parser(static_cast<const ColumnArray &>(*col_).getDataPtr())
|
||||
{
|
||||
}
|
||||
|
||||
Geometry createContainer() const
|
||||
Geometry<Point> createContainer() const
|
||||
{
|
||||
return RingType();
|
||||
return Ring<Point>();
|
||||
}
|
||||
|
||||
void get(Geometry & container, size_t i) const
|
||||
void get(Geometry<Point> & container, size_t i) const
|
||||
{
|
||||
get(boost::get<RingType>(container), i);
|
||||
get(boost::get<Ring<Point>>(container), i);
|
||||
}
|
||||
|
||||
void get(RingType & container, size_t i) const
|
||||
void get(Ring<Point> & container, size_t i) const
|
||||
{
|
||||
size_t l = offsets[i - 1];
|
||||
size_t r = offsets[i];
|
||||
@ -141,7 +155,7 @@ public:
|
||||
container.resize(r - l);
|
||||
|
||||
for (size_t j = l; j < r; j++) {
|
||||
pointParser.get(container[j - l], j);
|
||||
point_parser.get(container[j - l], j);
|
||||
}
|
||||
|
||||
// make ring closed
|
||||
@ -153,138 +167,127 @@ public:
|
||||
|
||||
private:
|
||||
const IColumn::Offsets & offsets;
|
||||
const PointParser pointParser;
|
||||
const PointFromColumnParser<Point> point_parser;
|
||||
};
|
||||
|
||||
template<class Geometry, class PolygonType, class RingParser>
|
||||
template<class Point>
|
||||
class PolygonFromColumnParser
|
||||
{
|
||||
public:
|
||||
PolygonFromColumnParser(ColumnPtr col_)
|
||||
: offsets(static_cast<const ColumnArray &>(*col_).getOffsets())
|
||||
, ringParser(static_cast<const ColumnArray &>(*col_).getDataPtr())
|
||||
, ring_parser(static_cast<const ColumnArray &>(*col_).getDataPtr())
|
||||
{}
|
||||
|
||||
Geometry createContainer() const
|
||||
Geometry<Point> createContainer() const
|
||||
{
|
||||
return PolygonType();
|
||||
return Polygon<Point>();
|
||||
}
|
||||
|
||||
void get(Geometry & container, size_t i) const
|
||||
void get(Geometry<Point> & container, size_t i) const
|
||||
{
|
||||
get(boost::get<PolygonType>(container), i);
|
||||
get(boost::get<Polygon<Point>>(container), i);
|
||||
}
|
||||
|
||||
void get(PolygonType & container, size_t i) const
|
||||
void get(Polygon<Point> & container, size_t i) const
|
||||
{
|
||||
size_t l = offsets[i - 1];
|
||||
size_t r = offsets[i];
|
||||
|
||||
ringParser.get(container.outer(), l);
|
||||
ring_parser.get(container.outer(), l);
|
||||
|
||||
container.inners().resize(r - l - 1);
|
||||
for (size_t j = l + 1; j < r; j++)
|
||||
{
|
||||
ringParser.get(container.inners()[j - l - 1], j);
|
||||
ring_parser.get(container.inners()[j - l - 1], j);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
const IColumn::Offsets & offsets;
|
||||
const RingParser ringParser;
|
||||
const RingFromColumnParser<Point> ring_parser;
|
||||
};
|
||||
|
||||
template<class Geometry, class MultiPolygonType, class PolygonParser>
|
||||
template<class Point>
|
||||
class MultiPolygonFromColumnParser
|
||||
{
|
||||
public:
|
||||
MultiPolygonFromColumnParser(ColumnPtr col_)
|
||||
: offsets(static_cast<const ColumnArray &>(*col_).getOffsets())
|
||||
, polygonParser(static_cast<const ColumnArray &>(*col_).getDataPtr())
|
||||
, polygon_parser(static_cast<const ColumnArray &>(*col_).getDataPtr())
|
||||
{}
|
||||
|
||||
Geometry createContainer() const
|
||||
Geometry<Point> createContainer() const
|
||||
{
|
||||
return MultiPolygonType();
|
||||
return MultiPolygon<Point>();
|
||||
}
|
||||
|
||||
void get(Geometry & container, size_t i) const
|
||||
void get(Geometry<Point> & container, size_t i) const
|
||||
{
|
||||
MultiPolygonType & multi_polygon = boost::get<MultiPolygonType>(container);
|
||||
auto & multi_polygon = boost::get<MultiPolygon<Point>>(container);
|
||||
size_t l = offsets[i - 1];
|
||||
size_t r = offsets[i];
|
||||
|
||||
multi_polygon.resize(r - l);
|
||||
for (size_t j = l; j < r; j++)
|
||||
{
|
||||
polygonParser.get(multi_polygon[j - l], j);
|
||||
polygon_parser.get(multi_polygon[j - l], j);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
const IColumn::Offsets & offsets;
|
||||
const PolygonParser polygonParser;
|
||||
const PolygonFromColumnParser<Point> polygon_parser;
|
||||
};
|
||||
|
||||
/// Cartesian coordinates
|
||||
|
||||
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
|
||||
template <typename Point>
|
||||
using GeometryFromColumnParser = boost::variant<
|
||||
PointFromColumnParser<Point>,
|
||||
RingFromColumnParser<Point>,
|
||||
PolygonFromColumnParser<Point>,
|
||||
MultiPolygonFromColumnParser<Point>
|
||||
>;
|
||||
|
||||
CartesianGeometry createContainer(const CartesianGeometryFromColumnParser & parser);
|
||||
template <typename Point>
|
||||
Geometry<Point> createContainer(const GeometryFromColumnParser<Point> & parser);
|
||||
|
||||
void get(const CartesianGeometryFromColumnParser & parser, CartesianGeometry & container, size_t i);
|
||||
extern template Geometry<CartesianPoint> createContainer(const GeometryFromColumnParser<CartesianPoint> & parser);
|
||||
extern template Geometry<GeographicPoint> createContainer(const GeometryFromColumnParser<GeographicPoint> & parser);
|
||||
|
||||
CartesianGeometryFromColumnParser makeCartesianGeometryFromColumnParser(const ColumnWithTypeAndName & col);
|
||||
template <typename Point>
|
||||
void get(const GeometryFromColumnParser<Point> & parser, Geometry<Point> & container, size_t i);
|
||||
|
||||
/// Geographic coordinates
|
||||
extern template void get(const GeometryFromColumnParser<CartesianPoint> & parser, Geometry<CartesianPoint> & container, size_t i);
|
||||
extern template void get(const GeometryFromColumnParser<GeographicPoint> & parser, Geometry<GeographicPoint> & container, size_t i);
|
||||
|
||||
using GeographicRingFromColumnParser = RingFromColumnParser<GeographicGeometry, GeographicRing, PointFromColumnParser<GeographicPoint>>;
|
||||
using GeographicPolygonFromColumnParser = PolygonFromColumnParser<GeographicGeometry, GeographicPolygon, GeographicRingFromColumnParser>;
|
||||
using GeographicMultiPolygonFromColumnParser = MultiPolygonFromColumnParser<GeographicGeometry, GeographicMultiPolygon, GeographicPolygonFromColumnParser>;
|
||||
template <typename Point>
|
||||
GeometryFromColumnParser<Point> makeGeometryFromColumnParser(const ColumnWithTypeAndName & col);
|
||||
|
||||
using GeographicGeometryFromColumnParser = boost::variant<
|
||||
PointFromColumnParser<GeographicPoint>,
|
||||
GeographicRingFromColumnParser,
|
||||
GeographicPolygonFromColumnParser,
|
||||
GeographicMultiPolygonFromColumnParser
|
||||
>;
|
||||
extern template GeometryFromColumnParser<CartesianPoint> makeGeometryFromColumnParser(const ColumnWithTypeAndName & col);
|
||||
extern template GeometryFromColumnParser<GeographicPoint> makeGeometryFromColumnParser(const ColumnWithTypeAndName & col);
|
||||
|
||||
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>
|
||||
/// To serialize Geographic or Cartesian point (a pair of numbers in both cases).
|
||||
template <typename Point>
|
||||
class PointSerializerVisitor : public boost::static_visitor<void>
|
||||
{
|
||||
public:
|
||||
CartesianPointSerializerVisitor()
|
||||
: x(ColumnFloat64::create())
|
||||
, y(ColumnFloat64::create())
|
||||
PointSerializerVisitor()
|
||||
: first(ColumnFloat64::create())
|
||||
, second(ColumnFloat64::create())
|
||||
{}
|
||||
|
||||
CartesianPointSerializerVisitor(size_t n)
|
||||
: x(ColumnFloat64::create(n))
|
||||
, y(ColumnFloat64::create(n))
|
||||
PointSerializerVisitor(size_t n)
|
||||
: first(ColumnFloat64::create(n))
|
||||
, second(ColumnFloat64::create(n))
|
||||
{}
|
||||
|
||||
void operator()(const CartesianPoint & point)
|
||||
void operator()(const Point & point)
|
||||
{
|
||||
x->insertValue(point.get<0>());
|
||||
y->insertValue(point.get<1>());
|
||||
first->insertValue(point.template get<0>());
|
||||
second->insertValue(point.template get<1>());
|
||||
}
|
||||
|
||||
void operator()(const CartesianRing & ring)
|
||||
void operator()(const Ring<Point> & ring)
|
||||
{
|
||||
if (ring.size() != 1) {
|
||||
throw Exception("Unable to write ring of size " + toString(ring.size()) + " != 1 to point column", ErrorCodes::BAD_ARGUMENTS);
|
||||
@ -292,7 +295,7 @@ public:
|
||||
(*this)(ring[0]);
|
||||
}
|
||||
|
||||
void operator()(const CartesianPolygon & polygon)
|
||||
void operator()(const Polygon<Point> & polygon)
|
||||
{
|
||||
if (polygon.inners().size() != 0) {
|
||||
throw Exception("Unable to write polygon with holes to point column", ErrorCodes::BAD_ARGUMENTS);
|
||||
@ -300,7 +303,7 @@ public:
|
||||
(*this)(polygon.outer());
|
||||
}
|
||||
|
||||
void operator()(const CartesianMultiPolygon & multi_polygon)
|
||||
void operator()(const MultiPolygon<Point> & 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);
|
||||
@ -311,29 +314,30 @@ public:
|
||||
ColumnPtr finalize()
|
||||
{
|
||||
Columns columns(2);
|
||||
columns[0] = std::move(x);
|
||||
columns[1] = std::move(y);
|
||||
columns[0] = std::move(first);
|
||||
columns[1] = std::move(second);
|
||||
|
||||
return ColumnTuple::create(columns);
|
||||
}
|
||||
|
||||
private:
|
||||
ColumnFloat64::MutablePtr x;
|
||||
ColumnFloat64::MutablePtr y;
|
||||
ColumnFloat64::MutablePtr first;
|
||||
ColumnFloat64::MutablePtr second;
|
||||
};
|
||||
|
||||
class CartesianRingSerializerVisitor : public boost::static_visitor<void>
|
||||
template <typename Point>
|
||||
class RingSerializerVisitor : public boost::static_visitor<void>
|
||||
{
|
||||
public:
|
||||
CartesianRingSerializerVisitor()
|
||||
RingSerializerVisitor()
|
||||
: offsets(ColumnUInt64::create())
|
||||
{}
|
||||
|
||||
CartesianRingSerializerVisitor(size_t n)
|
||||
RingSerializerVisitor(size_t n)
|
||||
: offsets(ColumnUInt64::create(n))
|
||||
{}
|
||||
|
||||
void operator()(const CartesianPoint & point)
|
||||
void operator()(const Point & point)
|
||||
{
|
||||
size++;
|
||||
offsets->insertValue(size);
|
||||
@ -341,7 +345,7 @@ public:
|
||||
pointSerializer(point);
|
||||
}
|
||||
|
||||
void operator()(const CartesianRing & ring)
|
||||
void operator()(const Ring<Point> & ring)
|
||||
{
|
||||
size += ring.size();
|
||||
offsets->insertValue(size);
|
||||
@ -351,7 +355,7 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
void operator()(const CartesianPolygon & polygon)
|
||||
void operator()(const Polygon<Point> & polygon)
|
||||
{
|
||||
if (polygon.inners().size() != 0) {
|
||||
throw Exception("Unable to write polygon with holes to ring column", ErrorCodes::BAD_ARGUMENTS);
|
||||
@ -359,7 +363,7 @@ public:
|
||||
(*this)(polygon.outer());
|
||||
}
|
||||
|
||||
void operator()(const CartesianMultiPolygon & multi_polygon)
|
||||
void operator()(const MultiPolygon<Point> & 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);
|
||||
@ -374,36 +378,37 @@ public:
|
||||
|
||||
private:
|
||||
size_t size = 0;
|
||||
CartesianPointSerializerVisitor pointSerializer;
|
||||
PointSerializerVisitor<Point> pointSerializer;
|
||||
ColumnUInt64::MutablePtr offsets;
|
||||
};
|
||||
|
||||
class CartesianPolygonSerializerVisitor : public boost::static_visitor<void>
|
||||
template <typename Point>
|
||||
class PolygonSerializerVisitor : public boost::static_visitor<void>
|
||||
{
|
||||
public:
|
||||
CartesianPolygonSerializerVisitor()
|
||||
PolygonSerializerVisitor()
|
||||
: offsets(ColumnUInt64::create())
|
||||
{}
|
||||
|
||||
CartesianPolygonSerializerVisitor(size_t n)
|
||||
PolygonSerializerVisitor(size_t n)
|
||||
: offsets(ColumnUInt64::create(n))
|
||||
{}
|
||||
|
||||
void operator()(const CartesianPoint & point)
|
||||
void operator()(const Point & point)
|
||||
{
|
||||
size++;
|
||||
offsets->insertValue(size);
|
||||
ringSerializer(point);
|
||||
}
|
||||
|
||||
void operator()(const CartesianRing & ring)
|
||||
void operator()(const Ring<Point> & ring)
|
||||
{
|
||||
size++;
|
||||
offsets->insertValue(size);
|
||||
ringSerializer(ring);
|
||||
}
|
||||
|
||||
void operator()(const CartesianPolygon & polygon)
|
||||
void operator()(const Polygon<Point> & polygon)
|
||||
{
|
||||
size += 1 + polygon.inners().size();
|
||||
offsets->insertValue(size);
|
||||
@ -414,7 +419,7 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
void operator()(const CartesianMultiPolygon & multi_polygon)
|
||||
void operator()(const MultiPolygon<Point> & 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);
|
||||
@ -429,43 +434,44 @@ public:
|
||||
|
||||
private:
|
||||
size_t size = 0;
|
||||
CartesianRingSerializerVisitor ringSerializer;
|
||||
RingSerializerVisitor<Point> ringSerializer;
|
||||
ColumnUInt64::MutablePtr offsets;
|
||||
};
|
||||
|
||||
class CartesianMultiPolygonSerializerVisitor : public boost::static_visitor<void>
|
||||
template <typename Point>
|
||||
class MultiPolygonSerializerVisitor : public boost::static_visitor<void>
|
||||
{
|
||||
public:
|
||||
CartesianMultiPolygonSerializerVisitor()
|
||||
MultiPolygonSerializerVisitor()
|
||||
: offsets(ColumnUInt64::create())
|
||||
{}
|
||||
|
||||
CartesianMultiPolygonSerializerVisitor(size_t n)
|
||||
MultiPolygonSerializerVisitor(size_t n)
|
||||
: offsets(ColumnUInt64::create(n))
|
||||
{}
|
||||
|
||||
void operator()(const CartesianPoint & point)
|
||||
void operator()(const Point & point)
|
||||
{
|
||||
size++;
|
||||
offsets->insertValue(size);
|
||||
polygonSerializer(point);
|
||||
}
|
||||
|
||||
void operator()(const CartesianRing & ring)
|
||||
void operator()(const Ring<Point> & ring)
|
||||
{
|
||||
size++;
|
||||
offsets->insertValue(size);
|
||||
polygonSerializer(ring);
|
||||
}
|
||||
|
||||
void operator()(const CartesianPolygon & polygon)
|
||||
void operator()(const Polygon<Point> & polygon)
|
||||
{
|
||||
size++;
|
||||
offsets->insertValue(size);
|
||||
polygonSerializer(polygon);
|
||||
}
|
||||
|
||||
void operator()(const CartesianMultiPolygon & multi_polygon)
|
||||
void operator()(const MultiPolygon<Point> & multi_polygon)
|
||||
{
|
||||
size += multi_polygon.size();
|
||||
offsets->insertValue(size);
|
||||
@ -482,7 +488,7 @@ public:
|
||||
|
||||
private:
|
||||
size_t size = 0;
|
||||
CartesianPolygonSerializerVisitor polygonSerializer;
|
||||
PolygonSerializerVisitor<Point> polygonSerializer;
|
||||
ColumnUInt64::MutablePtr offsets;
|
||||
};
|
||||
|
||||
@ -503,9 +509,16 @@ private:
|
||||
Visitor visitor;
|
||||
};
|
||||
|
||||
using CartesianPointSerializer = GeometrySerializer<CartesianGeometry, CartesianPointSerializerVisitor>;
|
||||
using CartesianRingSerializer = GeometrySerializer<CartesianGeometry, CartesianRingSerializerVisitor>;
|
||||
using CartesianPolygonSerializer = GeometrySerializer<CartesianGeometry, CartesianPolygonSerializerVisitor>;
|
||||
using CartesianMultiPolygonSerializer = GeometrySerializer<CartesianGeometry, CartesianMultiPolygonSerializerVisitor>;
|
||||
template <typename Point>
|
||||
using PointSerializer = GeometrySerializer<Geometry<Point>, PointSerializerVisitor<Point>>;
|
||||
|
||||
template <typename Point>
|
||||
using RingSerializer = GeometrySerializer<Geometry<Point>, RingSerializerVisitor<Point>>;
|
||||
|
||||
template <typename Point>
|
||||
using PolygonSerializer = GeometrySerializer<Geometry<Point>, PolygonSerializerVisitor<Point>>;
|
||||
|
||||
template <typename Point>
|
||||
using MultiPolygonSerializer = GeometrySerializer<Geometry<Point>, MultiPolygonSerializerVisitor<Point>>;
|
||||
|
||||
}
|
||||
|
@ -28,17 +28,17 @@ namespace ErrorCodes
|
||||
extern const int ILLEGAL_COLUMN;
|
||||
}
|
||||
|
||||
template <typename Derived>
|
||||
class FunctionPolygonAreaBase : public IFunction
|
||||
template <typename Point>
|
||||
class FunctionPolygonArea : public IFunction
|
||||
{
|
||||
public:
|
||||
static inline const char * name = Derived::name;
|
||||
static inline const char * name;
|
||||
|
||||
explicit FunctionPolygonAreaBase() = default;
|
||||
explicit FunctionPolygonArea() = default;
|
||||
|
||||
static FunctionPtr create(const Context &)
|
||||
{
|
||||
return std::make_shared<FunctionPolygonAreaBase>();
|
||||
return std::make_shared<FunctionPolygonArea>();
|
||||
}
|
||||
|
||||
String getName() const override
|
||||
@ -61,9 +61,24 @@ public:
|
||||
return std::make_shared<DataTypeFloat64>();
|
||||
}
|
||||
|
||||
ColumnPtr executeImpl(const ColumnsWithTypeAndName & arguments, const DataTypePtr & result_type, size_t input_rows_count) const override
|
||||
ColumnPtr executeImpl(const ColumnsWithTypeAndName & arguments, const DataTypePtr & /*result_type*/, size_t input_rows_count) const override
|
||||
{
|
||||
return static_cast<const Derived*>(this)->executeImplementation(arguments, result_type, input_rows_count);
|
||||
auto parser = makeGeometryFromColumnParser<Point>(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<MultiPolygon<Point>>(container));
|
||||
|
||||
res_column->insertValue(area);
|
||||
}
|
||||
|
||||
return res_column;
|
||||
}
|
||||
|
||||
bool useDefaultImplementationForConstants() const override
|
||||
@ -72,68 +87,18 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
const char * FunctionPolygonArea<CartesianPoint>::name = "polygonAreaCartesian";
|
||||
|
||||
class FunctionPolygonAreaCartesian : public FunctionPolygonAreaBase<FunctionPolygonAreaCartesian>
|
||||
template <>
|
||||
const char * FunctionPolygonArea<GeographicPoint>::name = "polygonAreaGeographic";
|
||||
|
||||
|
||||
void registerFunctionPolygonArea(FunctionFactory & factory)
|
||||
{
|
||||
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>();
|
||||
factory.registerFunction<FunctionPolygonArea<CartesianPoint>>();
|
||||
factory.registerFunction<FunctionPolygonArea<GeographicPoint>>();
|
||||
}
|
||||
|
||||
void registerFunctionPolygonAreaGeographic(FunctionFactory & factory)
|
||||
{
|
||||
factory.registerFunction<FunctionPolygonAreaGeographic>();
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -28,10 +28,11 @@ namespace ErrorCodes
|
||||
extern const int ILLEGAL_COLUMN;
|
||||
}
|
||||
|
||||
template <typename Point>
|
||||
class FunctionPolygonConvexHull : public IFunction
|
||||
{
|
||||
public:
|
||||
static inline const char * name = "polygonConvexHull";
|
||||
static const char * name;
|
||||
|
||||
explicit FunctionPolygonConvexHull() = default;
|
||||
|
||||
@ -62,27 +63,22 @@ public:
|
||||
|
||||
ColumnPtr executeImpl(const ColumnsWithTypeAndName & arguments, const DataTypePtr & /*result_type*/, size_t input_rows_count) const override
|
||||
{
|
||||
auto get_parser = [&arguments] (size_t i) {
|
||||
const ColumnWithTypeAndName polygon = arguments[i];
|
||||
return makeCartesianGeometryFromColumnParser(polygon);
|
||||
};
|
||||
|
||||
auto parser = get_parser(0);
|
||||
auto parser = makeGeometryFromColumnParser<Point>(arguments[0]);
|
||||
auto container = createContainer(parser);
|
||||
|
||||
CartesianPolygonSerializer serializer;
|
||||
PolygonSerializer<Point> serializer;
|
||||
|
||||
for (size_t i = 0; i < input_rows_count; i++)
|
||||
{
|
||||
get(parser, container, i);
|
||||
|
||||
CartesianGeometry convex_hull = CartesianPolygon({{{}}});
|
||||
Geometry<Point> convex_hull = Polygon<Point>({{{}}});
|
||||
boost::geometry::convex_hull(
|
||||
boost::get<CartesianMultiPolygon>(container),
|
||||
boost::get<CartesianPolygon>(convex_hull));
|
||||
boost::get<MultiPolygon<Point>>(container),
|
||||
boost::get<Polygon<Point>>(convex_hull));
|
||||
|
||||
boost::get<CartesianPolygon>(convex_hull).outer().erase(
|
||||
boost::get<CartesianPolygon>(convex_hull).outer().begin());
|
||||
boost::get<Polygon<Point>>(convex_hull).outer().erase(
|
||||
boost::get<Polygon<Point>>(convex_hull).outer().begin());
|
||||
|
||||
serializer.add(convex_hull);
|
||||
}
|
||||
@ -97,9 +93,17 @@ public:
|
||||
};
|
||||
|
||||
|
||||
template <>
|
||||
const char * FunctionPolygonConvexHull<CartesianPoint>::name = "polygonConvexHullCartesian";
|
||||
|
||||
// template <>
|
||||
// const char * FunctionPolygonConvexHull<GeographicPoint>::name = "polygonConvexHullGeographic";
|
||||
|
||||
|
||||
void registerFunctionPolygonConvexHull(FunctionFactory & factory)
|
||||
{
|
||||
factory.registerFunction<FunctionPolygonConvexHull>();
|
||||
factory.registerFunction<FunctionPolygonConvexHull<CartesianPoint>>();
|
||||
// factory.registerFunction<FunctionPolygonConvexHull<GeographicPoint>>();
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -28,17 +28,17 @@ namespace ErrorCodes
|
||||
extern const int ILLEGAL_COLUMN;
|
||||
}
|
||||
|
||||
template <typename Derived>
|
||||
class FunctionPolygonPerimeterBase : public IFunction
|
||||
template <typename Point>
|
||||
class FunctionPolygonPerimeter : public IFunction
|
||||
{
|
||||
public:
|
||||
static inline const char * name = Derived::name;
|
||||
static const char * name;
|
||||
|
||||
explicit FunctionPolygonPerimeterBase() = default;
|
||||
explicit FunctionPolygonPerimeter() = default;
|
||||
|
||||
static FunctionPtr create(const Context &)
|
||||
{
|
||||
return std::make_shared<FunctionPolygonPerimeterBase>();
|
||||
return std::make_shared<FunctionPolygonPerimeter>();
|
||||
}
|
||||
|
||||
String getName() const override
|
||||
@ -61,9 +61,24 @@ public:
|
||||
return std::make_shared<DataTypeFloat64>();
|
||||
}
|
||||
|
||||
ColumnPtr executeImpl(const ColumnsWithTypeAndName & arguments, const DataTypePtr & result_type, size_t input_rows_count) const override
|
||||
ColumnPtr executeImpl(const ColumnsWithTypeAndName & arguments, const DataTypePtr & /*result_type*/, size_t input_rows_count) const override
|
||||
{
|
||||
return static_cast<const Derived*>(this)->executeImplementation(arguments, result_type, input_rows_count);
|
||||
auto parser = makeGeometryFromColumnParser<Point>(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<MultiPolygon<Point>>(container));
|
||||
|
||||
res_column->insertValue(perimeter);
|
||||
}
|
||||
|
||||
return res_column;
|
||||
}
|
||||
|
||||
bool useDefaultImplementationForConstants() const override
|
||||
@ -72,69 +87,18 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
class FunctionPolygonPerimeterCartesian : public FunctionPolygonPerimeterBase<FunctionPolygonPerimeterCartesian>
|
||||
template <>
|
||||
const char * FunctionPolygonPerimeter<CartesianPoint>::name = "polygonPerimeterCartesian";
|
||||
|
||||
template <>
|
||||
const char * FunctionPolygonPerimeter<GeographicPoint>::name = "polygonPerimeterGeographic";
|
||||
|
||||
|
||||
void registerFunctionPolygonPerimeter(FunctionFactory & factory)
|
||||
{
|
||||
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();
|
||||
|
||||
for (size_t i = 0; i < input_rows_count; i++)
|
||||
{
|
||||
get(parser, container, i);
|
||||
|
||||
Float64 perimeter = boost::geometry::perimeter(
|
||||
boost::get<CartesianMultiPolygon>(container));
|
||||
|
||||
res_column->insertValue(perimeter);
|
||||
}
|
||||
|
||||
return res_column;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
class FunctionPolygonPerimeterGeographic : public FunctionPolygonPerimeterBase<FunctionPolygonPerimeterGeographic>
|
||||
{
|
||||
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>();
|
||||
factory.registerFunction<FunctionPolygonPerimeter<CartesianPoint>>();
|
||||
factory.registerFunction<FunctionPolygonPerimeter<GeographicPoint>>();
|
||||
}
|
||||
|
||||
void registerFunctionPolygonPerimeterGeographic(FunctionFactory & factory)
|
||||
{
|
||||
factory.registerFunction<FunctionPolygonPerimeterGeographic>();
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -30,17 +30,17 @@ namespace ErrorCodes
|
||||
extern const int ILLEGAL_COLUMN;
|
||||
}
|
||||
|
||||
template <typename Derived>
|
||||
class FunctionPolygonsDistanceBase : public IFunction
|
||||
template <typename Point>
|
||||
class FunctionPolygonsDistance : public IFunction
|
||||
{
|
||||
public:
|
||||
static inline const char * name = Derived::name;
|
||||
static inline const char * name;
|
||||
|
||||
explicit FunctionPolygonsDistanceBase() = default;
|
||||
explicit FunctionPolygonsDistance() = default;
|
||||
|
||||
static FunctionPtr create(const Context &)
|
||||
{
|
||||
return std::make_shared<FunctionPolygonsDistanceBase>();
|
||||
return std::make_shared<FunctionPolygonsDistance>();
|
||||
}
|
||||
|
||||
String getName() const override
|
||||
@ -63,9 +63,29 @@ public:
|
||||
return std::make_shared<DataTypeFloat64>();
|
||||
}
|
||||
|
||||
ColumnPtr executeImpl(const ColumnsWithTypeAndName & arguments, const DataTypePtr & result_type, size_t input_rows_count) const override
|
||||
ColumnPtr executeImpl(const ColumnsWithTypeAndName & arguments, const DataTypePtr & /*result_type*/, size_t input_rows_count) const override
|
||||
{
|
||||
return static_cast<const Derived*>(this)->executeImplementation(arguments, result_type, input_rows_count);
|
||||
auto first_parser = makeGeometryFromColumnParser<Point>(arguments[0]);
|
||||
auto first_container = createContainer(first_parser);
|
||||
|
||||
auto second_parser = makeGeometryFromColumnParser<Point>(arguments[1]);
|
||||
auto second_container = createContainer(second_parser);
|
||||
|
||||
auto res_column = ColumnFloat64::create();
|
||||
|
||||
for (size_t i = 0; i < input_rows_count; i++)
|
||||
{
|
||||
get(first_parser, first_container, i);
|
||||
get(second_parser, second_container, i);
|
||||
|
||||
Float64 distance = boost::geometry::distance(
|
||||
boost::get<MultiPolygon<Point>>(first_container),
|
||||
boost::get<MultiPolygon<Point>>(second_container));
|
||||
|
||||
res_column->insertValue(distance);
|
||||
}
|
||||
|
||||
return res_column;
|
||||
}
|
||||
|
||||
bool useDefaultImplementationForConstants() const override
|
||||
@ -74,73 +94,18 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
const char * FunctionPolygonsDistance<CartesianPoint>::name = "polygonsDistanceCartesian";
|
||||
|
||||
class FunctionPolygonsDistanceCartesian : public FunctionPolygonsDistanceBase<FunctionPolygonsDistanceCartesian>
|
||||
template <>
|
||||
const char * FunctionPolygonsDistance<GeographicPoint>::name = "polygonsDistanceGeographic";
|
||||
|
||||
|
||||
void registerFunctionPolygonsDistance(FunctionFactory & factory)
|
||||
{
|
||||
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>();
|
||||
factory.registerFunction<FunctionPolygonsDistance<CartesianPoint>>();
|
||||
factory.registerFunction<FunctionPolygonsDistance<GeographicPoint>>();
|
||||
}
|
||||
|
||||
void registerFunctionPolygonsDistanceGeographic(FunctionFactory & factory)
|
||||
{
|
||||
factory.registerFunction<FunctionPolygonsDistanceGeographic>();
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -70,9 +70,9 @@ public:
|
||||
|
||||
bool is_const = static_cast<bool>(const_col);
|
||||
|
||||
return std::pair<bool, CartesianGeometryFromColumnParser>{is_const, is_const ?
|
||||
makeCartesianGeometryFromColumnParser(ColumnWithTypeAndName(const_col->getDataColumnPtr(), arguments[i].type, arguments[i].name)) :
|
||||
makeCartesianGeometryFromColumnParser(arguments[i])};
|
||||
return std::pair<bool, GeometryFromColumnParser<CartesianPoint>>{is_const, is_const ?
|
||||
makeGeometryFromColumnParser<CartesianPoint>(ColumnWithTypeAndName(const_col->getDataColumnPtr(), arguments[i].type, arguments[i].name)) :
|
||||
makeGeometryFromColumnParser<CartesianPoint>(arguments[i])};
|
||||
};
|
||||
|
||||
auto [is_first_polygon_const, first_parser] = get_parser(0);
|
||||
|
@ -63,13 +63,13 @@ public:
|
||||
|
||||
ColumnPtr executeImpl(const ColumnsWithTypeAndName & arguments, const DataTypePtr & /*result_type*/, size_t input_rows_count) const override
|
||||
{
|
||||
auto first_parser = makeCartesianGeometryFromColumnParser(arguments[0]);
|
||||
auto first_parser = makeGeometryFromColumnParser<CartesianPoint>(arguments[0]);
|
||||
auto first_container = createContainer(first_parser);
|
||||
|
||||
auto second_parser = makeCartesianGeometryFromColumnParser(arguments[1]);
|
||||
auto second_parser = makeGeometryFromColumnParser<CartesianPoint>(arguments[1]);
|
||||
auto second_container = createContainer(second_parser);
|
||||
|
||||
CartesianMultiPolygonSerializer serializer;
|
||||
MultiPolygonSerializer<CartesianPoint> serializer;
|
||||
|
||||
for (size_t i = 0; i < input_rows_count; i++)
|
||||
{
|
||||
|
@ -28,10 +28,11 @@ namespace ErrorCodes
|
||||
extern const int ILLEGAL_COLUMN;
|
||||
}
|
||||
|
||||
template <typename Point>
|
||||
class FunctionPolygonsSymDifference : public IFunction
|
||||
{
|
||||
public:
|
||||
static inline const char * name = "polygonsSymDifference";
|
||||
static const char * name;
|
||||
|
||||
explicit FunctionPolygonsSymDifference() = default;
|
||||
|
||||
@ -62,40 +63,27 @@ public:
|
||||
|
||||
ColumnPtr executeImpl(const ColumnsWithTypeAndName & arguments, const DataTypePtr & /*result_type*/, size_t input_rows_count) const override
|
||||
{
|
||||
auto get_parser = [&arguments] (size_t i) {
|
||||
const auto * const_col =
|
||||
checkAndGetColumn<ColumnConst>(arguments[i].column.get());
|
||||
|
||||
bool is_const = static_cast<bool>(const_col);
|
||||
|
||||
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);
|
||||
auto first_parser = makeGeometryFromColumnParser<Point>(arguments[0]);
|
||||
auto first_container = createContainer(first_parser);
|
||||
|
||||
auto [is_second_polygon_const, second_parser] = get_parser(1);
|
||||
auto second_parser = makeGeometryFromColumnParser<Point>(arguments[1]);
|
||||
auto second_container = createContainer(second_parser);
|
||||
|
||||
CartesianMultiPolygonSerializer serializer;
|
||||
MultiPolygonSerializer<Point> serializer;
|
||||
|
||||
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);
|
||||
|
||||
CartesianGeometry sym_difference = CartesianMultiPolygon({{{{}}}});
|
||||
Geometry<Point> sym_difference = MultiPolygon<Point>({{{{}}}});
|
||||
boost::geometry::sym_difference(
|
||||
boost::get<CartesianMultiPolygon>(first_container),
|
||||
boost::get<CartesianMultiPolygon>(second_container),
|
||||
boost::get<CartesianMultiPolygon>(sym_difference));
|
||||
boost::get<MultiPolygon<Point>>(first_container),
|
||||
boost::get<MultiPolygon<Point>>(second_container),
|
||||
boost::get<MultiPolygon<Point>>(sym_difference));
|
||||
|
||||
boost::get<CartesianMultiPolygon>(sym_difference).erase(
|
||||
boost::get<CartesianMultiPolygon>(sym_difference).begin());
|
||||
boost::get<MultiPolygon<Point>>(sym_difference).erase(
|
||||
boost::get<MultiPolygon<Point>>(sym_difference).begin());
|
||||
|
||||
serializer.add(sym_difference);
|
||||
}
|
||||
@ -109,10 +97,18 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
const char * FunctionPolygonsSymDifference<CartesianPoint>::name = "polygonsSymDifferenceCartesian";
|
||||
|
||||
template <>
|
||||
const char * FunctionPolygonsSymDifference<GeographicPoint>::name = "polygonsSymDifferenceGeographic";
|
||||
|
||||
void registerFunctionPolygonsSymDifference(FunctionFactory & factory)
|
||||
{
|
||||
factory.registerFunction<FunctionPolygonsSymDifference>();
|
||||
factory.registerFunction<FunctionPolygonsSymDifference<CartesianPoint>>();
|
||||
factory.registerFunction<FunctionPolygonsSymDifference<GeographicPoint>>();
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
@ -70,9 +70,9 @@ public:
|
||||
|
||||
bool is_const = static_cast<bool>(const_col);
|
||||
|
||||
return std::pair<bool, CartesianGeometryFromColumnParser>{is_const, is_const ?
|
||||
makeCartesianGeometryFromColumnParser(ColumnWithTypeAndName(const_col->getDataColumnPtr(), arguments[i].type, arguments[i].name)) :
|
||||
makeCartesianGeometryFromColumnParser(arguments[i])};
|
||||
return std::pair<bool, GeometryFromColumnParser<CartesianPoint>>{is_const, is_const ?
|
||||
makeGeometryFromColumnParser<CartesianPoint>(ColumnWithTypeAndName(const_col->getDataColumnPtr(), arguments[i].type, arguments[i].name)) :
|
||||
makeGeometryFromColumnParser<CartesianPoint>(arguments[i])};
|
||||
};
|
||||
|
||||
auto [is_first_polygon_const, first_parser] = get_parser(0);
|
||||
|
@ -62,7 +62,7 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
class FunctionReadWktPoint : public FunctionReadWkt<DataTypeCustomPointSerialization, CartesianPoint, CartesianPointSerializer>
|
||||
class FunctionReadWktPoint : public FunctionReadWkt<DataTypeCustomPointSerialization, CartesianPoint, PointSerializer<CartesianPoint>>
|
||||
{
|
||||
public:
|
||||
static inline const char * name = "readWktPoint";
|
||||
@ -76,7 +76,7 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
class FunctionReadWktPolygon : public FunctionReadWkt<DataTypeCustomPolygonSerialization, CartesianPolygon, CartesianPolygonSerializer>
|
||||
class FunctionReadWktPolygon : public FunctionReadWkt<DataTypeCustomPolygonSerialization, CartesianPolygon, PolygonSerializer<CartesianPoint>>
|
||||
{
|
||||
public:
|
||||
static inline const char * name = "readWktPolygon";
|
||||
@ -90,7 +90,7 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
class FunctionReadWktMultiPolygon : public FunctionReadWkt<DataTypeCustomMultiPolygonSerialization, CartesianMultiPolygon, CartesianMultiPolygonSerializer>
|
||||
class FunctionReadWktMultiPolygon : public FunctionReadWkt<DataTypeCustomMultiPolygonSerialization, CartesianMultiPolygon, MultiPolygonSerializer<CartesianPoint>>
|
||||
{
|
||||
public:
|
||||
static inline const char * name = "readWktMultiPolygon";
|
||||
|
@ -12,16 +12,13 @@ void registerFunctionPointInEllipses(FunctionFactory & factory);
|
||||
void registerFunctionPointInPolygon(FunctionFactory & factory);
|
||||
void registerFunctionPolygonsIntersection(FunctionFactory & factory);
|
||||
void registerFunctionPolygonsUnion(FunctionFactory & factory);
|
||||
void registerFunctionPolygonAreaCartesian(FunctionFactory & factory);
|
||||
void registerFunctionPolygonAreaGeographic (FunctionFactory & factory);
|
||||
void registerFunctionPolygonArea(FunctionFactory & factory);
|
||||
void registerFunctionPolygonConvexHull(FunctionFactory & factory);
|
||||
void registerFunctionPolygonsSymDifference(FunctionFactory & factory);
|
||||
void registerFunctionPolygonsEquals(FunctionFactory & factory);
|
||||
void registerFunctionPolygonsDistanceCartesian(FunctionFactory & factory);
|
||||
void registerFunctionPolygonsDistanceGeographic(FunctionFactory & factory);
|
||||
void registerFunctionPolygonsDistance(FunctionFactory & factory);
|
||||
void registerFunctionPolygonsWithin(FunctionFactory & factory);
|
||||
void registerFunctionPolygonPerimeterCartesian(FunctionFactory & factory);
|
||||
void registerFunctionPolygonPerimeterGeographic(FunctionFactory & factory);
|
||||
void registerFunctionPolygonPerimeter(FunctionFactory & factory);
|
||||
void registerFunctionGeohashEncode(FunctionFactory & factory);
|
||||
void registerFunctionGeohashDecode(FunctionFactory & factory);
|
||||
void registerFunctionGeohashesInBox(FunctionFactory & factory);
|
||||
@ -53,16 +50,13 @@ void registerFunctionsGeo(FunctionFactory & factory)
|
||||
registerFunctionPointInPolygon(factory);
|
||||
registerFunctionPolygonsIntersection(factory);
|
||||
registerFunctionPolygonsUnion(factory);
|
||||
registerFunctionPolygonAreaCartesian(factory);
|
||||
registerFunctionPolygonAreaGeographic(factory);
|
||||
registerFunctionPolygonArea(factory);
|
||||
registerFunctionPolygonConvexHull(factory);
|
||||
registerFunctionPolygonsSymDifference(factory);
|
||||
registerFunctionPolygonsEquals(factory);
|
||||
registerFunctionPolygonsDistanceCartesian(factory);
|
||||
registerFunctionPolygonsDistanceGeographic(factory);
|
||||
registerFunctionPolygonsDistance(factory);
|
||||
registerFunctionPolygonsWithin(factory);
|
||||
registerFunctionPolygonPerimeterCartesian(factory);
|
||||
registerFunctionPolygonPerimeterGeographic(factory);
|
||||
registerFunctionPolygonPerimeter(factory);
|
||||
registerFunctionGeohashEncode(factory);
|
||||
registerFunctionGeohashDecode(factory);
|
||||
registerFunctionGeohashesInBox(factory);
|
||||
|
@ -65,8 +65,8 @@ public:
|
||||
const auto * const_col = checkAndGetColumn<ColumnConst>(arguments[0].column.get());
|
||||
|
||||
auto parser = const_col ?
|
||||
makeCartesianGeometryFromColumnParser(ColumnWithTypeAndName(const_col->getDataColumnPtr(), arguments[0].type, arguments[0].name)) :
|
||||
makeCartesianGeometryFromColumnParser(arguments[0]);
|
||||
makeGeometryFromColumnParser<CartesianPoint>(ColumnWithTypeAndName(const_col->getDataColumnPtr(), arguments[0].type, arguments[0].name)) :
|
||||
makeGeometryFromColumnParser<CartesianPoint>(arguments[0]);
|
||||
|
||||
bool geo_column_is_const = static_cast<bool>(const_col);
|
||||
|
||||
|
@ -38,7 +38,7 @@ public:
|
||||
|
||||
ColumnPtr executeImpl(const ColumnsWithTypeAndName & arguments, const DataTypePtr & /*result_type*/, size_t input_rows_count) const override
|
||||
{
|
||||
auto parser = makeCartesianGeometryFromColumnParser(arguments[0]);
|
||||
auto parser = makeGeometryFromColumnParser<CartesianPoint>(arguments[0]);
|
||||
auto res_column = ColumnString::create();
|
||||
|
||||
auto container = createContainer(parser);
|
||||
|
@ -1,7 +1,8 @@
|
||||
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
|
||||
|
||||
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;
|
||||
select polygonsDistanceGeographic(x, y) from polygon_01302;
|
||||
|
@ -1 +1,2 @@
|
||||
[[[(1,2.9),(2,2.6),(2.6,2),(2.9,1),(1,1),(1,2.9)]]]
|
||||
[]
|
||||
|
@ -1 +1,2 @@
|
||||
select polygonsIntersection([[[(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 polygonsIntersection([[[(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 polygonsIntersection([[[(0, 0),(0, 3),(1, 2.9),(2, 2.6),(2.6, 2),(2.9, 1),(3, 0),(0, 0)]]], [[[(3, 3),(3, 4),(4, 4),(4, 3),(3, 3)]]]);
|
Loading…
Reference in New Issue
Block a user