+ make interface to datasource attributes, featuresets, and features more pythonicby adding feature.envelope() method returning combined extent of geometries, ds.fields() method returning list of names, and featureset.features() which returns list of all features in featurset - now accessible via datasource.all_features()- closes #283, #280, #171
This commit is contained in:
parent
e2fd9c8329
commit
196b01c16c
7 changed files with 131 additions and 28 deletions
|
@ -90,10 +90,39 @@ class _Projection(Projection,_injector):
|
|||
return forward_(obj,self)
|
||||
def inverse(self,obj):
|
||||
return inverse_(obj,self)
|
||||
|
||||
|
||||
def get_types(num):
|
||||
if num == 1:
|
||||
return int
|
||||
elif num == 2:
|
||||
return float
|
||||
elif num == 3:
|
||||
return float
|
||||
elif num == 4:
|
||||
return str
|
||||
elif num == 5:
|
||||
return Geometry2d
|
||||
elif num == 6:
|
||||
return object
|
||||
|
||||
class _Datasource(Datasource,_injector):
|
||||
def describe(self):
|
||||
return Describe(self)
|
||||
def field_types(self):
|
||||
return map(get_types,self._field_types())
|
||||
def all_features(self):
|
||||
query = Query(self.envelope(),1.0)
|
||||
for fld in self.fields():
|
||||
query.add_property_name(fld)
|
||||
return self.features(query).features
|
||||
|
||||
class _Feature(Feature,_injector):
|
||||
@property
|
||||
def attributes(self):
|
||||
attr = {}
|
||||
for prop in self.properties:
|
||||
attr[prop[0]] = prop[1]
|
||||
return attr
|
||||
|
||||
#class _Filter(Filter,_injector):
|
||||
# """Mapnik Filter expression.
|
||||
|
|
|
@ -25,6 +25,8 @@
|
|||
#include <boost/python/detail/api_placeholder.hpp>
|
||||
// stl
|
||||
#include <sstream>
|
||||
#include <vector>
|
||||
|
||||
// mapnik
|
||||
#include <mapnik/envelope.hpp>
|
||||
#include <mapnik/datasource.hpp>
|
||||
|
@ -35,6 +37,8 @@
|
|||
|
||||
using mapnik::datasource;
|
||||
using mapnik::point_datasource;
|
||||
using mapnik::layer_descriptor;
|
||||
using mapnik::attribute_descriptor;
|
||||
|
||||
struct ds_pickle_suite : boost::python::pickle_suite
|
||||
{
|
||||
|
@ -92,7 +96,52 @@ namespace
|
|||
}
|
||||
return ss.str();
|
||||
}
|
||||
}
|
||||
|
||||
std::string encoding(boost::shared_ptr<mapnik::datasource> const& ds)
|
||||
{
|
||||
layer_descriptor ld = ds->get_descriptor();
|
||||
return ld.get_encoding();
|
||||
}
|
||||
|
||||
std::string name(boost::shared_ptr<mapnik::datasource> const& ds)
|
||||
{
|
||||
layer_descriptor ld = ds->get_descriptor();
|
||||
return ld.get_name();
|
||||
}
|
||||
|
||||
boost::python::list fields(boost::shared_ptr<mapnik::datasource> const& ds)
|
||||
{
|
||||
boost::python::list flds;
|
||||
if (ds)
|
||||
{
|
||||
layer_descriptor ld = ds->get_descriptor();
|
||||
std::vector<attribute_descriptor> const& desc_ar = ld.get_descriptors();
|
||||
std::vector<attribute_descriptor>::const_iterator it = desc_ar.begin();
|
||||
std::vector<attribute_descriptor>::const_iterator end = desc_ar.end();
|
||||
for (; it != end; ++it)
|
||||
{
|
||||
flds.append(it->get_name());
|
||||
}
|
||||
}
|
||||
return flds;
|
||||
}
|
||||
boost::python::list field_types(boost::shared_ptr<mapnik::datasource> const& ds)
|
||||
{
|
||||
boost::python::list fld_types;
|
||||
if (ds)
|
||||
{
|
||||
layer_descriptor ld = ds->get_descriptor();
|
||||
std::vector<attribute_descriptor> const& desc_ar = ld.get_descriptors();
|
||||
std::vector<attribute_descriptor>::const_iterator it = desc_ar.begin();
|
||||
std::vector<attribute_descriptor>::const_iterator end = desc_ar.end();
|
||||
for (; it != end; ++it)
|
||||
{
|
||||
unsigned type = it->get_type();
|
||||
fld_types.append(type);
|
||||
}
|
||||
}
|
||||
return fld_types;
|
||||
}}
|
||||
|
||||
void export_datasource()
|
||||
{
|
||||
|
@ -104,6 +153,10 @@ void export_datasource()
|
|||
.def("envelope",&datasource::envelope)
|
||||
.def("descriptor",&datasource::get_descriptor) //todo
|
||||
.def("features",&datasource::features)
|
||||
.def("fields",&fields)
|
||||
.def("_field_types",&field_types)
|
||||
.def("encoding",&encoding) //todo expose as property
|
||||
.def("name",&name)
|
||||
.def("features_at_point",&datasource::features_at_point)
|
||||
.def("params",&datasource::params,return_value_policy<copy_const_reference>(),
|
||||
"The configuration parameters of the data source. "
|
||||
|
|
|
@ -221,6 +221,7 @@ void export_feature()
|
|||
// .def("add_geometry", // TODO define more mapnik::Feature methods
|
||||
.def("num_geometries",&Feature::num_geometries)
|
||||
.def("get_geometry", make_function(get_geom1,return_value_policy<reference_existing_object>()))
|
||||
.def("envelope", &Feature::envelope)
|
||||
;
|
||||
|
||||
class_<std::map<std::string, mapnik::value> >("Properties")
|
||||
|
|
|
@ -29,18 +29,21 @@
|
|||
|
||||
namespace {
|
||||
using namespace boost::python;
|
||||
inline object pass_through(object const& o) { return o; }
|
||||
|
||||
inline mapnik::feature_ptr next(mapnik::featureset_ptr const& itr)
|
||||
{
|
||||
if (!itr)
|
||||
{
|
||||
PyErr_SetString(PyExc_StopIteration, "No more features.");
|
||||
boost::python::throw_error_already_set();
|
||||
}
|
||||
|
||||
return itr->next();
|
||||
}
|
||||
list features(mapnik::featureset_ptr const& itr)
|
||||
{
|
||||
list l;
|
||||
while (true)
|
||||
{
|
||||
mapnik::feature_ptr fp = itr->next();
|
||||
if (!fp)
|
||||
{
|
||||
break;
|
||||
}
|
||||
l.append(fp);
|
||||
}
|
||||
return l;
|
||||
}
|
||||
}
|
||||
|
||||
void export_featureset()
|
||||
|
@ -51,8 +54,6 @@ void export_featureset()
|
|||
|
||||
class_<Featureset,boost::shared_ptr<Featureset>,
|
||||
boost::noncopyable>("Featureset",no_init)
|
||||
.def("next",next)
|
||||
.def("__iter__",pass_through)
|
||||
.add_property("features",features)
|
||||
;
|
||||
}
|
||||
|
||||
|
|
|
@ -267,11 +267,11 @@ void export_map()
|
|||
"otherwise will return None.\n"
|
||||
"\n"
|
||||
"Usage:\n"
|
||||
">>> feat = m.query_map_point(0,200,200)\n"
|
||||
">>> feat\n"
|
||||
">>> <mapnik._mapnik.Featureset object at 0x5fe1f0>\n"
|
||||
">>> feat.next()\n"
|
||||
">>> <mapnik._mapnik.Feature object at 0x5fe230>\n"
|
||||
">>> featureset = m.query_map_point(0,200,200)\n"
|
||||
">>> featureset\n"
|
||||
"<mapnik._mapnik.Featureset object at 0x23b0b0>\n"
|
||||
">>> featureset.features\n"
|
||||
">>> [<mapnik.Feature object at 0x3995630>]\n"
|
||||
)
|
||||
|
||||
.def("query_point",&Map::query_point,
|
||||
|
@ -282,11 +282,11 @@ void export_map()
|
|||
"otherwise will return None.\n"
|
||||
"\n"
|
||||
"Usage:\n"
|
||||
">>> feat = m.query_point(0,-122,48)\n"
|
||||
">>> feat\n"
|
||||
">>> <mapnik._mapnik.Featureset object at 0x5fe130>\n"
|
||||
">>> feat.next()\n"
|
||||
">>> <mapnik._mapnik.Feature object at 0x5fe1b0>\n"
|
||||
">>> featureset = m.query_point(0,-122,48)\n"
|
||||
">>> featureset\n"
|
||||
"<mapnik._mapnik.Featureset object at 0x23b0b0>\n"
|
||||
">>> featureset.features\n"
|
||||
">>> [<mapnik.Feature object at 0x3995630>]\n"
|
||||
)
|
||||
|
||||
.def("remove_all",&Map::remove_all,
|
||||
|
|
|
@ -94,7 +94,26 @@ namespace mapnik {
|
|||
{
|
||||
return geom_cont_[index];
|
||||
}
|
||||
|
||||
|
||||
Envelope<double> envelope() const
|
||||
{
|
||||
Envelope<double> result;
|
||||
for (unsigned i=0;i<num_geometries();++i)
|
||||
{
|
||||
geometry2d const& geom = get_geometry(i);
|
||||
if (i==0)
|
||||
{
|
||||
Envelope<double> box = geom.envelope();
|
||||
result.init(box.minx(),box.miny(),box.maxx(),box.maxy());
|
||||
}
|
||||
else
|
||||
{
|
||||
result.expand_to_include(geom.envelope());
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
const raster_type& get_raster() const
|
||||
{
|
||||
return raster_;
|
||||
|
|
|
@ -130,7 +130,7 @@ def test_shapefile_init():
|
|||
# Shapefile properties
|
||||
def test_shapefile_properties():
|
||||
s = mapnik.Shapefile(file='../../demo/data/boundaries')
|
||||
f = s.features_at_point(s.envelope().center()).next()
|
||||
f = s.features_at_point(s.envelope().center()).features[0]
|
||||
|
||||
eq_(f.properties['CGNS_FID'], u'6f733341ba2011d892e2080020a0f4c9')
|
||||
eq_(f.properties['COUNTRY'], u'CAN')
|
||||
|
|
Loading…
Reference in a new issue