diff --git a/bindings/python/mapnik/__init__.py b/bindings/python/mapnik/__init__.py index 775646dea..aa96897d9 100644 --- a/bindings/python/mapnik/__init__.py +++ b/bindings/python/mapnik/__init__.py @@ -247,44 +247,6 @@ class _Datasource(Datasource,_injector): query.add_property_name(fld) return self.features(query) -class _DeprecatedFeatureProperties(object): - - def __init__(self, feature): - self._feature = feature - - def __getitem__(self, name): - warnings.warn("indexing feature.properties is deprecated, index the " - "feature object itself for the same effect", DeprecationWarning, 2) - return self._feature[name] - - def __iter__(self): - warnings.warn("iterating feature.properties is deprecated, iterate the " - "feature object itself for the same effect", DeprecationWarning, 2) - return iter(self._feature) - -class _Feature(Feature, _injector): - """ - A Feature. - - TODO: docs - """ - @property - def properties(self): - return _DeprecatedFeatureProperties(self) - - @property - def attributes(self): - #XXX Returns a copy! changes to it won't affect feat.'s attrs. - # maybe deprecate? - return dict(self) - - def __init__(self, ctx, id, wkt=None, **properties): - Feature._c___init__(self, ctx, id) - if wkt is not None: - self.add_geometries_from_wkt(wkt) - for k, v in properties.iteritems(): - self[k] = v - class _Color(Color,_injector): def __repr__(self): return "Color(R=%d,G=%d,B=%d,A=%d)" % (self.r,self.g,self.b,self.a) diff --git a/bindings/python/mapnik_feature.cpp b/bindings/python/mapnik_feature.cpp index 566075902..581d6e3f2 100644 --- a/bindings/python/mapnik_feature.cpp +++ b/bindings/python/mapnik_feature.cpp @@ -78,12 +78,22 @@ void __setitem__(Feature & feature, std::string const& name, mapnik::value const feature.put(name,val); } +boost::python::dict describe(Feature const& feature) +{ + boost::python::dict attributes; + feature_kv_iterator itr(feature,true); + feature_kv_iterator end(feature); + + for ( ;itr!=end; ++itr) + { + attributes[boost::get<0>(*itr)] = boost::get<1>(*itr); + } + + return attributes; +} + } // end anonymous namespace -namespace boost { namespace python { - -}} - struct UnicodeString_from_python_str { UnicodeString_from_python_str() @@ -168,6 +178,7 @@ void export_feature() .def("geometries",make_function(get_paths_by_const_ref,return_value_policy())) .def("envelope", &Feature::envelope) .def("has_key", &Feature::has_key) + .def("describe",&describe) .def("__setitem__",&__setitem__) .def("__getitem__",&__getitem__) .def("__getitem__",&__getitem2__) diff --git a/plugins/input/gdal/gdal_featureset.cpp b/plugins/input/gdal/gdal_featureset.cpp index 71c4d871a..a5ccfd51b 100644 --- a/plugins/input/gdal/gdal_featureset.cpp +++ b/plugins/input/gdal/gdal_featureset.cpp @@ -67,6 +67,7 @@ gdal_featureset::gdal_featureset(GDALDataset& dataset, filter_factor_(filter_factor), first_(true) { + ctx_->push("value"); ctx_->push("NODATA"); } diff --git a/plugins/input/postgis/postgis_datasource.cpp b/plugins/input/postgis/postgis_datasource.cpp index d9ae2a9fe..4417d16a1 100644 --- a/plugins/input/postgis/postgis_datasource.cpp +++ b/plugins/input/postgis/postgis_datasource.cpp @@ -581,12 +581,10 @@ featureset_ptr postgis_datasource::features_at_point(coord2d const& pt) const std::vector::const_iterator itr = desc_.get_descriptors().begin(); std::vector::const_iterator end = desc_.get_descriptors().end(); - unsigned size=0; for ( ; itr != end; ++itr) { mapnik::sql_utils::quote_attr(s,itr->get_name()); ctx->push(itr->get_name()); - ++size; } box2d box(pt.x,pt.y,pt.x,pt.y); diff --git a/plugins/input/sqlite/sqlite_datasource.cpp b/plugins/input/sqlite/sqlite_datasource.cpp index 2cd3f11e0..7a7529584 100644 --- a/plugins/input/sqlite/sqlite_datasource.cpp +++ b/plugins/input/sqlite/sqlite_datasource.cpp @@ -547,19 +547,24 @@ featureset_ptr sqlite_datasource::features(query const& q) const mapnik::box2d const& e = q.get_bbox(); std::ostringstream s; + mapnik::context_ptr ctx = boost::make_shared(); s << "SELECT " << geometry_field_; if (!key_field_.empty()) + { s << "," << key_field_; + ctx->push(key_field_); + } std::set const& props = q.property_names(); std::set::const_iterator pos = props.begin(); std::set::const_iterator end = props.end(); - while (pos != end) + + for ( ;pos != end;++pos) { // TODO - should we restrict duplicate key query? //if (*pos != key_field_) s << ",[" << *pos << "]"; - ++pos; + ctx->push(*pos); } s << " FROM "; @@ -601,6 +606,7 @@ featureset_ptr sqlite_datasource::features(query const& q) const boost::shared_ptr rs(dataset_->execute_query(s.str())); return boost::make_shared(rs, + ctx, desc_.get_encoding(), format_, using_subquery_); @@ -619,20 +625,26 @@ featureset_ptr sqlite_datasource::features_at_point(coord2d const& pt) const mapnik::box2d const e(pt.x, pt.y, pt.x, pt.y); std::ostringstream s; + mapnik::context_ptr ctx = boost::make_shared(); + s << "SELECT " << geometry_field_; if (!key_field_.empty()) + { s << "," << key_field_; + ctx->push(key_field_); + } + std::vector::const_iterator itr = desc_.get_descriptors().begin(); std::vector::const_iterator end = desc_.get_descriptors().end(); - while (itr != end) + + for ( ; itr != end; ++itr) { std::string fld_name = itr->get_name(); if (fld_name != key_field_) { s << ",[" << itr->get_name() << "]"; + ctx->push(itr->get_name()); } - - ++itr; } s << " FROM "; @@ -674,6 +686,7 @@ featureset_ptr sqlite_datasource::features_at_point(coord2d const& pt) const boost::shared_ptr rs(dataset_->execute_query(s.str())); return boost::make_shared(rs, + ctx, desc_.get_encoding(), format_, using_subquery_); diff --git a/plugins/input/sqlite/sqlite_featureset.cpp b/plugins/input/sqlite/sqlite_featureset.cpp index 4e7fbe6df..dc9aeb5d8 100644 --- a/plugins/input/sqlite/sqlite_featureset.cpp +++ b/plugins/input/sqlite/sqlite_featureset.cpp @@ -45,6 +45,7 @@ using mapnik::transcoder; using mapnik::feature_factory; sqlite_featureset::sqlite_featureset(boost::shared_ptr rs, + mapnik::context_ptr const& ctx, std::string const& encoding, mapnik::wkbFormat format, bool using_subquery) @@ -52,12 +53,8 @@ sqlite_featureset::sqlite_featureset(boost::shared_ptr rs, tr_(new transcoder(encoding)), format_(format), using_subquery_(using_subquery), - ctx_(boost::make_shared()) + ctx_(ctx) { - for (int i = 2; i < rs_->column_count(); ++i) - { - ctx_->push(rs_->column_name(i)); - } } sqlite_featureset::~sqlite_featureset() diff --git a/plugins/input/sqlite/sqlite_featureset.hpp b/plugins/input/sqlite/sqlite_featureset.hpp index cddc5d89f..b7feb7386 100644 --- a/plugins/input/sqlite/sqlite_featureset.hpp +++ b/plugins/input/sqlite/sqlite_featureset.hpp @@ -40,6 +40,7 @@ class sqlite_featureset : public mapnik::Featureset { public: sqlite_featureset(boost::shared_ptr rs, + mapnik::context_ptr const& ctx, std::string const& encoding, mapnik::wkbFormat format, bool using_subquery); diff --git a/tests/python_tests/csv_test.py b/tests/python_tests/csv_test.py index 8d760a49d..a7989683f 100644 --- a/tests/python_tests/csv_test.py +++ b/tests/python_tests/csv_test.py @@ -52,7 +52,7 @@ if 'csv' in mapnik.DatasourceCache.instance().plugin_names(): eq_(ds.field_types(),['str','str','str','str','float','float','str']) feat = ds.featureset().next() attr = {'City': u'New York, NY', 'geo_accuracy': u'house', 'Phone': u'(212) 334-0711', 'Address': u'19 Elizabeth Street', 'Precinct': u'5th Precinct', 'geo_longitude': -70, 'geo_latitude': 40} - eq_(feat.attributes,attr) + eq_(feat.describe(),attr) eq_(len(ds.all_features()),2) eq_(ds.describe(),{'geometry_type': mapnik.DataGeometryType.Point, 'type': mapnik.DataType.Vector, 'name': 'csv', 'encoding': 'utf-8'}) @@ -72,7 +72,7 @@ if 'csv' in mapnik.DatasourceCache.instance().plugin_names(): fs = ds.featureset() feat = fs.next() attr = {'x': 0, 'empty_column': u'', 'text': u'a b', 'float': 1.0, 'datetime': u'1971-01-01T04:14:00', 'y': 0, 'boolean': u'True', 'time': u'04:14:00', 'date': u'1971-01-01', 'integer': 40} - eq_(feat.attributes,attr) + eq_(feat.describe(),attr) while feat: eq_(len(feat),10) eq_(feat['empty_column'],u'') @@ -83,9 +83,9 @@ if 'csv' in mapnik.DatasourceCache.instance().plugin_names(): ds = get_csv_ds('has_attributes_with_slashes.csv') eq_(len(ds.fields()),3) fs = ds.all_features() - eq_(fs[0].attributes,{'x':0,'y':0,'name':u'a/a'}) - eq_(fs[1].attributes,{'x':1,'y':4,'name':u'b/b'}) - eq_(fs[2].attributes,{'x':10,'y':2.5,'name':u'c/c'}) + eq_(fs[0].describe(),{'x':0,'y':0,'name':u'a/a'}) + eq_(fs[1].describe(),{'x':1,'y':4,'name':u'b/b'}) + eq_(fs[2].describe(),{'x':10,'y':2.5,'name':u'c/c'}) eq_(ds.describe(),{'geometry_type': mapnik.DataGeometryType.Point, 'type': mapnik.DataType.Vector, 'name': 'csv', 'encoding': 'utf-8'}) def test_wkt_field(**kwargs): diff --git a/tests/python_tests/datasource_test.py b/tests/python_tests/datasource_test.py index e1bf8bce8..2abb0c916 100644 --- a/tests/python_tests/datasource_test.py +++ b/tests/python_tests/datasource_test.py @@ -69,7 +69,7 @@ def test_feature_attributes(): features = ds.all_features() feat = features[0] attrs = {'PRFEDEA': u'35043411', 'EAS_ID': 168, 'AREA': 215229.266} - eq_(feat.attributes, attrs) + eq_(feat.describe(), attrs) eq_(ds.fields(),['AREA', 'EAS_ID', 'PRFEDEA']) eq_(ds.field_types(),['float','int','str']) diff --git a/tests/python_tests/feature_id_test.py b/tests/python_tests/feature_id_test.py index e6206bb5b..badf63a73 100644 --- a/tests/python_tests/feature_id_test.py +++ b/tests/python_tests/feature_id_test.py @@ -32,10 +32,8 @@ def compare_shape_between_mapnik_and_ogr(shapefile,query=None): #import pdb;pdb.set_trace() eq_(feat1.id(),feat2.id(), '%s : ogr feature id %s "%s" does not equal shapefile feature id %s "%s"' - % (count,feat1.id(),str(feat1.attributes), feat2.id(),str(feat2.attributes)) ) - + % (count,feat1.id(),str(feat1.describe()), feat2.id(),str(feat2.describe()))) return True - def test_shapefile_line_featureset_id(): diff --git a/tests/python_tests/feature_test.py b/tests/python_tests/feature_test.py index ab6b35d1b..43ff7d581 100644 --- a/tests/python_tests/feature_test.py +++ b/tests/python_tests/feature_test.py @@ -6,71 +6,50 @@ from nose.tools import * import mapnik from binascii import unhexlify -class FeatureTest(unittest.TestCase): - def makeOne(self, *args, **kw): - return mapnik.Feature(*args, **kw) - - def test_default_constructor(self): - f = self.makeOne(1) - self.failUnless(f is not None) +def test_default_constructor(): + f = mapnik.Feature(mapnik.Context(),1) + eq_(f is not None,True) - def test_python_extended_constructor(self): - f = self.makeOne(1, 'POLYGON ((35 10, 10 20, 15 40, 45 45, 35 10),(20 30, 35 35, 30 20, 20 30))', foo="bar") - self.failUnlessEqual(f['foo'], 'bar') - self.failUnlessEqual(f.envelope(),mapnik.Box2d(10.0,10.0,45.0,45.0)) - - def test_set_get_properties(self): - f = self.makeOne(1) - counter = itertools.count(0) - def test_val(expected): - key = 'prop%d'%counter.next() - try: - f[key] = expected - except TypeError: - self.fail("%r (%s)"%(expected, type(expected))) - self.failUnlessEqual(f[key], expected) - for v in (1, True, 1.4, "foo", u"avión"): - test_val(v) - - def test_add_wkt_geometry(self): - def add_geom_wkt(wkt): - f = self.makeOne(1) - self.failUnlessEqual(len(f.geometries()), 0) - f.add_geometries_from_wkt(wkt) - self.failUnlessEqual(len(f.geometries()), 3) - e = mapnik.Box2d() - self.failUnlessEqual(e.valid(), False) - for g in f.geometries(): - if not e.valid(): - e = g.envelope() - else: - e +=g.envelope() - - self.failUnlessEqual(e, f.envelope()) - - def add_geom_wkb(wkb): - f = self.makeOne(1) - self.failUnlessEqual(len(f.geometries()), 0) - f.add_geometries_from_wkb(unhexlify(wkb)) - self.failUnlessEqual(len(f.geometries()), 1) - e = mapnik.Box2d() - self.failUnlessEqual(e.valid(), False) - for g in f.geometries(): - if not e.valid(): - e = g.envelope() - else: - e +=g.envelope() - - self.failUnlessEqual(e, f.envelope()) - - def run() : - add_geom_wkt('GEOMETRYCOLLECTION(POINT(4 6),LINESTRING(4 6,7 10),POLYGON ((30 10, 10 20, 20 40, 40 40, 30 10)))') - add_geom_wkb('010300000001000000050000000000000000003e4000000000000024400000000000002440000000000000344000000000000034400000000000004440000000000000444000000000000044400000000000003e400000000000002440') # POLYGON ((30 10, 10 20, 20 40, 40 40, 30 10)) - run() +def test_python_extended_constructor(): + context = mapnik.Context() + context.push('foo') + context.push('foo') + f = mapnik.Feature(context,1) + wkt = 'POLYGON ((35 10, 10 20, 15 40, 45 45, 35 10),(20 30, 35 35, 30 20, 20 30))' + f.add_geometries_from_wkt(wkt) + f['foo'] = 'bar' + eq_(f['foo'], 'bar') + eq_(f.envelope(),mapnik.Box2d(10.0,10.0,45.0,45.0)) + # reset + f['foo'] = u"avión" + eq_(f['foo'], u"avión") + f['foo'] = 1.4 + eq_(f['foo'], 1.4) + f['foo'] = True + eq_(f['foo'], True) +def test_add_geom_wkb(): +# POLYGON ((30 10, 10 20, 20 40, 40 40, 30 10)) + wkb = '010300000001000000050000000000000000003e4000000000000024400000000000002440000000000000344000000000000034400000000000004440000000000000444000000000000044400000000000003e400000000000002440' + context = mapnik.Context() + f = mapnik.Feature(context,1) + eq_(len(f.geometries()), 0) + f.add_geometries_from_wkb(unhexlify(wkb)) + eq_(len(f.geometries()), 1) + e = mapnik.Box2d() + eq_(e.valid(), False) + for g in f.geometries(): + if not e.valid(): + e = g.envelope() + else: + e +=g.envelope() + + eq_(e, f.envelope()) def test_feature_expression_evaluation(): - f = mapnik.Feature(1) + context = mapnik.Context() + context.push('name') + f = mapnik.Feature(context,1) f['name'] = 'a' eq_(f['name'],u'a') expr = mapnik.Expression("[name]='a'") @@ -82,7 +61,9 @@ def test_feature_expression_evaluation(): # https://github.com/mapnik/mapnik/issues/933 def test_feature_expression_evaluation_missing_attr(): - f = mapnik.Feature(1) + context = mapnik.Context() + context.push('name') + f = mapnik.Feature(context,1) f['name'] = u'a' eq_(f['name'],u'a') expr = mapnik.Expression("[fielddoesnotexist]='a'") @@ -94,7 +75,9 @@ def test_feature_expression_evaluation_missing_attr(): # https://github.com/mapnik/mapnik/issues/934 def test_feature_expression_evaluation_attr_with_spaces(): - f = mapnik.Feature(1) + context = mapnik.Context() + context.push('name with space') + f = mapnik.Feature(context,1) f['name with space'] = u'a' eq_(f['name with space'],u'a') expr = mapnik.Expression("[name with space]='a'") diff --git a/tests/python_tests/filter_test.py b/tests/python_tests/filter_test.py index d17f43652..aea7cf2fa 100644 --- a/tests/python_tests/filter_test.py +++ b/tests/python_tests/filter_test.py @@ -93,25 +93,33 @@ def test_filter_init(): def test_regex_match(): - f = mapnik.Feature(0) + context = mapnik.Context() + context.push('name') + f = mapnik.Feature(context,0) f["name"] = 'test' expr = mapnik.Expression("[name].match('test')") eq_(expr.evaluate(f),True) # 1 == True def test_unicode_regex_match(): - f = mapnik.Feature(0) + context = mapnik.Context() + context.push('name') + f = mapnik.Feature(context,0) f["name"] = 'Québec' expr = mapnik.Expression("[name].match('Québec')") eq_(expr.evaluate(f),True) # 1 == True def test_regex_replace(): - f = mapnik.Feature(0) + context = mapnik.Context() + context.push('name') + f = mapnik.Feature(context,0) f["name"] = 'test' expr = mapnik.Expression("[name].replace('(\B)|( )','$1 ')") eq_(expr.evaluate(f),'t e s t') def test_unicode_regex_replace(): - f = mapnik.Feature(0) + context = mapnik.Context() + context.push('name') + f = mapnik.Feature(context,0) f["name"] = 'Québec' expr = mapnik.Expression("[name].replace('(\B)|( )','$1 ')") eq_(expr.evaluate(f), u'Q u é b e c') diff --git a/tests/python_tests/geometry_io_test.py b/tests/python_tests/geometry_io_test.py index d937839df..b2bce104c 100644 --- a/tests/python_tests/geometry_io_test.py +++ b/tests/python_tests/geometry_io_test.py @@ -34,7 +34,7 @@ def compare_wkb_from_wkt(wkt,num=None): paths = mapnik.Path.from_wkt(wkt) # add geometry(s) to feature from wkt - f = mapnik.Feature(1) + f = mapnik.Feature(mapnik.Context(),1) f.add_geometries_from_wkt(wkt) # ensure both have same result @@ -65,7 +65,7 @@ def compare_wkt_from_wkt(wkt,num=None): paths = mapnik.Path.from_wkt(wkt) # add geometry(s) to feature from wkt - f = mapnik.Feature(1) + f = mapnik.Feature(mapnik.Context(),1) f.add_geometries_from_wkt(wkt) # compare to original, which may not have significant digits @@ -113,14 +113,14 @@ def test_geometry_index_error(): wkt = 'Point (0 0)' paths = mapnik.Path.from_wkt(wkt) paths[3] - f = mapnik.Feature(1) + f = mapnik.Feature(mapnik.Context(),1) f.add_geometries_from_wkt(wkt) f.geometries()[3] @raises(IndexError) def test_geometry_index_error2(): wkt = 'Point (0 0)' - f = mapnik.Feature(1) + f = mapnik.Feature(mapnik.Context(),1) f.add_geometries_from_wkt(wkt) f.geometries()[3] diff --git a/tests/python_tests/memory_datasource_test.py b/tests/python_tests/memory_datasource_test.py index 73b2575e3..4afce1046 100644 --- a/tests/python_tests/memory_datasource_test.py +++ b/tests/python_tests/memory_datasource_test.py @@ -1,40 +1,34 @@ #encoding: utf8 -import itertools -import unittest +import mapnik +from nose.tools import * -class MemoryDatasource(unittest.TestCase): - ids = itertools.count(0) +def test_add_feature(): + md = mapnik.MemoryDatasource() + eq_(md.num_features(), 0) + context = mapnik.Context() + context.push('foo') + feature = mapnik.Feature(context,1) + feature['foo'] = 'bar' + feature.add_geometries_from_wkt('POINT(2 3)') + md.add_feature(feature) + eq_(md.num_features(), 1) - def makeOne(self, *args, **kw): - from mapnik import MemoryDatasource - return MemoryDatasource(*args, **kw) + featureset = md.features_at_point(mapnik.Coord(2,3)) + retrieved = [] + feat = featureset.next() + while featureset.next(): + retrieved.append(feat) + + eq_(len(retrieved), 1) + f = retrieved[0] + eq_(f['foo'], 'bar') - def makeFeature(self, wkt, **properties): - from mapnik import Feature - f = Feature(self.ids.next()) - f.add_geometries_from_wkt(wkt) - for k,v in properties.iteritems(): - f[k] = v - return f - - def test_default_constructor(self): - f = self.makeOne() - self.failUnless(f is not None) - - def test_add_feature(self): - md = self.makeOne() - self.failUnlessEqual(md.num_features(), 0) - md.add_feature(self.makeFeature('Point(2 3)', foo='bar')) - self.failUnlessEqual(md.num_features(), 1) - - from mapnik import Coord - retrieved = md.features_at_point(Coord(2,3)).features - self.failUnlessEqual(len(retrieved), 1) - f = retrieved[0] - self.failUnlessEqual(f['foo'], 'bar') - - retrieved = md.features_at_point(Coord(20,30)).features - self.failUnlessEqual(len(retrieved), 0) + featureset = md.features_at_point(Coord(20,30)).features + retrieved = [] + feat = featureset.next() + while featureset.next(): + retrieved.append(feat) + eq_(len(retrieved), 0) if __name__ == "__main__": [eval(run)() for run in dir() if 'test_' in run] diff --git a/tests/python_tests/render_grid_test.py b/tests/python_tests/render_grid_test.py index a9dae422b..674319bb6 100644 --- a/tests/python_tests/render_grid_test.py +++ b/tests/python_tests/render_grid_test.py @@ -37,11 +37,28 @@ def resolve(grid,x,y): def create_grid_map(width,height): - places_ds = mapnik.MemoryDatasource() - places_ds.add_point(143.10,-38.60,'Name','South East') - places_ds.add_point(142.48,-38.60,'Name','South West') - places_ds.add_point(142.48,-38.38,'Name','North West') - places_ds.add_point(143.10,-38.38,'Name','North East') + ds = mapnik.MemoryDatasource() + context = mapnik.Context() + context.push('Name') + f = mapnik.Feature(context,1) + f['Name'] = 'South East' + f.add_geometries_from_wkt('POINT (143.10 -38.60)') + ds.add_feature(f) + + f = mapnik.Feature(context,2) + f['Name'] = 'South West' + f.add_geometries_from_wkt('POINT (142.48 -38.60)') + ds.add_feature(f) + + f = mapnik.Feature(context,3) + f['Name'] = 'North West' + f.add_geometries_from_wkt('POINT (142.48 -38.38)') + ds.add_feature(f) + + f = mapnik.Feature(context,4) + f['Name'] = 'North East' + f.add_geometries_from_wkt('POINT (143.10 -38.38)') + ds.add_feature(f) s = mapnik.Style() r = mapnik.Rule() #symb = mapnik.PointSymbolizer() @@ -59,7 +76,7 @@ def create_grid_map(width,height): s.rules.append(r) lyr = mapnik.Layer('Places') - lyr.datasource = places_ds + lyr.datasource = ds lyr.styles.append('places_labels') m = mapnik.Map(width,height) m.append_style('places_labels',s) diff --git a/tests/python_tests/render_test.py b/tests/python_tests/render_test.py index bcf49e15d..c1e15e2f0 100644 --- a/tests/python_tests/render_test.py +++ b/tests/python_tests/render_test.py @@ -120,29 +120,37 @@ def resolve(grid,x,y): def test_render_grid(): - places_ds = mapnik.MemoryDatasource() - places_ds.add_point(143.10,-38.60,'Name','South East') - places_ds.add_point(142.48,-38.60,'Name','South West') - places_ds.add_point(142.48,-38.38,'Name','North West') - places_ds.add_point(143.10,-38.38,'Name','North East') + ds = mapnik.MemoryDatasource() + context = mapnik.Context() + context.push('Name') + f = mapnik.Feature(context,1) + f['Name'] = 'South East' + f.add_geometries_from_wkt('POINT (143.10 -38.60)') + ds.add_feature(f) + + f = mapnik.Feature(context,2) + f['Name'] = 'South West' + f.add_geometries_from_wkt('POINT (142.48 -38.60)') + ds.add_feature(f) + + f = mapnik.Feature(context,3) + f['Name'] = 'North West' + f.add_geometries_from_wkt('POINT (142.48 -38.38)') + ds.add_feature(f) + + f = mapnik.Feature(context,4) + f['Name'] = 'North East' + f.add_geometries_from_wkt('POINT (143.10 -38.38)') + ds.add_feature(f) + s = mapnik.Style() r = mapnik.Rule() - #symb = mapnik.PointSymbolizer() symb = mapnik.MarkersSymbolizer() symb.allow_overlap = True r.symbols.append(symb) - label = mapnik.TextSymbolizer(mapnik.Expression('[Name]'), - 'DejaVu Sans Book', - 10, - mapnik.Color('black') - ) - label.allow_overlap = True - label.displacement = (0,-10) - #r.symbols.append(label) - s.rules.append(r) lyr = mapnik.Layer('Places') - lyr.datasource = places_ds + lyr.datasource = ds lyr.styles.append('places_labels') m = mapnik.Map(256,256) m.append_style('places_labels',s) @@ -184,9 +192,19 @@ def test_render_points(): if not mapnik.has_cairo(): return # create and populate point datasource (WGS84 lat-lon coordinates) - places_ds = mapnik.MemoryDatasource() - places_ds.add_point(142.48,-38.38,'Name','Westernmost Point') # westernmost - places_ds.add_point(143.10,-38.60,'Name','Southernmost Point') # southernmost + ds = mapnik.MemoryDatasource() + context = mapnik.Context() + context.push('Name') + f = mapnik.Feature(context,1) + f['Name'] = 'Westernmost Point' + f.add_geometries_from_wkt('POINT (142.48 -38.38)') + ds.add_feature(f) + + f = mapnik.Feature(context,2) + f['Name'] = 'Southernmost Point' + f.add_geometries_from_wkt('POINT (143.10,-38.60)') + ds.add_feature(f) + # create layer/rule/style s = mapnik.Style() r = mapnik.Rule() @@ -195,7 +213,7 @@ def test_render_points(): r.symbols.append(symb) s.rules.append(r) lyr = mapnik.Layer('Places','+proj=latlon +datum=WGS84') - lyr.datasource = places_ds + lyr.datasource = ds lyr.styles.append('places_labels') # latlon bounding box corners ul_lonlat = mapnik.Coord(142.30,-38.20) @@ -216,7 +234,7 @@ def test_render_points(): # Render to SVG so that it can be checked how many points are there with string comparison svg_file = os.path.join(tempfile.gettempdir(),'%s.svg') mapnik.render_to_file(m, svg_file) - num_points_present = len(places_ds.all_features()) + num_points_present = len(ds.all_features()) svg = open(svg_file,'r').read() num_points_rendered = svg.count('