forked from duckdb/duckdb-spatial
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
6 changed files
with
161 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,6 @@ | ||
set(EXTENSION_SOURCES | ||
${EXTENSION_SOURCES} | ||
${CMAKE_CURRENT_SOURCE_DIR}/st_envelope_agg.cpp | ||
${CMAKE_CURRENT_SOURCE_DIR}/st_svg_agg.cpp | ||
PARENT_SCOPE | ||
) |
46 changes: 46 additions & 0 deletions
46
spatial/src/spatial/core/functions/aggregate/st_svg_agg.cpp
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
#include "duckdb/common/types/null_value.hpp" | ||
#include "duckdb/execution/expression_executor.hpp" | ||
#include "duckdb/planner/expression/bound_constant_expression.hpp" | ||
|
||
#include "spatial/common.hpp" | ||
#include "spatial/core/functions/aggregate.hpp" | ||
#include "duckdb/function/scalar_macro_function.hpp" | ||
|
||
#include "duckdb/catalog/default/default_functions.hpp" | ||
|
||
namespace spatial { | ||
|
||
namespace core { | ||
|
||
void CoreAggregateFunctions::RegisterStSvgAgg(DatabaseInstance &db) { | ||
|
||
DefaultMacro macro = {nullptr}; | ||
macro.schema = DEFAULT_SCHEMA; | ||
macro.name = "st_svg_agg"; | ||
macro.parameters[0] = "geom"; | ||
macro.parameters[1] = "style"; | ||
macro.macro = R"--( | ||
format('<svg viewBox="{} {} {} {}" width="{}" height="{}" xmlns="http://www.w3.org/2000/svg"> {} </svg>', | ||
st_xmin(st_envelope_agg(geom)) - (st_xmax(st_envelope_agg(geom)) - st_xmin(st_envelope_agg(geom))) * padding, | ||
st_ymin(st_envelope_agg(geom)) - (st_ymax(st_envelope_agg(geom)) - st_ymin(st_envelope_agg(geom))) * padding, | ||
(st_xmax(st_envelope_agg(geom)) - st_xmin(st_envelope_agg(geom))) + (st_xmax(st_envelope_agg(geom)) - st_xmin(st_envelope_agg(geom))) * padding, | ||
(st_xmax(st_envelope_agg(geom)) - st_xmin(st_envelope_agg(geom))) + (st_ymax(st_envelope_agg(geom)) - st_ymin(st_envelope_agg(geom))) * padding, | ||
width, | ||
height, | ||
string_agg(ST_AsSVG(geom, style), '')); | ||
)--"; | ||
|
||
auto info = DefaultFunctionGenerator::CreateInternalMacroInfo(macro); | ||
info->function->default_parameters["order_by"] = make_uniq<ConstantExpression>(Value::BIGINT(0)); | ||
info->function->default_parameters["padding"] = make_uniq<ConstantExpression>(Value::DOUBLE(0.1)); | ||
info->function->default_parameters["width"] = make_uniq<ConstantExpression>(Value::BIGINT(100)); | ||
info->function->default_parameters["height"] = make_uniq<ConstantExpression>(Value::BIGINT(100)); | ||
info->parameter_names = {"geom", "style", "order_by", "padding", "width", "height"}; | ||
ExtensionUtil::RegisterFunction(db, *info); | ||
|
||
// ExtensionUtil::RegisterFunction(db, string_agg); | ||
} | ||
|
||
} // namespace core | ||
|
||
} // namespace spatial |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,107 @@ | ||
#include "duckdb/common/vector_operations/binary_executor.hpp" | ||
#include "duckdb/parser/parsed_data/create_scalar_function_info.hpp" | ||
|
||
#include "spatial/common.hpp" | ||
#include "spatial/core/functions/scalar.hpp" | ||
#include "spatial/core/functions/common.hpp" | ||
#include "spatial/core/geometry/geometry_factory.hpp" | ||
#include "spatial/core/types.hpp" | ||
|
||
namespace spatial { | ||
|
||
namespace core { | ||
|
||
//------------------------------------------------------------------------------ | ||
// GEOMETRY -> SVG | ||
//------------------------------------------------------------------------------ | ||
|
||
static void SetDefaultStyle(case_insensitive_map_t<string> style, GeometryType type) { | ||
switch(type) { | ||
case GeometryType::POINT: | ||
style["r"] = "0.1"; | ||
break; | ||
case GeometryType::LINESTRING: | ||
style["fill"] = "none"; | ||
style["stroke"] = "black"; | ||
style["stroke-width"] = "0.01"; | ||
break; | ||
default: | ||
break; | ||
} | ||
} | ||
|
||
static string GeometryToSVG(const Geometry &geom, const case_insensitive_map_t<string> &style) { | ||
|
||
string attributes; | ||
for (auto &entry : style) { | ||
attributes += StringUtil::Format("%s=\"%s\" ", entry.first.c_str(), entry.second.c_str()); | ||
} | ||
|
||
switch(geom.Type()) { | ||
case GeometryType::POINT: { | ||
auto point = geom.GetPoint(); | ||
auto vertex = point.GetVertex(); | ||
return StringUtil::Format(R"(<circle cx="%f" cy="%f" %s/>)", vertex.x, vertex.y, attributes); | ||
} | ||
case GeometryType::LINESTRING: { | ||
auto linestring = geom.GetLineString(); | ||
string result = StringUtil::Format("<polyline %s points=\"", attributes); | ||
for (idx_t i = 0; i < linestring.Count(); i++) { | ||
auto vertex = linestring.Vertices().Get(i); | ||
result += StringUtil::Format("%f,%f ", vertex.x, vertex.y); | ||
} | ||
result += "\"/>"; | ||
return result; | ||
} | ||
default: | ||
throw NotImplementedException("SVG for geometry type not implemented"); | ||
} | ||
} | ||
|
||
static void GeometryAsSVGFunction(DataChunk &args, ExpressionState &state, Vector &result) { | ||
D_ASSERT(args.data.size() == 2); | ||
auto &geom_vec = args.data[0]; | ||
auto &map_vec = args.data[1]; | ||
auto &key_vec = MapVector::GetKeys(map_vec); | ||
auto &value_vec = MapVector::GetValues(map_vec); | ||
auto key_data = FlatVector::GetData<string_t>(key_vec); | ||
auto value_data = FlatVector::GetData<string_t>(value_vec); | ||
|
||
auto count = args.size(); | ||
|
||
auto &lstate = GeometryFunctionLocalState::ResetAndGet(state); | ||
|
||
case_insensitive_map_t<string> style; | ||
|
||
BinaryExecutor::Execute<string_t, list_entry_t, string_t>(geom_vec, map_vec, result, count, [&](string_t input, list_entry_t properties) { | ||
// Deserialize the geometry | ||
auto geometry = lstate.factory.Deserialize(input); | ||
|
||
// Reset the style | ||
style.clear(); | ||
|
||
// Set defaults | ||
SetDefaultStyle(style, geometry.Type()); | ||
|
||
// Set the style from the properties | ||
for(auto i = properties.offset; i < properties.offset + properties.length; i++) { | ||
style[key_data[i].GetString()] = value_data[i].GetString(); | ||
} | ||
|
||
// Convert the geometry to SVG | ||
return StringVector::AddString(result, GeometryToSVG(geometry, style)); | ||
}); | ||
} | ||
|
||
//------------------------------------------------------------------------------ | ||
// Register functions | ||
//------------------------------------------------------------------------------ | ||
void CoreScalarFunctions::RegisterStAsSVG(DatabaseInstance &db) { | ||
ScalarFunction func("ST_AsSVG", {GeoTypes::GEOMETRY(), LogicalType::MAP(LogicalType::VARCHAR, LogicalType::VARCHAR)}, LogicalType::VARCHAR, GeometryAsSVGFunction, nullptr, | ||
nullptr, nullptr, GeometryFunctionLocalState::Init); | ||
ExtensionUtil::RegisterFunction(db, func); | ||
} | ||
|
||
} // namespace core | ||
|
||
} // namespace spatial |