mirror of
https://github.com/ClickHouse/ClickHouse.git
synced 2024-11-21 15:12:02 +00:00
better
This commit is contained in:
parent
2cce75808b
commit
05cf1b5bc5
@ -26,8 +26,9 @@ void DataTypeCustomPointSerialization::deserializeText(
|
||||
|
||||
DataTypePtr DataTypeCustomPointSerialization::nestedDataType()
|
||||
{
|
||||
static auto data_type = DataTypePtr(std::make_unique<DataTypeTuple>(
|
||||
DataTypes({std::make_unique<DataTypeFloat64>(), std::make_unique<DataTypeFloat64>()})));
|
||||
static const auto data_type = std::make_shared<const DataTypeTuple>(
|
||||
DataTypes{std::make_shared<const DataTypeFloat64>(), std::make_shared<const DataTypeFloat64>()}
|
||||
);
|
||||
return data_type;
|
||||
}
|
||||
|
||||
@ -45,7 +46,7 @@ void DataTypeCustomRingSerialization::deserializeText(
|
||||
|
||||
DataTypePtr DataTypeCustomRingSerialization::nestedDataType()
|
||||
{
|
||||
static auto data_type = DataTypePtr(std::make_unique<DataTypeArray>(DataTypeCustomPointSerialization::nestedDataType()));
|
||||
static auto data_type = std::make_shared<const DataTypeArray>(DataTypeCustomPointSerialization::nestedDataType());
|
||||
return data_type;
|
||||
}
|
||||
|
||||
@ -63,7 +64,7 @@ void DataTypeCustomPolygonSerialization::deserializeText(
|
||||
|
||||
DataTypePtr DataTypeCustomPolygonSerialization::nestedDataType()
|
||||
{
|
||||
static auto data_type = DataTypePtr(std::make_unique<DataTypeArray>(DataTypeCustomRingSerialization::nestedDataType()));
|
||||
static auto data_type = std::make_shared<const DataTypeArray>(DataTypeCustomRingSerialization::nestedDataType());
|
||||
return data_type;
|
||||
}
|
||||
|
||||
@ -81,7 +82,7 @@ void DataTypeCustomMultiPolygonSerialization::deserializeText(
|
||||
|
||||
DataTypePtr DataTypeCustomMultiPolygonSerialization::nestedDataType()
|
||||
{
|
||||
static auto data_type = DataTypePtr(std::make_unique<DataTypeArray>(DataTypeCustomPolygonSerialization::nestedDataType()));
|
||||
static auto data_type = std::make_shared<const DataTypeArray>(DataTypeCustomPolygonSerialization::nestedDataType());
|
||||
return data_type;
|
||||
}
|
||||
|
||||
|
@ -9,6 +9,8 @@ namespace DB
|
||||
namespace ErrorCodes
|
||||
{
|
||||
extern const int ILLEGAL_COLUMN;
|
||||
extern const int BAD_ARGUMENTS;
|
||||
extern const int LOGICAL_ERROR;
|
||||
}
|
||||
|
||||
namespace
|
||||
@ -108,4 +110,28 @@ template GeometryFromColumnParser<CartesianPoint> makeGeometryFromColumnParser(c
|
||||
template GeometryFromColumnParser<GeographicPoint> makeGeometryFromColumnParser(const ColumnWithTypeAndName & col);
|
||||
|
||||
|
||||
template <typename Point, template<typename> typename Desired>
|
||||
void checkColumnTypeOrThrow(const ColumnWithTypeAndName & column)
|
||||
{
|
||||
DataTypePtr desired_type;
|
||||
if constexpr (std::is_same_v<Desired<Point>, Ring<Point>>)
|
||||
desired_type = DataTypeCustomRingSerialization::nestedDataType();
|
||||
else if constexpr (std::is_same_v<Desired<Point>, Polygon<Point>>)
|
||||
desired_type = DataTypeCustomPolygonSerialization::nestedDataType();
|
||||
else if constexpr (std::is_same_v<Desired<Point>, MultiPolygon<Point>>)
|
||||
desired_type = DataTypeCustomMultiPolygonSerialization::nestedDataType();
|
||||
else
|
||||
throw Exception("Unexpected Desired type.", ErrorCodes::LOGICAL_ERROR);
|
||||
|
||||
if (!desired_type->equals(*column.type))
|
||||
throw Exception(fmt::format("Expected type {} (MultiPolygon), but got {}", desired_type->getName(), column.type->getName()), ErrorCodes::BAD_ARGUMENTS);
|
||||
}
|
||||
|
||||
template void checkColumnTypeOrThrow<CartesianPoint, Ring>(const ColumnWithTypeAndName &);
|
||||
template void checkColumnTypeOrThrow<CartesianPoint, Polygon>(const ColumnWithTypeAndName &);
|
||||
template void checkColumnTypeOrThrow<CartesianPoint, MultiPolygon>(const ColumnWithTypeAndName &);
|
||||
template void checkColumnTypeOrThrow<GeographicPoint, Ring>(const ColumnWithTypeAndName &);
|
||||
template void checkColumnTypeOrThrow<GeographicPoint, Polygon>(const ColumnWithTypeAndName &);
|
||||
template void checkColumnTypeOrThrow<GeographicPoint, MultiPolygon>(const ColumnWithTypeAndName &);
|
||||
|
||||
}
|
||||
|
@ -233,14 +233,18 @@ public:
|
||||
|
||||
void get(Geometry<Point> & container, size_t i) const
|
||||
{
|
||||
auto & multi_polygon = boost::get<MultiPolygon<Point>>(container);
|
||||
get(boost::get<MultiPolygon<Point>>(container), i);
|
||||
}
|
||||
|
||||
void get(MultiPolygon<Point> & container, size_t i) const
|
||||
{
|
||||
size_t l = offsets[i - 1];
|
||||
size_t r = offsets[i];
|
||||
|
||||
multi_polygon.resize(r - l);
|
||||
container.resize(r - l);
|
||||
for (size_t j = l; j < r; j++)
|
||||
{
|
||||
polygon_parser.get(multi_polygon[j - l], j);
|
||||
polygon_parser.get(container[j - l], j);
|
||||
}
|
||||
}
|
||||
|
||||
@ -262,18 +266,17 @@ using GeometryFromColumnParser = boost::variant<
|
||||
template <typename Point>
|
||||
Geometry<Point> createContainer(const GeometryFromColumnParser<Point> & parser);
|
||||
|
||||
extern template Geometry<CartesianPoint> createContainer(const GeometryFromColumnParser<CartesianPoint> & parser);
|
||||
extern template Geometry<GeographicPoint> createContainer(const GeometryFromColumnParser<GeographicPoint> & parser);
|
||||
|
||||
template <typename Point>
|
||||
void get(const GeometryFromColumnParser<Point> & parser, Geometry<Point> & container, size_t i);
|
||||
|
||||
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);
|
||||
|
||||
template <typename Point>
|
||||
GeometryFromColumnParser<Point> makeGeometryFromColumnParser(const ColumnWithTypeAndName & col);
|
||||
|
||||
|
||||
extern template Geometry<CartesianPoint> createContainer(const GeometryFromColumnParser<CartesianPoint> & parser);
|
||||
extern template Geometry<GeographicPoint> createContainer(const GeometryFromColumnParser<GeographicPoint> & parser);
|
||||
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);
|
||||
extern template GeometryFromColumnParser<CartesianPoint> makeGeometryFromColumnParser(const ColumnWithTypeAndName & col);
|
||||
extern template GeometryFromColumnParser<GeographicPoint> makeGeometryFromColumnParser(const ColumnWithTypeAndName & col);
|
||||
|
||||
@ -532,4 +535,8 @@ using PolygonSerializer = GeometrySerializer<Geometry<Point>, PolygonSerializerV
|
||||
template <typename Point>
|
||||
using MultiPolygonSerializer = GeometrySerializer<Geometry<Point>, MultiPolygonSerializerVisitor<Point>>;
|
||||
|
||||
|
||||
template <typename Point, template<typename> typename Desired>
|
||||
void checkColumnTypeOrThrow(const ColumnWithTypeAndName & column);
|
||||
|
||||
}
|
||||
|
@ -20,11 +20,6 @@
|
||||
namespace DB
|
||||
{
|
||||
|
||||
namespace ErrorCodes
|
||||
{
|
||||
extern const int BAD_ARGUMENTS;
|
||||
}
|
||||
|
||||
template <typename Point>
|
||||
class FunctionPolygonArea : public IFunction
|
||||
{
|
||||
@ -58,40 +53,18 @@ public:
|
||||
return std::make_shared<DataTypeFloat64>();
|
||||
}
|
||||
|
||||
void checkInputType(const ColumnsWithTypeAndName & arguments) const
|
||||
{
|
||||
/// Array(Array(Array(Tuple(Float64, Float64))))
|
||||
auto desired = std::make_shared<const DataTypeArray>(
|
||||
std::make_shared<const DataTypeArray>(
|
||||
std::make_shared<const DataTypeArray>(
|
||||
std::make_shared<const DataTypeTuple>(
|
||||
DataTypes{std::make_shared<const DataTypeFloat64>(), std::make_shared<const DataTypeFloat64>()}
|
||||
)
|
||||
)
|
||||
)
|
||||
);
|
||||
if (!desired->equals(*arguments[0].type))
|
||||
throw Exception(fmt::format("The type of first argument of function {} must be Array(Array(Array(Tuple(Float64, Float64))))", name), ErrorCodes::BAD_ARGUMENTS);
|
||||
}
|
||||
|
||||
ColumnPtr executeImpl(const ColumnsWithTypeAndName & arguments, const DataTypePtr & /*result_type*/, size_t input_rows_count) const override
|
||||
{
|
||||
checkInputType(arguments);
|
||||
auto parser = makeGeometryFromColumnParser<Point>(arguments[0]);
|
||||
|
||||
std::cout << arguments[0].type->getName() << std::endl;
|
||||
auto container = createContainer(parser);
|
||||
checkColumnTypeOrThrow<Point, MultiPolygon>(arguments[0]);
|
||||
auto parser = MultiPolygonFromColumnParser<Point>(std::move(arguments[0].column->convertToFullColumnIfConst()));
|
||||
MultiPolygon<Point> container;
|
||||
|
||||
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);
|
||||
parser.get(container, i);
|
||||
res_column->insertValue(boost::geometry::area(container));
|
||||
}
|
||||
|
||||
return res_column;
|
||||
|
@ -20,11 +20,6 @@
|
||||
namespace DB
|
||||
{
|
||||
|
||||
namespace ErrorCodes
|
||||
{
|
||||
extern const int BAD_ARGUMENTS;
|
||||
}
|
||||
|
||||
template <typename Point>
|
||||
class FunctionPolygonConvexHull : public IFunction
|
||||
{
|
||||
@ -58,42 +53,19 @@ public:
|
||||
return DataTypeCustomPolygonSerialization::nestedDataType();
|
||||
}
|
||||
|
||||
void checkInputType(const ColumnsWithTypeAndName & arguments) const
|
||||
{
|
||||
/// Array(Array(Array(Tuple(Float64, Float64))))
|
||||
auto desired = std::make_shared<const DataTypeArray>(
|
||||
std::make_shared<const DataTypeArray>(
|
||||
std::make_shared<const DataTypeArray>(
|
||||
std::make_shared<const DataTypeTuple>(
|
||||
DataTypes{std::make_shared<const DataTypeFloat64>(), std::make_shared<const DataTypeFloat64>()}
|
||||
)
|
||||
)
|
||||
)
|
||||
);
|
||||
if (!desired->equals(*arguments[0].type))
|
||||
throw Exception(fmt::format("The type of the argument of function {} must be Array(Array(Array(Tuple(Float64, Float64))))", name), ErrorCodes::BAD_ARGUMENTS);
|
||||
}
|
||||
|
||||
ColumnPtr executeImpl(const ColumnsWithTypeAndName & arguments, const DataTypePtr & /*result_type*/, size_t input_rows_count) const override
|
||||
{
|
||||
checkInputType(arguments);
|
||||
auto parser = makeGeometryFromColumnParser<Point>(arguments[0]);
|
||||
auto container = createContainer(parser);
|
||||
checkColumnTypeOrThrow<Point, MultiPolygon>(arguments[0]);
|
||||
auto parser = MultiPolygonFromColumnParser<Point>(std::move(arguments[0].column->convertToFullColumnIfConst()));
|
||||
MultiPolygon<Point> container;
|
||||
|
||||
PolygonSerializer<Point> serializer;
|
||||
Polygon<Point> convex_hull{};
|
||||
|
||||
for (size_t i = 0; i < input_rows_count; i++)
|
||||
{
|
||||
get(parser, container, i);
|
||||
|
||||
auto convex_hull = Polygon<Point>({{{}}});
|
||||
|
||||
boost::geometry::convex_hull(
|
||||
boost::get<MultiPolygon<Point>>(container),
|
||||
convex_hull);
|
||||
|
||||
convex_hull.outer().erase(convex_hull.outer().begin());
|
||||
|
||||
parser.get(container, i);
|
||||
boost::geometry::convex_hull(container, convex_hull);
|
||||
serializer.add(convex_hull);
|
||||
}
|
||||
|
||||
|
@ -20,11 +20,6 @@
|
||||
namespace DB
|
||||
{
|
||||
|
||||
namespace ErrorCodes
|
||||
{
|
||||
extern const int BAD_ARGUMENTS;
|
||||
}
|
||||
|
||||
template <typename Point>
|
||||
class FunctionPolygonPerimeter : public IFunction
|
||||
{
|
||||
@ -58,38 +53,18 @@ public:
|
||||
return std::make_shared<DataTypeFloat64>();
|
||||
}
|
||||
|
||||
void checkInputType(const ColumnsWithTypeAndName & arguments) const
|
||||
{
|
||||
/// Array(Array(Array(Tuple(Float64, Float64))))
|
||||
auto desired = std::make_shared<const DataTypeArray>(
|
||||
std::make_shared<const DataTypeArray>(
|
||||
std::make_shared<const DataTypeArray>(
|
||||
std::make_shared<const DataTypeTuple>(
|
||||
DataTypes{std::make_shared<const DataTypeFloat64>(), std::make_shared<const DataTypeFloat64>()}
|
||||
)
|
||||
)
|
||||
)
|
||||
);
|
||||
if (!desired->equals(*arguments[0].type))
|
||||
throw Exception(fmt::format("The type of the argument of function {} must be Array(Array(Array(Tuple(Float64, Float64))))", name), ErrorCodes::BAD_ARGUMENTS);
|
||||
}
|
||||
|
||||
ColumnPtr executeImpl(const ColumnsWithTypeAndName & arguments, const DataTypePtr & /*result_type*/, size_t input_rows_count) const override
|
||||
{
|
||||
checkInputType(arguments);
|
||||
auto parser = makeGeometryFromColumnParser<Point>(arguments[0]);
|
||||
auto container = createContainer(parser);
|
||||
checkColumnTypeOrThrow<Point, MultiPolygon>(arguments[0]);
|
||||
auto parser = MultiPolygonFromColumnParser<Point>(std::move(arguments[0].column->convertToFullColumnIfConst()));
|
||||
MultiPolygon<Point> container;
|
||||
|
||||
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);
|
||||
parser.get(container, i);
|
||||
res_column->insertValue(boost::geometry::perimeter(container));
|
||||
}
|
||||
|
||||
return res_column;
|
||||
|
@ -22,11 +22,6 @@
|
||||
namespace DB
|
||||
{
|
||||
|
||||
namespace ErrorCodes
|
||||
{
|
||||
extern const int BAD_ARGUMENTS;
|
||||
}
|
||||
|
||||
template <typename Point>
|
||||
class FunctionPolygonsDistance : public IFunction
|
||||
{
|
||||
@ -60,49 +55,27 @@ public:
|
||||
return std::make_shared<DataTypeFloat64>();
|
||||
}
|
||||
|
||||
void checkInputType(const ColumnsWithTypeAndName & arguments) const
|
||||
{
|
||||
/// Array(Array(Array(Tuple(Float64, Float64))))
|
||||
auto desired = std::make_shared<const DataTypeArray>(
|
||||
std::make_shared<const DataTypeArray>(
|
||||
std::make_shared<const DataTypeArray>(
|
||||
std::make_shared<const DataTypeTuple>(
|
||||
DataTypes{std::make_shared<const DataTypeFloat64>(), std::make_shared<const DataTypeFloat64>()}
|
||||
)
|
||||
)
|
||||
)
|
||||
);
|
||||
if (!desired->equals(*arguments[0].type))
|
||||
throw Exception(fmt::format("The type of the first argument of function {} must be Array(Array(Array(Tuple(Float64, Float64))))", name), ErrorCodes::BAD_ARGUMENTS);
|
||||
|
||||
if (!desired->equals(*arguments[1].type))
|
||||
throw Exception(fmt::format("The type of the second argument of function {} must be Array(Array(Array(Tuple(Float64, Float64))))", name), ErrorCodes::BAD_ARGUMENTS);
|
||||
}
|
||||
|
||||
ColumnPtr executeImpl(const ColumnsWithTypeAndName & arguments, const DataTypePtr & /*result_type*/, size_t input_rows_count) const override
|
||||
{
|
||||
auto first_parser = makeGeometryFromColumnParser<Point>(arguments[0]);
|
||||
auto first_container = createContainer(first_parser);
|
||||
checkColumnTypeOrThrow<Point, MultiPolygon>(arguments[0]);
|
||||
auto first_parser = MultiPolygonFromColumnParser<Point>(std::move(arguments[0].column->convertToFullColumnIfConst()));
|
||||
MultiPolygon<Point> first_container;
|
||||
|
||||
auto second_parser = makeGeometryFromColumnParser<Point>(arguments[1]);
|
||||
auto second_container = createContainer(second_parser);
|
||||
checkColumnTypeOrThrow<Point, MultiPolygon>(arguments[1]);
|
||||
auto second_parser = MultiPolygonFromColumnParser<Point>(std::move(arguments[1].column->convertToFullColumnIfConst()));
|
||||
MultiPolygon<Point> second_container;
|
||||
|
||||
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);
|
||||
first_parser.get(first_container, i);
|
||||
second_parser.get(second_container, i);
|
||||
|
||||
auto first = boost::get<MultiPolygon<Point>>(first_container);
|
||||
auto second = boost::get<MultiPolygon<Point>>(second_container);
|
||||
boost::geometry::correct(first_container);
|
||||
boost::geometry::correct(second_container);
|
||||
|
||||
boost::geometry::correct(first);
|
||||
boost::geometry::correct(second);
|
||||
|
||||
Float64 distance = boost::geometry::distance(first, second);
|
||||
|
||||
res_column->insertValue(distance);
|
||||
res_column->insertValue(boost::geometry::distance(first_container, second_container));
|
||||
}
|
||||
|
||||
return res_column;
|
||||
|
@ -22,11 +22,6 @@
|
||||
namespace DB
|
||||
{
|
||||
|
||||
namespace ErrorCodes
|
||||
{
|
||||
extern const int BAD_ARGUMENTS;
|
||||
}
|
||||
|
||||
template <typename Point>
|
||||
class FunctionPolygonsEquals : public IFunction
|
||||
{
|
||||
@ -60,50 +55,27 @@ public:
|
||||
return std::make_shared<DataTypeUInt8>();
|
||||
}
|
||||
|
||||
void checkInputType(const ColumnsWithTypeAndName & arguments) const
|
||||
{
|
||||
/// Array(Array(Array(Tuple(Float64, Float64))))
|
||||
auto desired = std::make_shared<const DataTypeArray>(
|
||||
std::make_shared<const DataTypeArray>(
|
||||
std::make_shared<const DataTypeArray>(
|
||||
std::make_shared<const DataTypeTuple>(
|
||||
DataTypes{std::make_shared<const DataTypeFloat64>(), std::make_shared<const DataTypeFloat64>()}
|
||||
)
|
||||
)
|
||||
)
|
||||
);
|
||||
if (!desired->equals(*arguments[0].type))
|
||||
throw Exception(fmt::format("The type of the first argument of function {} must be Array(Array(Array(Tuple(Float64, Float64))))", name), ErrorCodes::BAD_ARGUMENTS);
|
||||
|
||||
if (!desired->equals(*arguments[1].type))
|
||||
throw Exception(fmt::format("The type of the second argument of function {} must be Array(Array(Array(Tuple(Float64, Float64))))", name), ErrorCodes::BAD_ARGUMENTS);
|
||||
}
|
||||
|
||||
ColumnPtr executeImpl(const ColumnsWithTypeAndName & arguments, const DataTypePtr & /*result_type*/, size_t input_rows_count) const override
|
||||
{
|
||||
checkInputType(arguments);
|
||||
auto first_parser = makeGeometryFromColumnParser<Point>(arguments[0]);
|
||||
auto first_container = createContainer(first_parser);
|
||||
checkColumnTypeOrThrow<Point, MultiPolygon>(arguments[0]);
|
||||
auto first_parser = MultiPolygonFromColumnParser<Point>(std::move(arguments[0].column->convertToFullColumnIfConst()));
|
||||
MultiPolygon<Point> first_container;
|
||||
|
||||
auto second_parser = makeGeometryFromColumnParser<Point>(arguments[1]);
|
||||
auto second_container = createContainer(second_parser);
|
||||
checkColumnTypeOrThrow<Point, MultiPolygon>(arguments[1]);
|
||||
auto second_parser = MultiPolygonFromColumnParser<Point>(std::move(arguments[1].column->convertToFullColumnIfConst()));
|
||||
MultiPolygon<Point> second_container;
|
||||
|
||||
auto res_column = ColumnUInt8::create();
|
||||
|
||||
for (size_t i = 0; i < input_rows_count; i++)
|
||||
{
|
||||
get(first_parser, first_container, i);
|
||||
get(second_parser, second_container, i);
|
||||
first_parser.get(first_container, i);
|
||||
second_parser.get(second_container, i);
|
||||
|
||||
auto first = boost::get<MultiPolygon<Point>>(first_container);
|
||||
auto second = boost::get<MultiPolygon<Point>>(second_container);
|
||||
boost::geometry::correct(first_container);
|
||||
boost::geometry::correct(second_container);
|
||||
|
||||
boost::geometry::correct(first);
|
||||
boost::geometry::correct(second);
|
||||
|
||||
bool equals = boost::geometry::equals(first, second);
|
||||
|
||||
res_column->insertValue(equals);
|
||||
res_column->insertValue(boost::geometry::equals(first_container, second_container));
|
||||
}
|
||||
|
||||
return res_column;
|
||||
|
@ -20,11 +20,6 @@
|
||||
namespace DB
|
||||
{
|
||||
|
||||
namespace ErrorCodes
|
||||
{
|
||||
extern const int BAD_ARGUMENTS;
|
||||
}
|
||||
|
||||
template <typename Point>
|
||||
class FunctionPolygonsIntersection : public IFunction
|
||||
{
|
||||
@ -58,55 +53,32 @@ public:
|
||||
return DataTypeCustomMultiPolygonSerialization::nestedDataType();
|
||||
}
|
||||
|
||||
void checkInputType(const ColumnsWithTypeAndName & arguments) const
|
||||
{
|
||||
/// Array(Array(Array(Tuple(Float64, Float64))))
|
||||
auto desired = std::make_shared<const DataTypeArray>(
|
||||
std::make_shared<const DataTypeArray>(
|
||||
std::make_shared<const DataTypeArray>(
|
||||
std::make_shared<const DataTypeTuple>(
|
||||
DataTypes{std::make_shared<const DataTypeFloat64>(), std::make_shared<const DataTypeFloat64>()}
|
||||
)
|
||||
)
|
||||
)
|
||||
);
|
||||
if (!desired->equals(*arguments[0].type))
|
||||
throw Exception(fmt::format("The type of the first argument of function {} must be Array(Array(Array(Tuple(Float64, Float64))))", name), ErrorCodes::BAD_ARGUMENTS);
|
||||
|
||||
if (!desired->equals(*arguments[1].type))
|
||||
throw Exception(fmt::format("The type of the second argument of function {} must be Array(Array(Array(Tuple(Float64, Float64))))", name), ErrorCodes::BAD_ARGUMENTS);
|
||||
}
|
||||
|
||||
ColumnPtr executeImpl(const ColumnsWithTypeAndName & arguments, const DataTypePtr & /*result_type*/, size_t input_rows_count) const override
|
||||
{
|
||||
checkInputType(arguments);
|
||||
auto first_parser = makeGeometryFromColumnParser<Point>(arguments[0]);
|
||||
auto first_container = createContainer(first_parser);
|
||||
checkColumnTypeOrThrow<Point, MultiPolygon>(arguments[0]);
|
||||
auto first_parser = MultiPolygonFromColumnParser<Point>(std::move(arguments[0].column->convertToFullColumnIfConst()));
|
||||
MultiPolygon<Point> first_container;
|
||||
|
||||
auto second_parser = makeGeometryFromColumnParser<Point>(arguments[1]);
|
||||
auto second_container = createContainer(second_parser);
|
||||
checkColumnTypeOrThrow<Point, MultiPolygon>(arguments[1]);
|
||||
auto second_parser = MultiPolygonFromColumnParser<Point>(std::move(arguments[1].column->convertToFullColumnIfConst()));
|
||||
MultiPolygon<Point> second_container;
|
||||
|
||||
MultiPolygonSerializer<Point> serializer;
|
||||
MultiPolygon<Point> intersection{};
|
||||
|
||||
/// We are not interested in some pitfalls in third-party libraries
|
||||
/// NOLINTNEXTLINE(clang-analyzer-core.uninitialized.Assign)
|
||||
for (size_t i = 0; i < input_rows_count; i++)
|
||||
for (size_t i = 0; i < input_rows_count; ++i)
|
||||
{
|
||||
get(first_parser, first_container, i);
|
||||
get(second_parser, second_container, i);
|
||||
|
||||
auto intersection = MultiPolygon<Point>({{{{}}}});
|
||||
auto first = boost::get<MultiPolygon<Point>>(first_container);
|
||||
auto second = boost::get<MultiPolygon<Point>>(second_container);
|
||||
first_parser.get(first_container, i);
|
||||
second_parser.get(second_container, i);
|
||||
|
||||
/// Orient the polygons correctly.
|
||||
boost::geometry::correct(first);
|
||||
boost::geometry::correct(second);
|
||||
boost::geometry::correct(first_container);
|
||||
boost::geometry::correct(second_container);
|
||||
|
||||
/// Main work here.
|
||||
boost::geometry::intersection(first, second, intersection);
|
||||
|
||||
intersection.erase(intersection.begin());
|
||||
boost::geometry::intersection(first_container, second_container, intersection);
|
||||
|
||||
serializer.add(intersection);
|
||||
}
|
||||
|
@ -20,11 +20,6 @@
|
||||
namespace DB
|
||||
{
|
||||
|
||||
namespace ErrorCodes
|
||||
{
|
||||
extern const int BAD_ARGUMENTS;
|
||||
}
|
||||
|
||||
template <typename Point>
|
||||
class FunctionPolygonsSymDifference : public IFunction
|
||||
{
|
||||
@ -58,53 +53,29 @@ public:
|
||||
return DataTypeCustomMultiPolygonSerialization::nestedDataType();
|
||||
}
|
||||
|
||||
void checkInputType(const ColumnsWithTypeAndName & arguments) const
|
||||
{
|
||||
/// Array(Array(Array(Tuple(Float64, Float64))))
|
||||
auto desired = std::make_shared<const DataTypeArray>(
|
||||
std::make_shared<const DataTypeArray>(
|
||||
std::make_shared<const DataTypeArray>(
|
||||
std::make_shared<const DataTypeTuple>(
|
||||
DataTypes{std::make_shared<const DataTypeFloat64>(), std::make_shared<const DataTypeFloat64>()}
|
||||
)
|
||||
)
|
||||
)
|
||||
);
|
||||
if (!desired->equals(*arguments[0].type))
|
||||
throw Exception(fmt::format("The type of the first argument of function {} must be Array(Array(Array(Tuple(Float64, Float64))))", name), ErrorCodes::BAD_ARGUMENTS);
|
||||
|
||||
if (!desired->equals(*arguments[1].type))
|
||||
throw Exception(fmt::format("The type of the second argument of function {} must be Array(Array(Array(Tuple(Float64, Float64))))", name), ErrorCodes::BAD_ARGUMENTS);
|
||||
}
|
||||
|
||||
ColumnPtr executeImpl(const ColumnsWithTypeAndName & arguments, const DataTypePtr & /*result_type*/, size_t input_rows_count) const override
|
||||
{
|
||||
checkInputType(arguments);
|
||||
auto first_parser = makeGeometryFromColumnParser<Point>(arguments[0]);
|
||||
auto first_container = createContainer(first_parser);
|
||||
checkColumnTypeOrThrow<Point, MultiPolygon>(arguments[0]);
|
||||
auto first_parser = MultiPolygonFromColumnParser<Point>(std::move(arguments[0].column->convertToFullColumnIfConst()));
|
||||
MultiPolygon<Point> first_container;
|
||||
|
||||
auto second_parser = makeGeometryFromColumnParser<Point>(arguments[1]);
|
||||
auto second_container = createContainer(second_parser);
|
||||
checkColumnTypeOrThrow<Point, MultiPolygon>(arguments[1]);
|
||||
auto second_parser = MultiPolygonFromColumnParser<Point>(std::move(arguments[1].column->convertToFullColumnIfConst()));
|
||||
MultiPolygon<Point> second_container;
|
||||
|
||||
MultiPolygonSerializer<Point> serializer;
|
||||
MultiPolygon<Point> sym_difference{};
|
||||
|
||||
/// NOLINTNEXTLINE(clang-analyzer-core.uninitialized.Assign)
|
||||
for (size_t i = 0; i < input_rows_count; i++)
|
||||
{
|
||||
get(first_parser, first_container, i);
|
||||
get(second_parser, second_container, i);
|
||||
first_parser.get(first_container, i);
|
||||
second_parser.get(second_container, i);
|
||||
|
||||
auto sym_difference = MultiPolygon<Point>({{{{}}}});
|
||||
boost::geometry::correct(first_container);
|
||||
boost::geometry::correct(second_container);
|
||||
|
||||
auto first = boost::get<MultiPolygon<Point>>(first_container);
|
||||
auto second = boost::get<MultiPolygon<Point>>(second_container);
|
||||
|
||||
boost::geometry::correct(first);
|
||||
boost::geometry::correct(second);
|
||||
|
||||
boost::geometry::sym_difference(first, second, sym_difference);
|
||||
|
||||
sym_difference.erase(sym_difference.begin());
|
||||
boost::geometry::sym_difference(first_container, second_container, sym_difference);
|
||||
|
||||
serializer.add(sym_difference);
|
||||
}
|
||||
|
@ -19,10 +19,6 @@
|
||||
|
||||
namespace DB
|
||||
{
|
||||
namespace ErrorCodes
|
||||
{
|
||||
extern const int BAD_ARGUMENTS;
|
||||
}
|
||||
|
||||
template <typename Point>
|
||||
class FunctionPolygonsUnion : public IFunction
|
||||
@ -57,55 +53,32 @@ public:
|
||||
return DataTypeCustomMultiPolygonSerialization::nestedDataType();
|
||||
}
|
||||
|
||||
void checkInputType(const ColumnsWithTypeAndName & arguments) const
|
||||
{
|
||||
/// Array(Array(Array(Tuple(Float64, Float64))))
|
||||
auto desired = std::make_shared<const DataTypeArray>(
|
||||
std::make_shared<const DataTypeArray>(
|
||||
std::make_shared<const DataTypeArray>(
|
||||
std::make_shared<const DataTypeTuple>(
|
||||
DataTypes{std::make_shared<const DataTypeFloat64>(), std::make_shared<const DataTypeFloat64>()}
|
||||
)
|
||||
)
|
||||
)
|
||||
);
|
||||
if (!desired->equals(*arguments[0].type))
|
||||
throw Exception(fmt::format("The type of the first argument of function {} must be Array(Array(Array(Tuple(Float64, Float64))))", name), ErrorCodes::BAD_ARGUMENTS);
|
||||
|
||||
if (!desired->equals(*arguments[1].type))
|
||||
throw Exception(fmt::format("The type of the second argument of function {} must be Array(Array(Array(Tuple(Float64, Float64))))", name), ErrorCodes::BAD_ARGUMENTS);
|
||||
}
|
||||
|
||||
ColumnPtr executeImpl(const ColumnsWithTypeAndName & arguments, const DataTypePtr & /*result_type*/, size_t input_rows_count) const override
|
||||
{
|
||||
checkInputType(arguments);
|
||||
auto first_parser = makeGeometryFromColumnParser<Point>(arguments[0]);
|
||||
auto first_container = createContainer(first_parser);
|
||||
checkColumnTypeOrThrow<Point, MultiPolygon>(arguments[0]);
|
||||
auto first_parser = MultiPolygonFromColumnParser<Point>(std::move(arguments[0].column->convertToFullColumnIfConst()));
|
||||
MultiPolygon<Point> first_container;
|
||||
|
||||
auto second_parser = makeGeometryFromColumnParser<Point>(arguments[1]);
|
||||
auto second_container = createContainer(second_parser);
|
||||
checkColumnTypeOrThrow<Point, MultiPolygon>(arguments[1]);
|
||||
auto second_parser = MultiPolygonFromColumnParser<Point>(std::move(arguments[1].column->convertToFullColumnIfConst()));
|
||||
MultiPolygon<Point> second_container;
|
||||
|
||||
MultiPolygonSerializer<Point> serializer;
|
||||
MultiPolygon<Point> polygons_union{};
|
||||
|
||||
/// We are not interested in some pitfalls in third-party libraries
|
||||
/// NOLINTNEXTLINE(clang-analyzer-core.uninitialized.Assign)
|
||||
for (size_t i = 0; i < input_rows_count; i++)
|
||||
{
|
||||
get<Point>(first_parser, first_container, i);
|
||||
get<Point>(second_parser, second_container, i);
|
||||
|
||||
auto first = boost::get<MultiPolygon<Point>>(first_container);
|
||||
auto second = boost::get<MultiPolygon<Point>>(second_container);
|
||||
auto polygons_union = MultiPolygon<Point>({{{{}}}});
|
||||
first_parser.get(first_container, i);
|
||||
second_parser.get(second_container, i);
|
||||
|
||||
/// Orient the polygons correctly.
|
||||
boost::geometry::correct(first);
|
||||
boost::geometry::correct(second);
|
||||
boost::geometry::correct(first_container);
|
||||
boost::geometry::correct(second_container);
|
||||
|
||||
/// Main work here.
|
||||
boost::geometry::union_(first, second, polygons_union);
|
||||
|
||||
polygons_union.erase(polygons_union.begin());
|
||||
boost::geometry::union_(first_container, second_container, polygons_union);
|
||||
|
||||
serializer.add(polygons_union);
|
||||
}
|
||||
|
@ -22,11 +22,6 @@
|
||||
namespace DB
|
||||
{
|
||||
|
||||
namespace ErrorCodes
|
||||
{
|
||||
extern const int BAD_ARGUMENTS;
|
||||
}
|
||||
|
||||
template <typename Point>
|
||||
class FunctionPolygonsWithin : public IFunction
|
||||
{
|
||||
@ -60,51 +55,28 @@ public:
|
||||
return std::make_shared<DataTypeUInt8>();
|
||||
}
|
||||
|
||||
void checkInputType(const ColumnsWithTypeAndName & arguments) const
|
||||
{
|
||||
/// Array(Array(Array(Tuple(Float64, Float64))))
|
||||
auto desired = std::make_shared<const DataTypeArray>(
|
||||
std::make_shared<const DataTypeArray>(
|
||||
std::make_shared<const DataTypeArray>(
|
||||
std::make_shared<const DataTypeTuple>(
|
||||
DataTypes{std::make_shared<const DataTypeFloat64>(), std::make_shared<const DataTypeFloat64>()}
|
||||
)
|
||||
)
|
||||
)
|
||||
);
|
||||
if (!desired->equals(*arguments[0].type))
|
||||
throw Exception(fmt::format("The type of the first argument of function {} must be Array(Array(Array(Tuple(Float64, Float64))))", name), ErrorCodes::BAD_ARGUMENTS);
|
||||
|
||||
if (!desired->equals(*arguments[1].type))
|
||||
throw Exception(fmt::format("The type of the second argument of function {} must be Array(Array(Array(Tuple(Float64, Float64))))", name), ErrorCodes::BAD_ARGUMENTS);
|
||||
}
|
||||
|
||||
ColumnPtr executeImpl(const ColumnsWithTypeAndName & arguments, const DataTypePtr & /*result_type*/, size_t input_rows_count) const override
|
||||
{
|
||||
checkInputType(arguments);
|
||||
auto first_parser = makeGeometryFromColumnParser<Point>(arguments[0]);
|
||||
auto first_container = createContainer(first_parser);
|
||||
checkColumnTypeOrThrow<Point, MultiPolygon>(arguments[0]);
|
||||
auto first_parser = MultiPolygonFromColumnParser<Point>(std::move(arguments[0].column->convertToFullColumnIfConst()));
|
||||
MultiPolygon<Point> first_container;
|
||||
|
||||
auto second_parser = makeGeometryFromColumnParser<Point>(arguments[1]);
|
||||
auto second_container = createContainer(second_parser);
|
||||
checkColumnTypeOrThrow<Point, MultiPolygon>(arguments[1]);
|
||||
auto second_parser = MultiPolygonFromColumnParser<Point>(std::move(arguments[1].column->convertToFullColumnIfConst()));
|
||||
MultiPolygon<Point> second_container;
|
||||
|
||||
auto res_column = ColumnUInt8::create();
|
||||
|
||||
/// NOLINTNEXTLINE(clang-analyzer-core.uninitialized.Assign)
|
||||
for (size_t i = 0; i < input_rows_count; i++)
|
||||
{
|
||||
get<Point>(first_parser, first_container, i);
|
||||
get<Point>(second_parser, second_container, i);
|
||||
first_parser.get(first_container, i);
|
||||
second_parser.get(second_container, i);
|
||||
|
||||
auto first = boost::get<MultiPolygon<Point>>(first_container);
|
||||
auto second = boost::get<MultiPolygon<Point>>(second_container);
|
||||
boost::geometry::correct(first_container);
|
||||
boost::geometry::correct(second_container);
|
||||
|
||||
boost::geometry::correct(first);
|
||||
boost::geometry::correct(second);
|
||||
|
||||
bool within = boost::geometry::within(first, second);
|
||||
|
||||
res_column->insertValue(within);
|
||||
res_column->insertValue(boost::geometry::within(first_container, second_container));
|
||||
}
|
||||
|
||||
return res_column;
|
||||
|
@ -1 +1 @@
|
||||
select polygonConvexHullCartesian([[[(0, 0), (0, 5), (5, 5), (5, 0), (2, 3)]]]);
|
||||
select polygonConvexHullCartesian([[[(0., 0.), (0., 5.), (5., 5.), (5., 0.), (2., 3.)]]]);
|
||||
|
@ -1,5 +1,5 @@
|
||||
select polygonsWithinCartesian([[[(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 polygonsWithinCartesian([[[(2, 2), (2, 3), (3, 3), (3, 2)]]], [[[(1, 1),(1, 4),(4, 4),(4, 1),(1, 1)]]]);
|
||||
select polygonsWithinCartesian([[[(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 polygonsWithinCartesian([[[(2., 2.), (2., 3.), (3., 3.), (3., 2.)]]], [[[(1., 1.),(1., 4.),(4., 4.),(4., 1.),(1., 1.)]]]);
|
||||
|
||||
select polygonsWithinGeographic([[[(4.3613577, 50.8651821), (4.349556, 50.8535879), (4.3602419, 50.8435626), (4.3830299, 50.8428851), (4.3904543, 50.8564867), (4.3613148, 50.8651279)]]], [[[(4.346693, 50.858306), (4.367945, 50.852455), (4.366227, 50.840809), (4.344961, 50.833264), (4.338074, 50.848677), (4.346693, 50.858306)]]]);
|
||||
select polygonsWithinGeographic([[[(4.3501568, 50.8518269), (4.3444920, 50.8439961), (4.3565941, 50.8443213), (4.3501568, 50.8518269)]]], [[[(4.3679450, 50.8524550),(4.3466930, 50.8583060),(4.3380740, 50.8486770),(4.3449610, 50.8332640),(4.3662270, 50.8408090),(4.3679450, 50.8524550)]]]);
|
||||
|
@ -1,5 +1,5 @@
|
||||
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 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;
|
||||
|
@ -1,2 +1,2 @@
|
||||
select polygonsEqualsCartesian([[[(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 polygonsEqualsCartesian([[[(1, 1),(1, 4),(4, 4),(4, 1)]]], [[[(1, 1),(1, 4),(4, 4),(4, 1),(1, 1)]]]);
|
||||
select polygonsEqualsCartesian([[[(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 polygonsEqualsCartesian([[[(1., 1.),(1., 4.),(4., 4.),(4., 1.)]]], [[[(1., 1.),(1., 4.),(4., 4.),(4., 1.),(1., 1.)]]]);
|
@ -1,2 +1,2 @@
|
||||
select polygonsSymDifferenceCartesian([[[(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 polygonsSymDifferenceCartesian([[[(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.)]]])
|
||||
|
||||
|
@ -1,3 +1,3 @@
|
||||
select polygonsUnionCartesian([[[(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 polygonsUnionCartesian([[[(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 polygonsUnionGeographic([[[(4.3613577, 50.8651821), (4.349556, 50.8535879), (4.3602419, 50.8435626), (4.3830299, 50.8428851), (4.3904543, 50.8564867), (4.3613148, 50.8651279)]]], [[[(4.346693, 50.858306), (4.367945, 50.852455), (4.366227, 50.840809), (4.344961, 50.833264), (4.338074, 50.848677), (4.346693, 50.858306)]]]);
|
||||
|
@ -1,5 +1,5 @@
|
||||
select polygonsIntersectionCartesian([[[(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 polygonsIntersectionCartesian([[[(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)]]]);
|
||||
select polygonsIntersectionCartesian([[[(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 polygonsIntersectionCartesian([[[(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.)]]]);
|
||||
|
||||
select polygonsIntersectionGeographic([[[(4.346693, 50.858306), (4.367945, 50.852455), (4.366227, 50.840809), (4.344961, 50.833264), (4.338074, 50.848677), (4.346693, 50.858306)]]], [[[(25.0010, 136.9987), (17.7500, 142.5000), (11.3733, 142.5917)]]]);
|
||||
select polygonsIntersectionGeographic([[[(4.3613577, 50.8651821), (4.349556, 50.8535879), (4.3602419, 50.8435626), (4.3830299, 50.8428851), (4.3904543, 50.8564867), (4.3613148, 50.8651279)]]], [[[(4.346693, 50.858306), (4.367945, 50.852455), (4.366227, 50.840809), (4.344961, 50.833264), (4.338074, 50.848677), (4.346693, 50.858306)]]]);
|
@ -1 +1 @@
|
||||
select polygonPerimeterCartesian([[[(0, 0), (0., 5), (5, 5), (5., 0)]]]);
|
||||
select polygonPerimeterCartesian([[[(0., 0.), (0., 5.), (5., 5.), (5., 0.)]]]);
|
@ -1,3 +1,3 @@
|
||||
select polygonAreaCartesian([[[(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)]]]);
|
||||
SELECT polygonAreaCartesian([]); -- { serverError 36 }
|
Loading…
Reference in New Issue
Block a user