make it possible to disable compilation of grid_renderer - closes #1962

This commit is contained in:
Dane Springmeyer 2013-07-23 19:37:25 -04:00
parent 5ad2ebb30e
commit ef4dfeb747
14 changed files with 507 additions and 395 deletions

View file

@ -8,6 +8,10 @@ For a complete change history, see the git log.
## Future
- Added to python bindings: `has_tiff`, `has_png`, `has_webp`, `has_proj4`, `has_svg_renderer`, and `has_grid_renderer`
- Made it possible to disable compilation of `grid_renderer` with `./configure GRID_RENDERER=False` (#1962)
- Added `webp` image encoding and decoding support (#1955)
- Added `premultiplied` property on mapnik::image_32 / mapnik.Image to enable knowledge of premultiplied status of image buffer.

View file

@ -336,6 +336,7 @@ opts.AddVariables(
# Variables affecting rendering back-ends
BoolVariable('GRID_RENDERER', 'build support for native grid renderer', 'True'),
BoolVariable('SVG_RENDERER', 'build support for native svg renderer', 'False'),
BoolVariable('CPP_TESTS', 'Compile the C++ tests', 'True'),
BoolVariable('BENCHMARK', 'Compile the C++ benchmark scripts', 'False'),
@ -447,6 +448,7 @@ pickle_store = [# Scons internal variables
'CAIRO_LIBPATHS',
'CAIRO_ALL_LIBS',
'CAIRO_CPPPATHS',
'GRID_RENDERER',
'SVG_RENDERER',
'SQLITE_LINKFLAGS',
'BOOST_LIB_VERSION_FROM_HEADER',

View file

@ -20,6 +20,8 @@
*
*****************************************************************************/
#if defined(GRID_RENDERER)
// boost
#include <boost/python.hpp>
#include <boost/python/module.hpp>
@ -80,3 +82,5 @@ void export_grid()
;
}
#endif

View file

@ -20,6 +20,8 @@
*
*****************************************************************************/
#if defined(GRID_RENDERER)
// boost
#include <boost/python.hpp>
#include <boost/python/module.hpp>
@ -49,3 +51,5 @@ void export_grid_view()
)
;
}
#endif

View file

@ -41,8 +41,10 @@ void export_image();
void export_image_view();
void export_gamma_method();
void export_scaling_method();
#if defined(GRID_RENDERER)
void export_grid();
void export_grid_view();
#endif
void export_map();
void export_python();
void export_expression();
@ -92,7 +94,9 @@ void export_logger();
#include <mapnik/value_error.hpp>
#include <mapnik/save_map.hpp>
#include <mapnik/scale_denominator.hpp>
#if defined(GRID_RENDERER)
#include "python_grid_utils.hpp"
#endif
#include "mapnik_value_converter.hpp"
#include "mapnik_threads.hpp"
#include "python_optional.hpp"
@ -366,7 +370,33 @@ std::string mapnik_version_string()
return MAPNIK_VERSION_STRING;
}
// indicator for jpeg read/write support within libmapnik
bool has_proj4()
{
#if defined(MAPNIK_USE_PROJ4)
return true;
#else
return false;
#endif
}
bool has_svg_renderer()
{
#if defined(SVG_RENDERER)
return true;
#else
return false;
#endif
}
bool has_grid_renderer()
{
#if defined(GRID_RENDERER)
return true;
#else
return false;
#endif
}
bool has_jpeg()
{
#if defined(HAVE_JPEG)
@ -376,6 +406,33 @@ bool has_jpeg()
#endif
}
bool has_png()
{
#if defined(HAVE_PNG)
return true;
#else
return false;
#endif
}
bool has_tiff()
{
#if defined(HAVE_TIFF)
return true;
#else
return false;
#endif
}
bool has_webp()
{
#if defined(HAVE_WEBP)
return true;
#else
return false;
#endif
}
// indicator for cairo rendering support inside libmapnik
bool has_cairo()
{
@ -427,7 +484,6 @@ BOOST_PYTHON_MODULE(_mapnik)
using mapnik::load_map_string;
using mapnik::save_map;
using mapnik::save_map_to_string;
using mapnik::render_grid;
register_exception_translator<std::exception>(&standard_error_translator);
register_exception_translator<std::out_of_range>(&out_of_range_error_translator);
@ -448,8 +504,10 @@ BOOST_PYTHON_MODULE(_mapnik)
export_image_view();
export_gamma_method();
export_scaling_method();
#if defined(GRID_RENDERER)
export_grid();
export_grid_view();
#endif
export_expression();
export_rule();
export_style();
@ -487,7 +545,8 @@ BOOST_PYTHON_MODULE(_mapnik)
">>> clear_cache()\n"
);
def("render_grid",&render_grid,
#if defined(GRID_RENDERER)
def("render_grid",&mapnik::render_grid,
( arg("map"),
arg("layer"),
args("key")="__id__",
@ -495,6 +554,7 @@ BOOST_PYTHON_MODULE(_mapnik)
arg("fields")=boost::python::list()
)
);
#endif
def("render_to_file",&render_to_file1,
"\n"
@ -579,9 +639,11 @@ BOOST_PYTHON_MODULE(_mapnik)
(arg("map"),arg("image"),args("layer"))
);
#if defined(GRID_RENDERER)
def("render_layer", &mapnik::render_layer_for_grid,
(arg("map"),arg("grid"),args("layer"),arg("fields")=boost::python::list())
);
#endif
#if defined(HAVE_CAIRO) && defined(HAVE_PYCAIRO)
def("render",&render3,
@ -739,7 +801,12 @@ BOOST_PYTHON_MODULE(_mapnik)
def("save_map_to_string", &save_map_to_string, save_map_to_string_overloads());
def("mapnik_version", &mapnik_version,"Get the Mapnik version number");
def("mapnik_version_string", &mapnik_version_string,"Get the Mapnik version string");
def("has_proj4", &has_proj4, "Get proj4 status");
def("has_jpeg", &has_jpeg, "Get jpeg read/write support status");
def("has_png", &has_png, "Get png read/write support status");
def("has_tiff", &has_jpeg, "Get tiff read/write support status");
def("has_webp", &has_jpeg, "Get webp read/write support status");
def("has_grid_renderer", &has_grid_renderer, "Get grid_renderer status");
def("has_cairo", &has_cairo, "Get cairo library status");
def("has_pycairo", &has_pycairo, "Get pycairo module status");

View file

@ -20,6 +20,8 @@
*
*****************************************************************************/
#if defined(GRID_RENDERER)
// boost
#include <boost/python.hpp>
#include <boost/scoped_array.hpp>
@ -472,3 +474,5 @@ boost::python::dict render_grid(mapnik::Map const& map,
}
}
#endif

View file

@ -9,6 +9,9 @@ subdirs = ['','svg','wkt','grid','json','util','text_placements','formatting']
if env['SVG_RENDERER']:
subdirs.append('svg/output')
if env['GRID_RENDERER']:
subdirs.append('grid')
if 'install' in COMMAND_LINE_TARGETS:
for subdir in subdirs:
pathdir = os.path.join(base,subdir,'*.hpp')

View file

@ -27,7 +27,11 @@
#include <mapnik/svg/svg_path_attributes.hpp>
#include <mapnik/gradient.hpp>
#include <mapnik/box2d.hpp>
#if defined(GRID_RENDERER)
#include <mapnik/grid/grid_pixel.hpp>
#endif
#include <mapnik/noncopyable.hpp>
// boost
@ -334,6 +338,7 @@ public:
}
}
#if defined(GRID_RENDERER)
template <typename Rasterizer, typename Scanline, typename Renderer>
void render_id(Rasterizer& ras,
Scanline& sl,
@ -416,6 +421,7 @@ public:
}
}
}
#endif
private:

