This commit is contained in:
Nikita Mikhailov 2021-02-20 20:44:18 +03:00 committed by Nikita Mikhaylov
parent 4430322edc
commit a7427a9cdf
16 changed files with 240 additions and 154 deletions

View File

@ -75,12 +75,14 @@ template <typename Point>
class PointFromColumnConverter
{
public:
explicit PointFromColumnConverter(ColumnPtr col_) : col(col_)
{
}
std::vector<Point> convert() const;
std::vector<Point> convert() const
{
return convertImpl(0, col->size());
}
private:
std::vector<Point> convertImpl(size_t shift, size_t count) const;
@ -113,8 +115,6 @@ template<class Point>
class PolygonFromColumnConverter
{
public:
PolygonFromColumnConverter() = default;
explicit PolygonFromColumnConverter(ColumnPtr col_)
: col(col_)
, ring_converter(typeid_cast<const ColumnArray &>(*col_).getDataPtr())
@ -135,8 +135,6 @@ template<class Point>
class MultiPolygonFromColumnConverter
{
public:
MultiPolygonFromColumnConverter() = default;
explicit MultiPolygonFromColumnConverter(ColumnPtr col_)
: col(col_)
, polygon_converter(typeid_cast<const ColumnArray &>(*col_).getDataPtr())
@ -334,11 +332,13 @@ template <typename Point, typename F>
static void callOnGeometryDataType(DataTypePtr type, F && f)
{
/// There is no Point type, because for most of geometry functions it is useless.
if (DataTypeCustomRingSerialization::nestedDataType()->equals(*type))
if (DataTypeCustomPointSerialization::nestedDataType()->equals(*type))
return f(ConverterType<PointFromColumnConverter<Point>>());
else if (DataTypeCustomRingSerialization::nestedDataType()->equals(*type))
return f(ConverterType<RingFromColumnConverter<Point>>());
if (DataTypeCustomPolygonSerialization::nestedDataType()->equals(*type))
else if (DataTypeCustomPolygonSerialization::nestedDataType()->equals(*type))
return f(ConverterType<PolygonFromColumnConverter<Point>>());
if (DataTypeCustomMultiPolygonSerialization::nestedDataType()->equals(*type))
else if (DataTypeCustomMultiPolygonSerialization::nestedDataType()->equals(*type))
return f(ConverterType<MultiPolygonFromColumnConverter<Point>>());
throw Exception(fmt::format("Unknown geometry type {}", type->getName()), ErrorCodes::BAD_ARGUMENTS);
}

View File

@ -20,6 +20,11 @@
namespace DB
{
namespace ErrorCodes
{
extern const int ILLEGAL_TYPE_OF_ARGUMENT;
}
template <typename Point>
class FunctionPolygonArea : public IFunction
{
@ -61,14 +66,20 @@ public:
{
using TypeConverter = std::decay_t<decltype(type)>;
using Converter = typename TypeConverter::Type;
Converter converter(arguments[0].column->convertToFullColumnIfConst());
auto geometries = converter.convert();
auto & res_data = res_column->getData();
res_data.reserve(input_rows_count);
if constexpr (std::is_same_v<PointFromColumnConverter<Point>, Converter>)
throw Exception(fmt::format("The argument of function {} must not be Point", getName()), ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT);
else
{
Converter converter(arguments[0].column->convertToFullColumnIfConst());
auto geometries = converter.convert();
for (size_t i = 0; i < input_rows_count; i++)
res_data.emplace_back(boost::geometry::area(geometries[i]));
auto & res_data = res_column->getData();
res_data.reserve(input_rows_count);
for (size_t i = 0; i < input_rows_count; i++)
res_data.emplace_back(boost::geometry::area(geometries[i]));
}
}
);

View File

@ -67,8 +67,8 @@ public:
using TypeConverter = std::decay_t<decltype(type)>;
using Converter = typename TypeConverter::Type;
if (std::is_same_v<Converter, MultiPolygonSerializer<Point>>)
throw Exception(fmt::format("The argument of function {} could not be a MultiPolygon", getName()), ErrorCodes::BAD_ARGUMENTS);
if constexpr (std::is_same_v<Converter, PointFromColumnConverter<Point>>)
throw Exception(fmt::format("The argument of function {} must not be a Point", getName()), ErrorCodes::BAD_ARGUMENTS);
else
{
Converter converter(arguments[0].column->convertToFullColumnIfConst());

View File

@ -19,6 +19,11 @@
namespace DB
{
namespace ErrorCodes
{
extern const int ILLEGAL_TYPE_OF_ARGUMENT;
}
template <typename Point>
class FunctionPolygonPerimeter : public IFunction
@ -63,11 +68,17 @@ public:
{
using TypeConverter = std::decay_t<decltype(type)>;
using Converter = typename TypeConverter::Type;
Converter converter(arguments[0].column->convertToFullColumnIfConst());
auto geometries = converter.convert();
for (size_t i = 0; i < input_rows_count; i++)
res_data.emplace_back(boost::geometry::perimeter(geometries[i]));
if constexpr (std::is_same_v<PointFromColumnConverter<Point>, Converter>)
throw Exception(fmt::format("The argument of function {} must not be Point", getName()), ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT);
else
{
Converter converter(arguments[0].column->convertToFullColumnIfConst());
auto geometries = converter.convert();
for (size_t i = 0; i < input_rows_count; i++)
res_data.emplace_back(boost::geometry::perimeter(geometries[i]));
}
}
);

View File

@ -22,6 +22,11 @@
namespace DB
{
namespace ErrorCodes
{
extern const int ILLEGAL_TYPE_OF_ARGUMENT;
}
template <typename Point>
class FunctionPolygonsDistance : public IFunction
{
@ -69,15 +74,20 @@ public:
using LeftConverter = typename LeftConverterType::Type;
using RightConverter = typename RightConverterType::Type;
auto first = LeftConverter(arguments[0].column->convertToFullColumnIfConst()).convert();
auto second = RightConverter(arguments[1].column->convertToFullColumnIfConst()).convert();
for (size_t i = 0; i < input_rows_count; i++)
if constexpr (std::is_same_v<PointFromColumnConverter<Point>, LeftConverter> || std::is_same_v<PointFromColumnConverter<Point>, RightConverter>)
throw Exception(fmt::format("Any argument of function {} must not be Point", getName()), ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT);
else
{
boost::geometry::correct(first[i]);
boost::geometry::correct(second[i]);
auto first = LeftConverter(arguments[0].column->convertToFullColumnIfConst()).convert();
auto second = RightConverter(arguments[1].column->convertToFullColumnIfConst()).convert();
res_data.emplace_back(boost::geometry::distance(first[i], second[i]));
for (size_t i = 0; i < input_rows_count; i++)
{
boost::geometry::correct(first[i]);
boost::geometry::correct(second[i]);
res_data.emplace_back(boost::geometry::distance(first[i], second[i]));
}
}
});

View File

@ -21,6 +21,10 @@
namespace DB
{
namespace ErrorCodes
{
extern const int ILLEGAL_TYPE_OF_ARGUMENT;
}
template <typename Point>
class FunctionPolygonsEquals : public IFunction
@ -69,16 +73,21 @@ public:
using LeftConverter = typename LeftConverterType::Type;
using RightConverter = typename RightConverterType::Type;
auto first = LeftConverter(arguments[0].column->convertToFullColumnIfConst()).convert();
auto second = RightConverter(arguments[1].column->convertToFullColumnIfConst()).convert();
for (size_t i = 0; i < input_rows_count; i++)
if constexpr (std::is_same_v<PointFromColumnConverter<Point>, LeftConverter> || std::is_same_v<PointFromColumnConverter<Point>, RightConverter>)
throw Exception(fmt::format("Any argument of function {} must not be Point", getName()), ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT);
else
{
boost::geometry::correct(first[i]);
boost::geometry::correct(second[i]);
auto first = LeftConverter(arguments[0].column->convertToFullColumnIfConst()).convert();
auto second = RightConverter(arguments[1].column->convertToFullColumnIfConst()).convert();
/// Main work here.
res_data.emplace_back(boost::geometry::equals(first[i], second[i]));
for (size_t i = 0; i < input_rows_count; i++)
{
boost::geometry::correct(first[i]);
boost::geometry::correct(second[i]);
/// Main work here.
res_data.emplace_back(boost::geometry::equals(first[i], second[i]));
}
}
}
);

View File

@ -21,6 +21,11 @@
namespace DB
{
namespace ErrorCodes
{
extern const int ILLEGAL_TYPE_OF_ARGUMENT;
}
template <typename Point>
class FunctionPolygonsIntersection : public IFunction
{
@ -67,22 +72,27 @@ public:
using LeftConverter = typename LeftConverterType::Type;
using RightConverter = typename RightConverterType::Type;
auto first = LeftConverter(arguments[0].column->convertToFullColumnIfConst()).convert();
auto second = RightConverter(arguments[1].column->convertToFullColumnIfConst()).convert();
/// 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)
if constexpr (std::is_same_v<PointFromColumnConverter<Point>, LeftConverter> || std::is_same_v<PointFromColumnConverter<Point>, RightConverter>)
throw Exception(fmt::format("Any argument of function {} must not be Point", getName()), ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT);
else
{
/// Orient the polygons correctly.
boost::geometry::correct(first[i]);
boost::geometry::correct(second[i]);
auto first = LeftConverter(arguments[0].column->convertToFullColumnIfConst()).convert();
auto second = RightConverter(arguments[1].column->convertToFullColumnIfConst()).convert();
MultiPolygon<Point> intersection{};
/// Main work here.
boost::geometry::intersection(first[i], second[i], 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)
{
/// Orient the polygons correctly.
boost::geometry::correct(first[i]);
boost::geometry::correct(second[i]);
serializer.add(intersection);
MultiPolygon<Point> intersection{};
/// Main work here.
boost::geometry::intersection(first[i], second[i], intersection);
serializer.add(intersection);
}
}
});

View File

@ -20,6 +20,12 @@
namespace DB
{
namespace ErrorCodes
{
extern const int ILLEGAL_TYPE_OF_ARGUMENT;
}
template <typename Point>
class FunctionPolygonsSymDifference : public IFunction
{
@ -65,19 +71,24 @@ public:
using LeftConverter = typename LeftConverterType::Type;
using RightConverter = typename RightConverterType::Type;
auto first = LeftConverter(arguments[0].column->convertToFullColumnIfConst()).convert();
auto second = RightConverter(arguments[1].column->convertToFullColumnIfConst()).convert();
/// NOLINTNEXTLINE(clang-analyzer-core.uninitialized.Assign)
for (size_t i = 0; i < input_rows_count; i++)
if constexpr (std::is_same_v<PointFromColumnConverter<Point>, LeftConverter> || std::is_same_v<PointFromColumnConverter<Point>, RightConverter>)
throw Exception(fmt::format("Any argument of function {} must not be Point", getName()), ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT);
else
{
boost::geometry::correct(first[i]);
boost::geometry::correct(second[i]);
auto first = LeftConverter(arguments[0].column->convertToFullColumnIfConst()).convert();
auto second = RightConverter(arguments[1].column->convertToFullColumnIfConst()).convert();
MultiPolygon<Point> sym_difference{};
boost::geometry::sym_difference(first[i], second[i], sym_difference);
/// NOLINTNEXTLINE(clang-analyzer-core.uninitialized.Assign)
for (size_t i = 0; i < input_rows_count; i++)
{
boost::geometry::correct(first[i]);
boost::geometry::correct(second[i]);
serializer.add(sym_difference);
MultiPolygon<Point> sym_difference{};
boost::geometry::sym_difference(first[i], second[i], sym_difference);
serializer.add(sym_difference);
}
}
});

View File

@ -20,6 +20,12 @@
namespace DB
{
namespace ErrorCodes
{
extern const int ILLEGAL_TYPE_OF_ARGUMENT;
}
template <typename Point>
class FunctionPolygonsUnion : public IFunction
{
@ -65,22 +71,27 @@ public:
using LeftConverter = typename LeftConverterType::Type;
using RightConverter = typename RightConverterType::Type;
auto first = LeftConverter(arguments[0].column->convertToFullColumnIfConst()).convert();
auto second = RightConverter(arguments[1].column->convertToFullColumnIfConst()).convert();
/// 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++)
if constexpr (std::is_same_v<PointFromColumnConverter<Point>, LeftConverter> || std::is_same_v<PointFromColumnConverter<Point>, RightConverter>)
throw Exception(fmt::format("Any argument of function {} must not be Point", getName()), ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT);
else
{
/// Orient the polygons correctly.
boost::geometry::correct(first[i]);
boost::geometry::correct(second[i]);
auto first = LeftConverter(arguments[0].column->convertToFullColumnIfConst()).convert();
auto second = RightConverter(arguments[1].column->convertToFullColumnIfConst()).convert();
MultiPolygon<Point> polygons_union{};
/// Main work here.
boost::geometry::union_(first[i], second[i], 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++)
{
/// Orient the polygons correctly.
boost::geometry::correct(first[i]);
boost::geometry::correct(second[i]);
serializer.add(polygons_union);
MultiPolygon<Point> polygons_union{};
/// Main work here.
boost::geometry::union_(first[i], second[i], polygons_union);
serializer.add(polygons_union);
}
}
});

View File

@ -22,6 +22,12 @@
namespace DB
{
namespace ErrorCodes
{
extern const int ILLEGAL_TYPE_OF_ARGUMENT;
}
template <typename Point>
class FunctionPolygonsWithin : public IFunction
{
@ -69,16 +75,21 @@ public:
using LeftConverter = typename LeftConverterType::Type;
using RightConverter = typename RightConverterType::Type;
auto first = LeftConverter(arguments[0].column->convertToFullColumnIfConst()).convert();
auto second = RightConverter(arguments[1].column->convertToFullColumnIfConst()).convert();
/// NOLINTNEXTLINE(clang-analyzer-core.uninitialized.Assign)
for (size_t i = 0; i < input_rows_count; i++)
if constexpr (std::is_same_v<PointFromColumnConverter<Point>, LeftConverter> || std::is_same_v<PointFromColumnConverter<Point>, RightConverter>)
throw Exception(fmt::format("Any argument of function {} must not be Point", getName()), ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT);
else
{
boost::geometry::correct(first[i]);
boost::geometry::correct(second[i]);
auto first = LeftConverter(arguments[0].column->convertToFullColumnIfConst()).convert();
auto second = RightConverter(arguments[1].column->convertToFullColumnIfConst()).convert();
res_data.emplace_back(boost::geometry::within(first[i], second[i]));
/// NOLINTNEXTLINE(clang-analyzer-core.uninitialized.Assign)
for (size_t i = 0; i < input_rows_count; i++)
{
boost::geometry::correct(first[i]);
boost::geometry::correct(second[i]);
res_data.emplace_back(boost::geometry::within(first[i], second[i]));
}
}
});

View File

@ -71,6 +71,7 @@ public:
{
using TypeConverter = std::decay_t<decltype(type)>;
using Converter = typename TypeConverter::Type;
Converter converter(arguments[0].column->convertToFullColumnIfConst());
auto figures = converter.convert();

View File

@ -44,6 +44,7 @@ public:
{
using TypeConverter = std::decay_t<decltype(type)>;
using Converter = typename TypeConverter::Type;
Converter converter(arguments[0].column->convertToFullColumnIfConst());
auto figures = converter.convert();

View File

@ -1,11 +1,11 @@
<circle cx="0" cy="0" r="5" style=""/>
<polygon points="0,0 10,0 10,10 0,10 0,0" style=""/>
<g fill-rule="evenodd"><path d="M 0,0 L 10,0 L 10,10 L 0,10 L 0,0M 4,4 L 5,4 L 5,5 L 4,5 L 4,4 z " style=""/></g>
<g fill-rule="evenodd"><path d="M 0,0 L 10,0 L 10,10 L 0,10 L 0,0M 4,4 L 5,4 L 5,5 L 4,5 L 4,4 z " style=""/></g><g fill-rule="evenodd"><path d="M -10,-10 L -10,-9 L -9,10 L -10,-10 z " style=""/></g>
<polygon points="0,0 0,10 10,10 10,0 0,0" style=""/>
<g fill-rule="evenodd"><path d="M 0,0 L 0,10 L 10,10 L 10,0 L 0,0M 4,4 L 5,4 L 5,5 L 4,5 L 4,4 z " style=""/></g>
<g fill-rule="evenodd"><path d="M 0,0 L 0,10 L 10,10 L 10,0 L 0,0M 4,4 L 5,4 L 5,5 L 4,5 L 4,4 z " style=""/></g><g fill-rule="evenodd"><path d="M -10,-10 L -10,-9 L -9,10 L -10,-10 z " style=""/></g>
<circle cx="0" cy="0" r="5" style="b"/>
<polygon points="0,0 10,0 10,10 0,10 0,0" style="b"/>
<g fill-rule="evenodd"><path d="M 0,0 L 10,0 L 10,10 L 0,10 L 0,0M 4,4 L 5,4 L 5,5 L 4,5 L 4,4 z " style="b"/></g>
<g fill-rule="evenodd"><path d="M 0,0 L 10,0 L 10,10 L 0,10 L 0,0M 4,4 L 5,4 L 5,5 L 4,5 L 4,4 z " style="b"/></g><g fill-rule="evenodd"><path d="M -10,-10 L -10,-9 L -9,10 L -10,-10 z " style="b"/></g>
<polygon points="0,0 0,10 10,10 10,0 0,0" style="b"/>
<g fill-rule="evenodd"><path d="M 0,0 L 0,10 L 10,10 L 10,0 L 0,0M 4,4 L 5,4 L 5,5 L 4,5 L 4,4 z " style="b"/></g>
<g fill-rule="evenodd"><path d="M 0,0 L 0,10 L 10,10 L 10,0 L 0,0M 4,4 L 5,4 L 5,5 L 4,5 L 4,4 z " style="b"/></g><g fill-rule="evenodd"><path d="M -10,-10 L -10,-9 L -9,10 L -10,-10 z " style="b"/></g>
<circle cx="0" cy="0" r="5" style=""/>
<circle cx="1" cy="0" r="5" style=""/>
<circle cx="2" cy="0" r="5" style=""/>
@ -18,39 +18,39 @@
<circle cx="0" cy="0" r="5" style="b"/>
<circle cx="1" cy="0" r="5" style="c"/>
<circle cx="2" cy="0" r="5" style="d"/>
<polygon points="0,0 10,0 10,10 0,10 0,0" style=""/>
<polygon points="1,0 10,0 10,10 0,10 1,0" style=""/>
<polygon points="2,0 10,0 10,10 0,10 2,0" style=""/>
<polygon points="0,0 10,0 10,10 0,10 0,0" style="b"/>
<polygon points="1,0 10,0 10,10 0,10 1,0" style="b"/>
<polygon points="2,0 10,0 10,10 0,10 2,0" style="b"/>
<polygon points="0,0 10,0 10,10 0,10 0,0" style="b"/>
<polygon points="0,0 10,0 10,10 0,10 0,0" style="c"/>
<polygon points="0,0 10,0 10,10 0,10 0,0" style="d"/>
<polygon points="0,0 10,0 10,10 0,10 0,0" style="b"/>
<polygon points="1,0 10,0 10,10 0,10 1,0" style="c"/>
<polygon points="2,0 10,0 10,10 0,10 2,0" style="d"/>
<g fill-rule="evenodd"><path d="M 0,0 L 10,0 L 10,10 L 0,10 L 0,0M 4,4 L 5,4 L 5,5 L 4,5 L 4,4 z " style=""/></g>
<g fill-rule="evenodd"><path d="M 1,0 L 10,0 L 10,10 L 0,10 L 1,0M 4,4 L 5,4 L 5,5 L 4,5 L 4,4 z " style=""/></g>
<g fill-rule="evenodd"><path d="M 2,0 L 10,0 L 10,10 L 0,10 L 2,0M 4,4 L 5,4 L 5,5 L 4,5 L 4,4 z " style=""/></g>
<g fill-rule="evenodd"><path d="M 0,0 L 10,0 L 10,10 L 0,10 L 0,0M 4,4 L 5,4 L 5,5 L 4,5 L 4,4 z " style="b"/></g>
<g fill-rule="evenodd"><path d="M 1,0 L 10,0 L 10,10 L 0,10 L 1,0M 4,4 L 5,4 L 5,5 L 4,5 L 4,4 z " style="b"/></g>
<g fill-rule="evenodd"><path d="M 2,0 L 10,0 L 10,10 L 0,10 L 2,0M 4,4 L 5,4 L 5,5 L 4,5 L 4,4 z " style="b"/></g>
<g fill-rule="evenodd"><path d="M 0,0 L 10,0 L 10,10 L 0,10 L 0,0M 4,4 L 5,4 L 5,5 L 4,5 L 4,4 z " style="b"/></g>
<g fill-rule="evenodd"><path d="M 0,0 L 10,0 L 10,10 L 0,10 L 0,0M 4,4 L 5,4 L 5,5 L 4,5 L 4,4 z " style="c"/></g>
<g fill-rule="evenodd"><path d="M 0,0 L 10,0 L 10,10 L 0,10 L 0,0M 4,4 L 5,4 L 5,5 L 4,5 L 4,4 z " style="d"/></g>
<g fill-rule="evenodd"><path d="M 0,0 L 10,0 L 10,10 L 0,10 L 0,0M 4,4 L 5,4 L 5,5 L 4,5 L 4,4 z " style="b"/></g>
<g fill-rule="evenodd"><path d="M 1,0 L 10,0 L 10,10 L 0,10 L 1,0M 4,4 L 5,4 L 5,5 L 4,5 L 4,4 z " style="c"/></g>
<g fill-rule="evenodd"><path d="M 2,0 L 10,0 L 10,10 L 0,10 L 2,0M 4,4 L 5,4 L 5,5 L 4,5 L 4,4 z " style="d"/></g>
<g fill-rule="evenodd"><path d="M 0,0 L 10,0 L 10,10 L 0,10 L 0,0M 4,4 L 5,4 L 5,5 L 4,5 L 4,4 z " style=""/></g><g fill-rule="evenodd"><path d="M -10,-10 L -10,-9 L -9,10 L -10,-10 z " style=""/></g>
<g fill-rule="evenodd"><path d="M 1,0 L 10,0 L 10,10 L 0,10 L 1,0M 4,4 L 5,4 L 5,5 L 4,5 L 4,4 z " style=""/></g><g fill-rule="evenodd"><path d="M -10,-10 L -10,-9 L -9,10 L -10,-10 z " style=""/></g>
<g fill-rule="evenodd"><path d="M 2,0 L 10,0 L 10,10 L 0,10 L 2,0M 4,4 L 5,4 L 5,5 L 4,5 L 4,4 z " style=""/></g><g fill-rule="evenodd"><path d="M -10,-10 L -10,-9 L -9,10 L -10,-10 z " style=""/></g>
<g fill-rule="evenodd"><path d="M 0,0 L 10,0 L 10,10 L 0,10 L 0,0M 4,4 L 5,4 L 5,5 L 4,5 L 4,4 z " style="b"/></g><g fill-rule="evenodd"><path d="M -10,-10 L -10,-9 L -9,10 L -10,-10 z " style="b"/></g>
<g fill-rule="evenodd"><path d="M 1,0 L 10,0 L 10,10 L 0,10 L 1,0M 4,4 L 5,4 L 5,5 L 4,5 L 4,4 z " style="b"/></g><g fill-rule="evenodd"><path d="M -10,-10 L -10,-9 L -9,10 L -10,-10 z " style="b"/></g>
<g fill-rule="evenodd"><path d="M 2,0 L 10,0 L 10,10 L 0,10 L 2,0M 4,4 L 5,4 L 5,5 L 4,5 L 4,4 z " style="b"/></g><g fill-rule="evenodd"><path d="M -10,-10 L -10,-9 L -9,10 L -10,-10 z " style="b"/></g>
<g fill-rule="evenodd"><path d="M 0,0 L 10,0 L 10,10 L 0,10 L 0,0M 4,4 L 5,4 L 5,5 L 4,5 L 4,4 z " style="b"/></g><g fill-rule="evenodd"><path d="M -10,-10 L -10,-9 L -9,10 L -10,-10 z " style="b"/></g>
<g fill-rule="evenodd"><path d="M 0,0 L 10,0 L 10,10 L 0,10 L 0,0M 4,4 L 5,4 L 5,5 L 4,5 L 4,4 z " style="c"/></g><g fill-rule="evenodd"><path d="M -10,-10 L -10,-9 L -9,10 L -10,-10 z " style="c"/></g>
<g fill-rule="evenodd"><path d="M 0,0 L 10,0 L 10,10 L 0,10 L 0,0M 4,4 L 5,4 L 5,5 L 4,5 L 4,4 z " style="d"/></g><g fill-rule="evenodd"><path d="M -10,-10 L -10,-9 L -9,10 L -10,-10 z " style="d"/></g>
<g fill-rule="evenodd"><path d="M 0,0 L 10,0 L 10,10 L 0,10 L 0,0M 4,4 L 5,4 L 5,5 L 4,5 L 4,4 z " style="b"/></g><g fill-rule="evenodd"><path d="M -10,-10 L -10,-9 L -9,10 L -10,-10 z " style="b"/></g>
<g fill-rule="evenodd"><path d="M 1,0 L 10,0 L 10,10 L 0,10 L 1,0M 4,4 L 5,4 L 5,5 L 4,5 L 4,4 z " style="c"/></g><g fill-rule="evenodd"><path d="M -10,-10 L -10,-9 L -9,10 L -10,-10 z " style="c"/></g>
<g fill-rule="evenodd"><path d="M 2,0 L 10,0 L 10,10 L 0,10 L 2,0M 4,4 L 5,4 L 5,5 L 4,5 L 4,4 z " style="d"/></g><g fill-rule="evenodd"><path d="M -10,-10 L -10,-9 L -9,10 L -10,-10 z " style="d"/></g>
<polygon points="0,0 0,10 10,10 10,0 0,0" style=""/>
<polygon points="1,0 0,10 10,10 10,0 1,0" style=""/>
<polygon points="2,0 0,10 10,10 10,0 2,0" style=""/>
<polygon points="0,0 0,10 10,10 10,0 0,0" style="b"/>
<polygon points="1,0 0,10 10,10 10,0 1,0" style="b"/>
<polygon points="2,0 0,10 10,10 10,0 2,0" style="b"/>
<polygon points="0,0 0,10 10,10 10,0 0,0" style="b"/>
<polygon points="0,0 0,10 10,10 10,0 0,0" style="c"/>
<polygon points="0,0 0,10 10,10 10,0 0,0" style="d"/>
<polygon points="0,0 0,10 10,10 10,0 0,0" style="b"/>
<polygon points="1,0 0,10 10,10 10,0 1,0" style="c"/>
<polygon points="2,0 0,10 10,10 10,0 2,0" style="d"/>
<g fill-rule="evenodd"><path d="M 0,0 L 0,10 L 10,10 L 10,0 L 0,0M 4,4 L 5,4 L 5,5 L 4,5 L 4,4 z " style=""/></g>
<g fill-rule="evenodd"><path d="M 1,0 L 0,10 L 10,10 L 10,0 L 1,0M 4,4 L 5,4 L 5,5 L 4,5 L 4,4 z " style=""/></g>
<g fill-rule="evenodd"><path d="M 2,0 L 0,10 L 10,10 L 10,0 L 2,0M 4,4 L 5,4 L 5,5 L 4,5 L 4,4 z " style=""/></g>
<g fill-rule="evenodd"><path d="M 0,0 L 0,10 L 10,10 L 10,0 L 0,0M 4,4 L 5,4 L 5,5 L 4,5 L 4,4 z " style="b"/></g>
<g fill-rule="evenodd"><path d="M 1,0 L 0,10 L 10,10 L 10,0 L 1,0M 4,4 L 5,4 L 5,5 L 4,5 L 4,4 z " style="b"/></g>
<g fill-rule="evenodd"><path d="M 2,0 L 0,10 L 10,10 L 10,0 L 2,0M 4,4 L 5,4 L 5,5 L 4,5 L 4,4 z " style="b"/></g>
<g fill-rule="evenodd"><path d="M 0,0 L 0,10 L 10,10 L 10,0 L 0,0M 4,4 L 5,4 L 5,5 L 4,5 L 4,4 z " style="b"/></g>
<g fill-rule="evenodd"><path d="M 0,0 L 0,10 L 10,10 L 10,0 L 0,0M 4,4 L 5,4 L 5,5 L 4,5 L 4,4 z " style="c"/></g>
<g fill-rule="evenodd"><path d="M 0,0 L 0,10 L 10,10 L 10,0 L 0,0M 4,4 L 5,4 L 5,5 L 4,5 L 4,4 z " style="d"/></g>
<g fill-rule="evenodd"><path d="M 0,0 L 0,10 L 10,10 L 10,0 L 0,0M 4,4 L 5,4 L 5,5 L 4,5 L 4,4 z " style="b"/></g>
<g fill-rule="evenodd"><path d="M 1,0 L 0,10 L 10,10 L 10,0 L 1,0M 4,4 L 5,4 L 5,5 L 4,5 L 4,4 z " style="c"/></g>
<g fill-rule="evenodd"><path d="M 2,0 L 0,10 L 10,10 L 10,0 L 2,0M 4,4 L 5,4 L 5,5 L 4,5 L 4,4 z " style="d"/></g>
<g fill-rule="evenodd"><path d="M 0,0 L 0,10 L 10,10 L 10,0 L 0,0M 4,4 L 5,4 L 5,5 L 4,5 L 4,4 z " style=""/></g><g fill-rule="evenodd"><path d="M -10,-10 L -10,-9 L -9,10 L -10,-10 z " style=""/></g>
<g fill-rule="evenodd"><path d="M 1,0 L 0,10 L 10,10 L 10,0 L 1,0M 4,4 L 5,4 L 5,5 L 4,5 L 4,4 z " style=""/></g><g fill-rule="evenodd"><path d="M -10,-10 L -10,-9 L -9,10 L -10,-10 z " style=""/></g>
<g fill-rule="evenodd"><path d="M 2,0 L 0,10 L 10,10 L 10,0 L 2,0M 4,4 L 5,4 L 5,5 L 4,5 L 4,4 z " style=""/></g><g fill-rule="evenodd"><path d="M -10,-10 L -10,-9 L -9,10 L -10,-10 z " style=""/></g>
<g fill-rule="evenodd"><path d="M 0,0 L 0,10 L 10,10 L 10,0 L 0,0M 4,4 L 5,4 L 5,5 L 4,5 L 4,4 z " style="b"/></g><g fill-rule="evenodd"><path d="M -10,-10 L -10,-9 L -9,10 L -10,-10 z " style="b"/></g>
<g fill-rule="evenodd"><path d="M 1,0 L 0,10 L 10,10 L 10,0 L 1,0M 4,4 L 5,4 L 5,5 L 4,5 L 4,4 z " style="b"/></g><g fill-rule="evenodd"><path d="M -10,-10 L -10,-9 L -9,10 L -10,-10 z " style="b"/></g>
<g fill-rule="evenodd"><path d="M 2,0 L 0,10 L 10,10 L 10,0 L 2,0M 4,4 L 5,4 L 5,5 L 4,5 L 4,4 z " style="b"/></g><g fill-rule="evenodd"><path d="M -10,-10 L -10,-9 L -9,10 L -10,-10 z " style="b"/></g>
<g fill-rule="evenodd"><path d="M 0,0 L 0,10 L 10,10 L 10,0 L 0,0M 4,4 L 5,4 L 5,5 L 4,5 L 4,4 z " style="b"/></g><g fill-rule="evenodd"><path d="M -10,-10 L -10,-9 L -9,10 L -10,-10 z " style="b"/></g>
<g fill-rule="evenodd"><path d="M 0,0 L 0,10 L 10,10 L 10,0 L 0,0M 4,4 L 5,4 L 5,5 L 4,5 L 4,4 z " style="c"/></g><g fill-rule="evenodd"><path d="M -10,-10 L -10,-9 L -9,10 L -10,-10 z " style="c"/></g>
<g fill-rule="evenodd"><path d="M 0,0 L 0,10 L 10,10 L 10,0 L 0,0M 4,4 L 5,4 L 5,5 L 4,5 L 4,4 z " style="d"/></g><g fill-rule="evenodd"><path d="M -10,-10 L -10,-9 L -9,10 L -10,-10 z " style="d"/></g>
<g fill-rule="evenodd"><path d="M 0,0 L 0,10 L 10,10 L 10,0 L 0,0M 4,4 L 5,4 L 5,5 L 4,5 L 4,4 z " style="b"/></g><g fill-rule="evenodd"><path d="M -10,-10 L -10,-9 L -9,10 L -10,-10 z " style="b"/></g>
<g fill-rule="evenodd"><path d="M 1,0 L 0,10 L 10,10 L 10,0 L 1,0M 4,4 L 5,4 L 5,5 L 4,5 L 4,4 z " style="c"/></g><g fill-rule="evenodd"><path d="M -10,-10 L -10,-9 L -9,10 L -10,-10 z " style="c"/></g>
<g fill-rule="evenodd"><path d="M 2,0 L 0,10 L 10,10 L 10,0 L 2,0M 4,4 L 5,4 L 5,5 L 4,5 L 4,4 z " style="d"/></g><g fill-rule="evenodd"><path d="M -10,-10 L -10,-9 L -9,10 L -10,-10 z " style="d"/></g>

View File

@ -1,48 +1,48 @@
SELECT svg((0, 0));
SELECT svg([(0, 0), (10, 0), (10, 10), (0, 10)]);
SELECT svg([[(0, 0), (10, 0), (10, 10), (0, 10)], [(4, 4), (5, 4), (5, 5), (4, 5)]]);
SELECT svg([[[(0, 0), (10, 0), (10, 10), (0, 10)], [(4, 4), (5, 4), (5, 5), (4, 5)]], [[(-10, -10), (-10, -9), (-9, 10)]]]);
SELECT svg((0, 0), 'b');
SELECT svg([(0, 0), (10, 0), (10, 10), (0, 10)], 'b');
SELECT svg([[(0, 0), (10, 0), (10, 10), (0, 10)], [(4, 4), (5, 4), (5, 5), (4, 5)]], 'b');
SELECT svg([[[(0, 0), (10, 0), (10, 10), (0, 10)], [(4, 4), (5, 4), (5, 5), (4, 5)]], [[(-10, -10), (-10, -9), (-9, 10)]]], 'b');
SELECT svg((0., 0.));
SELECT svg([(0., 0.), (10, 0), (10, 10), (0, 10)]);
SELECT svg([[(0., 0.), (10, 0), (10, 10), (0, 10)], [(4., 4.), (5, 4), (5, 5), (4, 5)]]);
SELECT svg([[[(0., 0.), (10, 0), (10, 10), (0, 10)], [(4., 4.), (5, 4), (5, 5), (4, 5)]], [[(-10., -10.), (-10, -9), (-9, 10)]]]);
SELECT svg((0., 0.), 'b');
SELECT svg([(0., 0.), (10, 0), (10, 10), (0, 10)], 'b');
SELECT svg([[(0., 0.), (10, 0), (10, 10), (0, 10)], [(4., 4.), (5, 4), (5, 5), (4, 5)]], 'b');
SELECT svg([[[(0., 0.), (10, 0), (10, 10), (0, 10)], [(4., 4.), (5, 4), (5, 5), (4, 5)]], [[(-10., -10.), (-10, -9), (-9, 10)]]], 'b');
DROP TABLE IF EXISTS geo;
CREATE TABLE geo (p Tuple(Float64, Float64), s String, id Int) engine=Memory();
INSERT INTO geo VALUES ((0, 0), 'b', 1);
INSERT INTO geo VALUES ((1, 0), 'c', 2);
INSERT INTO geo VALUES ((2, 0), 'd', 3);
INSERT INTO geo VALUES ((0., 0.), 'b', 1);
INSERT INTO geo VALUES ((1., 0.), 'c', 2);
INSERT INTO geo VALUES ((2., 0.), 'd', 3);
SELECT svg(p) FROM geo ORDER BY id;
SELECT svg(p, 'b') FROM geo ORDER BY id;
SELECT svg((0, 0), s) FROM geo ORDER BY id;
SELECT svg((0., 0.), s) FROM geo ORDER BY id;
SELECT svg(p, s) FROM geo ORDER BY id;
DROP TABLE IF EXISTS geo;
CREATE TABLE geo (p Array(Tuple(Float64, Float64)), s String, id Int) engine=Memory();
INSERT INTO geo VALUES ([(0, 0), (10, 0), (10, 10), (0, 10)], 'b', 1);
INSERT INTO geo VALUES ([(1, 0), (10, 0), (10, 10), (0, 10)], 'c', 2);
INSERT INTO geo VALUES ([(2, 0), (10, 0), (10, 10), (0, 10)], 'd', 3);
INSERT INTO geo VALUES ([(0., 0.), (10, 0), (10, 10), (0, 10)], 'b', 1);
INSERT INTO geo VALUES ([(1., 0.), (10, 0), (10, 10), (0, 10)], 'c', 2);
INSERT INTO geo VALUES ([(2., 0.), (10, 0), (10, 10), (0, 10)], 'd', 3);
SELECT svg(p) FROM geo ORDER BY id;
SELECT svg(p, 'b') FROM geo ORDER BY id;
SELECT svg([(0, 0), (10, 0), (10, 10), (0, 10)], s) FROM geo ORDER BY id;
SELECT svg([(0., 0.), (10, 0), (10, 10), (0, 10)], s) FROM geo ORDER BY id;
SELECT svg(p, s) FROM geo ORDER BY id;
DROP TABLE IF EXISTS geo;
CREATE TABLE geo (p Array(Array(Tuple(Float64, Float64))), s String, id Int) engine=Memory();
INSERT INTO geo VALUES ([[(0, 0), (10, 0), (10, 10), (0, 10)], [(4, 4), (5, 4), (5, 5), (4, 5)]], 'b', 1);
INSERT INTO geo VALUES ([[(1, 0), (10, 0), (10, 10), (0, 10)], [(4, 4), (5, 4), (5, 5), (4, 5)]], 'c', 2);
INSERT INTO geo VALUES ([[(2, 0), (10, 0), (10, 10), (0, 10)], [(4, 4), (5, 4), (5, 5), (4, 5)]], 'd', 3);
INSERT INTO geo VALUES ([[(0., 0.), (10, 0), (10, 10), (0, 10)], [(4, 4), (5, 4), (5, 5), (4, 5)]], 'b', 1);
INSERT INTO geo VALUES ([[(1., 0.), (10, 0), (10, 10), (0, 10)], [(4, 4), (5, 4), (5, 5), (4, 5)]], 'c', 2);
INSERT INTO geo VALUES ([[(2., 0.), (10, 0), (10, 10), (0, 10)], [(4, 4), (5, 4), (5, 5), (4, 5)]], 'd', 3);
SELECT svg(p) FROM geo ORDER BY id;
SELECT svg(p, 'b') FROM geo ORDER BY id;
SELECT svg([[(0, 0), (10, 0), (10, 10), (0, 10)], [(4, 4), (5, 4), (5, 5), (4, 5)]], s) FROM geo ORDER BY id;
SELECT svg([[(0., 0.), (10, 0), (10, 10), (0, 10)], [(4., 4.), (5, 4), (5, 5), (4, 5)]], s) FROM geo ORDER BY id;
SELECT svg(p, s) FROM geo ORDER BY id;
DROP TABLE IF EXISTS geo;
CREATE TABLE geo (p Array(Array(Array(Tuple(Float64, Float64)))), s String, id Int) engine=Memory();
INSERT INTO geo VALUES ([[[(0, 0), (10, 0), (10, 10), (0, 10)], [(4, 4), (5, 4), (5, 5), (4, 5)]], [[(-10, -10), (-10, -9), (-9, 10)]]], 'b', 1);
INSERT INTO geo VALUES ([[[(1, 0), (10, 0), (10, 10), (0, 10)], [(4, 4), (5, 4), (5, 5), (4, 5)]], [[(-10, -10), (-10, -9), (-9, 10)]]], 'c', 2);
INSERT INTO geo VALUES ([[[(2, 0), (10, 0), (10, 10), (0, 10)], [(4, 4), (5, 4), (5, 5), (4, 5)]], [[(-10, -10), (-10, -9), (-9, 10)]]], 'd', 3);
INSERT INTO geo VALUES ([[[(0., 0.), (10, 0), (10, 10), (0, 10)], [(4., 4.), (5, 4), (5, 5), (4, 5)]], [[(-10., -10.), (-10, -9), (-9, 10)]]], 'b', 1);
INSERT INTO geo VALUES ([[[(1., 0.), (10, 0), (10, 10), (0, 10)], [(4., 4.), (5, 4), (5, 5), (4, 5)]], [[(-10., -10.), (-10, -9), (-9, 10)]]], 'c', 2);
INSERT INTO geo VALUES ([[[(2., 0.), (10, 0), (10, 10), (0, 10)], [(4., 4.), (5, 4), (5, 5), (4, 5)]], [[(-10., -10.), (-10, -9), (-9, 10)]]], 'd', 3);
SELECT svg(p) FROM geo ORDER BY id;
SELECT svg(p, 'b') FROM geo ORDER BY id;
SELECT svg([[[(0, 0), (10, 0), (10, 10), (0, 10)], [(4, 4), (5, 4), (5, 5), (4, 5)]], [[(-10, -10), (-10, -9), (-9, 10)]]], s) FROM geo ORDER BY id;
SELECT svg([[[(0., 0.), (10, 0), (10, 10), (0, 10)], [(4., 4.), (5, 4), (5, 5), (4, 5)]], [[(-10., -10.), (-10, -9), (-9, 10)]]], s) FROM geo ORDER BY id;
SELECT svg(p, s) FROM geo ORDER BY id;

View File

@ -1,13 +1,13 @@
POINT(0 0)
POLYGON((0 0,10 0,10 10,0 10,0 0))
POLYGON((0 0,10 0,10 10,0 10))
POLYGON((0 0,10 0,10 10,0 10,0 0),(4 4,5 4,5 5,4 5,4 4))
MULTIPOLYGON(((0 0,10 0,10 10,0 10,0 0),(4 4,5 4,5 5,4 5,4 4)),((-10 -10,-10 -9,-9 10,-10 -10)))
POINT(0 0)
POINT(1 0)
POINT(2 0)
POLYGON((0 0,10 0,10 10,0 10,0 0))
POLYGON((1 0,10 0,10 10,0 10,1 0))
POLYGON((2 0,10 0,10 10,0 10,2 0))
POLYGON((0 0,10 0,10 10,0 10))
POLYGON((1 0,10 0,10 10,0 10))
POLYGON((2 0,10 0,10 10,0 10))
POLYGON((0 0,10 0,10 10,0 10,0 0),(4 4,5 4,5 5,4 5,4 4))
POLYGON((1 0,10 0,10 10,0 10,1 0),(4 4,5 4,5 5,4 5,4 4))
POLYGON((2 0,10 0,10 10,0 10,2 0),(4 4,5 4,5 5,4 5,4 4))

View File

@ -1,7 +1,7 @@
SELECT wkt((0, 0));
SELECT wkt([(0, 0), (10, 0), (10, 10), (0, 10)]);
SELECT wkt([[(0, 0), (10, 0), (10, 10), (0, 10)], [(4, 4), (5, 4), (5, 5), (4, 5)]]);
SELECT wkt([[[(0, 0), (10, 0), (10, 10), (0, 10)], [(4, 4), (5, 4), (5, 5), (4, 5)]], [[(-10, -10), (-10, -9), (-9, 10)]]]);
SELECT wkt((0., 0.));
SELECT wkt([(0., 0.), (10., 0.), (10., 10.), (0., 10.)]);
SELECT wkt([[(0., 0.), (10., 0.), (10., 10.), (0., 10.)], [(4., 4.), (5., 4.), (5., 5.), (4., 5.)]]);
SELECT wkt([[[(0., 0.), (10., 0.), (10., 10.), (0., 10.)], [(4., 4.), (5., 4.), (5., 5.), (4., 5.)]], [[(-10., -10.), (-10., -9.), (-9., 10.)]]]);
DROP TABLE IF EXISTS geo;
CREATE TABLE geo (p Tuple(Float64, Float64), id Int) engine=Memory();