b085b401db
If the CirclesDatasource class was not available from the python_plugin_tests module then the 'load_good_maps' test would fail. The class would not be available if, for example, the python plugin had not been built or if shapely was not available on the test system. (Pull request #1414 removes the dependency on Shapely.) The error reporting should be tidied up for this case but for the moment, move the Python plugin's test maps into their own directory since they're not guaranteed to be 'good maps' in all cases at the moment. Hopefully addresses issue #1407
158 lines
5.4 KiB
Python
158 lines
5.4 KiB
Python
#!/usr/bin/env python
|
|
# -*- coding: utf-8 -*-
|
|
|
|
import os
|
|
import math
|
|
import mapnik
|
|
import sys
|
|
from utilities import execution_path
|
|
from nose.tools import *
|
|
|
|
try:
|
|
from shapely.geometry import Point
|
|
have_shapely = True
|
|
except ImportError:
|
|
print('Shapely is required for python data source test.')
|
|
have_shapely = False
|
|
|
|
def setup():
|
|
# All of the paths used are relative, if we run the tests
|
|
# from another directory we need to chdir()
|
|
os.chdir(execution_path('.'))
|
|
|
|
class PointDatasource(mapnik.PythonDatasource):
|
|
def __init__(self):
|
|
super(PointDatasource, self).__init__(
|
|
envelope = mapnik.Box2d(0,-10,100,110)
|
|
)
|
|
|
|
def features(self, query):
|
|
return mapnik.PythonDatasource.wkb_features(
|
|
keys = ('label',),
|
|
features = (
|
|
( Point(5,6).wkb, { 'label': 'foo-bar'} ),
|
|
( Point(60,50).wkb, { 'label': 'buzz-quux'} ),
|
|
)
|
|
)
|
|
|
|
def box2d_to_shapely(box):
|
|
import shapely.geometry
|
|
return shapely.geometry.box(box.minx, box.miny, box.maxx, box.maxy)
|
|
|
|
class ConcentricCircles(object):
|
|
def __init__(self, centre, bounds, step=1):
|
|
self.centre = centre
|
|
self.bounds = bounds
|
|
self.step = step
|
|
|
|
class Iterator(object):
|
|
def __init__(self, container):
|
|
self.container = container
|
|
|
|
centre = self.container.centre
|
|
bounds = self.container.bounds
|
|
step = self.container.step
|
|
|
|
if centre.within(bounds):
|
|
self.radius = step
|
|
else:
|
|
self.radius = math.ceil(centre.distance(bounds) / float(step)) * step
|
|
|
|
def next(self):
|
|
circle = self.container.centre.buffer(self.radius)
|
|
self.radius += self.container.step
|
|
|
|
# has the circle grown so large that the boundary is entirely within it?
|
|
if circle.contains(self.container.bounds):
|
|
raise StopIteration()
|
|
|
|
return ( circle.wkb, { } )
|
|
|
|
def __iter__(self):
|
|
return ConcentricCircles.Iterator(self)
|
|
|
|
class CirclesDatasource(mapnik.PythonDatasource):
|
|
def __init__(self, centre_x=-20, centre_y=0, step=10):
|
|
super(CirclesDatasource, self).__init__(
|
|
geometry_type=mapnik.DataGeometryType.Polygon
|
|
)
|
|
|
|
# note that the plugin loader will set all arguments to strings and will not try to parse them
|
|
centre_x = int(centre_x)
|
|
centre_y = int(centre_y)
|
|
step = int(step)
|
|
|
|
self.centre_x = centre_x
|
|
self.centre_y = centre_y
|
|
self.step = step
|
|
|
|
def features(self, query):
|
|
# Get the query bounding-box as a shapely bounding box
|
|
bounding_box = box2d_to_shapely(query.bbox)
|
|
centre = Point(self.centre_x, self.centre_y)
|
|
|
|
return mapnik.PythonDatasource.wkb_features(
|
|
keys = (),
|
|
features = ConcentricCircles(centre, bounding_box, self.step)
|
|
)
|
|
|
|
if 'python' in mapnik.DatasourceCache.instance().plugin_names() and have_shapely:
|
|
# make sure we can load from ourself as a module
|
|
sys.path.append(execution_path('.'))
|
|
|
|
def test_python_point_init():
|
|
ds = mapnik.Python(factory='python_plugin_test:PointDatasource')
|
|
e = ds.envelope()
|
|
|
|
assert_almost_equal(e.minx, 0, places=7)
|
|
assert_almost_equal(e.miny, -10, places=7)
|
|
assert_almost_equal(e.maxx, 100, places=7)
|
|
assert_almost_equal(e.maxy, 110, places=7)
|
|
|
|
def test_python_circle_init():
|
|
ds = mapnik.Python(factory='python_plugin_test:CirclesDatasource')
|
|
e = ds.envelope()
|
|
|
|
assert_almost_equal(e.minx, -180, places=7)
|
|
assert_almost_equal(e.miny, -90, places=7)
|
|
assert_almost_equal(e.maxx, 180, places=7)
|
|
assert_almost_equal(e.maxy, 90, places=7)
|
|
|
|
def test_python_circle_init_with_args():
|
|
ds = mapnik.Python(factory='python_plugin_test:CirclesDatasource', centre_x=40, centre_y=7)
|
|
e = ds.envelope()
|
|
|
|
assert_almost_equal(e.minx, -180, places=7)
|
|
assert_almost_equal(e.miny, -90, places=7)
|
|
assert_almost_equal(e.maxx, 180, places=7)
|
|
assert_almost_equal(e.maxy, 90, places=7)
|
|
|
|
def test_python_point_rendering():
|
|
m = mapnik.Map(512,512)
|
|
mapnik.load_map(m,'../data/python_plugin/python_point_datasource.xml')
|
|
m.zoom_all()
|
|
im = mapnik.Image(512,512)
|
|
mapnik.render(m,im)
|
|
actual = '/tmp/mapnik-python-point-render1.png'
|
|
expected = 'images/support/mapnik-python-point-render1.png'
|
|
im.save(actual)
|
|
expected_im = mapnik.Image.open(expected)
|
|
eq_(im.tostring(),expected_im.tostring(),
|
|
'failed comparing actual (%s) and expected (%s)' % (actual,'tests/python_tests/'+ expected))
|
|
|
|
def test_python_circle_rendering():
|
|
m = mapnik.Map(512,512)
|
|
mapnik.load_map(m,'../data/python_plugin/python_circle_datasource.xml')
|
|
m.zoom_all()
|
|
im = mapnik.Image(512,512)
|
|
mapnik.render(m,im)
|
|
actual = '/tmp/mapnik-python-circle-render1.png'
|
|
expected = 'images/support/mapnik-python-circle-render1.png'
|
|
im.save(actual)
|
|
expected_im = mapnik.Image.open(expected)
|
|
eq_(im.tostring(),expected_im.tostring(),
|
|
'failed comparing actual (%s) and expected (%s)' % (actual,'tests/python_tests/'+ expected))
|
|
|
|
if __name__ == "__main__":
|
|
setup()
|
|
[eval(run)() for run in dir() if 'test_' in run]
|