View file

@ -292,21 +292,24 @@ if env['RUNTIME_LINK'] == "static":
source += glob.glob('../deps/agg/src/' + '*.cpp')
# grid backend
source += Split(
"""
grid/grid.cpp
grid/grid_renderer.cpp
grid/process_building_symbolizer.cpp
grid/process_line_pattern_symbolizer.cpp
grid/process_line_symbolizer.cpp
grid/process_markers_symbolizer.cpp
grid/process_point_symbolizer.cpp
grid/process_polygon_pattern_symbolizer.cpp
grid/process_polygon_symbolizer.cpp
grid/process_raster_symbolizer.cpp
grid/process_shield_symbolizer.cpp
grid/process_text_symbolizer.cpp
""")
if env['GRID_RENDERER']: # svg backend
source += Split(
"""
grid/grid.cpp
grid/grid_renderer.cpp
grid/process_building_symbolizer.cpp
grid/process_line_pattern_symbolizer.cpp
grid/process_line_symbolizer.cpp
grid/process_markers_symbolizer.cpp
grid/process_point_symbolizer.cpp
grid/process_polygon_pattern_symbolizer.cpp
grid/process_polygon_symbolizer.cpp
grid/process_raster_symbolizer.cpp
grid/process_shield_symbolizer.cpp
grid/process_text_symbolizer.cpp
""")
lib_env.Append(CPPDEFINES = '-DGRID_RENDERER')
libmapnik_defines.append('-DGRID_RENDERER')
# https://github.com/mapnik/mapnik/issues/1438
if env['SVG_RENDERER']: # svg backend

View file

@ -24,8 +24,11 @@
#include <mapnik/feature_style_processor_impl.hpp>
#include <mapnik/agg_renderer.hpp>
#include <mapnik/graphics.hpp>
#if defined(GRID_RENDERER)
#include <mapnik/grid/grid_renderer.hpp>
#include <mapnik/grid/grid.hpp>
#endif
#if defined(HAVE_CAIRO)
#include <cairo.h>
@ -48,7 +51,10 @@ template class feature_style_processor<cairo_renderer<cairo_surface_ptr> >;
template class feature_style_processor<svg_renderer<std::ostream_iterator<char> > >;
#endif
#if defined(GRID_RENDERER)
template class feature_style_processor<grid_renderer<grid> >;
#endif
template class feature_style_processor<agg_renderer<image_32> >;
}

View file

@ -25,7 +25,11 @@
#include <mapnik/font_engine_freetype.hpp>
#include <mapnik/text_properties.hpp>
#include <mapnik/graphics.hpp>
#if defined(GRID_RENDERER)
#include <mapnik/grid/grid.hpp>
#endif
#include <mapnik/text_path.hpp>
#include <mapnik/pixel_position.hpp>
#include <mapnik/font_util.hpp>
@ -686,6 +690,7 @@ void text_renderer<T>::render(pixel_position const& pos)
}
}
#if defined(GRID_RENDERER)
template <typename T>
void text_renderer<T>::render_id(mapnik::value_integer feature_id,
pixel_position const& pos)
@ -715,6 +720,7 @@ void text_renderer<T>::render_id(mapnik::value_integer feature_id,
}
}
}
#endif
#ifdef MAPNIK_THREADSAFE
boost::mutex freetype_engine::mutex_;
@ -729,6 +735,7 @@ template text_renderer<image_32>::text_renderer(image_32&,
double);
template box2d<double>text_renderer<image_32>::prepare_glyphs(text_path const&);
template void text_renderer<image_32>::render(pixel_position const&);
#if defined(GRID_RENDERER)
template void text_renderer<grid>::render_id(mapnik::value_integer,
pixel_position const&);
template text_renderer<grid>::text_renderer(grid&,
@ -736,4 +743,5 @@ template text_renderer<grid>::text_renderer(grid&,
halo_rasterizer_e,
composite_mode_e, double);
template box2d<double>text_renderer<grid>::prepare_glyphs(text_path const& );
#endif
}

View file

@ -45,18 +45,18 @@ def make_map():
m.zoom_all()
return m
def test_clearing_grid_data():
g = mapnik.Grid(256,256)
utf = g.encode()
# make sure it equals itself
eq_(g.encode(),utf)
m = make_map()
mapnik.render_layer(m,g,layer=0,fields=['__id__','Name'])
eq_(g.encode()!=utf,True)
# clear grid, should now match original
g.clear()
eq_(g.encode(),utf)
if mapnik.has_grid_renderer():
def test_clearing_grid_data():
g = mapnik.Grid(256,256)
utf = g.encode()
# make sure it equals itself
eq_(g.encode(),utf)
m = make_map()
mapnik.render_layer(m,g,layer=0,fields=['__id__','Name'])
eq_(g.encode()!=utf,True)
# clear grid, should now match original
g.clear()
eq_(g.encode(),utf)
if __name__ == "__main__":
setup()

