+ 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:
Dane Springmeyer 2009-05-01 01:21:29 +00:00
parent e2fd9c8329
commit 196b01c16c
7 changed files with 131 additions and 28 deletions

View file

@ -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.

View file

@ -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. "

View file

@ -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")

View file

@ -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)
;
}

View file

@ -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,

View file

@ -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_;

View file

@ -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')