提交 78e0db26 编写于 作者: A Alexey Ilyukhov 提交者: Nikita Mikhaylov

Add ring parser

上级 33acc2aa
#include <Columns/ColumnsNumber.h>
#include <Columns/ColumnTuple.h>
#include <DataTypes/DataTypeArray.h>
#include <DataTypes/IDataType.h>
#include <Functions/geometryFromColumn.h>
namespace DB {
namespace ErrorCodes
{
extern const int ILLEGAL_COLUMN;
}
namespace {
Exception failedToParse(const ColumnWithTypeAndName & col, std::string reason = "")
{
return Exception("Cannot parse geometry from column with type " + col.type->getName()
+ (reason.empty() ? std::string() : ", " + reason), ErrorCodes::ILLEGAL_COLUMN);
}
size_t getArrayDepth(const ColumnWithTypeAndName & col, size_t max_depth)
{
size_t depth = 0;
......@@ -35,37 +20,15 @@ size_t getArrayDepth(const ColumnWithTypeAndName & col, size_t max_depth)
}
PointFromColumnParser::PointFromColumnParser(const ColumnWithTypeAndName & col)
{
const auto & tuple_columns = static_cast<const ColumnTuple &>(*col.column).getColumns();
if (tuple_columns.size() != 2) {
throw failedToParse(col, "tuple must have exactly 2 columns");
}
x = static_cast<const ColumnFloat64 &>(*tuple_columns[0]).getData().data();
y = static_cast<const ColumnFloat64 &>(*tuple_columns[1]).getData().data();
}
Point PointFromColumnParser::createContainer() const
{
return Point();
}
void PointFromColumnParser::get(Point & container, size_t i) const
{
boost::geometry::set<0>(container, x[i]);
boost::geometry::set<0>(container, y[i]);
}
GeometryFromColumnParser makeGeometryFromColumnParser(const ColumnWithTypeAndName & col)
{
switch (getArrayDepth(col, 3)) {
case 0: return PointFromColumnParser(col);
// case 1: return parseRing(col, i);
case 0: return Float64PointFromColumnParser(*col.column);
case 1: return Float64RingFromColumnParser(*col.column);
// case 2: return parsePolygon(col, i);
// case 3: return parseMultyPoligon(col, i);
default: throw failedToParse(col, "array depth is too big");
default: throw Exception("Cannot parse geometry from column with type " + col.type->getName()
+ ", array depth is too big", ErrorCodes::ILLEGAL_COLUMN);
}
}
......
......@@ -8,27 +8,101 @@
#include <boost/geometry.hpp>
#include <boost/geometry/geometries/point_xy.hpp>
#include <Columns/ColumnsNumber.h>
#include <Columns/ColumnArray.h>
#include <Columns/ColumnTuple.h>
#include <DataTypes/DataTypeArray.h>
#include <DataTypes/IDataType.h>
namespace DB {
using Point = boost::geometry::model::d2::point_xy<Float64>;
using Ring = boost::geometry::model::ring<Point>;
using Polygon = boost::geometry::model::polygon<Point>;
using MultiPolygon = boost::geometry::model::multi_polygon<Polygon>;
using Geometry = boost::variant<Point, Ring, Polygon, MultiPolygon>;
namespace ErrorCodes
{
extern const int ILLEGAL_COLUMN;
}
class PointFromColumnParser
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>;
class Float64PointFromColumnParser
{
public:
PointFromColumnParser(const ColumnWithTypeAndName & col);
Point createContainer() const;
void get(Point & container, size_t i) const;
Float64PointFromColumnParser(const IColumn & col)
{
const auto & tuple_columns = static_cast<const ColumnTuple &>(col).getColumns();
if (tuple_columns.size() != 2)
{
throw Exception("tuple size must be equal to 2", ErrorCodes::ILLEGAL_COLUMN);
}
x = static_cast<const ColumnFloat64 &>(*tuple_columns[0]).getData().data();
if (!x)
{
throw Exception("failed to get x column", ErrorCodes::ILLEGAL_COLUMN);
}
y = static_cast<const ColumnFloat64 &>(*tuple_columns[1]).getData().data();
if (!y)
{
throw Exception("failed to get y column", ErrorCodes::ILLEGAL_COLUMN);
}
}
Float64Point createContainer() const
{
return Float64Point();
}
void get(Float64Point & container, size_t i) const
{
boost::geometry::set<0>(container, x[i]);
boost::geometry::set<0>(container, y[i]);
}
private:
const Float64 * x;
const Float64 * y;
};
using GeometryFromColumnParser = boost::variant<PointFromColumnParser>;
template<class RingType, class PointParser>
class RingFromColumnParser
{
public:
RingFromColumnParser(const IColumn & col)
: offsets(static_cast<const ColumnArray &>(col).getOffsets())
, pointParser(static_cast<const ColumnArray &>(col).getData())
{
}
RingType createContainer() const
{
return RingType();
}
void get(RingType & container, size_t i) const
{
size_t l = offsets[i - 1];
size_t r = offsets[i];
container.resize(r - l);
for (size_t j = l; j < r; j++) {
pointParser.parse(container[j - l], l);
}
}
private:
const IColumn::Offsets & offsets;
PointParser pointParser;
};
using Float64RingFromColumnParser = RingFromColumnParser<Float64Ring, Float64PointFromColumnParser>;
using GeometryFromColumnParser = boost::variant<Float64PointFromColumnParser, Float64RingFromColumnParser>;
GeometryFromColumnParser makeGeometryFromColumnParser(const ColumnWithTypeAndName & col);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册