View file

@ -15,370 +15,371 @@ def setup():
# from another directory we need to chdir()
os.chdir(execution_path('.'))
def show_grids(name,g1,g2):
g1_file = '/tmp/mapnik-%s-actual.json' % name
open(g1_file,'w').write(json.dumps(g1,sort_keys=True))
g2_file = '/tmp/mapnik-%s-expected.json' % name
open(g2_file,'w').write(json.dumps(g2,sort_keys=True))
val = 'JSON does not match ->\n'
if g1['grid'] != g2['grid']:
val += ' X grid does not match\n'
else:
val += ' ✓ grid matches\n'
if g1['data'].keys() != g2['data'].keys():
val += ' X data does not match\n'
else:
val += ' ✓ data matches\n'
if g1['keys'] != g2['keys']:
val += ' X keys do not\n'
else:
val += ' ✓ keys match\n'
val += '\n\t%s\n\t%s' % (g1_file,g2_file)
return val
def show_grids2(name,g1,g2):
g2_expected = '../data/grids/mapnik-%s-actual.json' % name
if not os.path.exists(g2_expected):
# create test fixture based on actual results
open(g2_expected,'a+').write(json.dumps(g1,sort_keys=True))
return
g1_file = '/tmp/mapnik-%s-actual.json' % name
open(g1_file,'w').write(json.dumps(g1,sort_keys=True))
val = 'JSON does not match ->\n'
if g1['grid'] != g2['grid']:
val += ' X grid does not match\n'
else:
val += ' ✓ grid matches\n'
if g1['data'].keys() != g2['data'].keys():
val += ' X data does not match\n'
else:
val += ' ✓ data matches\n'
if g1['keys'] != g2['keys']:
val += ' X keys do not\n'
else:
val += ' ✓ keys match\n'
val += '\n\t%s\n\t%s' % (g1_file,g2_expected)
return val
# first pass impl where resolution is passed as render
# time rather than encoding time, likely will be deprecated soon
grid_correct_old = {"keys": ["", "North West", "North East", "South West", "South East"], "data": {"South East": {"Name": "South East"}, "North East": {"Name": "North East"}, "North West": {"Name": "North West"}, "South West": {"Name": "South West"}}, "grid": [" ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " !!! ### ", " !!!!! ##### ", " !!!!! ##### ", " !!! ### ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " $$$$ %%%% ", " $$$$$ %%%%% ", " $$$$$ %%%%% ", " $$$ %%% ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " "]}
# now using svg rendering
grid_correct_old2 = {"data": {"North East": {"Name": "North East"}, "North West": {"Name": "North West"}, "South East": {"Name": "South East"}, "South West": {"Name": "South West"}}, "grid": [" ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " !!! ### ", " !!! ### ", " !!! ### ", " !!! ### ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " $$$ %%% ", " $$$ %%% ", " $$$ %%% ", " $$$ %%% ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " "], "keys": ["", "North West", "North East", "South West", "South East"]}
grid_correct_old3 = {"data": {"North East": {"Name": "North East"}, "North West": {"Name": "North West"}, "South East": {"Name": "South East"}, "South West": {"Name": "South West"}}, "grid": [" ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " !!! ### ", " !!! ### ", " !!! ### ", " !!! ### ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " $$$ %%% ", " $$$ %%% ", " $$$ %%% ", " $$ %% ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " "], "keys": ["", "North West", "North East", "South West", "South East"]}
# previous rendering using agg ellipse directly
grid_correct_new = {"data": {"North East": {"Name": "North East"}, "North West": {"Name": "North West"}, "South East": {"Name": "South East"}, "South West": {"Name": "South West"}}, "grid": [" ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " !! ## ", " !!! ### ", " !! ## ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " $$ %% ", " $$$ %% ", " $$ %% ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " "], "keys": ["", "North West", "North East", "South West", "South East"]}
# newer rendering using svg
grid_correct_new2 = {"data": {"North East": {"Name": "North East"}, "North West": {"Name": "North West"}, "South East": {"Name": "South East"}, "South West": {"Name": "South West"}}, "grid": [" ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " !! ## ", " !!! ### ", " !! ## ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " $$ %% ", " $$$ %% ", " $$ %% ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " "], "keys": ["", "North West", "North East", "South West", "South East"]}
grid_correct_new3 = {"data": {"North East": {"Name": "North East"}, "North West": {"Name": "North West"}, "South East": {"Name": "South East"}, "South West": {"Name": "South West"}}, "grid": [" ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " !! ## ", " !!! ### ", " !! ## ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " $$ %% ", " $$$ %% ", " $ %% ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " "], "keys": ["", "North West", "North East", "South West", "South East"]}
def resolve(grid,row,col):
""" Resolve the attributes for a given pixel in a grid.
"""
row = grid['grid'][row]
utf_val = row[col]
#http://docs.python.org/library/functions.html#ord
codepoint = ord(utf_val)
if (codepoint >= 93):
codepoint-=1
if (codepoint >= 35):
codepoint-=1
codepoint -= 32
key = grid['keys'][codepoint]
return grid['data'].get(key)
def create_grid_map(width,height,sym):
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()
sym.allow_overlap = True
r.symbols.append(sym)
s.rules.append(r)
lyr = mapnik.Layer('Places')
lyr.datasource = ds
lyr.styles.append('places_labels')
m = mapnik.Map(width,height)
m.append_style('places_labels',s)
m.layers.append(lyr)
return m
def test_render_grid_old():
""" test old method """
width,height = 256,256
symb = mapnik.PointSymbolizer(mapnik.PathExpression('../data/images/dummy.png'))
sym = mapnik.MarkersSymbolizer()
sym.width = mapnik.Expression('10')
sym.height = mapnik.Expression('10')
m = create_grid_map(width,height,sym)
#print mapnik.save_map_to_string(m)
ul_lonlat = mapnik.Coord(142.30,-38.20)
lr_lonlat = mapnik.Coord(143.40,-38.80)
m.zoom_to_box(mapnik.Box2d(ul_lonlat,lr_lonlat))
grid = mapnik.render_grid(m,0,key='Name',resolution=4,fields=['Name'])
eq_(grid,grid_correct_old3,show_grids('old-markers',grid,grid_correct_old3))
eq_(resolve(grid,0,0),None)
# check every pixel of the nw symbol
expected = {"Name": "North West"}
# top row
eq_(resolve(grid,23,9),expected)
eq_(resolve(grid,23,10),expected)
eq_(resolve(grid,23,11),expected)
def test_render_grid_new():
""" test old against new"""
width,height = 256,256
sym = mapnik.MarkersSymbolizer()
sym.width = mapnik.Expression('10')
sym.height = mapnik.Expression('10')
m = create_grid_map(width,height,sym)
ul_lonlat = mapnik.Coord(142.30,-38.20)
lr_lonlat = mapnik.Coord(143.40,-38.80)
m.zoom_to_box(mapnik.Box2d(ul_lonlat,lr_lonlat))
# new method
grid = mapnik.Grid(m.width,m.height,key='Name')
mapnik.render_layer(m,grid,layer=0,fields=['Name'])
utf1 = grid.encode('utf',resolution=4)
eq_(utf1,grid_correct_new3,show_grids('new-markers',utf1,grid_correct_new3))
# check a full view is the same as a full image
grid_view = grid.view(0,0,width,height)
# for kicks check at full res too
utf3 = grid.encode('utf',resolution=1)
utf4 = grid_view.encode('utf',resolution=1)
eq_(utf3['grid'],utf4['grid'])
eq_(utf3['keys'],utf4['keys'])
eq_(utf3['data'],utf4['data'])
eq_(resolve(utf4,0,0),None)
# resolve some center points in the
# resampled view
utf5 = grid_view.encode('utf',resolution=4)
eq_(resolve(utf5,25,10),{"Name": "North West"})
eq_(resolve(utf5,25,46),{"Name": "North East"})
eq_(resolve(utf5,38,10),{"Name": "South West"})
eq_(resolve(utf5,38,46),{"Name": "South East"})
grid_feat_id = {'keys': ['', '3', '4', '2', '1'], 'data': {'1': {'Name': 'South East'}, '3': {'Name': u'North West'}, '2': {'Name': 'South West'}, '4': {'Name': 'North East'}}, 'grid': [' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' !! ## ', ' !!! ### ', ' !! ## ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' $$$ %% ', ' $$$ %%% ', ' $$ %% ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ']}
grid_feat_id2 = {"data": {"1": {"Name": "South East"}, "2": {"Name": "South West"}, "3": {"Name": "North West"}, "4": {"Name": "North East"}}, "grid": [" ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " !! ## ", " !!! ### ", " !! ## ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " $$ %% ", " $$$ %% ", " $$ %% ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " "], "keys": ["", "3", "4", "2", "1"]}
grid_feat_id3 = {"data": {"1": {"Name": "South East", "__id__": 1}, "2": {"Name": "South West", "__id__": 2}, "3": {"Name": "North West", "__id__": 3}, "4": {"Name": "North East", "__id__": 4}}, "grid": [" ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " !! ## ", " !!! ### ", " !! ## ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " $$ %% ", " $$$ %% ", " $ %% ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " "], "keys": ["", "3", "4", "2", "1"]}
def test_render_grid3():
""" test using feature id"""
width,height = 256,256
sym = mapnik.MarkersSymbolizer()
sym.width = mapnik.Expression('10')
sym.height = mapnik.Expression('10')
m = create_grid_map(width,height,sym)
ul_lonlat = mapnik.Coord(142.30,-38.20)
lr_lonlat = mapnik.Coord(143.40,-38.80)
m.zoom_to_box(mapnik.Box2d(ul_lonlat,lr_lonlat))
grid = mapnik.Grid(m.width,m.height,key='__id__')
mapnik.render_layer(m,grid,layer=0,fields=['__id__','Name'])
utf1 = grid.encode('utf',resolution=4)
eq_(utf1,grid_feat_id3,show_grids('id-markers',utf1,grid_feat_id3))
# check a full view is the same as a full image
grid_view = grid.view(0,0,width,height)
# for kicks check at full res too
utf3 = grid.encode('utf',resolution=1)
utf4 = grid_view.encode('utf',resolution=1)
eq_(utf3['grid'],utf4['grid'])
eq_(utf3['keys'],utf4['keys'])
eq_(utf3['data'],utf4['data'])
eq_(resolve(utf4,0,0),None)
# resolve some center points in the
# resampled view
utf5 = grid_view.encode('utf',resolution=4)
eq_(resolve(utf5,25,10),{"Name": "North West","__id__": 3})
eq_(resolve(utf5,25,46),{"Name": "North East","__id__": 4})
eq_(resolve(utf5,38,10),{"Name": "South West","__id__": 2})
eq_(resolve(utf5,38,46),{"Name": "South East","__id__": 1})
def gen_grid_for_id(pixel_key):
ds = mapnik.MemoryDatasource()
context = mapnik.Context()
context.push('Name')
f = mapnik.Feature(context,pixel_key)
f['Name'] = str(pixel_key)
f.add_geometries_from_wkt('POLYGON ((0 0, 0 256, 256 256, 256 0, 0 0))')
ds.add_feature(f)
s = mapnik.Style()
r = mapnik.Rule()
symb = mapnik.PolygonSymbolizer()
r.symbols.append(symb)
s.rules.append(r)
lyr = mapnik.Layer('Places')
lyr.datasource = ds
lyr.styles.append('places_labels')
width,height = 256,256
m = mapnik.Map(width,height)
m.append_style('places_labels',s)
m.layers.append(lyr)
m.zoom_all()
grid = mapnik.Grid(m.width,m.height,key='__id__')
mapnik.render_layer(m,grid,layer=0,fields=['__id__','Name'])
return grid
def test_negative_id():
grid = gen_grid_for_id(-1)
eq_(grid.get_pixel(128,128),-1)
utf1 = grid.encode('utf',resolution=4)
eq_(utf1['keys'],['-1'])
def test_32bit_int_id():
int32 = 2147483647
grid = gen_grid_for_id(int32)
eq_(grid.get_pixel(128,128),int32)
utf1 = grid.encode('utf',resolution=4)
eq_(utf1['keys'],[str(int32)])
max_neg = -(int32)
grid = gen_grid_for_id(max_neg)
eq_(grid.get_pixel(128,128),max_neg)
utf1 = grid.encode('utf',resolution=4)
eq_(utf1['keys'],[str(max_neg)])
def test_64bit_int_id():
int64 = 0x7FFFFFFFFFFFFFFF
grid = gen_grid_for_id(int64)
eq_(grid.get_pixel(128,128),int64)
utf1 = grid.encode('utf',resolution=4)
eq_(utf1['keys'],[str(int64)])
max_neg = -(int64)
grid = gen_grid_for_id(max_neg)
eq_(grid.get_pixel(128,128),max_neg)
utf1 = grid.encode('utf',resolution=4)
eq_(utf1['keys'],[str(max_neg)])
def test_id_zero():
grid = gen_grid_for_id(0)
eq_(grid.get_pixel(128,128),0)
utf1 = grid.encode('utf',resolution=4)
eq_(utf1['keys'],['0'])
line_expected = {"keys": ["", "1"], "data": {"1": {"Name": "1"}}, "grid": [" !", " !! ", " !! ", " !! ", " !! ", " !! ", " !! ", " !! ", " !! ", " !! ", " !! ", " !! ", " !! ", " !! ", " !! ", " !! ", " !! ", " !! ", " !! ", " !! ", " !! ", "!! ", " ! ", " ! ", " ! ", " ! ", " ! ", " ! ", " ! ", " ! ", " ! ", " ! ", " ! ", " ! ", " ! ", " ! ", " ! ", " ! ", " ! ", " ! ", " ! ", " ! ", " ! ", " ! ", " ! ", " ! ", " ! ", " ! ", " ! ", " ! ", " ! ", " ! ", " ! ", " ! ", " ! ", " ! ", " ! ", " ! ", " ! ", " ! ", " ! ", " ! ", " ! ", " ! "]}
def test_line_rendering():
ds = mapnik.MemoryDatasource()
context = mapnik.Context()
context.push('Name')
pixel_key = 1
f = mapnik.Feature(context,pixel_key)
f['Name'] = str(pixel_key)
f.add_geometries_from_wkt('LINESTRING (30 10, 10 30, 40 40)')
ds.add_feature(f)
s = mapnik.Style()
r = mapnik.Rule()
symb = mapnik.LineSymbolizer()
r.symbols.append(symb)
s.rules.append(r)
lyr = mapnik.Layer('Places')
lyr.datasource = ds
lyr.styles.append('places_labels')
width,height = 256,256
m = mapnik.Map(width,height)
m.append_style('places_labels',s)
m.layers.append(lyr)
m.zoom_all()
#mapnik.render_to_file(m,'test.png')
grid = mapnik.Grid(m.width,m.height,key='__id__')
mapnik.render_layer(m,grid,layer=0,fields=['Name'])
utf1 = grid.encode()
eq_(utf1,line_expected,show_grids('line',utf1,line_expected))
point_expected = {"data": {"1": {"Name": "South East"}, "2": {"Name": "South West"}, "3": {"Name": "North West"}, "4": {"Name": "North East"}}, "grid": [" ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " !!!! #### ", " !!!! #### ", " !!!! #### ", " !!!! #### ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " $$$$ %%%% ", " $$$$ %%%% ", " $$$$ %%%% ", " $$$$ %%%% ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " "], "keys": ["", "3", "4", "2", "1"]}
def test_point_symbolizer_grid():
width,height = 256,256
sym = mapnik.PointSymbolizer(mapnik.PathExpression('../data/images/dummy.png'))
m = create_grid_map(width,height,sym)
ul_lonlat = mapnik.Coord(142.30,-38.20)
lr_lonlat = mapnik.Coord(143.40,-38.80)
m.zoom_to_box(mapnik.Box2d(ul_lonlat,lr_lonlat))
grid = mapnik.Grid(m.width,m.height)
mapnik.render_layer(m,grid,layer=0,fields=['Name'])
utf1 = grid.encode()
eq_(utf1,point_expected,show_grids('point-sym',utf1,point_expected))
# should throw because this is a mis-usage
# https://github.com/mapnik/mapnik/issues/1325
@raises(RuntimeError)
def test_render_to_grid_multiple_times():
# create map with two layers
m = mapnik.Map(256,256)
s = mapnik.Style()
r = mapnik.Rule()
sym = mapnik.MarkersSymbolizer()
sym.allow_overlap = True
r.symbols.append(sym)
s.rules.append(r)
m.append_style('points',s)
# NOTE: we use a csv datasource here
# because the memorydatasource fails silently for
# queries requesting fields that do not exist in the datasource
ds1 = mapnik.Datasource(**{"type":"csv","inline":'''
wkt,Name
"POINT (143.10 -38.60)",South East'''})
lyr1 = mapnik.Layer('One')
lyr1.datasource = ds1
lyr1.styles.append('points')
m.layers.append(lyr1)
ds2 = mapnik.Datasource(**{"type":"csv","inline":'''
wkt,Value
"POINT (142.48 -38.60)",South West'''})
lyr2 = mapnik.Layer('Two')
lyr2.datasource = ds2
lyr2.styles.append('points')
m.layers.append(lyr2)
ul_lonlat = mapnik.Coord(142.30,-38.20)
lr_lonlat = mapnik.Coord(143.40,-38.80)
m.zoom_to_box(mapnik.Box2d(ul_lonlat,lr_lonlat))
grid = mapnik.Grid(m.width,m.height)
mapnik.render_layer(m,grid,layer=0,fields=['Name'])
# should throw right here since Name will be a property now on the `grid` object
# and it is not found on the second layer
mapnik.render_layer(m,grid,layer=1,fields=['Value'])
utf1 = grid.encode()
if mapnik.has_grid_renderer():
def show_grids(name,g1,g2):
g1_file = '/tmp/mapnik-%s-actual.json' % name
open(g1_file,'w').write(json.dumps(g1,sort_keys=True))
g2_file = '/tmp/mapnik-%s-expected.json' % name
open(g2_file,'w').write(json.dumps(g2,sort_keys=True))
val = 'JSON does not match ->\n'
if g1['grid'] != g2['grid']:
val += ' X grid does not match\n'
else:
val += ' ✓ grid matches\n'
if g1['data'].keys() != g2['data'].keys():
val += ' X data does not match\n'
else:
val += ' ✓ data matches\n'
if g1['keys'] != g2['keys']:
val += ' X keys do not\n'
else:
val += ' ✓ keys match\n'
val += '\n\t%s\n\t%s' % (g1_file,g2_file)
return val
def show_grids2(name,g1,g2):
g2_expected = '../data/grids/mapnik-%s-actual.json' % name
if not os.path.exists(g2_expected):
# create test fixture based on actual results
open(g2_expected,'a+').write(json.dumps(g1,sort_keys=True))
return
g1_file = '/tmp/mapnik-%s-actual.json' % name
open(g1_file,'w').write(json.dumps(g1,sort_keys=True))
val = 'JSON does not match ->\n'
if g1['grid'] != g2['grid']:
val += ' X grid does not match\n'
else:
val += ' ✓ grid matches\n'
if g1['data'].keys() != g2['data'].keys():
val += ' X data does not match\n'
else:
val += ' ✓ data matches\n'
if g1['keys'] != g2['keys']:
val += ' X keys do not\n'
else:
val += ' ✓ keys match\n'
val += '\n\t%s\n\t%s' % (g1_file,g2_expected)
return val
# first pass impl where resolution is passed as render
# time rather than encoding time, likely will be deprecated soon
grid_correct_old = {"keys": ["", "North West", "North East", "South West", "South East"], "data": {"South East": {"Name": "South East"}, "North East": {"Name": "North East"}, "North West": {"Name": "North West"}, "South West": {"Name": "South West"}}, "grid": [" ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " !!! ### ", " !!!!! ##### ", " !!!!! ##### ", " !!! ### ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " $$$$ %%%% ", " $$$$$ %%%%% ", " $$$$$ %%%%% ", " $$$ %%% ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " "]}
# now using svg rendering
grid_correct_old2 = {"data": {"North East": {"Name": "North East"}, "North West": {"Name": "North West"}, "South East": {"Name": "South East"}, "South West": {"Name": "South West"}}, "grid": [" ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " !!! ### ", " !!! ### ", " !!! ### ", " !!! ### ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " $$$ %%% ", " $$$ %%% ", " $$$ %%% ", " $$$ %%% ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " "], "keys": ["", "North West", "North East", "South West", "South East"]}
grid_correct_old3 = {"data": {"North East": {"Name": "North East"}, "North West": {"Name": "North West"}, "South East": {"Name": "South East"}, "South West": {"Name": "South West"}}, "grid": [" ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " !!! ### ", " !!! ### ", " !!! ### ", " !!! ### ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " $$$ %%% ", " $$$ %%% ", " $$$ %%% ", " $$ %% ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " "], "keys": ["", "North West", "North East", "South West", "South East"]}
# previous rendering using agg ellipse directly
grid_correct_new = {"data": {"North East": {"Name": "North East"}, "North West": {"Name": "North West"}, "South East": {"Name": "South East"}, "South West": {"Name": "South West"}}, "grid": [" ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " !! ## ", " !!! ### ", " !! ## ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " $$ %% ", " $$$ %% ", " $$ %% ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " "], "keys": ["", "North West", "North East", "South West", "South East"]}
# newer rendering using svg
grid_correct_new2 = {"data": {"North East": {"Name": "North East"}, "North West": {"Name": "North West"}, "South East": {"Name": "South East"}, "South West": {"Name": "South West"}}, "grid": [" ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " !! ## ", " !!! ### ", " !! ## ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " $$ %% ", " $$$ %% ", " $$ %% ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " "], "keys": ["", "North West", "North East", "South West", "South East"]}
grid_correct_new3 = {"data": {"North East": {"Name": "North East"}, "North West": {"Name": "North West"}, "South East": {"Name": "South East"}, "South West": {"Name": "South West"}}, "grid": [" ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " !! ## ", " !!! ### ", " !! ## ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " $$ %% ", " $$$ %% ", " $ %% ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " "], "keys": ["", "North West", "North East", "South West", "South East"]}
def resolve(grid,row,col):
""" Resolve the attributes for a given pixel in a grid.
"""
row = grid['grid'][row]
utf_val = row[col]
#http://docs.python.org/library/functions.html#ord
codepoint = ord(utf_val)
if (codepoint >= 93):
codepoint-=1
if (codepoint >= 35):
codepoint-=1
codepoint -= 32
key = grid['keys'][codepoint]
return grid['data'].get(key)
def create_grid_map(width,height,sym):
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()
sym.allow_overlap = True
r.symbols.append(sym)
s.rules.append(r)
lyr = mapnik.Layer('Places')
lyr.datasource = ds
lyr.styles.append('places_labels')
m = mapnik.Map(width,height)
m.append_style('places_labels',s)
m.layers.append(lyr)
return m
def test_render_grid_old():
""" test old method """
width,height = 256,256
symb = mapnik.PointSymbolizer(mapnik.PathExpression('../data/images/dummy.png'))
sym = mapnik.MarkersSymbolizer()
sym.width = mapnik.Expression('10')
sym.height = mapnik.Expression('10')
m = create_grid_map(width,height,sym)
#print mapnik.save_map_to_string(m)
ul_lonlat = mapnik.Coord(142.30,-38.20)
lr_lonlat = mapnik.Coord(143.40,-38.80)
m.zoom_to_box(mapnik.Box2d(ul_lonlat,lr_lonlat))
grid = mapnik.render_grid(m,0,key='Name',resolution=4,fields=['Name'])
eq_(grid,grid_correct_old3,show_grids('old-markers',grid,grid_correct_old3))
eq_(resolve(grid,0,0),None)
# check every pixel of the nw symbol
expected = {"Name": "North West"}
# top row
eq_(resolve(grid,23,9),expected)
eq_(resolve(grid,23,10),expected)
eq_(resolve(grid,23,11),expected)
def test_render_grid_new():
""" test old against new"""
width,height = 256,256
sym = mapnik.MarkersSymbolizer()
sym.width = mapnik.Expression('10')
sym.height = mapnik.Expression('10')
m = create_grid_map(width,height,sym)
ul_lonlat = mapnik.Coord(142.30,-38.20)
lr_lonlat = mapnik.Coord(143.40,-38.80)
m.zoom_to_box(mapnik.Box2d(ul_lonlat,lr_lonlat))
# new method
grid = mapnik.Grid(m.width,m.height,key='Name')
mapnik.render_layer(m,grid,layer=0,fields=['Name'])
utf1 = grid.encode('utf',resolution=4)
eq_(utf1,grid_correct_new3,show_grids('new-markers',utf1,grid_correct_new3))
# check a full view is the same as a full image
grid_view = grid.view(0,0,width,height)
# for kicks check at full res too
utf3 = grid.encode('utf',resolution=1)
utf4 = grid_view.encode('utf',resolution=1)
eq_(utf3['grid'],utf4['grid'])
eq_(utf3['keys'],utf4['keys'])
eq_(utf3['data'],utf4['data'])
eq_(resolve(utf4,0,0),None)
# resolve some center points in the
# resampled view
utf5 = grid_view.encode('utf',resolution=4)
eq_(resolve(utf5,25,10),{"Name": "North West"})
eq_(resolve(utf5,25,46),{"Name": "North East"})
eq_(resolve(utf5,38,10),{"Name": "South West"})
eq_(resolve(utf5,38,46),{"Name": "South East"})
grid_feat_id = {'keys': ['', '3', '4', '2', '1'], 'data': {'1': {'Name': 'South East'}, '3': {'Name': u'North West'}, '2': {'Name': 'South West'}, '4': {'Name': 'North East'}}, 'grid': [' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' !! ## ', ' !!! ### ', ' !! ## ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' $$$ %% ', ' $$$ %%% ', ' $$ %% ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ']}
grid_feat_id2 = {"data": {"1": {"Name": "South East"}, "2": {"Name": "South West"}, "3": {"Name": "North West"}, "4": {"Name": "North East"}}, "grid": [" ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " !! ## ", " !!! ### ", " !! ## ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " $$ %% ", " $$$ %% ", " $$ %% ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " "], "keys": ["", "3", "4", "2", "1"]}
grid_feat_id3 = {"data": {"1": {"Name": "South East", "__id__": 1}, "2": {"Name": "South West", "__id__": 2}, "3": {"Name": "North West", "__id__": 3}, "4": {"Name": "North East", "__id__": 4}}, "grid": [" ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " !! ## ", " !!! ### ", " !! ## ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " $$ %% ", " $$$ %% ", " $ %% ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " "], "keys": ["", "3", "4", "2", "1"]}
def test_render_grid3():
""" test using feature id"""
width,height = 256,256
sym = mapnik.MarkersSymbolizer()
sym.width = mapnik.Expression('10')
sym.height = mapnik.Expression('10')
m = create_grid_map(width,height,sym)
ul_lonlat = mapnik.Coord(142.30,-38.20)
lr_lonlat = mapnik.Coord(143.40,-38.80)
m.zoom_to_box(mapnik.Box2d(ul_lonlat,lr_lonlat))
grid = mapnik.Grid(m.width,m.height,key='__id__')
mapnik.render_layer(m,grid,layer=0,fields=['__id__','Name'])
utf1 = grid.encode('utf',resolution=4)
eq_(utf1,grid_feat_id3,show_grids('id-markers',utf1,grid_feat_id3))
# check a full view is the same as a full image
grid_view = grid.view(0,0,width,height)
# for kicks check at full res too
utf3 = grid.encode('utf',resolution=1)
utf4 = grid_view.encode('utf',resolution=1)
eq_(utf3['grid'],utf4['grid'])
eq_(utf3['keys'],utf4['keys'])
eq_(utf3['data'],utf4['data'])
eq_(resolve(utf4,0,0),None)
# resolve some center points in the
# resampled view
utf5 = grid_view.encode('utf',resolution=4)
eq_(resolve(utf5,25,10),{"Name": "North West","__id__": 3})
eq_(resolve(utf5,25,46),{"Name": "North East","__id__": 4})
eq_(resolve(utf5,38,10),{"Name": "South West","__id__": 2})
eq_(resolve(utf5,38,46),{"Name": "South East","__id__": 1})
def gen_grid_for_id(pixel_key):
ds = mapnik.MemoryDatasource()
context = mapnik.Context()
context.push('Name')
f = mapnik.Feature(context,pixel_key)
f['Name'] = str(pixel_key)
f.add_geometries_from_wkt('POLYGON ((0 0, 0 256, 256 256, 256 0, 0 0))')
ds.add_feature(f)
s = mapnik.Style()
r = mapnik.Rule()
symb = mapnik.PolygonSymbolizer()
r.symbols.append(symb)
s.rules.append(r)
lyr = mapnik.Layer('Places')
lyr.datasource = ds
lyr.styles.append('places_labels')
width,height = 256,256
m = mapnik.Map(width,height)
m.append_style('places_labels',s)
m.layers.append(lyr)
m.zoom_all()
grid = mapnik.Grid(m.width,m.height,key='__id__')
mapnik.render_layer(m,grid,layer=0,fields=['__id__','Name'])
return grid
def test_negative_id():
grid = gen_grid_for_id(-1)
eq_(grid.get_pixel(128,128),-1)
utf1 = grid.encode('utf',resolution=4)
eq_(utf1['keys'],['-1'])
def test_32bit_int_id():
int32 = 2147483647
grid = gen_grid_for_id(int32)
eq_(grid.get_pixel(128,128),int32)
utf1 = grid.encode('utf',resolution=4)
eq_(utf1['keys'],[str(int32)])
max_neg = -(int32)
grid = gen_grid_for_id(max_neg)
eq_(grid.get_pixel(128,128),max_neg)
utf1 = grid.encode('utf',resolution=4)
eq_(utf1['keys'],[str(max_neg)])
def test_64bit_int_id():
int64 = 0x7FFFFFFFFFFFFFFF
grid = gen_grid_for_id(int64)
eq_(grid.get_pixel(128,128),int64)
utf1 = grid.encode('utf',resolution=4)
eq_(utf1['keys'],[str(int64)])
max_neg = -(int64)
grid = gen_grid_for_id(max_neg)
eq_(grid.get_pixel(128,128),max_neg)
utf1 = grid.encode('utf',resolution=4)
eq_(utf1['keys'],[str(max_neg)])
def test_id_zero():
grid = gen_grid_for_id(0)
eq_(grid.get_pixel(128,128),0)
utf1 = grid.encode('utf',resolution=4)
eq_(utf1['keys'],['0'])
line_expected = {"keys": ["", "1"], "data": {"1": {"Name": "1"}}, "grid": [" !", " !! ", " !! ", " !! ", " !! ", " !! ", " !! ", " !! ", " !! ", " !! ", " !! ", " !! ", " !! ", " !! ", " !! ", " !! ", " !! ", " !! ", " !! ", " !! ", " !! ", "!! ", " ! ", " ! ", " ! ", " ! ", " ! ", " ! ", " ! ", " ! ", " ! ", " ! ", " ! ", " ! ", " ! ", " ! ", " ! ", " ! ", " ! ", " ! ", " ! ", " ! ", " ! ", " ! ", " ! ", " ! ", " ! ", " ! ", " ! ", " ! ", " ! ", " ! ", " ! ", " ! ", " ! ", " ! ", " ! ", " ! ", " ! ", " ! ", " ! ", " ! ", " ! ", " ! "]}
def test_line_rendering():
ds = mapnik.MemoryDatasource()
context = mapnik.Context()
context.push('Name')
pixel_key = 1
f = mapnik.Feature(context,pixel_key)
f['Name'] = str(pixel_key)
f.add_geometries_from_wkt('LINESTRING (30 10, 10 30, 40 40)')
ds.add_feature(f)
s = mapnik.Style()
r = mapnik.Rule()
symb = mapnik.LineSymbolizer()
r.symbols.append(symb)
s.rules.append(r)
lyr = mapnik.Layer('Places')
lyr.datasource = ds
lyr.styles.append('places_labels')
width,height = 256,256
m = mapnik.Map(width,height)
m.append_style('places_labels',s)
m.layers.append(lyr)
m.zoom_all()
#mapnik.render_to_file(m,'test.png')
grid = mapnik.Grid(m.width,m.height,key='__id__')
mapnik.render_layer(m,grid,layer=0,fields=['Name'])
utf1 = grid.encode()
eq_(utf1,line_expected,show_grids('line',utf1,line_expected))
point_expected = {"data": {"1": {"Name": "South East"}, "2": {"Name": "South West"}, "3": {"Name": "North West"}, "4": {"Name": "North East"}}, "grid": [" ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " !!!! #### ", " !!!! #### ", " !!!! #### ", " !!!! #### ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " $$$$ %%%% ", " $$$$ %%%% ", " $$$$ %%%% ", " $$$$ %%%% ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " "], "keys": ["", "3", "4", "2", "1"]}
def test_point_symbolizer_grid():
width,height = 256,256
sym = mapnik.PointSymbolizer(mapnik.PathExpression('../data/images/dummy.png'))
m = create_grid_map(width,height,sym)
ul_lonlat = mapnik.Coord(142.30,-38.20)
lr_lonlat = mapnik.Coord(143.40,-38.80)
m.zoom_to_box(mapnik.Box2d(ul_lonlat,lr_lonlat))
grid = mapnik.Grid(m.width,m.height)
mapnik.render_layer(m,grid,layer=0,fields=['Name'])
utf1 = grid.encode()
eq_(utf1,point_expected,show_grids('point-sym',utf1,point_expected))
# should throw because this is a mis-usage
# https://github.com/mapnik/mapnik/issues/1325
@raises(RuntimeError)
def test_render_to_grid_multiple_times():
# create map with two layers
m = mapnik.Map(256,256)
s = mapnik.Style()
r = mapnik.Rule()
sym = mapnik.MarkersSymbolizer()
sym.allow_overlap = True
r.symbols.append(sym)
s.rules.append(r)
m.append_style('points',s)
# NOTE: we use a csv datasource here
# because the memorydatasource fails silently for
# queries requesting fields that do not exist in the datasource
ds1 = mapnik.Datasource(**{"type":"csv","inline":'''
wkt,Name
"POINT (143.10 -38.60)",South East'''})
lyr1 = mapnik.Layer('One')
lyr1.datasource = ds1
lyr1.styles.append('points')
m.layers.append(lyr1)
ds2 = mapnik.Datasource(**{"type":"csv","inline":'''
wkt,Value
"POINT (142.48 -38.60)",South West'''})
lyr2 = mapnik.Layer('Two')
lyr2.datasource = ds2
lyr2.styles.append('points')
m.layers.append(lyr2)
ul_lonlat = mapnik.Coord(142.30,-38.20)
lr_lonlat = mapnik.Coord(143.40,-38.80)
m.zoom_to_box(mapnik.Box2d(ul_lonlat,lr_lonlat))
grid = mapnik.Grid(m.width,m.height)
mapnik.render_layer(m,grid,layer=0,fields=['Name'])
# should throw right here since Name will be a property now on the `grid` object
# and it is not found on the second layer
mapnik.render_layer(m,grid,layer=1,fields=['Value'])
utf1 = grid.encode()
if __name__ == "__main__":
setup()

View file

@ -21,7 +21,7 @@ defaults = {
'scales':[1.0,2.0],
'agg': True,
'cairo': mapnik.has_cairo(),
'grid': True
'grid': mapnik.has_grid_renderer()
}
cairo_threshold = 10