postgis.input - add support for TWKB (https://github.com/TWKB/Specification/blob/master/twkb.md) via https://github.com/CartoDB/mapnik/tree/2.3.x.cartodb ref #3355
This commit is contained in:
parent
2204a983c6
commit
7d4f894d98
4 changed files with 122 additions and 20 deletions
|
@ -88,6 +88,17 @@ postgis_datasource::postgis_datasource(parameters const& params)
|
|||
extent_from_subquery_(*params.get<mapnik::boolean_type>("extent_from_subquery", false)),
|
||||
max_async_connections_(*params_.get<mapnik::value_integer>("max_async_connection", 1)),
|
||||
asynchronous_request_(false),
|
||||
twkb_encoding_(false),
|
||||
twkb_rounding_adjustment_(*params_.get<mapnik::value_double>("twkb_rounding_adjustment", 0.0)),
|
||||
simplify_snap_ratio_(*params_.get<mapnik::value_double>("simplify_snap_ratio", 1.0/40.0)),
|
||||
// 1/20 of pixel seems to be a good compromise to avoid
|
||||
// drop of collapsed polygons.
|
||||
// See https://github.com/mapnik/mapnik/issues/1639
|
||||
// See http://trac.osgeo.org/postgis/ticket/2093
|
||||
simplify_dp_ratio_(*params_.get<mapnik::value_double>("simplify_dp_ratio", 1.0/20.0)),
|
||||
simplify_prefilter_(*params_.get<mapnik::value_double>("simplify_prefilter", 0.0)),
|
||||
simplify_dp_preserve_(false),
|
||||
simplify_clip_resolution_(*params_.get<mapnik::value_double>("simplify_clip_resolution", 0.0)),
|
||||
// TODO - use for known tokens too: "(@\\w+|!\\w+!)"
|
||||
pattern_(boost::regex("(@\\w+)",boost::regex::normal | boost::regbase::icase)),
|
||||
// params below are for testing purposes only and may be removed at any time
|
||||
|
@ -130,6 +141,12 @@ postgis_datasource::postgis_datasource(parameters const& params)
|
|||
boost::optional<mapnik::boolean_type> simplify_opt = params.get<mapnik::boolean_type>("simplify_geometries", false);
|
||||
simplify_geometries_ = simplify_opt && *simplify_opt;
|
||||
|
||||
boost::optional<mapnik::boolean_type> twkb_opt = params.get<mapnik::boolean_type>("twkb_encoding", false);
|
||||
twkb_encoding_ = twkb_opt && *twkb_opt;
|
||||
|
||||
boost::optional<mapnik::boolean_type> simplify_preserve_opt = params.get<mapnik::boolean_type>("simplify_dp_preserve", false);
|
||||
simplify_dp_preserve_ = simplify_preserve_opt && *simplify_preserve_opt;
|
||||
|
||||
ConnectionManager::instance().registerPool(creator_, *initial_size, pool_max_size_);
|
||||
CnxPool_ptr pool = ConnectionManager::instance().getPool(creator_.id());
|
||||
if (pool)
|
||||
|
@ -794,25 +811,91 @@ featureset_ptr postgis_datasource::features_with_context(query const& q,processo
|
|||
|
||||
const double px_gw = 1.0 / std::get<0>(q.resolution());
|
||||
const double px_gh = 1.0 / std::get<1>(q.resolution());
|
||||
const double px_sz = std::min(px_gw, px_gh);
|
||||
|
||||
s << "SELECT ST_AsBinary(";
|
||||
if (twkb_encoding_)
|
||||
{
|
||||
// This will only work against PostGIS 2.2, or a back-patched version
|
||||
// that has (a) a ST_Simplify with a "preserve collapsed" flag and
|
||||
// (b) a ST_RemoveRepeatedPoints with a tolerance parameter and
|
||||
// (c) a ST_AsTWKB implementation
|
||||
|
||||
if (simplify_geometries_) {
|
||||
s << "ST_Simplify(";
|
||||
// What number of decimals of rounding does the pixel size imply?
|
||||
const int twkb_rounding = -1 * std::lround(log10(px_sz) + twkb_rounding_adjustment_) + 1;
|
||||
// And what's that in map units?
|
||||
const double twkb_tolerance = pow(10.0, -1.0 * twkb_rounding);
|
||||
|
||||
s << "SELECT ST_AsTWKB(";
|
||||
s << "ST_Simplify(";
|
||||
s << "ST_RemoveRepeatedPoints(";
|
||||
|
||||
if (simplify_clip_resolution_ > 0.0 && simplify_clip_resolution_ > px_sz)
|
||||
{
|
||||
s << "ST_ClipByBox2D(";
|
||||
}
|
||||
s << "\"" << geometryColumn_ << "\"";
|
||||
|
||||
// ! ST_ClipByBox2D()
|
||||
if (simplify_clip_resolution_ > 0.0 && simplify_clip_resolution_ > px_sz)
|
||||
{
|
||||
s << "," << sql_bbox(box) << ")";
|
||||
}
|
||||
|
||||
// ! ST_RemoveRepeatedPoints()
|
||||
s << "," << twkb_tolerance << ")";
|
||||
// ! ST_Simplify(), with parameter to keep collapsed geometries
|
||||
s << "," << twkb_tolerance << ",true)";
|
||||
// ! ST_TWKB()
|
||||
s << "," << twkb_rounding << ") AS geom";
|
||||
}
|
||||
else
|
||||
{
|
||||
s << "SELECT ST_AsBinary(";
|
||||
if (simplify_geometries_)
|
||||
{
|
||||
s << "ST_Simplify(";
|
||||
}
|
||||
if (simplify_clip_resolution_ > 0.0 && simplify_clip_resolution_ > px_sz)
|
||||
{
|
||||
s << "ST_ClipByBox2D(";
|
||||
}
|
||||
if (simplify_geometries_ && simplify_snap_ratio_ > 0.0)
|
||||
{
|
||||
s<< "ST_SnapToGrid(";
|
||||
}
|
||||
|
||||
s << "\"" << geometryColumn_ << "\"";
|
||||
// Geometry column!
|
||||
s << "\"" << geometryColumn_ << "\"";
|
||||
|
||||
if (simplify_geometries_) {
|
||||
// 1/20 of pixel seems to be a good compromise to avoid
|
||||
// drop of collapsed polygons.
|
||||
// See https://github.com/mapnik/mapnik/issues/1639
|
||||
const double tolerance = std::min(px_gw, px_gh) / 20.0;
|
||||
s << ", " << tolerance << ")";
|
||||
// ! ST_SnapToGrid()
|
||||
if (simplify_geometries_ && simplify_snap_ratio_ > 0.0)
|
||||
{
|
||||
const double tolerance = px_sz * simplify_snap_ratio_;
|
||||
s << "," << tolerance << ")";
|
||||
}
|
||||
|
||||
// ! ST_ClipByBox2D()
|
||||
if (simplify_clip_resolution_ > 0.0 && simplify_clip_resolution_ > px_sz)
|
||||
{
|
||||
s << "," << sql_bbox(box) << ")";
|
||||
}
|
||||
|
||||
// ! ST_Simplify()
|
||||
if (simplify_geometries_)
|
||||
{
|
||||
const double tolerance = px_sz * simplify_dp_ratio_;
|
||||
s << ", " << tolerance;
|
||||
// Add parameter to ST_Simplify to keep collapsed geometries
|
||||
if (simplify_dp_preserve_)
|
||||
{
|
||||
s << ", true";
|
||||
}
|
||||
s << ")";
|
||||
}
|
||||
|
||||
// ! ST_AsBinary()
|
||||
s << ") AS geom";
|
||||
}
|
||||
|
||||
s << ") AS geom";
|
||||
|
||||
mapnik::context_ptr ctx = std::make_shared<mapnik::context_type>();
|
||||
std::set<std::string> const& props = q.property_names();
|
||||
std::set<std::string>::const_iterator pos = props.begin();
|
||||
|
@ -854,7 +937,8 @@ featureset_ptr postgis_datasource::features_with_context(query const& q,processo
|
|||
}
|
||||
|
||||
std::shared_ptr<IResultSet> rs = get_resultset(conn, s.str(), pool, proc_ctx);
|
||||
return std::make_shared<postgis_featureset>(rs, ctx, desc_.get_encoding(), !key_field_.empty(), key_field_as_attribute_);
|
||||
return std::make_shared<postgis_featureset>(rs, ctx, desc_.get_encoding(), !key_field_.empty(),
|
||||
key_field_as_attribute_, twkb_encoding_);
|
||||
|
||||
}
|
||||
|
||||
|
@ -941,7 +1025,8 @@ featureset_ptr postgis_datasource::features_at_point(coord2d const& pt, double t
|
|||
}
|
||||
|
||||
std::shared_ptr<IResultSet> rs = get_resultset(conn, s.str(), pool);
|
||||
return std::make_shared<postgis_featureset>(rs, ctx, desc_.get_encoding(), !key_field_.empty(), key_field_as_attribute_);
|
||||
return std::make_shared<postgis_featureset>(rs, ctx, desc_.get_encoding(), !key_field_.empty(),
|
||||
key_field_as_attribute_, twkb_encoding_);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -119,6 +119,13 @@ private:
|
|||
bool estimate_extent_;
|
||||
int max_async_connections_;
|
||||
bool asynchronous_request_;
|
||||
bool twkb_encoding_;
|
||||
mapnik::value_double twkb_rounding_adjustment_;
|
||||
mapnik::value_double simplify_snap_ratio_;
|
||||
mapnik::value_double simplify_dp_ratio_;
|
||||
mapnik::value_double simplify_prefilter_;
|
||||
bool simplify_dp_preserve_;
|
||||
mapnik::value_double simplify_clip_resolution_;
|
||||
boost::regex pattern_;
|
||||
int intersect_min_scale_;
|
||||
int intersect_max_scale_;
|
||||
|
|
|
@ -49,14 +49,16 @@ postgis_featureset::postgis_featureset(std::shared_ptr<IResultSet> const& rs,
|
|||
context_ptr const& ctx,
|
||||
std::string const& encoding,
|
||||
bool key_field,
|
||||
bool key_field_as_attribute)
|
||||
bool key_field_as_attribute,
|
||||
bool twkb_encoding)
|
||||
: rs_(rs),
|
||||
ctx_(ctx),
|
||||
tr_(new transcoder(encoding)),
|
||||
totalGeomSize_(0),
|
||||
feature_id_(1),
|
||||
key_field_(key_field),
|
||||
key_field_as_attribute_(key_field_as_attribute)
|
||||
key_field_as_attribute_(key_field_as_attribute),
|
||||
twkb_encoding_(twkb_encoding)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -123,8 +125,14 @@ feature_ptr postgis_featureset::next()
|
|||
int size = rs_->getFieldLength(0);
|
||||
const char *data = rs_->getValue(0);
|
||||
|
||||
mapnik::geometry::geometry<double> geometry = geometry_utils::from_wkb(data, size);
|
||||
feature->set_geometry(std::move(geometry));
|
||||
if (twkb_encoding_ )
|
||||
{
|
||||
feature->set_geometry(geometry_utils::from_twkb(data, size));
|
||||
}
|
||||
else
|
||||
{
|
||||
feature->set_geometry(geometry_utils::from_wkb(data, size));
|
||||
}
|
||||
|
||||
totalGeomSize_ += size;
|
||||
unsigned num_attrs = ctx_->size() + 1;
|
||||
|
|
|
@ -44,7 +44,8 @@ public:
|
|||
context_ptr const& ctx,
|
||||
std::string const& encoding,
|
||||
bool key_field,
|
||||
bool key_field_as_attribute);
|
||||
bool key_field_as_attribute,
|
||||
bool twkb_encoding);
|
||||
feature_ptr next();
|
||||
~postgis_featureset();
|
||||
|
||||
|
@ -56,6 +57,7 @@ private:
|
|||
mapnik::value_integer feature_id_;
|
||||
bool key_field_;
|
||||
bool key_field_as_attribute_;
|
||||
bool twkb_encoding_;
|
||||
};
|
||||
|
||||
#endif // POSTGIS_FEATURESET_HPP
|
||||
|
|
Loading…
Reference in a new issue