rework the grid rendering interface to be object oriented and template based allowing for working both with grids and grid views for metatiling
This commit is contained in:
parent
9cc93552f2
commit
7c2549ff46
3 changed files with 347 additions and 73 deletions
|
@ -78,9 +78,6 @@ class _MapnikMetaclass(BoostPythonMetaclass):
|
|||
# http://mikewatkins.ca/2008/11/29/python-2-and-3-metaclasses/
|
||||
_injector = _MapnikMetaclass('_injector', (object, ), {})
|
||||
|
||||
def render_grid(m,layer,key,resolution=4,fields=[]):
|
||||
return render_grid_(m,layer,key,resolution,fields)
|
||||
|
||||
def Filter(*args,**kwargs):
|
||||
warnings.warn("'Filter' is deprecated and will be removed in Mapnik 2.0.1, use 'Expression' instead",
|
||||
DeprecationWarning, 2)
|
||||
|
|
|
@ -36,6 +36,8 @@ void export_query();
|
|||
void export_geometry();
|
||||
void export_image();
|
||||
void export_image_view();
|
||||
void export_grid();
|
||||
void export_grid_view();
|
||||
void export_map();
|
||||
void export_python();
|
||||
void export_expression();
|
||||
|
@ -71,13 +73,13 @@ void export_inmem_metawriter();
|
|||
#ifdef HAVE_CAIRO
|
||||
#include <mapnik/cairo_renderer.hpp>
|
||||
#endif
|
||||
#include "python_grid_utils.hpp"
|
||||
#include <mapnik/graphics.hpp>
|
||||
#include <mapnik/image_util.hpp>
|
||||
#include <mapnik/load_map.hpp>
|
||||
#include <mapnik/config_error.hpp>
|
||||
#include <mapnik/value_error.hpp>
|
||||
#include <mapnik/save_map.hpp>
|
||||
#include "python_grid_utils.hpp"
|
||||
|
||||
#if defined(HAVE_CAIRO) && defined(HAVE_PYCAIRO)
|
||||
#include <pycairo.h>
|
||||
|
@ -104,6 +106,35 @@ void render(const mapnik::Map& map,
|
|||
Py_END_ALLOW_THREADS
|
||||
}
|
||||
|
||||
void render_layer2(const mapnik::Map& map,
|
||||
mapnik::image_32& image,
|
||||
unsigned layer_idx)
|
||||
{
|
||||
std::vector<mapnik::layer> const& layers = map.layers();
|
||||
std::size_t layer_num = layers.size();
|
||||
if (layer_idx >= layer_num) {
|
||||
std::ostringstream s;
|
||||
s << "Zero-based layer index '" << layer_idx << "' not valid, only '"
|
||||
<< layer_num << "' layers are in map\n";
|
||||
throw std::runtime_error(s.str());
|
||||
}
|
||||
|
||||
Py_BEGIN_ALLOW_THREADS
|
||||
try
|
||||
{
|
||||
mapnik::layer const& layer = layers[layer_idx];
|
||||
mapnik::agg_renderer<mapnik::image_32> ren(map,image,1.0,0,0);
|
||||
std::set<std::string> names;
|
||||
ren.apply(layer,names);
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
Py_BLOCK_THREADS
|
||||
throw;
|
||||
}
|
||||
Py_END_ALLOW_THREADS
|
||||
}
|
||||
|
||||
#if defined(HAVE_CAIRO) && defined(HAVE_PYCAIRO)
|
||||
|
||||
void render3(const mapnik::Map& map,
|
||||
|
@ -354,6 +385,8 @@ BOOST_PYTHON_MODULE(_mapnik2)
|
|||
export_envelope();
|
||||
export_image();
|
||||
export_image_view();
|
||||
export_grid();
|
||||
export_grid_view();
|
||||
export_expression();
|
||||
export_rule();
|
||||
export_style();
|
||||
|
@ -380,7 +413,14 @@ BOOST_PYTHON_MODULE(_mapnik2)
|
|||
export_glyph_symbolizer();
|
||||
export_inmem_metawriter();
|
||||
|
||||
def("render_grid_",&render_grid);
|
||||
def("render_grid",&render_grid,
|
||||
( arg("map"),
|
||||
arg("layer"),
|
||||
args("key")="__id__",
|
||||
arg("resolution")=4,
|
||||
arg("fields")=boost::python::list()
|
||||
)
|
||||
);
|
||||
|
||||
def("render_to_file",&render_to_file1,
|
||||
"\n"
|
||||
|
@ -447,6 +487,14 @@ BOOST_PYTHON_MODULE(_mapnik2)
|
|||
">>> render(m,im,scale_factor,offset[0],offset[1])\n"
|
||||
"\n"
|
||||
));
|
||||
|
||||
def("render_layer", &render_layer2,
|
||||
(arg("map"),arg("image"),args("layer"))
|
||||
);
|
||||
|
||||
def("render_layer", &mapnik::render_layer_for_grid,
|
||||
(arg("map"),arg("grid"),args("layer"),arg("fields")=boost::python::list())
|
||||
);
|
||||
|
||||
#if defined(HAVE_CAIRO) && defined(HAVE_PYCAIRO)
|
||||
def("render",&render3,
|
||||
|
|
|
@ -30,28 +30,34 @@
|
|||
// mapnik
|
||||
#include <mapnik/grid/grid_renderer.hpp>
|
||||
#include <mapnik/grid/grid.hpp>
|
||||
#include <mapnik/grid/grid_util.hpp>
|
||||
#include <mapnik/grid/grid_view.hpp>
|
||||
#include <mapnik/value_error.hpp>
|
||||
#include "mapnik_value_converter.hpp"
|
||||
|
||||
|
||||
namespace mapnik {
|
||||
|
||||
|
||||
void grid2utf(mapnik::grid const& grid,
|
||||
template <typename T>
|
||||
static void grid2utf(T const& grid_type,
|
||||
boost::python::list& l,
|
||||
std::vector<mapnik::grid::lookup_type>& key_order)
|
||||
std::vector<grid::lookup_type>& key_order)
|
||||
{
|
||||
mapnik::grid::data_type const& data = grid.data();
|
||||
mapnik::grid::feature_key_type const& feature_keys = grid.get_feature_keys();
|
||||
mapnik::grid::key_type keys;
|
||||
mapnik::grid::key_type::const_iterator key_pos;
|
||||
mapnik::grid::feature_key_type::const_iterator feature_pos;
|
||||
uint16_t codepoint = 31;
|
||||
|
||||
typename T::data_type const& data = grid_type.data();
|
||||
typename T::feature_key_type const& feature_keys = grid_type.get_feature_keys();
|
||||
typename T::key_type keys;
|
||||
typename T::key_type::const_iterator key_pos;
|
||||
typename T::feature_key_type::const_iterator feature_pos;
|
||||
// start counting at utf8 codepoint 32, aka space character
|
||||
uint16_t codepoint = 32;
|
||||
|
||||
unsigned array_size = data.width();
|
||||
for (unsigned y = 0; y < data.height(); ++y)
|
||||
{
|
||||
uint16_t idx = 0;
|
||||
boost::scoped_array<Py_UNICODE> line(new Py_UNICODE[data.width()]);
|
||||
mapnik::grid::value_type const* row = data.getRow(y);
|
||||
boost::scoped_array<Py_UNICODE> line(new Py_UNICODE[array_size]);
|
||||
typename T::value_type const* row = data.getRow(y);
|
||||
for (unsigned x = 0; x < data.width(); ++x)
|
||||
{
|
||||
feature_pos = feature_keys.find(row[x]);
|
||||
|
@ -63,13 +69,13 @@ void grid2utf(mapnik::grid const& grid,
|
|||
{
|
||||
// Create a new entry for this key. Skip the codepoints that
|
||||
// can't be encoded directly in JSON.
|
||||
++codepoint;
|
||||
if (codepoint == 34) ++codepoint; // Skip "
|
||||
else if (codepoint == 92) ++codepoint; // Skip backslash
|
||||
|
||||
keys[val] = codepoint;
|
||||
key_order.push_back(val);
|
||||
line[idx++] = static_cast<Py_UNICODE>(codepoint);
|
||||
++codepoint;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -80,27 +86,138 @@ void grid2utf(mapnik::grid const& grid,
|
|||
}
|
||||
l.append(boost::python::object(
|
||||
boost::python::handle<>(
|
||||
PyUnicode_FromUnicode(line.get(), data.width()))));
|
||||
PyUnicode_FromUnicode(line.get(), array_size))));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void write_features(mapnik::grid::feature_type const& g_features,
|
||||
boost::python::dict& feature_data,
|
||||
std::vector<mapnik::grid::lookup_type> const& key_order,
|
||||
std::string const& join_field,
|
||||
std::set<std::string> const& attributes)
|
||||
template <typename T>
|
||||
static void grid2utf(T const& grid_type,
|
||||
boost::python::list& l,
|
||||
std::vector<typename T::lookup_type>& key_order,
|
||||
unsigned int resolution)
|
||||
{
|
||||
mapnik::grid::feature_type::const_iterator feat_itr = g_features.begin();
|
||||
mapnik::grid::feature_type::const_iterator feat_end = g_features.end();
|
||||
bool include_join_field = (attributes.find(join_field) != attributes.end());
|
||||
//typename T::data_type const& data = grid_type.data();
|
||||
typename T::feature_key_type const& feature_keys = grid_type.get_feature_keys();
|
||||
typename T::key_type keys;
|
||||
typename T::key_type::const_iterator key_pos;
|
||||
typename T::feature_key_type::const_iterator feature_pos;
|
||||
// start counting at utf8 codepoint 32, aka space character
|
||||
uint16_t codepoint = 32;
|
||||
|
||||
// TODO - use double?
|
||||
unsigned array_size = static_cast<unsigned int>(grid_type.width()/resolution);
|
||||
for (unsigned y = 0; y < grid_type.height(); y=y+resolution)
|
||||
{
|
||||
uint16_t idx = 0;
|
||||
boost::scoped_array<Py_UNICODE> line(new Py_UNICODE[array_size]);
|
||||
mapnik::grid::value_type const* row = grid_type.getRow(y);
|
||||
for (unsigned x = 0; x < grid_type.width(); x=x+resolution)
|
||||
{
|
||||
feature_pos = feature_keys.find(row[x]);
|
||||
if (feature_pos != feature_keys.end())
|
||||
{
|
||||
mapnik::grid::lookup_type val = feature_pos->second;
|
||||
key_pos = keys.find(val);
|
||||
if (key_pos == keys.end())
|
||||
{
|
||||
// Create a new entry for this key. Skip the codepoints that
|
||||
// can't be encoded directly in JSON.
|
||||
if (codepoint == 34) ++codepoint; // Skip "
|
||||
else if (codepoint == 92) ++codepoint; // Skip backslash
|
||||
keys[val] = codepoint;
|
||||
key_order.push_back(val);
|
||||
line[idx++] = static_cast<Py_UNICODE>(codepoint);
|
||||
++codepoint;
|
||||
}
|
||||
else
|
||||
{
|
||||
line[idx++] = static_cast<Py_UNICODE>(key_pos->second);
|
||||
}
|
||||
}
|
||||
// else, shouldn't get here...
|
||||
}
|
||||
l.append(boost::python::object(
|
||||
boost::python::handle<>(
|
||||
PyUnicode_FromUnicode(line.get(), array_size))));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template <typename T>
|
||||
static void grid2utf2(T const& grid_type,
|
||||
boost::python::list& l,
|
||||
std::vector<typename T::lookup_type>& key_order,
|
||||
unsigned int resolution)
|
||||
{
|
||||
typename T::data_type const& data = grid_type.data();
|
||||
typename T::feature_key_type const& feature_keys = grid_type.get_feature_keys();
|
||||
typename T::key_type keys;
|
||||
typename T::key_type::const_iterator key_pos;
|
||||
typename T::feature_key_type::const_iterator feature_pos;
|
||||
// start counting at utf8 codepoint 32, aka space character
|
||||
uint16_t codepoint = 32;
|
||||
|
||||
mapnik::grid::data_type target(data.width()/resolution,data.height()/resolution);
|
||||
mapnik::scale_grid(target,grid_type.data(),0.0,0.0);
|
||||
|
||||
unsigned array_size = target.width();
|
||||
for (unsigned y = 0; y < target.height(); ++y)
|
||||
{
|
||||
uint16_t idx = 0;
|
||||
boost::scoped_array<Py_UNICODE> line(new Py_UNICODE[array_size]);
|
||||
mapnik::grid::value_type * row = target.getRow(y);
|
||||
unsigned x;
|
||||
for (x = 0; x < target.width(); ++x)
|
||||
{
|
||||
feature_pos = feature_keys.find(row[x]);
|
||||
if (feature_pos != feature_keys.end())
|
||||
{
|
||||
mapnik::grid::lookup_type val = feature_pos->second;
|
||||
key_pos = keys.find(val);
|
||||
if (key_pos == keys.end())
|
||||
{
|
||||
// Create a new entry for this key. Skip the codepoints that
|
||||
// can't be encoded directly in JSON.
|
||||
if (codepoint == 34) ++codepoint; // Skip "
|
||||
else if (codepoint == 92) ++codepoint; // Skip backslash
|
||||
keys[val] = codepoint;
|
||||
key_order.push_back(val);
|
||||
line[idx++] = static_cast<Py_UNICODE>(codepoint);
|
||||
++codepoint;
|
||||
}
|
||||
else
|
||||
{
|
||||
line[idx++] = static_cast<Py_UNICODE>(key_pos->second);
|
||||
}
|
||||
}
|
||||
// else, shouldn't get here...
|
||||
}
|
||||
l.append(boost::python::object(
|
||||
boost::python::handle<>(
|
||||
PyUnicode_FromUnicode(line.get(), array_size))));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template <typename T>
|
||||
static void write_features(T const& grid_type,
|
||||
boost::python::dict& feature_data,
|
||||
std::vector<typename T::lookup_type> const& key_order)
|
||||
{
|
||||
std::string const& key = grid_type.get_key();
|
||||
std::set<std::string> const& attributes = grid_type.property_names();
|
||||
typename T::feature_type const& g_features = grid_type.get_grid_features();
|
||||
typename T::feature_type::const_iterator feat_itr = g_features.begin();
|
||||
typename T::feature_type::const_iterator feat_end = g_features.end();
|
||||
bool include_key = (attributes.find(key) != attributes.end());
|
||||
for (; feat_itr != feat_end; ++feat_itr)
|
||||
{
|
||||
std::map<std::string,mapnik::value> const& props = feat_itr->second;
|
||||
std::map<std::string,mapnik::value>::const_iterator const& itr = props.find(join_field);
|
||||
std::map<std::string,mapnik::value>::const_iterator const& itr = props.find(key);
|
||||
if (itr != props.end())
|
||||
{
|
||||
mapnik::grid::lookup_type const& join_value = itr->second.to_string();
|
||||
typename T::lookup_type const& join_value = itr->second.to_string();
|
||||
|
||||
// only serialize features visible in the grid
|
||||
if(std::find(key_order.begin(), key_order.end(), join_value) != key_order.end()) {
|
||||
|
@ -110,10 +227,10 @@ void write_features(mapnik::grid::feature_type const& g_features,
|
|||
bool found = false;
|
||||
for (; it != end; ++it)
|
||||
{
|
||||
std::string const& key = it->first;
|
||||
if (key == join_field) {
|
||||
// drop join_field unless requested
|
||||
if (include_join_field) {
|
||||
std::string const& key_name = it->first;
|
||||
if (key_name == key) {
|
||||
// drop key unless requested
|
||||
if (include_key) {
|
||||
found = true;
|
||||
feat[it->first] = boost::python::object(
|
||||
boost::python::handle<>(
|
||||
|
@ -122,7 +239,7 @@ void write_features(mapnik::grid::feature_type const& g_features,
|
|||
it->second.base())));
|
||||
}
|
||||
}
|
||||
else if ( (attributes.find(key) != attributes.end()) )
|
||||
else if ( (attributes.find(key_name) != attributes.end()) )
|
||||
{
|
||||
found = true;
|
||||
feat[it->first] = boost::python::object(
|
||||
|
@ -140,16 +257,77 @@ void write_features(mapnik::grid::feature_type const& g_features,
|
|||
}
|
||||
else
|
||||
{
|
||||
std::clog << "should not get here: join_field '" << join_field << "' not found in grid feature properties\n";
|
||||
std::clog << "should not get here: key '" << key << "' not found in grid feature properties\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
boost::python::dict render_grid(const mapnik::Map& map,
|
||||
unsigned layer_idx, // layer
|
||||
std::string const& join_field, // key_name
|
||||
unsigned int step, // resolution
|
||||
boost::python::list fields)
|
||||
template <typename T>
|
||||
static void grid_encode_utf(T const& grid_type,
|
||||
boost::python::dict & json,
|
||||
bool add_features,
|
||||
unsigned int resolution)
|
||||
{
|
||||
// convert buffer to utf and gather key order
|
||||
boost::python::list l;
|
||||
std::vector<typename T::lookup_type> key_order;
|
||||
|
||||
if (resolution != 1) {
|
||||
// resample on the fly - faster, less accurate
|
||||
mapnik::grid2utf<T>(grid_type,l,key_order,resolution);
|
||||
|
||||
// resample first - slower, more accurate
|
||||
//mapnik::grid2utf2<T>(grid_type,l,key_order,resolution);
|
||||
}
|
||||
else
|
||||
{
|
||||
mapnik::grid2utf<T>(grid_type,l,key_order);
|
||||
}
|
||||
|
||||
// convert key order to proper python list
|
||||
boost::python::list keys_a;
|
||||
BOOST_FOREACH ( typename T::lookup_type const& key_id, key_order )
|
||||
{
|
||||
keys_a.append(key_id);
|
||||
}
|
||||
|
||||
// gather feature data
|
||||
boost::python::dict feature_data;
|
||||
if (add_features) {
|
||||
mapnik::write_features<T>(grid_type,feature_data,key_order);
|
||||
}
|
||||
|
||||
json["grid"] = l;
|
||||
json["keys"] = keys_a;
|
||||
json["data"] = feature_data;
|
||||
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
static boost::python::dict grid_encode( T const& grid, std::string format, bool add_features, unsigned int resolution)
|
||||
{
|
||||
if (format == "utf") {
|
||||
boost::python::dict json;
|
||||
grid_encode_utf<T>(grid,json,add_features,resolution);
|
||||
return json;
|
||||
}
|
||||
else
|
||||
{
|
||||
std::stringstream s;
|
||||
s << "'utf' is currently the only supported encoding format.";
|
||||
throw mapnik::value_error(s.str());
|
||||
}
|
||||
}
|
||||
|
||||
/* new approach: key comes from grid object
|
||||
* grid size should be same as the map
|
||||
* encoding, resizing handled as method on grid object
|
||||
* whether features are dumped is determined by argument not 'fields'
|
||||
*/
|
||||
static void render_layer_for_grid(const mapnik::Map& map,
|
||||
mapnik::grid& grid,
|
||||
unsigned layer_idx, // TODO - layer by name or index
|
||||
boost::python::list const& fields)
|
||||
{
|
||||
std::vector<mapnik::layer> const& layers = map.layers();
|
||||
std::size_t layer_num = layers.size();
|
||||
|
@ -160,11 +338,6 @@ boost::python::dict render_grid(const mapnik::Map& map,
|
|||
throw std::runtime_error(s.str());
|
||||
}
|
||||
|
||||
unsigned int grid_width = map.width()/step;
|
||||
unsigned int grid_height = map.height()/step;
|
||||
|
||||
mapnik::grid grid(grid_width,grid_height,join_field,step);
|
||||
|
||||
// convert python list to std::vector
|
||||
boost::python::ssize_t num_fields = boost::python::len(fields);
|
||||
for(boost::python::ssize_t i=0; i<num_fields; i++) {
|
||||
|
@ -182,18 +355,92 @@ boost::python::dict render_grid(const mapnik::Map& map,
|
|||
|
||||
// copy property names
|
||||
std::set<std::string> attributes = grid.property_names();
|
||||
|
||||
if (join_field == grid.id_name_)
|
||||
std::string const& key = grid.get_key();
|
||||
|
||||
// if key is special __id__ keyword
|
||||
if (key == grid.id_name_)
|
||||
{
|
||||
// TODO - should feature.id() be a first class attribute?
|
||||
if (attributes.find(join_field) != attributes.end())
|
||||
|
||||
// if __id__ is requested to be dumped out
|
||||
// remove it so that datasource queries will not break
|
||||
if (attributes.find(key) != attributes.end())
|
||||
{
|
||||
attributes.erase(join_field);
|
||||
attributes.erase(key);
|
||||
}
|
||||
}
|
||||
else if (attributes.find(join_field) == attributes.end())
|
||||
// if key is not the special __id__ keyword
|
||||
else if (attributes.find(key) == attributes.end())
|
||||
{
|
||||
attributes.insert(join_field);
|
||||
// them make sure the datasource query includes this field
|
||||
attributes.insert(key);
|
||||
}
|
||||
|
||||
mapnik::grid_renderer<mapnik::grid> ren(map,grid,1.0,0,0);
|
||||
mapnik::layer const& layer = layers[layer_idx];
|
||||
ren.apply(layer,attributes);
|
||||
}
|
||||
|
||||
/* old, original impl - to be removed after further testing
|
||||
* grid object is created on the fly at potentially reduced size
|
||||
*/
|
||||
static boost::python::dict render_grid(const mapnik::Map& map,
|
||||
unsigned layer_idx, // layer
|
||||
std::string const& key, // key_name
|
||||
unsigned int step, // resolution
|
||||
boost::python::list const& fields)
|
||||
{
|
||||
|
||||
std::vector<mapnik::layer> const& layers = map.layers();
|
||||
std::size_t layer_num = layers.size();
|
||||
if (layer_idx >= layer_num) {
|
||||
std::ostringstream s;
|
||||
s << "Zero-based layer index '" << layer_idx << "' not valid, only '"
|
||||
<< layer_num << "' layers are in map\n";
|
||||
throw std::runtime_error(s.str());
|
||||
}
|
||||
|
||||
unsigned int grid_width = map.width()/step;
|
||||
unsigned int grid_height = map.height()/step;
|
||||
|
||||
// TODO - no need to pass step here
|
||||
mapnik::grid grid(grid_width,grid_height,key,step);
|
||||
|
||||
// convert python list to std::vector
|
||||
boost::python::ssize_t num_fields = boost::python::len(fields);
|
||||
for(boost::python::ssize_t i=0; i<num_fields; i++) {
|
||||
boost::python::extract<std::string> name(fields[i]);
|
||||
if (name.check()) {
|
||||
grid.add_property_name(name());
|
||||
}
|
||||
else
|
||||
{
|
||||
std::stringstream s;
|
||||
s << "list of field names must be strings";
|
||||
throw mapnik::value_error(s.str());
|
||||
}
|
||||
}
|
||||
|
||||
// copy property names
|
||||
std::set<std::string> attributes = grid.property_names();
|
||||
|
||||
// if key is special __id__ keyword
|
||||
if (key == grid.id_name_)
|
||||
{
|
||||
// TODO - should feature.id() be a first class attribute?
|
||||
|
||||
// if __id__ is requested to be dumped out
|
||||
// remove it so that datasource queries will not break
|
||||
if (attributes.find(key) != attributes.end())
|
||||
{
|
||||
attributes.erase(key);
|
||||
}
|
||||
}
|
||||
// if key is not the special __id__ keyword
|
||||
else if (attributes.find(key) == attributes.end())
|
||||
{
|
||||
// them make sure the datasource query includes this field
|
||||
attributes.insert(key);
|
||||
}
|
||||
|
||||
try
|
||||
|
@ -206,31 +453,13 @@ boost::python::dict render_grid(const mapnik::Map& map,
|
|||
{
|
||||
throw;
|
||||
}
|
||||
|
||||
// convert buffer to utf and gather key order
|
||||
boost::python::list l;
|
||||
std::vector<mapnik::grid::lookup_type> key_order;
|
||||
mapnik::grid2utf(grid,l,key_order);
|
||||
|
||||
// convert key order to proper python list
|
||||
boost::python::list keys_a;
|
||||
BOOST_FOREACH ( mapnik::grid::lookup_type const& key_id, key_order )
|
||||
{
|
||||
keys_a.append(key_id);
|
||||
}
|
||||
|
||||
// gather feature data
|
||||
boost::python::dict feature_data;
|
||||
if (num_fields > 0) {
|
||||
mapnik::grid::feature_type const& g_features = grid.get_grid_features();
|
||||
mapnik::write_features(g_features,feature_data,key_order,join_field,grid.property_names());
|
||||
}
|
||||
|
||||
|
||||
bool add_features = false;
|
||||
if (num_fields > 0)
|
||||
add_features = true;
|
||||
// build dictionary and return to python
|
||||
boost::python::dict json;
|
||||
json["grid"] = l;
|
||||
json["keys"] = keys_a;
|
||||
json["data"] = feature_data;
|
||||
grid_encode_utf(grid,json,add_features,1);
|
||||
return json;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue