Merge branch 'master' into grouped-rendering

Conflicts:
	include/mapnik/feature_type_style.hpp
	src/feature_type_style.cpp
This commit is contained in:
Konstantin Käfer 2011-12-07 22:02:29 +01:00
commit ac8b4c6d2d
550 changed files with 15151 additions and 10654 deletions

21
.gitignore vendored
View file

@ -1,3 +1,5 @@
.DS_Store
*~
*.o
*.pyc
*.os
@ -19,7 +21,24 @@ tests/python_tests/raster_colorizer_test_save.xml
utils/mapnik-config/mapnik-config
utils/mapnik-config/mapnik2.pc
utils/shapeindex/shapeindex
utils/ogrindex/ogrindex
utils/pgsql2sqlite/pgsql2sqlite
utils/svg2png/svg2png
demo/python/demo*
demo/python/map.xml
demo/python/map.xml
tests/cpp_tests/svg_renderer_tests/background_color_test
tests/cpp_tests/svg_renderer_tests/combined_test
tests/cpp_tests/svg_renderer_tests/compilation_test
tests/cpp_tests/svg_renderer_tests/file_output_test
tests/cpp_tests/svg_renderer_tests/file_output_test_case.svg
tests/cpp_tests/svg_renderer_tests/path_element_test
tests/cpp_tests/svg_renderer_tests/path_element_test_case_1.svg
tests/cpp_tests/svg_renderer_tests/root_element_test
tests/data/sqlite/*index
demo/c++/cairo-demo.pdf
demo/c++/cairo-demo.png
demo/c++/cairo-demo256.png
demo/c++/demo.jpg
demo/c++/demo.png
demo/c++/demo256.png

View file

@ -3,7 +3,7 @@
----------------
Mapnik Changelog
----------------
A simple log of core changes affecting Mapnik usage.
Developers: Please commit along with changes.
@ -11,7 +11,19 @@ Developers: Please commit along with changes.
For a complete change history, see the SVN log.
Mapnik Trunk
Mapnik 2.1.0
------------
- New CSV plugin - reads tabular files - autodetecting geo columns, newlines, and delimiters. Uses in-memory featureset for fast rendering and is not designed for large files (#902)
- Fixed bug in shield line placement when dx/dy are used to shift the label relative to the placement point (Matt Amos) (#908)
- Added <layer_by_sql> parameter in OGR plugin to select a layer by SQL query (besides name or index): see http://www.gdal.org/ogr/ogr_sql.html for specifications (kunitoki) (#472)
- Added suppport for output maps as tiff files (addresses #967 partially)
Mapnik 2.0.0
------------
- Add minimum-path-length property to text_symbolizer to allow labels to be placed only on lines of a certain length (#865)
@ -36,7 +48,7 @@ Mapnik Trunk
- Added map.base parameter that can be set to control where files with relative paths should be interpreted
from when a map is loaded from a string or saved to a string. It defaults to an empty string which means
that the base path will be the current working directory of the mapnik process. When a stylesheet is read
from a file that files directory is used. And a custom value can still be passed as an argument to
from a file that files directory is used. And a custom value can still be passed as an argument to
load_map_from_string().
- Added python function 'render_grid' to allow conversion of grid buffer to python object containing list of grid
@ -101,6 +113,50 @@ Mapnik Trunk
- Implement MarkersSymbolizer in Cairo render and improve the markers placement finder. (#553)
Mapnik 0.7.2 Release
--------------------
- Added forward compatibility for Mapnik 2.0 XML syntax (https://trac.mapnik.org/wiki/Mapnik2/Changes)
- Build fixes to ensure boost_threads are not used unless THREADING=multi build option is used
- Fixes for the clang compiler
- Support for latest libpng (>= 1.5.x) (r2999)
- Fixes to the postgres pool
- Fix for correct transparency levels in png256/png8 output (#540)
- Various build system fixes, especially for gcc compiler on open solaris.
- When plugins are not found, report the searched directories (#568)
- Improved font loading support (#559)
- Fix to shapeindex for allowing indexing of directory of shapefiles like `shapeindex dir/*shp`
- Fixed handling of null and multipatch shapes in shapefile driver - avoiding inf loop (#573)
- Fixed raster alpha blending (#589,#674)
- Enhanced support for faster reprojection if proj >= 4.8 is used (#575)
- Allow for late-binding of datasources (#622)
- Fix to OSM plugin to avoid over-caching of data (#542)
- Various fixes to sqlite, ogr, and occi driver backported from trunk.
- Ensured that '\n' triggers linebreaks in text rendering (#584)
- Support for boost filesystem v3
- Fixes to cairo renderer to avoid missing images (r2526)
- Fixed reading of label_position_tolerance on text_symbolizer and height for building_symbolizer
Mapnik 0.7.0 Release
--------------------
@ -114,9 +170,9 @@ Mapnik 0.7.0 Release
* Use the gdaladdo utility to add overviews to existing GDAL datasets
- PostGIS: Added an optional 'geometry_table' parameter. The 'geometry_table' used by Mapnik to look up
- PostGIS: Added an optional 'geometry_table' parameter. The 'geometry_table' used by Mapnik to look up
metadata in the geometry_columns and calculate extents (when the 'geometry_field' and 'srid' parameters
are not supplied). If 'geometry_table' is not specified Mapnik will attempt to determine the name of the
are not supplied). If 'geometry_table' is not specified Mapnik will attempt to determine the name of the
table to query based on parsing the 'table' parameter, which may fail for complex queries with more than
one 'from' keyword. Using this parameter should allow for existing metadata and table indexes to be used
while opening the door to much more complicated subqueries being passed to the 'table' parameter without
@ -138,7 +194,7 @@ Mapnik 0.7.0 Release
query to be used by indexes. (#415)
* Pass the bbox token inside a subquery like: !bbox!
* Valid Usages include:
<Parameter name="table">
@ -157,7 +213,7 @@ Mapnik 0.7.0 Release
- PostGIS Plugin: Added support for quoted table names (r1454) (#393)
- PostGIS: Add a 'persist_connection' option (default true), that when false will release
- PostGIS: Add a 'persist_connection' option (default true), that when false will release
the idle psql connection after datasource goes out of scope (r1337) (#433,#434)
- PostGIS: Added support for BigInt (int8) postgres type (384)
@ -181,14 +237,14 @@ Mapnik 0.7.0 Release
- PolygonSymbolizer: Added 'gamma' attribute to allow for dilation of polygon edges - a solution
to gap artifacts or "ghost lines" between adjacent polygons and allows for slight sharpening of
the edges of non overlapping polygons. Accepts any values but 0-1 is the recommended range.
- TextSymbolizer: Large set of new attributes: 'text_transform', 'line_spacing', 'character_spacing',
- TextSymbolizer: Large set of new attributes: 'text_transform', 'line_spacing', 'character_spacing',
'wrap_character', 'wrap_before', 'horizontal_alignment', 'justify_alignment', and 'opacity'.
* More details at changesets: r1254 and r1341
- SheildSymbolizer: Added special new attributes: 'unlock_image', 'VERTEX' placement, 'no_text' and many
attributes previously only supported in the TextSymbolizer: 'allow_overlap', 'vertical_alignment',
attributes previously only supported in the TextSymbolizer: 'allow_overlap', 'vertical_alignment',
'horizontal_alignment', 'justify_alignment', 'wrap_width', 'wrap_character', 'wrap_before', 'text_transform',
'line_spacing', 'character_spacing', and 'opacity'.
@ -218,8 +274,6 @@ Mapnik 0.7.0 Release
- Python: Fixed potential crash if pycairo support is enabled but python-cairo module is missing (#392)
- Python: Added 'mapnik.mapnik_svn_revision()' function to svn revision of Mapnik was compiled at.
- Python: Added 'mapnik.has_pycairo()' function to test for pycairo support (r1278) (#284)
- Python: Added 'mapnik.register_plugins()' and 'mapnik.register_fonts()' functions (r1256)
@ -228,7 +282,7 @@ Mapnik 0.7.0 Release
- Python: Ensured mapnik::config_errors now throw RuntimeError exception instead of UserWarning exception (#442)
- Filters: Added support for '!=' as an alias to '<>' for not-equals filters (avoids &lt;&gt;) (r1326) (#427)
- Filters: Added support for '!=' as an alias to '<>' for not-equals filters (avoids &lt;&gt;) (r1326) (#427)
- SCons: Improved boost auto-detection (r1255,r1279)
@ -250,7 +304,7 @@ Mapnik 0.6.1 Release
(Packaged from r1247)
- Plugins: expose list of registered plugins as a 'plugin_names()' method of DatasourceCache (r1180)
- Plugins: expose list of registered plugins as a 'plugin_names()' method of DatasourceCache (r1180)
- XML: Fixed serialization and parsing bugs related to handling of integers and Enums (#328,#353)
@ -353,10 +407,6 @@ Mapnik 0.6.0 Release
- Python: Added further pickling/copy support to Map, Layers, Datasources, Styles,and Rules (r907,r913,r921)
- OGCServer: Added support for load_map(), allowing reading of XML styles and layers (r901)
- OGCServer: Enabled friendly html output when in debug mode (debug=1 in ogcserver.conf) (r899)
- Plugins: Added Sqlite driver for reading sqlite databases (r881)
- Python: Exposed a number of properties for the Text Symbolizer (r869)

View file

@ -102,6 +102,7 @@ PLUGINS = { # plugins with external dependencies
# plugins without external dependencies requiring CheckLibWithHeader...
'shape': {'default':True,'path':None,'inc':None,'lib':None,'lang':'C++'},
'csv': {'default':True,'path':None,'inc':None,'lib':None,'lang':'C++'},
'raster': {'default':True,'path':None,'inc':None,'lib':None,'lang':'C++'},
'kismet': {'default':False,'path':None,'inc':None,'lib':None,'lang':'C++'},
}
@ -139,34 +140,6 @@ def strip_first(string,find,replace=''):
return string.replace(find,replace,1)
return string
def get_libtool_major_version():
"""libtool >= 2.1b support lt_dlopenadvise and the previous
release appears to be 1.9f (based on NEWS) so checking for
>= 2 seems adequate.
"""
cmd = 'libtool'
if platform.uname()[0] == "Darwin":
cmd = 'glibtool'
version = None
fallback_version = 2
pattern = r'(.*[^\S])(\d{1}\.\d+\.?\d?)(.*[^\S])'
ret = os.popen('%s --version' % cmd).read()
match = re.match(pattern,ret)
if match:
groups = match.groups()
if len(groups):
version_string = groups[1]
if version_string:
version_string = version_string.split('.')[0]
try:
version = int(version_string)
except ValueError:
pass
if not version:
color_print(1,'Could not detect libtool --version, assuming major version 2')
return fallback_version
return version
# http://www.scons.org/wiki/InstallTargets
def create_uninstall_target(env, path, is_glob=False):
if 'uninstall' in COMMAND_LINE_TARGETS:
@ -230,7 +203,7 @@ def sort_paths(items,priority):
else:
path_types['user'].append(i)
# key system libs (likely others will fall into 'other')
elif '/usr/' in i or '/System' in i or '/lib' in i:
elif '/usr/' in i or '/System' in i or i.startswith('/lib'):
path_types['system'].append(i)
# anything not yet matched...
# likely a combo of rare system lib paths and
@ -301,6 +274,7 @@ opts.AddVariables(
EnumVariable('OPTIMIZATION','Set g++ optimization level','3', ['0','1','2','3','4','s']),
# Note: setting DEBUG=True will override any custom OPTIMIZATION level
BoolVariable('DEBUG', 'Compile a debug version of Mapnik', 'False'),
BoolVariable('DEBUG_UNDEFINED', 'Compile a version of Mapnik using clang/llvm undefined behavior asserts', 'False'),
ListVariable('INPUT_PLUGINS','Input drivers to include',DEFAULT_PLUGINS,PLUGINS.keys()),
('WARNING_CXXFLAGS', 'Compiler flags you can set to reduce warning levels which are placed after -Wall.', ''),
@ -317,7 +291,9 @@ opts.AddVariables(
('PREFIX', 'The install path "prefix"', '/usr/local'),
('PYTHON_PREFIX','Custom install path "prefix" for python bindings (default of no prefix)',''),
('DESTDIR', 'The root directory to install into. Useful mainly for binary package building', '/'),
('PATH_INSERT', 'A custom path to append to the $PATH env to prioritize usage of shell programs like pkg-config will be used if multiple are present on the system', ''),
('PATH', 'A custom path (or multiple paths divided by ":") to append to the $PATH env to prioritize usage of command line programs (if multiple are present on the system)', ''),
('PATH_REMOVE', 'A path prefix to exclude from all known command and compile paths', ''),
('PATH_REPLACE', 'Two path prefixes (divided with a :) to search/replace from all known command and compile paths', ''),
# Boost variables
# default is '/usr/include', see FindBoost method below
@ -327,7 +303,7 @@ opts.AddVariables(
('BOOST_TOOLKIT','Specify boost toolkit, e.g., gcc41.','',False),
('BOOST_ABI', 'Specify boost ABI, e.g., d.','',False),
('BOOST_VERSION','Specify boost version, e.g., 1_35.','',False),
('BOOST_PYTHON_LIB','Specify library name or full path to boost_python lib (e.g. "boost_python-py26" or "/usr/lib/libboost_python.dylib")',''),
('BOOST_PYTHON_LIB','Specify library name to specific Boost Python lib (e.g. "boost_python-py26")',''),
# Variables for required dependencies
('FREETYPE_CONFIG', 'The path to the freetype-config executable.', 'freetype-config'),
@ -373,7 +349,7 @@ opts.AddVariables(
# Other variables
BoolVariable('SHAPE_MEMORY_MAPPED_FILE', 'Utilize memory-mapped files in Shapefile Plugin (higher memory usage, better performance)', 'True'),
('SYSTEM_FONTS','Provide location for python bindings to register fonts (if given aborts installation of bundled DejaVu fonts)',''),
('LIB_DIR_NAME','Name to use for the subfolder beside libmapnik where fonts and plugins are installed','mapnik2'),
('LIB_DIR_NAME','Name to use for the subfolder beside libmapnik where fonts and plugins are installed','mapnik'),
PathVariable('PYTHON','Full path to Python executable used to build bindings', sys.executable),
BoolVariable('FRAMEWORK_PYTHON', 'Link against Framework Python on Mac OS X', 'True'),
BoolVariable('PYTHON_DYNAMIC_LOOKUP', 'On OSX, do not directly link python lib, but rather dynamically lookup symbols', 'True'),
@ -423,16 +399,15 @@ pickle_store = [# Scons internal variables
'PYTHON_INSTALL_LOCATION',
'PYTHON_SYS_PREFIX',
'COLOR_PRINT',
'HAS_BOOST_SYSTEM',
'SVN_REVISION',
'HAS_CAIRO',
'HAS_PYCAIRO',
'HAS_LIBXML2',
'LIBTOOL_SUPPORTS_ADVISE',
'PYTHON_IS_64BIT',
'SAMPLE_INPUT_PLUGINS',
'PKG_CONFIG_PATH',
'PATH_INSERT',
'PATH',
'PATH_REMOVE',
'PATH_REPLACE',
'MAPNIK_LIB_DIR',
'MAPNIK_LIB_DIR_DEST',
'INSTALL_PREFIX',
@ -448,6 +423,8 @@ pickle_store = [# Scons internal variables
'CAIROMM_LIBPATHS',
'CAIROMM_LINKFLAGS',
'CAIROMM_CPPPATHS',
'SVG_RENDERER',
'SQLITE_LINKFLAGS'
]
# Add all other user configurable options to pickle pickle_store
@ -522,19 +499,13 @@ if sys.platform == "win32":
color_print(4,'\nWelcome to Mapnik...\n')
color_print(1,'*'*45)
color_print(1,'You are compiling Mapnik trunk (aka Mapnik2)')
color_print(1,'See important details at:\nhttp://trac.mapnik.org/wiki/Mapnik2')
color_print(1,('*'*45)+'\n')
#### Custom Configure Checks ###
def prioritize_paths(context,silent=True):
env = context.env
prefs = env['LINK_PRIORITY'].split(',')
if not silent:
context.Message( 'Sorting lib and inc compiler paths by priority... %s' % ','.join(prefs) )
context.Message( 'Sorting lib and inc compiler paths...')
env['LIBPATH'] = sort_paths(env['LIBPATH'],prefs)
env['CPPPATH'] = sort_paths(env['CPPPATH'],prefs)
if silent:
@ -835,10 +806,10 @@ int main()
major, minor = map(int,result.split('.'))
if major >= 4 and minor >= 0:
color_print(4,'\nFound icu version... %s\n' % result)
color_print(4,'found: icu %s' % result)
return True
color_print(1,'\nFound insufficient icu version... %s\n' % result)
color_print(1,'\nFound insufficient icu version... %s' % result)
return False
def boost_regex_has_icu(context):
@ -877,18 +848,34 @@ def sqlite_has_rtree(context):
ret = context.TryRun("""
extern "C" {
#include <sqlite3.h>
}
#include <sqlite3.h>
#include <stdio.h>
int main()
{
sqlite3_rtree_geometry *p;
//sqlite3_compileoption_used("ENABLE_RTREE");
return 0;
sqlite3* db;
int rc;
rc = sqlite3_open(":memory:", &db);
if (rc != SQLITE_OK)
{
printf("error 1: %s\\n", sqlite3_errmsg(db));
}
const char * sql = "create virtual table foo using rtree(pkid, xmin, xmax, ymin, ymax)";
rc = sqlite3_exec(db, sql, 0, 0, 0);
if (rc != SQLITE_OK)
{
printf("error 2: %s\\n", sqlite3_errmsg(db));
}
else
{
printf("yes, has rtree!\\n");
return 0;
}
return -1;
}
""", '.cpp')
""", '.c')
context.Message('Checking if SQLite supports RTREE... ')
context.Result(ret[0])
if ret[0]:
@ -933,7 +920,7 @@ if not preconfigured:
opts.files.append(conf)
color_print(4,"SCons CONFIG found: '%s', variables will be inherited..." % conf)
optfile = file(conf)
print optfile.read().replace("\n", " ").replace("'","").replace(" = ","=")
#print optfile.read().replace("\n", " ").replace("'","").replace(" = ","=")
optfile.close()
elif not conf == SCONS_LOCAL_CONFIG:
@ -956,8 +943,6 @@ if not preconfigured:
env['PLATFORM'] = platform.uname()[0]
color_print(4,"Configuring on %s in *%s*..." % (env['PLATFORM'],mode))
env['LIBTOOL_SUPPORTS_ADVISE'] = get_libtool_major_version() >= 2
env['MISSING_DEPS'] = []
env['SKIPPED_DEPS'] = []
env['HAS_CAIRO'] = False
@ -966,14 +951,13 @@ if not preconfigured:
env['CAIROMM_CPPPATHS'] = []
env['HAS_PYCAIRO'] = False
env['HAS_LIBXML2'] = False
env['SVN_REVISION'] = None
env['LIBMAPNIK_LIBS'] = []
env['LIBMAPNIK_CPPATHS'] = []
env['LIBMAPNIK_CXXFLAGS'] = []
env['LIBDIR_SCHEMA'] = LIBDIR_SCHEMA
env['PLUGINS'] = PLUGINS
env['EXTRA_FREETYPE_LIBS'] = []
env['SQLITE_LINKFLAGS'] = []
# previously a leading / was expected for LIB_DIR_NAME
# now strip it to ensure expected behavior
if env['LIB_DIR_NAME'].startswith(os.path.sep):
@ -1007,16 +991,17 @@ if not preconfigured:
env['MAPNIK_FONTS_DEST'] = os.path.join(env['MAPNIK_LIB_DIR_DEST'],'fonts')
if env['LINKING'] == 'static':
env['MAPNIK_LIB_NAME'] = '${LIBPREFIX}mapnik2${LIBSUFFIX}'
env['MAPNIK_LIB_NAME'] = '${LIBPREFIX}mapnik${LIBSUFFIX}'
else:
env['MAPNIK_LIB_NAME'] = '${SHLIBPREFIX}mapnik2${SHLIBSUFFIX}'
env['MAPNIK_LIB_NAME'] = '${SHLIBPREFIX}mapnik${SHLIBSUFFIX}'
if env['PKG_CONFIG_PATH']:
env['ENV']['PKG_CONFIG_PATH'] = os.path.realpath(env['PKG_CONFIG_PATH'])
# otherwise this variable == os.environ["PKG_CONFIG_PATH"]
if env['PATH_INSERT']:
env['ENV']['PATH'] = os.path.realpath(env['PATH_INSERT']) + ':' + env['ENV']['PATH']
if env['PATH']:
env['ENV']['PATH'] = os.path.realpath(env['PATH']) + ':' + env['ENV']['PATH']
if env['SYSTEM_FONTS']:
if not os.path.isdir(env['SYSTEM_FONTS']):
color_print(1,'Warning: Directory specified for SYSTEM_FONTS does not exist!')
@ -1072,15 +1057,17 @@ if not preconfigured:
env.AppendUnique(CPPPATH = os.path.realpath(inc_path))
env.AppendUnique(LIBPATH = os.path.realpath(lib_path))
conf.parse_config('FREETYPE_CONFIG')
# check if freetype links to bz2
if env['RUNTIME_LINK'] == 'static':
temp_env = env.Clone()
temp_env['LIBS'] = []
temp_env.ParseConfig('%s --libs' % env['FREETYPE_CONFIG'])
if 'bz2' in temp_env['LIBS']:
env['EXTRA_FREETYPE_LIBS'].append('bz2')
if conf.parse_config('FREETYPE_CONFIG'):
# check if freetype links to bz2
if env['RUNTIME_LINK'] == 'static':
temp_env = env.Clone()
temp_env['LIBS'] = []
try:
temp_env.ParseConfig('%s --libs' % env['FREETYPE_CONFIG'])
if 'bz2' in temp_env['LIBS']:
env['EXTRA_FREETYPE_LIBS'].append('bz2')
except OSError,e:
pass
# libxml2 should be optional but is currently not
# https://github.com/mapnik/mapnik/issues/913
@ -1107,14 +1094,14 @@ if not preconfigured:
if env['PRIORITIZE_LINKING']:
conf.prioritize_paths(silent=False)
for libinfo in LIBSHEADERS:
if not conf.CheckLibWithHeader(libinfo[0], libinfo[1], libinfo[3]):
if libinfo[2]:
color_print(1,'Could not find required header or shared library for %s' % libinfo[0])
env['MISSING_DEPS'].append(libinfo[0])
for libname, headers, required, lang in LIBSHEADERS:
if not conf.CheckLibWithHeader(libname, headers, lang):
if required:
color_print(1, 'Could not find required header or shared library for %s' % libname)
env['MISSING_DEPS'].append(libname)
else:
color_print(4,'Could not find optional header or shared library for %s' % libinfo[0])
env['SKIPPED_DEPS'].append(libinfo[0])
color_print(4, 'Could not find optional header or shared library for %s' % libname)
env['SKIPPED_DEPS'].append(libname)
if env['ICU_LIB_NAME'] not in env['MISSING_DEPS']:
if not conf.icu_at_least_four_two():
@ -1128,18 +1115,14 @@ if not preconfigured:
conf.FindBoost(BOOST_SEARCH_PREFIXES,thread_flag)
# boost system is used in boost 1.35 and greater
env['HAS_BOOST_SYSTEM'] = False
boost_lib_version_from_header = conf.GetBoostLibVersion()
if boost_lib_version_from_header:
boost_version_from_header = int(boost_lib_version_from_header.split('_')[1])
if boost_version_from_header >= 35:
env['HAS_BOOST_SYSTEM'] = True
# The other required boost headers.
BOOST_LIBSHEADERS = [
['system', 'boost/system/system_error.hpp', env['HAS_BOOST_SYSTEM']],
['system', 'boost/system/system_error.hpp', True],
['filesystem', 'boost/filesystem/operations.hpp', True],
['regex', 'boost/regex.hpp', True],
['program_options', 'boost/program_options.hpp', False]
@ -1222,12 +1205,30 @@ if not preconfigured:
if not conf.CheckLibWithHeader(details['lib'], details['inc'], details['lang']):
env.Replace(**backup)
env['SKIPPED_DEPS'].append(details['lib'])
#if plugin == 'sqlite':
# if not conf.sqlite_has_rtree():
# env.Replace(**backup)
# if details['lib'] in env['LIBS']:
# env['LIBS'].remove(details['lib'])
# env['SKIPPED_DEPS'].append('sqlite_rtree')
if plugin == 'sqlite':
sqlite_backup = env.Clone().Dictionary()
# if statically linking, on linux we likely
# need to link sqlite to pthreads and dl
if env['RUNTIME_LINK'] == 'static':
if conf.CheckPKGConfig('0.15.0') and conf.CheckPKG('sqlite3'):
sqlite_env = env.Clone()
try:
sqlite_env.ParseConfig('pkg-config --static --libs sqlite3')
for lib in sqlite_env['LIBS']:
if not lib in env['LIBS']:
env["SQLITE_LINKFLAGS"].append(lib)
env.Append(LIBS=lib)
except OSError,e:
pass
if not conf.sqlite_has_rtree():
env.Replace(**sqlite_backup)
if details['lib'] in env['LIBS']:
env['LIBS'].remove(details['lib'])
env['SKIPPED_DEPS'].append('sqlite_rtree')
else:
env.Replace(**sqlite_backup)
elif details['lib'] and details['inc']:
if not conf.CheckLibWithHeader(details['lib'], details['inc'], details['lang']):
@ -1239,10 +1240,10 @@ if not preconfigured:
env.PrependUnique(CPPPATH = '#', delete_existing=True)
env.PrependUnique(LIBPATH = '#src', delete_existing=True)
#if env['PGSQL2SQLITE']:
# if not conf.sqlite_has_rtree():
# env['SKIPPED_DEPS'].append('pgsql2sqlite_rtree')
# env['PGSQL2SQLITE'] = False
if env['PGSQL2SQLITE']:
if not conf.sqlite_has_rtree():
env['SKIPPED_DEPS'].append('pgsql2sqlite_rtree')
env['PGSQL2SQLITE'] = False
# Decide which libagg to use
# if we are using internal agg, then prepend to make sure
@ -1300,21 +1301,29 @@ if not preconfigured:
env['HAS_CAIRO'] = False
env['SKIPPED_DEPS'].append('cairomm-version')
else:
print 'Checking for cairo/cairomm lib and include paths... ',
cmd = 'pkg-config --libs --cflags cairomm-1.0'
if env['RUNTIME_LINK'] == 'static':
cmd += ' --static'
cairo_env = env.Clone()
cairo_env.ParseConfig(cmd)
for lib in cairo_env['LIBS']:
if not lib in env['LIBS']:
env["CAIROMM_LINKFLAGS"].append(lib)
for lpath in cairo_env['LIBPATH']:
if not lpath in env['LIBPATH']:
env["CAIROMM_LIBPATHS"].append(lpath)
for inc in cairo_env['CPPPATH']:
if not inc in env['CPPPATH']:
env["CAIROMM_CPPPATHS"].append(inc)
env['HAS_CAIRO'] = True
try:
cairo_env.ParseConfig(cmd)
for lib in cairo_env['LIBS']:
if not lib in env['LIBS']:
env["CAIROMM_LINKFLAGS"].append(lib)
for lpath in cairo_env['LIBPATH']:
if not lpath in env['LIBPATH']:
env["CAIROMM_LIBPATHS"].append(lpath)
for inc in cairo_env['CPPPATH']:
if not inc in env['CPPPATH']:
env["CAIROMM_CPPPATHS"].append(inc)
env['HAS_CAIRO'] = True
print 'yes'
except OSError,e:
color_print(1,'no')
env['SKIPPED_DEPS'].append('cairo')
env['SKIPPED_DEPS'].append('cairomm')
color_print(1,'pkg-config reported: %s' % e)
else:
color_print(4,'Not building with cairo support, pass CAIRO=True to enable')
@ -1325,7 +1334,7 @@ if not preconfigured:
if not conf.CheckHeader(header='boost/python/detail/config.hpp',language='C++'):
color_print(1,'Could not find required header files for boost python')
env['MISSING_DEPS'].append('boost python')
if env['CAIRO']:
if conf.CheckPKGConfig('0.15.0') and conf.CheckPKG('pycairo'):
env['HAS_PYCAIRO'] = True
@ -1390,13 +1399,6 @@ if not preconfigured:
else :
common_cxx_flags = '-D%s ' % env['PLATFORM'].upper()
svn_version = call('svnversion')
if not svn_version == 'exported':
pattern = r'(\d+)(.*)'
try:
env['SVN_REVISION'] = re.match(pattern,svn_version).groups()[0]
except: pass
# Mac OSX (Darwin) special settings
if env['PLATFORM'] == 'Darwin':
pthread = ''
@ -1414,6 +1416,7 @@ if not preconfigured:
debug_flags = '-g -DDEBUG -DMAPNIK_DEBUG'
ndebug_flags = '-DNDEBUG'
# Customizing the C++ compiler flags depending on:
# (1) the C++ compiler used; and
# (2) whether debug binaries are requested.
@ -1428,7 +1431,9 @@ if not preconfigured:
if env['DEBUG']:
env.Append(CXXFLAGS = gcc_cxx_flags + '-O0 -fno-inline %s' % debug_flags)
else:
env.Append(CXXFLAGS = gcc_cxx_flags + '-O%s -finline-functions -Wno-inline %s' % (env['OPTIMIZATION'],ndebug_flags))
env.Append(CXXFLAGS = gcc_cxx_flags + '-O%s -finline-functions -Wno-inline -Wno-parentheses -Wno-char-subscripts %s' % (env['OPTIMIZATION'],ndebug_flags))
if env['DEBUG_UNDEFINED']:
env.Append(CXXFLAGS = '-fcatch-undefined-behavior') #-ftrapv -fwrapv
if 'python' in env['BINDINGS']:
if not os.access(env['PYTHON'], os.X_OK):
@ -1496,14 +1501,23 @@ if not preconfigured:
if not conf.CheckHeader(header='Python.h',language='C'):
color_print(1,'Could not find required header files for the Python language (version %s)' % env['PYTHON_VERSION'])
env.Replace(**backup)
env['MISSING_DEPS'].append('python %s development headers' % env['PYTHON_VERSION'])
Exit(1)
else:
env.Replace(**backup)
if (int(majver), int(minver)) < (2, 2):
color_print(1,"Python version 2.2 or greater required")
Exit(1)
if env['BOOST_PYTHON_LIB']:
env.Append(LIBS='python%s' % env['PYTHON_VERSION'])
if not conf.CheckLibWithHeader(libs=[env['BOOST_PYTHON_LIB']], header='boost/python/detail/config.hpp', language='C++'):
color_print(1, 'Could not find library %s for boost python' % env['BOOST_PYTHON_LIB'])
env.Replace(**backup)
Exit(1)
else:
env.Replace(**backup)
color_print(4,'Bindings Python version... %s' % env['PYTHON_VERSION'])
color_print(4,'Python %s prefix... %s' % (env['PYTHON_VERSION'], env['PYTHON_SYS_PREFIX']))
color_print(4,'Python bindings will install in... %s' % os.path.normpath(env['PYTHON_INSTALL_LOCATION']))
@ -1543,7 +1557,7 @@ if not preconfigured:
except: pass
if 'configure' in command_line_args:
color_print(4,'\n*Configure complete*\nNow run "python scons/scons.py" to build or "python scons/scons.py install" to install')
color_print(4,'\nConfigure completed: run `make` to build or `make install`')
if not HELP_REQUESTED:
Exit(0)
@ -1562,17 +1576,57 @@ if not HELP_REQUESTED:
env['ENV']['PKG_CONFIG_PATH'] = os.path.realpath(env['PKG_CONFIG_PATH'])
# otherwise this variable == os.environ["PKG_CONFIG_PATH"]
if env['PATH_INSERT']:
env['ENV']['PATH'] = os.path.realpath(env['PATH_INSERT']) + ':' + env['ENV']['PATH']
if env['PATH']:
env['ENV']['PATH'] = os.path.realpath(env['PATH']) + ':' + env['ENV']['PATH']
if env['PATH_REMOVE']:
p = env['PATH_REMOVE']
if p in env['ENV']['PATH']:
env['ENV']['PATH'].replace(p,'')
def rm_path(set):
for i in env[set]:
if p in i:
env[set].remove(i)
rm_path('LIBPATH')
rm_path('CPPPATH')
rm_path('CXXFLAGS')
rm_path('CAIROMM_LIBPATHS')
rm_path('CAIROMM_CPPPATHS')
if env['PATH_REPLACE']:
searches,replace = env['PATH_REPLACE'].split(':')
for search in searches.split(','):
if search in env['ENV']['PATH']:
env['ENV']['PATH'] = os.path.abspath(env['ENV']['PATH'].replace(search,replace))
def replace_path(set,s,r):
idx = 0
for i in env[set]:
if s in i:
env[set][idx] = os.path.abspath(env[set][idx].replace(s,r))
idx +=1
replace_path('LIBPATH',search,replace)
replace_path('CPPPATH',search,replace)
replace_path('CXXFLAGS',search,replace)
replace_path('CAIROMM_LIBPATHS',search,replace)
replace_path('CAIROMM_CPPPATHS',search,replace)
# export env so it is available in build.py files
Export('env')
plugin_base = env.Clone()
# for this to work you need:
# if __GNUC__ >= 4
# define MAPNIK_EXP __attribute__ ((visibility ("default")))
#plugin_base.Append(CXXFLAGS='-fvisibility=hidden')
#plugin_base.Append(CXXFLAGS='-fvisibility-inlines-hidden')
Export('plugin_base')
# clear the '_CPPDEFFLAGS' variable
# for unknown reasons this variable puts -DNone
# in the g++ args prompting unnecessary recompiles
env['_CPPDEFFLAGS'] = None
plugin_base['_CPPDEFFLAGS'] = None
if env['FAST']:
@ -1658,7 +1712,7 @@ if not HELP_REQUESTED:
# Install the python speed testing scripts if python bindings will be available
SConscript('utils/performance/build.py')
# Install the mapnik2 upgrade script
# Install the mapnik upgrade script
SConscript('utils/upgrade_map_xml/build.py')
# Configure fonts and if requested install the bundled DejaVu fonts

View file

@ -40,21 +40,15 @@ def is_py3():
prefix = env['PREFIX']
target_path = os.path.normpath(env['PYTHON_INSTALL_LOCATION'] + os.path.sep + 'mapnik2')
target_path = os.path.normpath(env['PYTHON_INSTALL_LOCATION'] + os.path.sep + 'mapnik')
libraries = ['mapnik2','png']
libraries = ['mapnik','png']
if env['JPEG']:
libraries.append('jpeg')
if env['BOOST_PYTHON_LIB']:
if os.path.sep in env['BOOST_PYTHON_LIB']:
pylib_dir = os.path.dirname(env['BOOST_PYTHON_LIB'])
env.Prepend(LIBPATH = pylib_dir)
pylib_name = os.path.splitext(os.path.basename(env['BOOST_PYTHON_LIB']))[0].replace('lib','',1)
libraries.append(pylib_name)
else:
libraries.append(env['BOOST_PYTHON_LIB'].replace('lib','',1))
libraries.append(env['BOOST_PYTHON_LIB'])
else:
if is_py3():
libraries.append('boost_python3%s' % env['BOOST_APPEND'])
@ -157,7 +151,11 @@ if 'install' in COMMAND_LINE_TARGETS:
init_files.remove('mapnik/paths.py')
init_module = env.Install(target_path, init_files)
env.Alias(target='install', source=init_module)
# install mapnik2 module which redirects to mapnik and issues DeprecatedWarning
path = os.path.normpath(env['PYTHON_INSTALL_LOCATION'] + os.path.sep + 'mapnik2')
init_mapnik2 = env.Install(path, 'mapnik2/__init__.py')
env.Alias(target='install', source=init_mapnik2)
# fix perms and install the custom generated 'paths.py'
if 'install' in COMMAND_LINE_TARGETS:
targetp = os.path.join(target_path,'paths.py')
@ -169,18 +167,11 @@ if 'install' in COMMAND_LINE_TARGETS:
Copy("$TARGET","$SOURCE"),
Chmod("$TARGET", 0644),
])
# install the ogcserver module code
if 'install' in COMMAND_LINE_TARGETS:
ogcserver_files = glob.glob('mapnik/ogcserver/*.py')
ogcserver_module = env.Install(target_path + '/ogcserver', ogcserver_files)
env.Alias(target='install', source=ogcserver_module)
# install the shared object beside the module directory
sources = glob.glob('*.cpp')
py_env = env.Clone()
py_env.Append(CPPPATH = env['PYTHON_INCLUDES'])
@ -194,13 +185,7 @@ if env['HAS_PYCAIRO']:
py_env.ParseConfig('pkg-config --cflags pycairo')
py_env.Append(CXXFLAGS = '-DHAVE_PYCAIRO')
if env['SVN_REVISION']:
sources.remove('mapnik_python.cpp')
env2 = py_env.Clone()
env2.Append(CXXFLAGS='-DSVN_REVISION=%s' % env['SVN_REVISION'])
sources.insert(0,env2.SharedObject('mapnik_python.cpp'))
_mapnik = py_env.LoadableModule('mapnik/_mapnik2', sources, LIBS=libraries, LDMODULEPREFIX='', LDMODULESUFFIX='.so',LINKFLAGS=linkflags)
_mapnik = py_env.LoadableModule('mapnik/_mapnik', sources, LIBS=libraries, LDMODULEPREFIX='', LDMODULESUFFIX='.so',LINKFLAGS=linkflags)
Depends(_mapnik, env.subst('../../src/%s' % env['MAPNIK_LIB_NAME']))
@ -219,4 +204,4 @@ if 'uninstall' not in COMMAND_LINE_TARGETS:
env['create_uninstall_target'](env, target_path)

View file

@ -43,7 +43,7 @@ import os
import sys
import warnings
from _mapnik2 import *
from _mapnik import *
from paths import inputpluginspath, fontscollectionpath
import printing
@ -410,6 +410,13 @@ def Raster(**keywords):
Optional keyword arguments:
base -- path prefix (default None)
multi -- whether the image is in tiles on disk (default False)
Multi-tiled keyword arguments:
x_width -- virtual image number of tiles in X direction (required)
y_width -- virtual image number of tiles in Y direction (required)
tile_size -- if an image is in tiles, how large are the tiles (default 256)
tile_stride -- if an image is in tiles, what's the increment between rows/cols (default 1)
>>> from mapnik import Raster, Layer
>>> raster = Raster(base='/home/mapnik/data',file='elevation.tif',lox=-122.8,loy=48.5,hix=-122.7,hiy=48.6)
@ -478,10 +485,11 @@ def Ogr(**keywords):
Required keyword arguments:
file -- path to OGR supported dataset
layer -- name of layer to use within datasource (optional if layer_by_index is used)
layer -- name of layer to use within datasource (optional if layer_by_index or layer_by_sql is used)
Optional keyword arguments:
layer_by_index -- choose layer by index number instead of by layer name.
layer_by_index -- choose layer by index number instead of by layer name or sql.
layer_by_sql -- choose layer by sql query number instead of by layer name or index.
base -- path prefix (default None)
encoding -- file encoding (default 'utf-8')
multiple_geometries -- boolean, direct the Mapnik wkb reader to interpret as multigeometries (default False)
@ -710,7 +718,6 @@ __all__ = [
# version and environment
'mapnik_version_string',
'mapnik_version',
'mapnik_svn_revision',
'has_cairo',
'has_pycairo',
# factory methods

View file

@ -1,125 +0,0 @@
#
# This file is part of Mapnik (c++ mapping toolkit)
#
# Copyright (C) 2006 Jean-Francois Doyon
#
# Mapnik is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.
#
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#
# $Id$
"""Interface for registering map styles and layers for availability in WMS Requests."""
from common import Version, copy_style, copy_layer
from exceptions import OGCException, ServerConfigurationError
from wms111 import ServiceHandler as ServiceHandler111
from wms130 import ServiceHandler as ServiceHandler130
from mapnik2 import Style, Map, load_map
import re
import sys
def ServiceHandlerFactory(conf, mapfactory, onlineresource, version):
if not version:
version = Version('1.3.0')
else:
version = Version(version)
if version >= '1.3.0':
return ServiceHandler130(conf, mapfactory, onlineresource)
else:
return ServiceHandler111(conf, mapfactory, onlineresource)
class BaseWMSFactory:
def __init__(self):
self.layers = {}
self.ordered_layers = []
self.styles = {}
self.aggregatestyles = {}
def loadXML(self, xmlfile, strict=False):
tmp_map = Map(0,0)
load_map (tmp_map, xmlfile, strict)
for lyr in tmp_map.layers:
style_count = len(lyr.styles)
if style_count == 0:
raise ServerConfigurationError("Cannot register Layer '%s' without a style" % lyr.name)
elif style_count == 1:
style_obj = tmp_map.find_style(lyr.styles[0])
style_obj = copy_style(style_obj)
style_name = lyr.styles[0]
if style_name not in self.aggregatestyles.keys() and style_name not in self.styles.keys():
self.register_style(style_name, style_obj)
self.register_layer(copy_layer(lyr), style_name, extrastyles=(style_name,))
elif style_count > 1:
for style_name in lyr.styles:
style_obj = tmp_map.find_style(style_name)
style_obj = copy_style(style_obj)
if style_name not in self.aggregatestyles.keys() and style_name not in self.styles.keys():
self.register_style(style_name, style_obj)
aggregates = tuple([sty for sty in lyr.styles])
aggregates_name = '%s_aggregates' % lyr.name
self.register_aggregate_style(aggregates_name,aggregates)
self.register_layer(copy_layer(lyr), aggregates_name, extrastyles=aggregates)
def register_layer(self, layer, defaultstyle, extrastyles=()):
layername = layer.name
if not layername:
raise ServerConfigurationError('Attempted to register an unnamed layer.')
if not re.match('^\+init=epsg:\d+$', layer.srs) and not re.match('^\+proj=.*$', layer.srs):
raise ServerConfigurationError('Attempted to register a layer without an epsg projection defined.')
if defaultstyle not in self.styles.keys() + self.aggregatestyles.keys():
raise ServerConfigurationError('Attempted to register a layer with an non-existent default style.')
layer.wmsdefaultstyle = defaultstyle
if isinstance(extrastyles, tuple):
for stylename in extrastyles:
if type(stylename) == type(''):
if stylename not in self.styles.keys() + self.aggregatestyles.keys():
raise ServerConfigurationError('Attempted to register a layer with an non-existent extra style.')
else:
ServerConfigurationError('Attempted to register a layer with an invalid extra style name.')
layer.wmsextrastyles = extrastyles
else:
raise ServerConfigurationError('Layer "%s" was passed an invalid list of extra styles. List must be a tuple of strings.' % layername)
self.ordered_layers.append(layer)
self.layers[layername] = layer
def register_style(self, name, style):
if not name:
raise ServerConfigurationError('Attempted to register a style without providing a name.')
if name in self.aggregatestyles.keys() or name in self.styles.keys():
raise ServerConfigurationError("Attempted to register a style with a name already in use: '%s'" % name)
if not isinstance(style, Style):
raise ServerConfigurationError('Bad style object passed to register_style() for style "%s".' % name)
self.styles[name] = style
def register_aggregate_style(self, name, stylenames):
if not name:
raise ServerConfigurationError('Attempted to register an aggregate style without providing a name.')
if name in self.aggregatestyles.keys() or name in self.styles.keys():
raise ServerConfigurationError('Attempted to register an aggregate style with a name already in use.')
self.aggregatestyles[name] = []
for stylename in stylenames:
if stylename not in self.styles.keys():
raise ServerConfigurationError('Attempted to register an aggregate style containing a style that does not exist.')
self.aggregatestyles[name].append(stylename)
def finalize(self):
if len(self.layers) == 0:
raise ServerConfigurationError('No layers defined!')
if len(self.styles) == 0:
raise ServerConfigurationError('No styles defined!')
for layer in self.layers.values():
for style in list(layer.styles) + list(layer.wmsextrastyles):
if style not in self.styles.keys() + self.aggregatestyles.keys():
raise ServerConfigurationError('Layer "%s" refers to undefined style "%s".' % (layer.name, style))

View file

@ -1,28 +0,0 @@
#
# This file is part of Mapnik (c++ mapping toolkit)
#
# Copyright (C) 2006 Jean-Francois Doyon
#
# Mapnik is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.
#
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#
# $Id$
"""Mapnik OGC WMS Server."""
import os
import warnings
warnings.warn("ogcserver module development has moved to https://github.com/mapnik/OGCServer.\n This code will function fine with this version, but will be removed in Mapnik 2.1.0. Disable this warning by editing this file: %s" % os.path.realpath(__file__), DeprecationWarning, 2)

View file

@ -1,116 +0,0 @@
#
# This file is part of Mapnik (c++ mapping toolkit)
#
# Copyright (C) 2006 Jean-Francois Doyon
#
# Mapnik is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.
#
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#
# $Id$
"""CGI/FastCGI handler for Mapnik OGC WMS Server.
Requires 'jon' module.
"""
from os import environ
from tempfile import gettempdir
environ['PYTHON_EGG_CACHE'] = gettempdir()
import sys
from jon import cgi
from exceptions import OGCException, ServerConfigurationError
from wms111 import ExceptionHandler as ExceptionHandler111
from wms130 import ExceptionHandler as ExceptionHandler130
from configparser import SafeConfigParser
from common import Version
class Handler(cgi.DebugHandler):
def __init__(self):
conf = SafeConfigParser()
conf.readfp(open(self.configpath))
self.conf = conf
if not conf.has_option_with_value('server', 'module'):
raise ServerConfigurationError('The factory module is not defined in the configuration file.')
try:
mapfactorymodule = __import__(conf.get('server', 'module'))
except ImportError:
raise ServerConfigurationError('The factory module could not be loaded.')
if hasattr(mapfactorymodule, 'WMSFactory'):
self.mapfactory = getattr(mapfactorymodule, 'WMSFactory')()
else:
raise ServerConfigurationError('The factory module does not have a WMSFactory class.')
if conf.has_option('server', 'debug'):
self.debug = int(conf.get('server', 'debug'))
else:
self.debug = 0
def process(self, req):
reqparams = lowerparams(req.params)
onlineresource = 'http://%s:%s%s?' % (req.environ['SERVER_NAME'], req.environ['SERVER_PORT'], req.environ['SCRIPT_NAME'])
if not reqparams.has_key('request'):
raise OGCException('Missing request parameter.')
request = reqparams['request']
del reqparams['request']
if request == 'GetCapabilities' and not reqparams.has_key('service'):
raise OGCException('Missing service parameter.')
if request in ['GetMap', 'GetFeatureInfo']:
service = 'WMS'
else:
service = reqparams['service']
if reqparams.has_key('service'):
del reqparams['service']
try:
mapnikmodule = __import__('mapnik2.ogcserver.' + service)
except:
raise OGCException('Unsupported service "%s".' % service)
ServiceHandlerFactory = getattr(mapnikmodule.ogcserver, service).ServiceHandlerFactory
servicehandler = ServiceHandlerFactory(self.conf, self.mapfactory, onlineresource, reqparams.get('version', None))
if reqparams.has_key('version'):
del reqparams['version']
if request not in servicehandler.SERVICE_PARAMS.keys():
raise OGCException('Operation "%s" not supported.' % request, 'OperationNotSupported')
ogcparams = servicehandler.processParameters(request, reqparams)
try:
requesthandler = getattr(servicehandler, request)
except:
raise OGCException('Operation "%s" not supported.' % request, 'OperationNotSupported')
response = requesthandler(ogcparams)
req.set_header('Content-Type', response.content_type)
req.set_header('Content-Length', str(len(response.content)))
req.write(response.content)
def traceback(self, req):
reqparams = lowerparams(req.params)
version = reqparams.get('version', None)
if not version:
version = Version('1.3.0')
else:
version = Version(version)
if version >= '1.3.0':
eh = ExceptionHandler130(self.debug)
else:
eh = ExceptionHandler111(self.debug)
response = eh.getresponse(reqparams)
req.set_header('Content-Type', response.content_type)
req.set_header('Content-Length', str(len(response.content)))
req.write(response.content)
def lowerparams(params):
reqparams = {}
for key, value in params.items():
reqparams[key.lower()] = value
return reqparams

View file

@ -1,539 +0,0 @@
#
# This file is part of Mapnik (c++ mapping toolkit)
#
# Copyright (C) 2006 Jean-Francois Doyon
#
# Mapnik is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.
#
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#
# $Id$
"""Core OGCServer classes and functions."""
from exceptions import OGCException, ServerConfigurationError
from mapnik2 import Map, Color, Box2d, render, Image, Layer, Style, Projection as MapnikProjection, Coord
from PIL.Image import new
from PIL.ImageDraw import Draw
from StringIO import StringIO
from copy import deepcopy
from traceback import format_exception, format_exception_only
from sys import exc_info
import re
import sys
try:
from lxml import etree as ElementTree
except ImportError:
import xml.etree.ElementTree as ElementTree
except ImportError:
import elementtree.ElementTree as ElementTree
# from elementtree import ElementTree
# ElementTree._namespace_map.update({'http://www.opengis.net/wms': 'wms',
# 'http://www.opengis.net/ogc': 'ogc',
# 'http://www.w3.org/1999/xlink': 'xlink',
# 'http://www.w3.org/2001/XMLSchema-instance': 'xsi'
# })
PIL_TYPE_MAPPING = {'image/jpeg': 'jpeg', 'image/png': 'png'}
class ParameterDefinition:
def __init__(self, mandatory, cast, default=None, allowedvalues=None, fallback=False):
""" An OGC request parameter definition. Used to describe a
parameter's characteristics.
@param mandatory: Is this parameter required by the request?
@type mandatory: Boolean.
@param default: Default value to use if one is not provided
and the parameter is optional.
@type default: None or any valid value.
@param allowedvalues: A list of allowed values for the parameter.
If a value is provided that is not in this
list, an error is raised.
@type allowedvalues: A python tuple of values.
@param fallback: Whether the value of the parameter should fall
back to the default should an illegal value be
provided.
@type fallback: Boolean.
@return: A L{ParameterDefinition} instance.
"""
if mandatory not in [True, False]:
raise ServerConfigurationError("Bad value for 'mandatory' parameter, must be True or False.")
self.mandatory = mandatory
if not callable(cast):
raise ServerConfigurationError('Cast parameter definition must be callable.')
self.cast = cast
self.default = default
if allowedvalues and type(allowedvalues) != type(()):
raise ServerConfigurationError("Bad value for 'allowedvalues' parameter, must be a tuple.")
self.allowedvalues = allowedvalues
if fallback not in [True, False]:
raise ServerConfigurationError("Bad value for 'fallback' parameter, must be True or False.")
self.fallback = fallback
class BaseServiceHandler:
CONF_CONTACT_PERSON_PRIMARY = [
['contactperson', 'ContactPerson', str],
['contactorganization', 'ContactOrganization', str]
]
CONF_CONTACT_ADDRESS = [
['addresstype', 'AddressType', str],
['address', 'Address', str],
['city', 'City', str],
['stateorprovince', 'StateOrProvince', str],
['postcode', 'PostCode', str],
['country', 'Country', str]
]
CONF_CONTACT = [
['contactposition', 'ContactPosition', str],
['contactvoicetelephone', 'ContactVoiceTelephone', str],
['contactelectronicmailaddress', 'ContactElectronicMailAddress', str]
]
def processParameters(self, requestname, params):
finalparams = {}
for paramname, paramdef in self.SERVICE_PARAMS[requestname].items():
if paramname not in params.keys() and paramdef.mandatory:
raise OGCException('Mandatory parameter "%s" missing from request.' % paramname)
elif paramname in params.keys():
try:
params[paramname] = paramdef.cast(params[paramname])
except OGCException:
raise
except:
raise OGCException('Invalid value "%s" for parameter "%s".' % (params[paramname], paramname))
if paramdef.allowedvalues and params[paramname] not in paramdef.allowedvalues:
if not paramdef.fallback:
raise OGCException('Parameter "%s" has an illegal value.' % paramname)
else:
finalparams[paramname] = paramdef.default
else:
finalparams[paramname] = params[paramname]
elif not paramdef.mandatory and paramdef.default:
finalparams[paramname] = paramdef.default
return finalparams
def processServiceCapabilities(self, capetree):
if len(self.conf.items('service')) > 0:
servicee = capetree.find('{http://www.opengis.net/wms}Service')
for item in self.CONF_SERVICE:
if self.conf.has_option_with_value('service', item[0]):
value = self.conf.get('service', item[0]).strip()
try:
item[2](value)
except:
raise ServerConfigurationError('Configuration parameter [%s]->%s has an invalid value: %s.' % ('service', item[0], value))
if item[0] == 'onlineresource':
element = ElementTree.Element('%s' % item[1])
servicee.append(element)
element.set('{http://www.w3.org/1999/xlink}href', value)
element.set('{http://www.w3.org/1999/xlink}type', 'simple')
elif item[0] == 'keywordlist':
element = ElementTree.Element('%s' % item[1])
servicee.append(element)
keywords = value.split(',')
keywords = map(str.strip, keywords)
for keyword in keywords:
kelement = ElementTree.Element('Keyword')
kelement.text = keyword
element.append(kelement)
else:
element = ElementTree.Element('%s' % item[1])
element.text = value
servicee.append(element)
if len(self.conf.items_with_value('contact')) > 0:
element = ElementTree.Element('ContactInformation')
servicee.append(element)
for item in self.CONF_CONTACT:
if self.conf.has_option_with_value('contact', item[0]):
value = self.conf.get('contact', item[0]).strip()
try:
item[2](value)
except:
raise ServerConfigurationError('Configuration parameter [%s]->%s has an invalid value: %s.' % ('service', item[0], value))
celement = ElementTree.Element('%s' % item[1])
celement.text = value
element.append(celement)
for item in self.CONF_CONTACT_PERSON_PRIMARY + self.CONF_CONTACT_ADDRESS:
if item in self.CONF_CONTACT_PERSON_PRIMARY:
tagname = 'ContactPersonPrimary'
else:
tagname = 'ContactAddress'
if self.conf.has_option_with_value('contact', item[0]):
if element.find(tagname) == None:
subelement = ElementTree.Element(tagname)
element.append(subelement)
value = self.conf.get('contact', item[0]).strip()
try:
item[2](value)
except:
raise ServerConfigurationError('Configuration parameter [%s]->%s has an invalid value: %s.' % ('service', item[0], value))
celement = ElementTree.Element('%s' % item[1])
celement.text = value
subelement.append(celement)
class Response:
def __init__(self, content_type, content):
self.content_type = content_type
self.content = content
class Version:
def __init__(self, version):
version = version.split('.')
if len(version) != 3:
raise OGCException('Badly formatted version number.')
try:
version = map(int, version)
except:
raise OGCException('Badly formatted version number.')
self.version = version
def __repr__(self):
return '%s.%s.%s' % (self.version[0], self.version[1], self.version[2])
def __cmp__(self, other):
if isinstance(other, str):
other = Version(other)
if self.version[0] < other.version[0]:
return -1
elif self.version[0] > other.version[0]:
return 1
else:
if self.version[1] < other.version[1]:
return -1
elif self.version[1] > other.version[1]:
return 1
else:
if self.version[2] < other.version[2]:
return -1
elif self.version[2] > other.version[2]:
return 1
else:
return 0
class ListFactory:
def __init__(self, cast):
self.cast = cast
def __call__(self, string):
seq = string.split(',')
return map(self.cast, seq)
def ColorFactory(colorstring):
if re.match('^0x[a-fA-F0-9]{6}$', colorstring):
return Color(eval('0x' + colorstring[2:4]), eval('0x' + colorstring[4:6]), eval('0x' + colorstring[6:8]))
else:
raise OGCException('Invalid color value. Must be of format "0xFFFFFF".')
class CRS:
def __init__(self, namespace, code):
self.namespace = namespace.lower()
self.code = int(code)
self.proj = None
def __repr__(self):
return '%s:%s' % (self.namespace, self.code)
def __eq__(self, other):
if str(other) == str(self):
return True
return False
def inverse(self, x, y):
if not self.proj:
self.proj = Projection('+init=%s:%s' % (self.namespace, self.code))
return self.proj.inverse(Coord(x, y))
def forward(self, x, y):
if not self.proj:
self.proj = Projection('+init=%s:%s' % (self.namespace, self.code))
return self.proj.forward(Coord(x, y))
class CRSFactory:
def __init__(self, allowednamespaces):
self.allowednamespaces = allowednamespaces
def __call__(self, crsstring):
if not re.match('^[A-Z]{3,5}:\d+$', crsstring):
raise OGCException('Invalid format for the CRS parameter: %s' % crsstring, 'InvalidCRS')
crsparts = crsstring.split(':')
if crsparts[0] in self.allowednamespaces:
return CRS(crsparts[0], crsparts[1])
else:
raise OGCException('Invalid CRS Namespace: %s' % crsparts[0], 'InvalidCRS')
def copy_layer(obj):
lyr = Layer(obj.name)
lyr.abstract = obj.abstract
lyr.active = obj.active
lyr.clear_label_cache = obj.clear_label_cache
lyr.datasource = obj.datasource
#lyr.maxzoom = obj.maxzoom
#lyr.minzoom = obj.minzoom
lyr.queryable = obj.queryable
lyr.srs = obj.srs
lyr.title = obj.title
if hasattr(obj,'wmsdefaultstyle'):
lyr.wmsdefaultstyle = obj.wmsdefaultstyle
if hasattr(obj,'wmsextrastyles'):
lyr.wmsextrastyles = obj.wmsextrastyles
return lyr
def copy_style(obj):
sty = Style()
for rule in obj.rules:
sty.rules.append(rule)
return sty
class WMSBaseServiceHandler(BaseServiceHandler):
def GetMap(self, params):
m = self._buildMap(params)
im = Image(params['width'], params['height'])
render(m, im)
return Response(params['format'], im.tostring(PIL_TYPE_MAPPING[params['format']]))
def GetFeatureInfo(self, params, querymethodname='query_point'):
m = self._buildMap(params)
if params['info_format'] == 'text/plain':
writer = TextFeatureInfo()
elif params['info_format'] == 'text/xml':
writer = XMLFeatureInfo()
if params['query_layers'] and params['query_layers'][0] == '__all__':
for layerindex, layer in enumerate(m.layers):
featureset = getattr(m, querymethodname)(layerindex, params['i'], params['j'])
features = featureset.features
if features:
writer.addlayer(layer.name)
for feat in features:
writer.addfeature()
for prop in feat.properties:
writer.addattribute(prop[0], prop[1])
else:
for layerindex, layername in enumerate(params['query_layers']):
if layername in params['layers']:
if m.layers[layerindex].queryable:
featureset = getattr(m, querymethodname)(layerindex, params['i'], params['j'])
features = featureset.features
if features:
writer.addlayer(m.layers[layerindex].name)
for feat in features:
writer.addfeature()
for prop in feat.properties:
writer.addattribute(prop[0], prop[1])
else:
raise OGCException('Requested query layer "%s" is not marked queryable.' % layername, 'LayerNotQueryable')
else:
raise OGCException('Requested query layer "%s" not in the LAYERS parameter.' % layername)
return Response(params['info_format'], str(writer))
def _buildMap(self, params):
if str(params['crs']) not in self.allowedepsgcodes:
raise OGCException('Unsupported CRS "%s" requested.' % str(params['crs']).upper(), 'InvalidCRS')
if params['bbox'][0] >= params['bbox'][2]:
raise OGCException("BBOX values don't make sense. minx is greater than maxx.")
if params['bbox'][1] >= params['bbox'][3]:
raise OGCException("BBOX values don't make sense. miny is greater than maxy.")
if params.has_key('styles') and len(params['styles']) != len(params['layers']):
raise OGCException('STYLES length does not match LAYERS length.')
m = Map(params['width'], params['height'], '+init=%s' % params['crs'])
if params.has_key('transparent') and params['transparent'] == 'FALSE':
if params['bgcolor']:
m.background = params['bgcolor']
else:
m.background = Color(0, 0, 0, 0)
maplayers = self.mapfactory.layers
orderedmaplayers = self.mapfactory.ordered_layers
mapstyles = self.mapfactory.styles
mapaggregatestyles = self.mapfactory.aggregatestyles
# a non WMS spec way of requesting all layers
if params['layers'] and params['layers'][0] == '__all__':
for layername in orderedmaplayers:
layer = copy_layer(layername)
reqstyle = layer.wmsdefaultstyle
if reqstyle in mapaggregatestyles.keys():
for stylename in mapaggregatestyles[reqstyle]:
layer.styles.append(stylename)
else:
layer.styles.append(reqstyle)
for stylename in layer.styles:
if stylename in mapstyles.keys():
m.append_style(stylename, mapstyles[stylename])
m.layers.append(layer)
else:
for layerindex, layername in enumerate(params['layers']):
try:
layer = copy_layer(maplayers[layername])
except KeyError:
raise OGCException('Layer "%s" not defined.' % layername, 'LayerNotDefined')
try:
reqstyle = params['styles'][layerindex]
except IndexError:
reqstyle = ''
if reqstyle and reqstyle not in layer.wmsextrastyles:
raise OGCException('Invalid style "%s" requested for layer "%s".' % (reqstyle, layername), 'StyleNotDefined')
if not reqstyle:
reqstyle = layer.wmsdefaultstyle
if reqstyle in mapaggregatestyles.keys():
for stylename in mapaggregatestyles[reqstyle]:
layer.styles.append(stylename)
else:
layer.styles.append(reqstyle)
for stylename in layer.styles:
if stylename in mapstyles.keys():
m.append_style(stylename, mapstyles[stylename])
else:
raise ServerConfigurationError('Layer "%s" refers to non-existent style "%s".' % (layername, stylename))
m.layers.append(layer)
m.zoom_to_box(Box2d(params['bbox'][0], params['bbox'][1], params['bbox'][2], params['bbox'][3]))
return m
class BaseExceptionHandler:
def __init__(self, debug):
self.debug = debug
def getresponse(self, params):
code = ''
message = '\n'
if not params:
message = '''
<h2>Welcome to the Mapnik OGCServer.</h2>
<h3>Ready to accept map requests...</h5>
<h4>For more info see: <a href="http://trac.mapnik.org/wiki/OgcServer">trac.mapnik.org</a></h4>
'''
return self.htmlhandler('', message)
excinfo = exc_info()
if self.debug:
messagelist = format_exception(excinfo[0], excinfo[1], excinfo[2])
else:
messagelist = format_exception_only(excinfo[0], excinfo[1])
message += ''.join(messagelist)
if isinstance(excinfo[1], OGCException) and len(excinfo[1].args) > 1:
code = excinfo[1].args[1]
exceptions = params.get('exceptions', None)
if self.debug:
return self.htmlhandler(code, message)
if not exceptions or not self.handlers.has_key(exceptions):
exceptions = self.defaulthandler
return self.handlers[exceptions](self, code, message, params)
def htmlhandler(self,code,message):
if code:
resp_text = '<h2>OGCServer Error:</h2><pre>%s</pre>\n<h3>Traceback:</h3><pre>%s</pre>\n' % (message, code)
else:
resp_text = message
return Response('text/html', resp_text)
def xmlhandler(self, code, message, params):
ogcexcetree = deepcopy(self.xmltemplate)
e = ogcexcetree.find(self.xpath)
e.text = message
if code:
e.set('code', code)
return Response(self.xmlmimetype, ElementTree.tostring(ogcexcetree))
def inimagehandler(self, code, message, params):
im = new('RGBA', (int(params['width']), int(params['height'])))
im.putalpha(new('1', (int(params['width']), int(params['height']))))
draw = Draw(im)
for count, line in enumerate(message.strip().split('\n')):
draw.text((12,15*(count+1)), line, fill='#000000')
fh = StringIO()
im.save(fh, PIL_TYPE_MAPPING[params['format']])
fh.seek(0)
return Response(params['format'], fh.read())
def blankhandler(self, code, message, params):
bgcolor = params.get('bgcolor', '#FFFFFF')
bgcolor = bgcolor.replace('0x', '#')
transparent = params.get('transparent', 'FALSE')
if transparent == 'TRUE':
im = new('RGBA', (int(params['width']), int(params['height'])))
im.putalpha(new('1', (int(params['width']), int(params['height']))))
else:
im = new('RGBA', (int(params['width']), int(params['height'])), bgcolor)
fh = StringIO()
im.save(fh, PIL_TYPE_MAPPING[params['format']])
fh.seek(0)
return Response(params['format'], fh.read())
class Projection(MapnikProjection):
def epsgstring(self):
return self.params().split('=')[1].upper()
class TextFeatureInfo:
def __init__(self):
self.buffer = ''
def addlayer(self, name):
self.buffer += '\n[%s]\n' % name
def addfeature(self):
pass#self.buffer += '\n'
def addattribute(self, name, value):
self.buffer += '%s=%s\n' % (name, str(value))
def __str__(self):
return self.buffer
class XMLFeatureInfo:
basexml = """<?xml version="1.0"?>
<resultset>
</resultset>
"""
def __init__(self):
self.rootelement = ElementTree.fromstring(self.basexml)
def addlayer(self, name):
layer = ElementTree.Element('layer')
layer.set('name', name)
self.rootelement.append(layer)
self.currentlayer = layer
def addfeature(self):
feature = ElementTree.Element('feature')
self.currentlayer.append(feature)
self.currentfeature = feature
def addattribute(self, name, value):
attribute = ElementTree.Element('attribute')
attname = ElementTree.Element('name')
attname.text = name
attvalue = ElementTree.Element('value')
attvalue.text = unicode(value)
attribute.append(attname)
attribute.append(attvalue)
self.currentfeature.append(attribute)
def __str__(self):
return '<?xml version="1.0"?>\n' + ElementTree.tostring(self.rootelement)

View file

@ -1,44 +0,0 @@
#
# This file is part of Mapnik (c++ mapping toolkit)
#
# Copyright (C) 2006 Jean-Francois Doyon
#
# Mapnik is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.
#
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#
# $Id$
""" Change SafeConfigParser behavior to treat options without values as
non-existent.
"""
from ConfigParser import SafeConfigParser as OrigSafeConfigParser
class SafeConfigParser(OrigSafeConfigParser):
def items_with_value(self, section):
finallist = []
items = self.items(section)
for item in items:
if item[1] != '':
finallist.append(item)
return finallist
def has_option_with_value(self, section, option):
if self.has_option(section, option):
if self.get(section, option) == '':
return False
else:
return False
return True

View file

@ -1,28 +0,0 @@
#
# This file is part of Mapnik (c++ mapping toolkit)
#
# Copyright (C) 2006 Jean-Francois Doyon
#
# Mapnik is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.
#
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#
# $Id$
"""Custom OGCServer Exceptions"""
class OGCException(Exception):
pass
class ServerConfigurationError(Exception):
pass

View file

@ -1,133 +0,0 @@
#
# This file is part of Mapnik (c++ mapping toolkit)
#
# Copyright (C) 2006 Jean-Francois Doyon
#
# Mapnik is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.
#
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#
# $Id: modserver.py 283 2006-07-22 18:54:53Z jdoyon $
"""Mod_python handler for Mapnik OGC WMS Server."""
import sys
from mod_python import apache, util
from exceptions import OGCException, ServerConfigurationError
from wms111 import ExceptionHandler as ExceptionHandler111
from wms130 import ExceptionHandler as ExceptionHandler130
from configparser import SafeConfigParser
from common import Version
class ModHandler(object):
def __init__(self, configpath):
conf = SafeConfigParser()
conf.readfp(open(configpath))
self.conf = conf
if not conf.has_option_with_value('server', 'module'):
raise ServerConfigurationError('The factory module is not defined in the configuration file.')
try:
mapfactorymodule = __import__(conf.get('server', 'module'))
except ImportError:
raise ServerConfigurationError('The factory module could not be loaded.')
if hasattr(mapfactorymodule, 'WMSFactory'):
self.mapfactory = getattr(mapfactorymodule, 'WMSFactory')()
else:
raise ServerConfigurationError('The factory module does not have a WMSFactory class.')
if conf.has_option('server', 'debug'):
self.debug = int(conf.get('server', 'debug'))
else:
self.debug = 0
if self.conf.has_option_with_value('server', 'maxage'):
self.max_age = 'max-age=%d' % self.conf.get('server', 'maxage')
else:
self.max_age = None
def __call__(self, apacheReq):
try:
reqparams = util.FieldStorage(apacheReq,keep_blank_values=1)
if not reqparams:
eh = ExceptionHandler130(self.debug)
response = eh.getresponse(reqparams)
apacheReq.content_type = response.content_type
else:
reqparams = lowerparams(reqparams)
port = apacheReq.connection.local_addr[1]
onlineresource = 'http://%s:%s%s?' % (apacheReq.hostname, port, apacheReq.subprocess_env['SCRIPT_NAME'])
if not reqparams.has_key('request'):
raise OGCException('Missing Request parameter.')
request = reqparams['request']
del reqparams['request']
if request == 'GetCapabilities' and not reqparams.has_key('service'):
raise OGCException('Missing service parameter.')
if request in ['GetMap', 'GetFeatureInfo']:
service = 'WMS'
else:
service = reqparams['service']
if reqparams.has_key('service'):
del reqparams['service']
try:
mapnikmodule = __import__('mapnik2.ogcserver.' + service)
except:
raise OGCException('Unsupported service "%s".' % service)
ServiceHandlerFactory = getattr(mapnikmodule.ogcserver, service).ServiceHandlerFactory
servicehandler = ServiceHandlerFactory(self.conf, self.mapfactory, onlineresource, reqparams.get('version', None))
if reqparams.has_key('version'):
del reqparams['version']
if request not in servicehandler.SERVICE_PARAMS.keys():
raise OGCException('Operation "%s" not supported.' % request, 'OperationNotSupported')
# Get parameters and pass to WMSFactory in custom "setup" method
ogcparams = servicehandler.processParameters(request, reqparams)
try:
requesthandler = getattr(servicehandler, request)
except:
raise OGCException('Operation "%s" not supported.' % request, 'OperationNotSupported')
response = requesthandler(ogcparams)
apacheReq.content_type = response.content_type
apacheReq.status = apache.HTTP_OK
except Exception, E:
return self.traceback(apacheReq,E)
if self.max_age:
apacheReq.headers_out.add('Cache-Control', max_age)
apacheReq.headers_out.add('Content-Length', str(len(response.content)))
apacheReq.send_http_header()
apacheReq.write(response.content)
return apache.OK
def traceback(self, apacheReq,E):
reqparams = lowerparams(util.FieldStorage(apacheReq))
version = reqparams.get('version', None)
if not version:
version = Version('1.3.0')
else:
version = Version(version)
if version >= '1.3.0':
eh = ExceptionHandler130(self.debug)
else:
eh = ExceptionHandler111(self.debug)
response = eh.getresponse(reqparams)
apacheReq.content_type = response.content_type
apacheReq.headers_out.add('Content-Length', str(len(response.content)))
apacheReq.send_http_header()
apacheReq.write(response.content)
return apache.OK
def lowerparams(params):
reqparams = {}
for key, value in params.items():
reqparams[key.lower()] = value
return reqparams

View file

@ -1,238 +0,0 @@
#
# This file is part of Mapnik (c++ mapping toolkit)
#
# Copyright (C) 2006 Jean-Francois Doyon
#
# Mapnik is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.
#
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#
# $Id$
"""WMS 1.1.1 compliant GetCapabilities, GetMap, GetFeatureInfo, and Exceptions interface."""
from common import ParameterDefinition, Response, Version, ListFactory, \
ColorFactory, CRSFactory, WMSBaseServiceHandler, CRS, \
BaseExceptionHandler, Projection
from exceptions import OGCException, ServerConfigurationError
from mapnik2 import Coord
try:
from lxml import etree as ElementTree
except ImportError:
import xml.etree.ElementTree as ElementTree
except ImportError:
import elementtree.ElementTree as ElementTree
class ServiceHandler(WMSBaseServiceHandler):
SERVICE_PARAMS = {
'GetCapabilities': {
'updatesequence': ParameterDefinition(False, str)
},
'GetMap': {
'layers': ParameterDefinition(True, ListFactory(str)),
'styles': ParameterDefinition(True, ListFactory(str)),
'srs': ParameterDefinition(True, CRSFactory(['EPSG'])),
'bbox': ParameterDefinition(True, ListFactory(float)),
'width': ParameterDefinition(True, int),
'height': ParameterDefinition(True, int),
'format': ParameterDefinition(True, str, allowedvalues=('image/png', 'image/jpeg')),
'transparent': ParameterDefinition(False, str, 'FALSE', ('TRUE', 'FALSE')),
'bgcolor': ParameterDefinition(False, ColorFactory, ColorFactory('0xFFFFFF')),
'exceptions': ParameterDefinition(False, str, 'application/vnd.ogc.se_xml', ('application/vnd.ogc.se_xml', 'application/vnd.ogc.se_inimage', 'application/vnd.ogc.se_blank','text/html'))
},
'GetFeatureInfo': {
'layers': ParameterDefinition(True, ListFactory(str)),
'styles': ParameterDefinition(False, ListFactory(str)),
'srs': ParameterDefinition(True, CRSFactory(['EPSG'])),
'bbox': ParameterDefinition(True, ListFactory(float)),
'width': ParameterDefinition(True, int),
'height': ParameterDefinition(True, int),
'format': ParameterDefinition(False, str, allowedvalues=('image/png', 'image/jpeg')),
'transparent': ParameterDefinition(False, str, 'FALSE', ('TRUE', 'FALSE')),
'bgcolor': ParameterDefinition(False, ColorFactory, ColorFactory('0xFFFFFF')),
'exceptions': ParameterDefinition(False, str, 'application/vnd.ogc.se_xml', ('application/vnd.ogc.se_xml', 'application/vnd.ogc.se_inimage', 'application/vnd.ogc.se_blank','text/html')),
'query_layers': ParameterDefinition(True, ListFactory(str)),
'info_format': ParameterDefinition(True, str, allowedvalues=('text/plain', 'text/xml')),
'feature_count': ParameterDefinition(False, int, 1),
'x': ParameterDefinition(True, int),
'y': ParameterDefinition(True, int)
}
}
CONF_SERVICE = [
['title', 'Title', str],
['abstract', 'Abstract', str],
['onlineresource', 'OnlineResource', str],
['fees', 'Fees', str],
['accessconstraints', 'AccessConstraints', str],
['keywordlist', 'KeywordList', str]
]
capabilitiesxmltemplate = """<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE WMT_MS_Capabilities SYSTEM "http://www.digitalearth.gov/wmt/xml/capabilities_1_1_1.dtd">
<WMT_MS_Capabilities version="1.1.1" updateSequence="0" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns="http://www.opengis.net/wms">
<Service>
<Name>WMS</Name>
</Service>
<Capability>
<Request>
<GetCapabilities>
<Format>application/vnd.ogc.wms_xml</Format>
<DCPType>
<HTTP>
<Get>
<OnlineResource xlink:type="simple"/>
</Get>
</HTTP>
</DCPType>
</GetCapabilities>
<GetMap>
<Format>image/png</Format>
<Format>image/jpeg</Format>
<DCPType>
<HTTP>
<Get>
<OnlineResource xlink:type="simple"/>
</Get>
</HTTP>
</DCPType>
</GetMap>
<GetFeatureInfo>
<Format>text/plain</Format>
<DCPType>
<HTTP>
<Get>
<OnlineResource xlink:type="simple"/>
</Get>
</HTTP>
</DCPType>
</GetFeatureInfo>
</Request>
<Exception>
<Format>application/vnd.ogc.se_xml</Format>
<Format>application/vnd.ogc.se_inimage</Format>
<Format>application/vnd.ogc.se_blank</Format>
</Exception>
<Layer>
<Title>A Mapnik WMS Server</Title>
<Abstract>A Mapnik WMS Server</Abstract>
</Layer>
</Capability>
</WMT_MS_Capabilities>
"""
def __init__(self, conf, mapfactory, opsonlineresource):
self.conf = conf
self.mapfactory = mapfactory
self.opsonlineresource = opsonlineresource
if self.conf.has_option('service', 'allowedepsgcodes'):
self.allowedepsgcodes = map(lambda code: 'epsg:%s' % code, self.conf.get('service', 'allowedepsgcodes').split(','))
else:
raise ServerConfigurationError('Allowed EPSG codes not properly configured.')
self.capabilities = None
def GetCapabilities(self, params):
if not self.capabilities:
capetree = ElementTree.fromstring(self.capabilitiesxmltemplate)
elements = capetree.findall('Capability//OnlineResource')
for element in elements:
element.set('{http://www.w3.org/1999/xlink}href', self.opsonlineresource)
self.processServiceCapabilities(capetree)
rootlayerelem = capetree.find('{http://www.opengis.net/wms}Capability/{http://www.opengis.net/wms}Layer')
for epsgcode in self.allowedepsgcodes:
rootlayercrs = ElementTree.Element('SRS')
rootlayercrs.text = epsgcode.upper()
rootlayerelem.append(rootlayercrs)
for layer in self.mapfactory.ordered_layers:
layerproj = Projection(layer.srs)
layername = ElementTree.Element('Name')
layername.text = layer.name
env = layer.envelope()
llp = layerproj.inverse(Coord(env.minx, env.miny))
urp = layerproj.inverse(Coord(env.maxx, env.maxy))
latlonbb = ElementTree.Element('LatLonBoundingBox')
latlonbb.set('minx', str(llp.x))
latlonbb.set('miny', str(llp.y))
latlonbb.set('maxx', str(urp.x))
latlonbb.set('maxy', str(urp.y))
layerbbox = ElementTree.Element('BoundingBox')
layerbbox.set('SRS', layerproj.epsgstring())
layerbbox.set('minx', str(env.minx))
layerbbox.set('miny', str(env.miny))
layerbbox.set('maxx', str(env.maxx))
layerbbox.set('maxy', str(env.maxy))
layere = ElementTree.Element('Layer')
layere.append(layername)
if layer.title:
layertitle = ElementTree.Element('Title')
layertitle.text = layer.title
layere.append(layertitle)
if layer.abstract:
layerabstract = ElementTree.Element('Abstract')
layerabstract.text = layer.abstract
layere.append(layerabstract)
if layer.queryable:
layere.set('queryable', '1')
layere.append(latlonbb)
layere.append(layerbbox)
if len(layer.wmsextrastyles) > 0:
for extrastyle in [layer.wmsdefaultstyle] + list(layer.wmsextrastyles):
style = ElementTree.Element('Style')
stylename = ElementTree.Element('Name')
stylename.text = extrastyle
styletitle = ElementTree.Element('Title')
styletitle.text = extrastyle
style.append(stylename)
style.append(styletitle)
layere.append(style)
rootlayerelem.append(layere)
self.capabilities = '<?xml version="1.0" encoding="UTF-8" standalone="no"?>\n' + ElementTree.tostring(capetree)
response = Response('application/vnd.ogc.wms_xml', self.capabilities)
return response
def GetMap(self, params):
params['crs'] = params['srs']
return WMSBaseServiceHandler.GetMap(self, params)
def GetFeatureInfo(self, params):
params['crs'] = params['srs']
params['i'] = params['x']
params['j'] = params['y']
return WMSBaseServiceHandler.GetFeatureInfo(self, params, 'query_map_point')
class ExceptionHandler(BaseExceptionHandler):
xmlmimetype = "application/vnd.ogc.se_xml"
xmltemplate = ElementTree.fromstring("""<?xml version='1.0' encoding="UTF-8" standalone="no"?>
<!DOCTYPE ServiceExceptionReport SYSTEM "http://www.digitalearth.gov/wmt/xml/exception_1_1_1.dtd">
<ServiceExceptionReport version="1.1.1">
<ServiceException />
</ServiceExceptionReport>
""")
xpath = 'ServiceException'
handlers = {'application/vnd.ogc.se_xml': BaseExceptionHandler.xmlhandler,
'application/vnd.ogc.se_inimage': BaseExceptionHandler.inimagehandler,
'application/vnd.ogc.se_blank': BaseExceptionHandler.blankhandler,
'text/html': BaseExceptionHandler.htmlhandler}
defaulthandler = 'application/vnd.ogc.se_xml'

View file

@ -1,264 +0,0 @@
#
# This file is part of Mapnik (c++ mapping toolkit)
#
# Copyright (C) 2006 Jean-Francois Doyon
#
# Mapnik is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.
#
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#
# $Id$
"""WMS 1.3.0 compliant GetCapabilities, GetMap, GetFeatureInfo, and Exceptions interface."""
from common import ParameterDefinition, Response, Version, ListFactory, \
ColorFactory, CRSFactory, CRS, WMSBaseServiceHandler, \
BaseExceptionHandler, Projection, Box2d
from exceptions import OGCException, ServerConfigurationError
from mapnik2 import Coord
try:
from lxml import etree as ElementTree
except ImportError:
import xml.etree.ElementTree as ElementTree
except ImportError:
import elementtree.ElementTree as ElementTree
class ServiceHandler(WMSBaseServiceHandler):
SERVICE_PARAMS = {
'GetCapabilities': {
'format': ParameterDefinition(False, str, 'text/xml', ('text/xml',), True),
'updatesequence': ParameterDefinition(False, str)
},
'GetMap': {
'layers': ParameterDefinition(True, ListFactory(str)),
'styles': ParameterDefinition(True, ListFactory(str)),
'crs': ParameterDefinition(True, CRSFactory(['EPSG'])),
'bbox': ParameterDefinition(True, ListFactory(float)),
'width': ParameterDefinition(True, int),
'height': ParameterDefinition(True, int),
'format': ParameterDefinition(True, str, allowedvalues=('image/png', 'image/jpeg')),
'transparent': ParameterDefinition(False, str, 'FALSE', ('TRUE', 'FALSE')),
'bgcolor': ParameterDefinition(False, ColorFactory, ColorFactory('0xFFFFFF')),
'exceptions': ParameterDefinition(False, str, 'XML', ('XML', 'INIMAGE', 'BLANK','HTML')),
},
'GetFeatureInfo': {
'layers': ParameterDefinition(True, ListFactory(str)),
'styles': ParameterDefinition(False, ListFactory(str)),
'crs': ParameterDefinition(True, CRSFactory(['EPSG'])),
'bbox': ParameterDefinition(True, ListFactory(float)),
'width': ParameterDefinition(True, int),
'height': ParameterDefinition(True, int),
'format': ParameterDefinition(False, str, allowedvalues=('image/png', 'image/jpeg')),
'transparent': ParameterDefinition(False, str, 'FALSE', ('TRUE', 'FALSE')),
'bgcolor': ParameterDefinition(False, ColorFactory, ColorFactory('0xFFFFFF')),
'exceptions': ParameterDefinition(False, str, 'XML', ('XML', 'INIMAGE', 'BLANK','HTML')),
'query_layers': ParameterDefinition(True, ListFactory(str)),
'info_format': ParameterDefinition(True, str, allowedvalues=('text/plain', 'text/xml')),
'feature_count': ParameterDefinition(False, int, 1),
'i': ParameterDefinition(True, float),
'j': ParameterDefinition(True, float)
}
}
CONF_SERVICE = [
['title', 'Title', str],
['abstract', 'Abstract', str],
['onlineresource', 'OnlineResource', str],
['fees', 'Fees', str],
['accessconstraints', 'AccessConstraints', str],
['layerlimit', 'LayerLimit', int],
['maxwidth', 'MaxWidth', int],
['maxheight', 'MaxHeight', int],
['keywordlist', 'KeywordList', str]
]
capabilitiesxmltemplate = """<?xml version="1.0" encoding="UTF-8"?>
<WMS_Capabilities version="1.3.0" xmlns="http://www.opengis.net/wms"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.opengis.net/wms http://schemas.opengis.net/wms/1.3.0/capabilities_1_3_0.xsd">
<Service>
<Name>WMS</Name>
</Service>
<Capability>
<Request>
<GetCapabilities>
<Format>text/xml</Format>
<DCPType>
<HTTP>
<Get>
<OnlineResource xlink:type="simple"/>
</Get>
</HTTP>
</DCPType>
</GetCapabilities>
<GetMap>
<Format>image/png</Format>
<Format>image/jpeg</Format>
<DCPType>
<HTTP>
<Get>
<OnlineResource xlink:type="simple"/>
</Get>
</HTTP>
</DCPType>
</GetMap>
<GetFeatureInfo>
<Format>text/plain</Format>
<DCPType>
<HTTP>
<Get>
<OnlineResource xlink:type="simple"/>
</Get>
</HTTP>
</DCPType>
</GetFeatureInfo>
</Request>
<Exception>
<Format>XML</Format>
<Format>INIMAGE</Format>
<Format>BLANK</Format>
</Exception>
<Layer>
<Title>A Mapnik WMS Server</Title>
<Abstract>A Mapnik WMS Server</Abstract>
</Layer>
</Capability>
</WMS_Capabilities>
"""
def __init__(self, conf, mapfactory, opsonlineresource):
self.conf = conf
self.mapfactory = mapfactory
self.opsonlineresource = opsonlineresource
if self.conf.has_option('service', 'allowedepsgcodes'):
self.allowedepsgcodes = map(lambda code: 'epsg:%s' % code, self.conf.get('service', 'allowedepsgcodes').split(','))
else:
raise ServerConfigurationError('Allowed EPSG codes not properly configured.')
self.capabilities = None
def GetCapabilities(self, params):
if not self.capabilities:
capetree = ElementTree.fromstring(self.capabilitiesxmltemplate)
elements = capetree.findall('{http://www.opengis.net/wms}Capability//{http://www.opengis.net/wms}OnlineResource')
for element in elements:
element.set('{http://www.w3.org/1999/xlink}href', self.opsonlineresource)
self.processServiceCapabilities(capetree)
rootlayerelem = capetree.find('{http://www.opengis.net/wms}Capability/{http://www.opengis.net/wms}Layer')
for epsgcode in self.allowedepsgcodes:
rootlayercrs = ElementTree.Element('CRS')
rootlayercrs.text = epsgcode.upper()
rootlayerelem.append(rootlayercrs)
for layer in self.mapfactory.ordered_layers:
layerproj = Projection(layer.srs)
layername = ElementTree.Element('Name')
layername.text = layer.name
env = layer.envelope()
layerexgbb = ElementTree.Element('EX_GeographicBoundingBox')
ll = layerproj.inverse(Coord(env.minx, env.miny))
ur = layerproj.inverse(Coord(env.maxx, env.maxy))
exgbb_wbl = ElementTree.Element('westBoundLongitude')
exgbb_wbl.text = str(ll.x)
layerexgbb.append(exgbb_wbl)
exgbb_ebl = ElementTree.Element('eastBoundLongitude')
exgbb_ebl.text = str(ur.x)
layerexgbb.append(exgbb_ebl)
exgbb_sbl = ElementTree.Element('southBoundLatitude')
exgbb_sbl.text = str(ll.y)
layerexgbb.append(exgbb_sbl)
exgbb_nbl = ElementTree.Element('northBoundLatitude')
exgbb_nbl.text = str(ur.y)
layerexgbb.append(exgbb_nbl)
layerbbox = ElementTree.Element('BoundingBox')
layerbbox.set('CRS', layerproj.epsgstring())
layerbbox.set('minx', str(env.minx))
layerbbox.set('miny', str(env.miny))
layerbbox.set('maxx', str(env.maxx))
layerbbox.set('maxy', str(env.maxy))
layere = ElementTree.Element('Layer')
layere.append(layername)
if layer.title:
layertitle = ElementTree.Element('Title')
layertitle.text = layer.title
layere.append(layertitle)
if layer.abstract:
layerabstract = ElementTree.Element('Abstract')
layerabstract.text = layer.abstract
layere.append(layerabstract)
if layer.queryable:
layere.set('queryable', '1')
layere.append(layerexgbb)
layere.append(layerbbox)
if len(layer.wmsextrastyles) > 0:
for extrastyle in [layer.wmsdefaultstyle] + list(layer.wmsextrastyles):
style = ElementTree.Element('Style')
stylename = ElementTree.Element('Name')
stylename.text = extrastyle
styletitle = ElementTree.Element('Title')
styletitle.text = extrastyle
style.append(stylename)
style.append(styletitle)
layere.append(style)
rootlayerelem.append(layere)
self.capabilities = '<?xml version="1.0" encoding="UTF-8"?>' + ElementTree.tostring(capetree)
response = Response('text/xml', self.capabilities)
return response
def GetMap(self, params):
if params['width'] > int(self.conf.get('service', 'maxwidth')) or params['height'] > int(self.conf.get('service', 'maxheight')):
raise OGCException('Requested map size exceeds limits set by this server.')
return WMSBaseServiceHandler.GetMap(self, params)
def _buildMap(self, params):
""" Override _buildMap method to handle reverse axis ordering in WMS 1.3.0.
More info: http://mapserver.org/development/rfc/ms-rfc-30.html
'when using epsg code >=4000 and <5000 will be assumed to have a reversed axes.'
"""
# Call superclass method
m = WMSBaseServiceHandler._buildMap(self, params)
# for range of epsg codes reverse axis
if params['crs'].code >= 4000 and params['crs'].code < 5000:
m.zoom_to_box(Box2d(params['bbox'][1], params['bbox'][0], params['bbox'][3], params['bbox'][2]))
return m
class ExceptionHandler(BaseExceptionHandler):
xmlmimetype = "text/xml"
xmltemplate = ElementTree.fromstring("""<?xml version='1.0' encoding="UTF-8"?>
<ServiceExceptionReport version="1.3.0"
xmlns="http://www.opengis.net/ogc"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.opengis.net/ogc http://schemas.opengis.net/wms/1.3.0/exceptions_1_3_0.xsd">
<ServiceException/>
</ServiceExceptionReport>
""")
xpath = '{http://www.opengis.net/ogc}ServiceException'
handlers = {'XML': BaseExceptionHandler.xmlhandler,
'INIMAGE': BaseExceptionHandler.inimagehandler,
'BLANK': BaseExceptionHandler.blankhandler,
'HTML': BaseExceptionHandler.htmlhandler}
defaulthandler = 'XML'

View file

@ -1,106 +0,0 @@
#
# This file is part of Mapnik (c++ mapping toolkit)
#
# Copyright (C) 2006 Jean-Francois Doyon
#
# Mapnik is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.
#
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#
# $Id$
"""WSGI application wrapper for Mapnik OGC WMS Server."""
from exceptions import OGCException, ServerConfigurationError
from configparser import SafeConfigParser
from cgi import parse_qs
from wms111 import ExceptionHandler as ExceptionHandler111
from wms130 import ExceptionHandler as ExceptionHandler130
from common import Version
class WSGIApp:
def __init__(self, configpath):
conf = SafeConfigParser()
conf.readfp(open(configpath))
self.conf = conf
if not conf.has_option_with_value('server', 'module'):
raise ServerConfigurationError('The factory module is not defined in the configuration file.')
try:
mapfactorymodule = __import__(conf.get('server', 'module'))
except ImportError:
raise ServerConfigurationError('The factory module could not be loaded.')
if hasattr(mapfactorymodule, 'WMSFactory'):
self.mapfactory = getattr(mapfactorymodule, 'WMSFactory')()
else:
raise ServerConfigurationError('The factory module does not have a WMSFactory class.')
if conf.has_option('server', 'debug'):
self.debug = int(conf.get('server', 'debug'))
else:
self.debug = 0
if self.conf.has_option_with_value('server', 'maxage'):
self.max_age = 'max-age=%d' % self.conf.get('server', 'maxage')
else:
self.max_age = None
def __call__(self, environ, start_response):
reqparams = {}
for key, value in parse_qs(environ['QUERY_STRING'], True).items():
reqparams[key.lower()] = value[0]
onlineresource = 'http://%s:%s%s?' % (environ['SERVER_NAME'], environ['SERVER_PORT'], environ['PATH_INFO'])
try:
if not reqparams.has_key('request'):
raise OGCException('Missing request parameter.')
request = reqparams['request']
del reqparams['request']
if request == 'GetCapabilities' and not reqparams.has_key('service'):
raise OGCException('Missing service parameter.')
if request in ['GetMap', 'GetFeatureInfo']:
service = 'WMS'
else:
service = reqparams['service']
if reqparams.has_key('service'):
del reqparams['service']
try:
mapnikmodule = __import__('mapnik2.ogcserver.' + service)
except:
raise OGCException('Unsupported service "%s".' % service)
ServiceHandlerFactory = getattr(mapnikmodule.ogcserver, service).ServiceHandlerFactory
servicehandler = ServiceHandlerFactory(self.conf, self.mapfactory, onlineresource, reqparams.get('version', None))
if reqparams.has_key('version'):
del reqparams['version']
if request not in servicehandler.SERVICE_PARAMS.keys():
raise OGCException('Operation "%s" not supported.' % request, 'OperationNotSupported')
ogcparams = servicehandler.processParameters(request, reqparams)
try:
requesthandler = getattr(servicehandler, request)
except:
raise OGCException('Operation "%s" not supported.' % request, 'OperationNotSupported')
response = requesthandler(ogcparams)
except:
version = reqparams.get('version', None)
if not version:
version = Version('1.3.0')
else:
version = Version(version)
if version >= '1.3.0':
eh = ExceptionHandler130(self.debug)
else:
eh = ExceptionHandler111(self.debug)
response = eh.getresponse(reqparams)
response_headers = [('Content-Type', response.content_type),('Content-Length', str(len(response.content)))]
if self.max_age:
response_headers.append(('Cache-Control', max_age))
start_response('200 OK', response_headers)
yield response.content

View file

@ -4,17 +4,18 @@
basic usage is along the lines of
import mapnik2
import mapnik
page = mapnik2.printing.PDFPrinter()
m = mapnik2.Map(100,100)
mapnik2.load_map(m, "my_xml_map_description", True)
page = mapnik.printing.PDFPrinter()
m = mapnik.Map(100,100)
mapnik.load_map(m, "my_xml_map_description", True)
m.zoom_all()
page.render_map(m,"my_output_file.pdf")
see the documentation of mapnik2.printing.PDFPrinter() for options
see the documentation of mapnik.printing.PDFPrinter() for options
"""
from __future__ import absolute_import
from . import render, Map, Box2d, MemoryDatasource, Layer, Feature, Projection, ProjTransform, Coord, Style, Rule, Geometry2d
import math

View file

@ -0,0 +1,27 @@
#
# This file is part of Mapnik (C++/Python mapping toolkit)
# Copyright (C) 2011 Artem Pavlenko
#
# Mapnik is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
# mapnik2 module (Deprecated)
import warnings
from mapnik import *
warnings.simplefilter("default")
msg=""" mapnik2 module has been deprecated,
please use 'import mapnik' """
warnings.warn(msg, DeprecationWarning)

View file

@ -1,5 +1,5 @@
/*****************************************************************************
*
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2006 Artem Pavlenko, Jean-Francois Doyon
@ -40,7 +40,7 @@ struct color_pickle_suite : boost::python::pickle_suite
}
};
void export_color ()
void export_color ()
{
using namespace boost::python;
class_<color>("Color", init<int,int,int,int>(

View file

@ -1,5 +1,5 @@
/*****************************************************************************
*
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2006 Artem Pavlenko, Jean-Francois Doyon
@ -42,7 +42,7 @@ struct coord_pickle_suite : boost::python::pickle_suite
void export_coord()
{
using namespace boost::python;
class_<coord<double,2> >("Coord",init<double, double>(
class_<coord<double,2> >("Coord",init<double, double>(
// class docstring is in mapnik/__init__.py, class _Coord
(arg("x"), arg("y")),
"Constructs a new point with the given coordinates.\n")
@ -59,7 +59,7 @@ void export_coord()
.def(self - self) // __sub__
.def(self - float())
.def(self * float()) //__mult__
.def(float() * self)
.def(float() * self)
.def(self / float()) // __div__
;
}

View file

@ -1,5 +1,5 @@
/*****************************************************************************
*
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2006 Artem Pavlenko, Jean-Francois Doyon
@ -41,7 +41,7 @@ using mapnik::memory_datasource;
using mapnik::layer_descriptor;
using mapnik::attribute_descriptor;
namespace
namespace
{
//user-friendly wrapper that uses Python dictionary
using namespace boost::python;
@ -54,17 +54,17 @@ boost::shared_ptr<mapnik::datasource> create_datasource(const dict& d)
{
std::string key = extract<std::string>(keys[i]);
object obj = d[key];
if (key == "bind")
{
bind = extract<bool>(obj)();
continue;
}
extract<std::string> ex0(obj);
extract<int> ex1(obj);
extract<double> ex2(obj);
if (ex0.check())
{
params[key] = ex0();
@ -78,10 +78,10 @@ boost::shared_ptr<mapnik::datasource> create_datasource(const dict& d)
params[key] = ex2();
}
}
return mapnik::datasource_cache::create(params, bind);
}
std::string describe(boost::shared_ptr<mapnik::datasource> const& ds)
{
std::stringstream ss;
@ -95,7 +95,7 @@ std::string describe(boost::shared_ptr<mapnik::datasource> const& ds)
}
return ss.str();
}
std::string encoding(boost::shared_ptr<mapnik::datasource> const& ds)
{
layer_descriptor ld = ds->get_descriptor();
@ -134,7 +134,7 @@ boost::python::list field_types(boost::shared_ptr<mapnik::datasource> const& ds)
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();
if (type == mapnik::Integer)
// this crashes, so send back strings instead
@ -162,7 +162,7 @@ boost::python::list field_types(boost::shared_ptr<mapnik::datasource> const& ds)
void export_datasource()
{
using namespace boost::python;
class_<datasource,boost::shared_ptr<datasource>,
boost::noncopyable>("Datasource",no_init)
.def("envelope",&datasource::envelope)
@ -174,11 +174,11 @@ void export_datasource()
.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. "
.def("params",&datasource::params,return_value_policy<copy_const_reference>(),
"The configuration parameters of the data source. "
"These vary depending on the type of data source.")
;
def("Describe",&describe);
def("CreateDatasource",&create_datasource);

View file

@ -1,5 +1,5 @@
/*****************************************************************************
*
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2006 Artem Pavlenko, Jean-Francois Doyon
@ -36,7 +36,7 @@ void export_datasource_cache()
return_value_policy<reference_existing_object>())
.staticmethod("instance")
;
class_<datasource_cache,bases<singleton<datasource_cache,CreateStatic> >,
boost::noncopyable>("DatasourceCache",no_init)
.def("create",&datasource_cache::create)
@ -44,6 +44,6 @@ void export_datasource_cache()
.def("register_datasources",&datasource_cache::register_datasources)
.staticmethod("register_datasources")
.def("plugin_names",&datasource_cache::plugin_names)
.staticmethod("plugin_names")
.staticmethod("plugin_names")
;
}

View file

@ -1,5 +1,5 @@
/*****************************************************************************
*
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2006 Artem Pavlenko, Jean-Francois Doyon
@ -26,7 +26,7 @@ namespace mapnik {
template <typename EnumWrapper>
class enumeration_ :
public boost::python::enum_<typename EnumWrapper::native_type>
public boost::python::enum_<typename EnumWrapper::native_type>
{
// some short cuts
typedef boost::python::enum_<typename EnumWrapper::native_type> base_type;
@ -46,7 +46,7 @@ public:
enumeration_(const char * python_alias, const char * doc) :
base_type( python_alias, doc )
#else
enumeration_(const char * python_alias, const char * /*doc*/) :
enumeration_(const char * python_alias, const char * /*doc*/) :
// Boost.Python < 1.35.0 doesn't support
// docstrings for enums so we ignore it.
base_type( python_alias )

View file

@ -1,5 +1,5 @@
/*****************************************************************************
*
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2006 Artem Pavlenko, Jean-Francois Doyon
@ -102,13 +102,13 @@ void export_envelope()
"Equivalent to Box2d(ll.x, ll.y, ur.x, ur.y).\n"))
.def("from_string",from_string)
.staticmethod("from_string")
.add_property("minx", &box2d<double>::minx,
.add_property("minx", &box2d<double>::minx,
"X coordinate for the lower left corner")
.add_property("miny", &box2d<double>::miny,
.add_property("miny", &box2d<double>::miny,
"Y coordinate for the lower left corner")
.add_property("maxx", &box2d<double>::maxx,
"X coordinate for the upper right corner")
.add_property("maxy", &box2d<double>::maxy,
.add_property("maxy", &box2d<double>::maxy,
"Y coordinate for the upper right corner")
.def("center", &box2d<double>::center,
"Returns the coordinates of the center of the bounding box.\n"
@ -259,14 +259,13 @@ void export_envelope()
">>> e1 = Box2d(0, 0, 100, 100)\n"
">>> e2 = Box2d(50, 50, 150, 150)\n"
">>> e1.intersect(e2)\n"
"Box2d(50.0, 50.0, 100.0, 100.0)\n"
"Box2d(50.0, 50.0, 100.0, 100.0)\n"
)
.def(self == self) // __eq__
.def(self != self) // __neq__
.def(self + self) // __add__
//.def(self - self) // __sub__
.def(self * float()) // __mult__
.def(float() * self)
.def(float() * self)
.def(self / float()) // __div__
.def("__getitem__",&box2d<double>::operator[])
.def("valid",&box2d<double>::valid)

View file

@ -1,5 +1,5 @@
/*****************************************************************************
*
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2006 Artem Pavlenko, Jean-Francois Doyon
@ -76,7 +76,7 @@ void export_expression()
.def("evaluate", &expression_evaluate_)
.def("__str__",&to_expression_string);
;
def("Expression",&parse_expression_,(arg("expr")),"Expression string");
class_<mapnik::path_expression ,boost::noncopyable>("PathExpression",
@ -85,6 +85,6 @@ void export_expression()
.def("evaluate", &path_evaluate_) // note: "pass" is a reserved word in Python
.def("__str__",&path_to_string_);
;
def("PathExpression",&parse_path_,(arg("expr")),"PathExpression string");
}

View file

@ -1,5 +1,5 @@
/*****************************************************************************
*
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2006 Artem Pavlenko, Jean-Francois Doyon
@ -34,7 +34,6 @@
#include <mapnik/datasource.hpp>
#include <mapnik/wkb.hpp>
#include <mapnik/wkt/wkt_factory.hpp>
#include "mapnik_value_converter.hpp"
mapnik::geometry_type & (mapnik::Feature::*get_geom1)(unsigned) = &mapnik::Feature::get_geometry;
@ -59,7 +58,7 @@ void feature_add_geometries_from_wkt(Feature &feature, std::string wkt)
namespace boost { namespace python {
// Forward declaration
// Forward declaration
template <class Container, bool NoProxy, class DerivedPolicies>
class map_indexing_suite2;
@ -70,7 +69,7 @@ namespace boost { namespace python {
: public map_indexing_suite2<Container,
NoProxy, final_map_derived_policies<Container, NoProxy> > {};
}
template <class Container,bool NoProxy = false,
class DerivedPolicies = detail::final_map_derived_policies<Container, NoProxy> >
class map_indexing_suite2
@ -95,9 +94,11 @@ namespace boost { namespace python {
template <class Class>
static void
extension_def(Class& /*cl*/)
extension_def(Class& cl)
{
cl
.def("get", &get)
;
}
static data_type&
@ -106,42 +107,55 @@ namespace boost { namespace python {
typename Container::iterator i = container.props().find(i_);
if (i == container.end())
{
PyErr_SetString(PyExc_KeyError, "Invalid key");
PyErr_SetString(PyExc_KeyError, i_.c_str());
throw_error_already_set();
}
// will be auto-converted to proper python type by `mapnik_value_to_python`
return i->second;
}
static data_type
get(Container& container, index_type i_)
{
typename Container::iterator i = container.props().find(i_);
if (i != container.end())
{
// will be auto-converted to proper python type by `mapnik_value_to_python`
return i->second;
}
return mapnik::value_null();
}
static void
set_item(Container& container, index_type i, data_type const& v)
{
container[i] = v;
}
static void
delete_item(Container& container, index_type i)
{
container.props().erase(i);
}
static size_t
size(Container& container)
{
return container.props().size();
}
static bool
contains(Container& container, key_type const& key)
{
return container.props().find(key) != container.end();
}
static bool
compare_index(Container& container, index_type a, index_type b)
{
return container.props().key_comp()(a, b);
}
static index_type
convert_index(Container& /*container*/, PyObject* i_)
{
@ -156,13 +170,13 @@ namespace boost { namespace python {
if (i.check())
return i();
}
PyErr_SetString(PyExc_TypeError, "Invalid index type");
throw_error_already_set();
return index_type();
}
};
template <typename T1, typename T2>
struct std_pair_to_tuple
@ -173,7 +187,7 @@ namespace boost { namespace python {
boost::python::make_tuple(p.first, p.second).ptr());
}
};
template <typename T1, typename T2>
struct std_pair_to_python_converter
{
@ -201,9 +215,9 @@ struct UnicodeString_from_python_str
{
if (!(
#if PY_VERSION_HEX >= 0x03000000
PyBytes_Check(obj_ptr)
PyBytes_Check(obj_ptr)
#else
PyString_Check(obj_ptr)
PyString_Check(obj_ptr)
#endif
|| PyUnicode_Check(obj_ptr)))
return 0;
@ -245,7 +259,7 @@ void export_feature()
{
using namespace boost::python;
using mapnik::Feature;
implicitly_convertible<int,mapnik::value>();
implicitly_convertible<double,mapnik::value>();
implicitly_convertible<UnicodeString,mapnik::value>();
@ -253,7 +267,7 @@ void export_feature()
std_pair_to_python_converter<std::string const,mapnik::value>();
UnicodeString_from_python_str();
class_<Feature,boost::shared_ptr<Feature>,
boost::noncopyable>("Feature",init<int>("Default ctor."))
.def("id",&Feature::id)

View file

@ -1,5 +1,5 @@
/*****************************************************************************
*
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2006 Artem Pavlenko, Jean-Francois Doyon
@ -65,21 +65,21 @@ void export_featureset()
using namespace boost::python;
using mapnik::Feature;
using mapnik::Featureset;
class_<Featureset,boost::shared_ptr<Featureset>,
boost::noncopyable>("Featureset",no_init)
.def("__iter__",pass_through)
.def("next",next)
.add_property("features",features,
"The list of features.\n"
"\n"
"Usage:\n"
">>> m.query_map_point(0, 10, 10)\n"
"<mapnik2._mapnik2.Featureset object at 0x1004d2938>\n"
">>> fs = m.query_map_point(0, 10, 10)\n"
">>> for f in fs.features:\n"
">>> print f\n"
"<mapnik2.Feature object at 0x105e64140>\n"
"The list of features.\n"
"\n"
"Usage:\n"
">>> m.query_map_point(0, 10, 10)\n"
"<mapnik._mapnik.Featureset object at 0x1004d2938>\n"
">>> fs = m.query_map_point(0, 10, 10)\n"
">>> for f in fs.features:\n"
">>> print f\n"
"<mapnik.Feature object at 0x105e64140>\n"
)
;
}

View file

@ -1,5 +1,5 @@
/*****************************************************************************
*
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2006 Artem Pavlenko, Jean-Francois Doyon

View file

@ -1,5 +1,5 @@
/*****************************************************************************
*
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* This library is free software; you can redistribute it and/or
@ -31,6 +31,7 @@
#include <mapnik/geometry.hpp>
#include <mapnik/wkt/wkt_factory.hpp>
#include <mapnik/wkb.hpp>
#include <mapnik/util/geometry_to_wkb.hpp>
namespace {
@ -47,23 +48,51 @@ geometry_type const& getitem_impl(path_type & p, int key)
throw boost::python::error_already_set();
}
void from_wkt_impl(path_type& p, std::string const& wkt)
void add_wkt_impl(path_type& p, std::string const& wkt)
{
bool result = mapnik::from_wkt(wkt, p);
bool result = mapnik::from_wkt(wkt , p);
if (!result) throw std::runtime_error("Failed to parse WKT");
}
void from_wkb_impl(path_type& p, std::string const& wkb)
void add_wkb_impl(path_type& p, std::string const& wkb)
{
mapnik::geometry_utils::from_wkb(p, wkb.c_str(), wkb.size(), true);
}
boost::shared_ptr<path_type> from_wkt_impl(std::string const& wkt)
{
boost::shared_ptr<path_type> paths = boost::make_shared<path_type>();
bool result = mapnik::from_wkt(wkt, *paths);
if (!result) throw std::runtime_error("Failed to parse WKT");
return paths;
}
boost::shared_ptr<path_type> from_wkb_impl(std::string const& wkb)
{
boost::shared_ptr<path_type> paths = boost::make_shared<path_type>();
mapnik::geometry_utils::from_wkb(*paths, wkb.c_str(), wkb.size(), true);
return paths;
}
}
PyObject* to_wkb( geometry_type const& geom)
{
mapnik::util::wkb_buffer_ptr wkb = mapnik::util::to_wkb(geom,mapnik::util::wkbXDR);
return
#if PY_VERSION_HEX >= 0x03000000
::PyBytes_FromStringAndSize
#else
::PyString_FromStringAndSize
#endif
((const char*)wkb->buffer(),wkb->size());
}
void export_geometry()
{
using namespace boost::python;
enum_<mapnik::eGeomType>("GeometryType")
.value("Point",mapnik::Point)
.value("LineString",mapnik::LineString)
@ -72,21 +101,25 @@ void export_geometry()
.value("MultiLineString",mapnik::MultiLineString)
.value("MultiPolygon",mapnik::MultiPolygon)
;
using mapnik::geometry_type;
class_<geometry_type, std::auto_ptr<geometry_type>,boost::noncopyable>("Geometry2d",no_init)
class_<geometry_type, std::auto_ptr<geometry_type>, boost::noncopyable>("Geometry2d",no_init)
.def("envelope",&geometry_type::envelope)
// .def("__str__",&geometry_type::to_string)
.def("type",&geometry_type::type)
.def("area",&geometry_type::area)
.def("to_wkb",&to_wkb)
// TODO add other geometry_type methods
;
class_<path_type,boost::noncopyable>("Path")
class_<path_type, boost::shared_ptr<path_type>, boost::noncopyable>("Path")
.def("__getitem__", getitem_impl,return_value_policy<reference_existing_object>())
.def("__len__", &path_type::size)
.def("add_wkt",add_wkt_impl)
.def("add_wkb",add_wkb_impl)
.def("from_wkt",from_wkt_impl)
.def("from_wkb",from_wkb_impl)
.staticmethod("from_wkt")
.staticmethod("from_wkb")
;
}

View file

@ -73,7 +73,7 @@ void export_glyph_symbolizer()
&glyph_symbolizer::set_halo_fill)
.add_property("halo_radius",
&glyph_symbolizer::get_halo_radius,
&glyph_symbolizer::get_halo_radius,
&glyph_symbolizer::set_halo_radius)
.add_property("size",
@ -117,5 +117,5 @@ void export_glyph_symbolizer()
"defined).\n"
"Only needed if no explicit color is provided"
)
;
;
}

View file

@ -1,5 +1,5 @@
/*****************************************************************************
*
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2011 Artem Pavlenko
@ -43,10 +43,10 @@ bool painted(mapnik::grid const& grid)
void export_grid()
{
class_<mapnik::grid,boost::shared_ptr<mapnik::grid> >(
"Grid",
"This class represents a feature hitgrid.",
init<int,int,std::string,unsigned>(
( arg("width"),arg("height"),arg("key")="__id__",arg("resolution")=1 ),
"Grid",
"This class represents a feature hitgrid.",
init<int,int,std::string,unsigned>(
( boost::python::arg("width"), boost::python::arg("height"),boost::python::arg("key")="__id__", boost::python::arg("resolution")=1 ),
"Create a mapnik.Grid object\n"
))
.def("painted",&painted)
@ -54,16 +54,16 @@ void export_grid()
.def("height",&mapnik::grid::height)
.def("view",&mapnik::grid::get_view)
.def("encode",encode,
( arg("encoding")="utf",arg("features")=true,arg("resolution")=4 ),
"Encode the grid as as optimized json\n"
( boost::python::arg("encoding")="utf", boost::python::arg("features")=true,boost::python::arg("resolution")=4 ),
"Encode the grid as as optimized json\n"
)
.add_property("key",
make_function(&mapnik::grid::get_key,return_value_policy<copy_const_reference>()),
&mapnik::grid::set_key,
"Get/Set key to be used as unique indentifier for features\n"
"The value should either be __id__ to refer to the feature.id()\n"
"or some globally unique integer or string attribute field\n"
)
make_function(&mapnik::grid::get_key,return_value_policy<copy_const_reference>()),
&mapnik::grid::set_key,
"Get/Set key to be used as unique indentifier for features\n"
"The value should either be __id__ to refer to the feature.id()\n"
"or some globally unique integer or string attribute field\n"
)
;
}

View file

@ -1,5 +1,5 @@
/*****************************************************************************
*
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2011 Artem Pavlenko
@ -40,13 +40,13 @@ static dict (*encode)( mapnik::grid_view const&, std::string, bool, unsigned int
void export_grid_view()
{
class_<mapnik::grid_view,
boost::shared_ptr<mapnik::grid_view> >("GridView",
"This class represents a feature hitgrid subset.",no_init)
boost::shared_ptr<mapnik::grid_view> >("GridView",
"This class represents a feature hitgrid subset.",no_init)
.def("width",&mapnik::grid_view::width)
.def("height",&mapnik::grid_view::height)
.def("encode",encode,
( arg("encoding")="utf",arg("add_features")=true,arg("resolution")=4 ),
"Encode the grid as as optimized json\n"
( boost::python::arg("encoding")="utf",boost::python::arg("add_features")=true,boost::python::arg("resolution")=4 ),
"Encode the grid as as optimized json\n"
)
;
}

View file

@ -1,5 +1,5 @@
/*****************************************************************************
*
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2006 Artem Pavlenko, Jean-Francois Doyon
@ -68,7 +68,7 @@ PyObject* tostring1( image_32 const& im)
{
int size = im.width() * im.height() * 4;
return
#if PY_VERSION_HEX >= 0x03000000
#if PY_VERSION_HEX >= 0x03000000
::PyBytes_FromStringAndSize
#else
::PyString_FromStringAndSize
@ -81,24 +81,24 @@ PyObject* tostring2(image_32 const & im, std::string const& format)
{
std::string s = save_to_string(im, format);
return
#if PY_VERSION_HEX >= 0x03000000
#if PY_VERSION_HEX >= 0x03000000
::PyBytes_FromStringAndSize
#else
::PyString_FromStringAndSize
#endif
(s.data(),s.size());
(s.data(),s.size());
}
PyObject* tostring3(image_32 const & im, std::string const& format, mapnik::rgba_palette const& pal)
{
std::string s = save_to_string(im, format, pal);
return
#if PY_VERSION_HEX >= 0x03000000
#if PY_VERSION_HEX >= 0x03000000
::PyBytes_FromStringAndSize
#else
::PyString_FromStringAndSize
#endif
(s.data(),s.size());
(s.data(),s.size());
}
@ -131,16 +131,16 @@ boost::shared_ptr<image_32> open_from_file(std::string const& filename)
std::auto_ptr<image_reader> reader(get_image_reader(filename,*type));
if (reader.get())
{
boost::shared_ptr<image_32> image_ptr = boost::make_shared<image_32>(reader->width(),reader->height());
reader->read(0,0,image_ptr->data());
return image_ptr;
}
throw mapnik::image_reader_exception("Failed to load: " + filename);
throw mapnik::image_reader_exception("Failed to load: " + filename);
}
throw mapnik::image_reader_exception("Unsupported image format:" + filename);
}
void blend (image_32 & im, unsigned x, unsigned y, image_32 const& im2, float opacity)
{
im.set_rectangle_alpha2(im2.data(),x,y,opacity);
@ -169,7 +169,7 @@ void export_image()
.value("src", mapnik::src)
.value("dst", mapnik::dst)
.value("src_over", mapnik::src_over)
.value("dst_over", mapnik::dst_over)
.value("dst_over", mapnik::dst_over)
.value("src_in", mapnik::src_in)
.value("dst_in", mapnik::dst_in)
.value("src_out", mapnik::src_out)
@ -194,7 +194,7 @@ void export_image()
.value("invert", mapnik::invert)
.value("invert_rgb", mapnik::invert_rgb)
;
class_<image_32,boost::shared_ptr<image_32> >("Image","This class represents a 32 bit RGBA image.",init<int,int>())
.def("width",&image_32::width)
.def("height",&image_32::height)
@ -209,7 +209,7 @@ void export_image()
.def("blend",&blend)
.def("composite",&composite)
//TODO(haoyu) The method name 'tostring' might be confusing since they actually return bytes in Python 3
.def("tostring",&tostring1)
.def("tostring",&tostring2)
.def("tostring",&tostring3)
@ -222,6 +222,6 @@ void export_image()
.def("from_cairo",&from_cairo)
.staticmethod("from_cairo")
#endif
;
;
}

View file

@ -1,5 +1,5 @@
/*****************************************************************************
*
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2006 Artem Pavlenko, Jean-Francois Doyon
@ -48,10 +48,10 @@ PyObject* view_tostring1(image_view<image_data_32> const& view)
std::ostringstream ss(std::ios::out|std::ios::binary);
for (unsigned i=0;i<view.height();i++)
{
ss.write(reinterpret_cast<const char*>(view.getRow(i)),
ss.write(reinterpret_cast<const char*>(view.getRow(i)),
view.width() * sizeof(image_view<image_data_32>::pixel_type));
}
return
return
#if PY_VERSION_HEX >= 0x03000000
::PyBytes_FromStringAndSize
#else
@ -64,7 +64,7 @@ PyObject* view_tostring1(image_view<image_data_32> const& view)
PyObject* view_tostring2(image_view<image_data_32> const & view, std::string const& format)
{
std::string s = save_to_string(view, format);
return
return
#if PY_VERSION_HEX >= 0x03000000
::PyBytes_FromStringAndSize
#else
@ -76,7 +76,7 @@ PyObject* view_tostring2(image_view<image_data_32> const & view, std::string con
PyObject* view_tostring3(image_view<image_data_32> const & view, std::string const& format, mapnik::rgba_palette const& pal)
{
std::string s = save_to_string(view, format, pal);
return
return
#if PY_VERSION_HEX >= 0x03000000
::PyBytes_FromStringAndSize
#else
@ -85,22 +85,22 @@ PyObject* view_tostring3(image_view<image_data_32> const & view, std::string con
(s.data(),s.size());
}
void save_view1(image_view<image_data_32> const& view,
void save_view1(image_view<image_data_32> const& view,
std::string const& filename)
{
save_to_file(view,filename);
}
void save_view2(image_view<image_data_32> const& view,
std::string const& filename,
void save_view2(image_view<image_data_32> const& view,
std::string const& filename,
std::string const& type)
{
save_to_file(view,filename,type);
}
void save_view3(image_view<image_data_32> const& view,
std::string const& filename,
std::string const& type,
void save_view3(image_view<image_data_32> const& view,
std::string const& filename,
std::string const& type,
mapnik::rgba_palette const& pal)
{
save_to_file(view,filename,type,pal);

View file

@ -1,5 +1,5 @@
/*****************************************************************************
*
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2011 Artem Pavlenko
@ -33,36 +33,36 @@ using mapnik::metawriter_inmem;
using mapnik::metawriter_inmem_ptr;
namespace {
std::map<std::string, mapnik::value>::const_iterator
std::map<std::string, mapnik::value>::const_iterator
mapnik_value_map_begin(const std::map<std::string, mapnik::value> &m) {
return m.begin();
return m.begin();
}
std::map<std::string, mapnik::value>::const_iterator
std::map<std::string, mapnik::value>::const_iterator
mapnik_value_map_end(const std::map<std::string, mapnik::value> &m) {
return m.end();
return m.end();
}
}
void export_inmem_metawriter() {
using namespace boost::python;
using namespace boost::python;
class_<std::map<std::string, mapnik::value> >
("MapnikProperties", "Retarded.", init<>())
.def("__iter__", range(&mapnik_value_map_begin, &mapnik_value_map_end))
;
class_<std::map<std::string, mapnik::value> >
("MapnikProperties", "Retarded.", init<>())
.def("__iter__", range(&mapnik_value_map_begin, &mapnik_value_map_end))
;
class_<metawriter_inmem::meta_instance>
("MetaInstance", "Single rendered instance of meta-information.", no_init)
.def_readonly("box", &metawriter_inmem::meta_instance::box)
.def_readonly("properties", &metawriter_inmem::meta_instance::properties)
;
class_<metawriter_inmem::meta_instance>
("MetaInstance", "Single rendered instance of meta-information.", no_init)
.def_readonly("box", &metawriter_inmem::meta_instance::box)
.def_readonly("properties", &metawriter_inmem::meta_instance::properties)
;
class_<metawriter_inmem, metawriter_inmem_ptr, boost::noncopyable>
("MetaWriterInMem",
"Collects meta-information about elements rendered.",
no_init)
.def("__iter__", range(&metawriter_inmem::inst_begin,
&metawriter_inmem::inst_end))
;
class_<metawriter_inmem, metawriter_inmem_ptr, boost::noncopyable>
("MetaWriterInMem",
"Collects meta-information about elements rendered.",
no_init)
.def("__iter__", range(&metawriter_inmem::inst_begin,
&metawriter_inmem::inst_end))
;
}

View file

@ -0,0 +1,123 @@
/*****************************************************************************
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2011 Artem Pavlenko
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*****************************************************************************/
#include <boost/python.hpp>
#include <boost/python/module.hpp>
#include <boost/python/def.hpp>
#include <boost/make_shared.hpp>
#include <mapnik/label_collision_detector.hpp>
#include <mapnik/map.hpp>
#include <list>
using mapnik::label_collision_detector4;
using mapnik::box2d;
using mapnik::Map;
using boost::make_shared;
namespace
{
boost::shared_ptr<label_collision_detector4>
create_label_collision_detector_from_extent(box2d<double> const &extent)
{
return make_shared<label_collision_detector4>(extent);
}
boost::shared_ptr<label_collision_detector4>
create_label_collision_detector_from_map(Map const &m)
{
double buffer = m.buffer_size();
box2d<double> extent(-buffer, -buffer, m.width() + buffer, m.height() + buffer);
return make_shared<label_collision_detector4>(extent);
}
boost::python::list
make_label_boxes(boost::shared_ptr<label_collision_detector4> det)
{
boost::python::list boxes;
for (label_collision_detector4::query_iterator jtr = det->begin();
jtr != det->end(); ++jtr)
{
boxes.append<box2d<double> >(jtr->box);
}
return boxes;
}
}
void export_label_collision_detector()
{
using namespace boost::python;
// for overload resolution
void (label_collision_detector4::*insert_box)(box2d<double> const &) = &label_collision_detector4::insert;
class_<label_collision_detector4, boost::shared_ptr<label_collision_detector4>, boost::noncopyable>
("LabelCollisionDetector",
"Object to detect collisions between labels, used in the rendering process.",
no_init)
.def("__init__", make_constructor(create_label_collision_detector_from_extent),
"Creates an empty collision detection object with a given extent. Note "
"that the constructor from Map objects is a sensible default and usually "
"what you want to do.\n"
"\n"
"Example:\n"
">>> m = Map(size_x, size_y)\n"
">>> buf_sz = m.buffer_size\n"
">>> extent = mapnik.Box2d(-buf_sz, -buf_sz, m.width + buf_sz, m.height + buf_sz)\n"
">>> detector = mapnik.LabelCollisionDetector(extent)")
.def("__init__", make_constructor(create_label_collision_detector_from_map),
"Creates an empty collision detection object matching the given Map object. "
"The created detector will have the same size, including the buffer, as the "
"map object. This is usually what you want to do.\n"
"\n"
"Example:\n"
">>> m = Map(size_x, size_y)\n"
">>> detector = mapnik.LabelCollisionDetector(m)")
.def("extent", &label_collision_detector4::extent, return_value_policy<copy_const_reference>(),
"Returns the total extent (bounding box) of all labels inside the detector.\n"
"\n"
"Example:\n"
">>> detector.extent()\n"
"Box2d(573.252589209,494.789179821,584.261023823,496.83610261)")
.def("boxes", &make_label_boxes,
"Returns a list of all the label boxes inside the detector.")
.def("insert", insert_box,
"Insert a 2d box into the collision detector. This can be used to ensure that "
"some space is left clear on the map for later overdrawing, for example by "
"non-Mapnik processes.\n"
"\n"
"Example:\n"
">>> m = Map(size_x, size_y)\n"
">>> detector = mapnik.LabelCollisionDetector(m)"
">>> detector.insert(mapnik.Box2d(196, 254, 291, 389))")
;
}

View file

@ -1,5 +1,5 @@
/*****************************************************************************
*
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2006 Artem Pavlenko, Jean-Francois Doyon
@ -53,7 +53,7 @@ struct layer_pickle_suite : boost::python::pickle_suite
for (unsigned i = 0; i < style_names.size(); ++i)
{
s.append(style_names[i]);
}
}
return boost::python::make_tuple(l.abstract(),l.title(),l.clear_label_cache(),l.getMinZoom(),l.getMaxZoom(),l.isQueryable(),l.datasource()->params(),l.cache_features(),s);
}
@ -84,7 +84,7 @@ struct layer_pickle_suite : boost::python::pickle_suite
mapnik::parameters params = extract<parameters>(state[6]);
l.set_datasource(datasource_cache::instance()->create(params));
boost::python::list s = extract<boost::python::list>(state[7]);
for (int i=0;i<len(s);++i)
{
@ -103,7 +103,7 @@ void export_layer()
class_<std::vector<std::string> >("Names")
.def(vector_indexing_suite<std::vector<std::string>,true >())
;
class_<layer>("Layer", "A Mapnik map layer.", init<std::string const&,optional<std::string const&> >(
"Create a Layer with a named string and, optionally, an srs string.\n"
"\n"
@ -119,8 +119,8 @@ void export_layer()
))
.def_pickle(layer_pickle_suite())
.def("envelope",&layer::envelope,
.def("envelope",&layer::envelope,
"Return the geographic envelope/bounding box."
"\n"
"Determined based on the layer datasource.\n"
@ -131,7 +131,7 @@ void export_layer()
">>> lyr.envelope()\n"
"box2d(-1.0,-1.0,0.0,0.0) # default until a datasource is loaded\n"
)
.def("visible", &layer::isVisible,
"Return True if this layer's data is active and visible at a given scale.\n"
"\n"
@ -151,8 +151,8 @@ void export_layer()
">>> lyr.visible(1.0/1000000)\n"
"False\n"
)
.add_property("abstract",
.add_property("abstract",
make_function(&layer::abstract,return_value_policy<copy_const_reference>()),
&layer::set_abstract,
"Get/Set the abstract of the layer.\n"
@ -181,7 +181,7 @@ void export_layer()
">>> lyr.active\n"
"False\n"
)
.add_property("clear_label_cache",
&layer::clear_label_cache,
&layer::set_clear_label_cache,
@ -190,7 +190,7 @@ void export_layer()
"Usage:\n"
">>> lyr.clear_label_cache\n"
"False # False by default, meaning label positions from other layers will impact placement \n"
">>> lyr.clear_label_cache = True # set to True to clear the label collision detector cache\n"
">>> lyr.clear_label_cache = True # set to True to clear the label collision detector cache\n"
)
.add_property("cache_features",
@ -201,9 +201,9 @@ void export_layer()
"Usage:\n"
">>> lyr.cache_features\n"
"False # False by default\n"
">>> lyr.cache_features = True # set to True to enable feature caching\n"
">>> lyr.cache_features = True # set to True to enable feature caching\n"
)
.add_property("datasource",
&layer::datasource,
&layer::set_datasource,
@ -231,7 +231,7 @@ void export_layer()
">>> lyr.maxzoom\n"
"9.9999999999999995e-07\n"
)
.add_property("minzoom",
&layer::getMinZoom,
&layer::setMinZoom,
@ -245,9 +245,9 @@ void export_layer()
">>> lyr.minzoom = 1.0/1000000\n"
">>> lyr.minzoom\n"
"9.9999999999999995e-07\n"
)
)
.add_property("name",
.add_property("name",
make_function(&layer::name, return_value_policy<copy_const_reference>()),
&layer::set_name,
"Get/Set the name of the layer.\n"
@ -277,7 +277,7 @@ void export_layer()
"True\n"
)
.add_property("srs",
.add_property("srs",
make_function(&layer::srs,return_value_policy<copy_const_reference>()),
&layer::set_srs,
"Get/Set the SRS of the layer.\n"
@ -309,7 +309,7 @@ void export_layer()
">>> lyr.styles[0]\n"
"'My Style'\n"
)
.add_property("title",
make_function(&layer::title, return_value_policy<copy_const_reference>()),
&layer::set_title,
@ -324,6 +324,6 @@ void export_layer()
">>> lyr.title\n"
"'My first layer'\n"
)
;
}

View file

@ -1,5 +1,5 @@
/*****************************************************************************
*
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2006 Artem Pavlenko, Jean-Francois Doyon
@ -38,14 +38,14 @@ using mapnik::parse_path;
namespace {
using namespace boost::python;
const std::string get_filename(line_pattern_symbolizer const& t)
{
return path_processor_type::to_string(*t.get_filename());
const std::string get_filename(line_pattern_symbolizer const& t)
{
return path_processor_type::to_string(*t.get_filename());
}
void set_filename(line_pattern_symbolizer & t, std::string const& file_expr)
{
t.set_filename(parse_path(file_expr));
void set_filename(line_pattern_symbolizer & t, std::string const& file_expr)
{
t.set_filename(parse_path(file_expr));
}
}
@ -56,7 +56,7 @@ struct line_pattern_symbolizer_pickle_suite : boost::python::pickle_suite
getinitargs(const line_pattern_symbolizer& l)
{
std::string filename = path_processor_type::to_string(*l.get_filename());
// FIXME : Do we need "type" parameter at all ?
// FIXME : Do we need "type" parameter at all ?
return boost::python::make_tuple(filename, guess_type(filename));
}
};
@ -64,16 +64,16 @@ struct line_pattern_symbolizer_pickle_suite : boost::python::pickle_suite
void export_line_pattern_symbolizer()
{
using namespace boost::python;
class_<line_pattern_symbolizer>("LinePatternSymbolizer",
init<path_expression_ptr>
("<image file expression>"))
//.def_pickle(line_pattern_symbolizer_pickle_suite())
.add_property("transform",
mapnik::get_svg_transform<line_pattern_symbolizer>,
mapnik::set_svg_transform<line_pattern_symbolizer>)
mapnik::get_svg_transform<line_pattern_symbolizer>,
mapnik::set_svg_transform<line_pattern_symbolizer>)
.add_property("filename",
&get_filename,
&set_filename)
;
;
}

View file

@ -1,5 +1,5 @@
/*****************************************************************************
*
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2006 Artem Pavlenko, Jean-Francois Doyon
@ -43,7 +43,7 @@ struct line_symbolizer_pickle_suite : boost::python::pickle_suite
void export_line_symbolizer()
{
using namespace boost::python;
enumeration_<line_rasterizer_e>("line_rasterizer")
.value("FULL",RASTERIZER_FULL)
.value("FAST",RASTERIZER_FAST)
@ -62,5 +62,5 @@ void export_line_symbolizer()
(&line_symbolizer::get_stroke,
return_value_policy<copy_const_reference>()),
&line_symbolizer::set_stroke)
;
;
}

View file

@ -1,5 +1,5 @@
/*****************************************************************************
*
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2006 Artem Pavlenko, Jean-Francois Doyon
@ -57,7 +57,7 @@ struct map_pickle_suite : boost::python::pickle_suite
{
l.append(m.getLayer(i));
}
boost::python::list s;
Map::const_style_iterator it = m.styles().begin();
Map::const_style_iterator end = m.styles().end();
@ -91,14 +91,14 @@ struct map_pickle_suite : boost::python::pickle_suite
{
color bg = extract<color>(state[1]);
m.set_background(bg);
}
}
boost::python::list l=extract<boost::python::list>(state[2]);
for (int i=0;i<len(l);++i)
{
m.addLayer(extract<layer>(l[i]));
}
boost::python::list s=extract<boost::python::list>(state[3]);
for (int i=0;i<len(s);++i)
{
@ -112,13 +112,15 @@ struct map_pickle_suite : boost::python::pickle_suite
{
std::string base_path = extract<std::string>(state[4]);
m.set_base_path(base_path);
}
}
}
};
std::vector<layer>& (Map::*layers_nonconst)() = &Map::layers;
std::vector<layer> const& (Map::*layers_const)() const = &Map::layers;
mapnik::parameters& (Map::*attr_nonconst)() = &Map::get_extra_attributes;
mapnik::parameters& (Map::*params_nonconst)() = &Map::get_extra_parameters;
mapnik::feature_type_style find_style (mapnik::Map const& m, std::string const& name)
{
@ -138,17 +140,17 @@ bool has_metawriter(mapnik::Map const& m)
return false;
}
// returns empty shared_ptr when the metawriter isn't found, or is
// returns empty shared_ptr when the metawriter isn't found, or is
// of the wrong type. empty pointers make it back to Python as a None.
mapnik::metawriter_inmem_ptr find_inmem_metawriter(const mapnik::Map &m, const std::string &name) {
mapnik::metawriter_ptr metawriter = m.find_metawriter(name);
mapnik::metawriter_inmem_ptr inmem;
mapnik::metawriter_ptr metawriter = m.find_metawriter(name);
mapnik::metawriter_inmem_ptr inmem;
if (metawriter) {
inmem = boost::dynamic_pointer_cast<mapnik::metawriter_inmem>(metawriter);
}
return inmem;
if (metawriter) {
inmem = boost::dynamic_pointer_cast<mapnik::metawriter_inmem>(metawriter);
}
return inmem;
}
// TODO - we likely should allow indexing by negative number from python
@ -157,7 +159,7 @@ mapnik::featureset_ptr query_point(mapnik::Map const& m, int index, double x, do
{
if (index < 0){
PyErr_SetString(PyExc_IndexError, "Please provide a layer index >= 0");
boost::python::throw_error_already_set();
boost::python::throw_error_already_set();
}
unsigned idx = index;
return m.query_point(idx, x, y);
@ -167,16 +169,17 @@ mapnik::featureset_ptr query_map_point(mapnik::Map const& m, int index, double x
{
if (index < 0){
PyErr_SetString(PyExc_IndexError, "Please provide a layer index >= 0");
boost::python::throw_error_already_set();
boost::python::throw_error_already_set();
}
unsigned idx = index;
return m.query_map_point(idx, x, y);
}
void export_map()
void export_map()
{
using namespace boost::python;
// aspect ratio fix modes
mapnik::enumeration_<mapnik::aspect_fix_mode_e>("aspect_fix_mode")
.value("GROW_BBOX", mapnik::Map::GROW_BBOX)
@ -188,12 +191,12 @@ void export_map()
.value("ADJUST_CANVAS_WIDTH",mapnik::Map::ADJUST_CANVAS_WIDTH)
.value("ADJUST_CANVAS_HEIGHT", mapnik::Map::ADJUST_CANVAS_HEIGHT)
;
python_optional<mapnik::color> ();
class_<std::vector<layer> >("Layers")
.def(vector_indexing_suite<std::vector<layer> >())
;
class_<Map>("Map","The map object.",init<int,int,optional<std::string const&> >(
( arg("width"),arg("height"),arg("srs") ),
"Create a Map with a width and height as integers and, optionally,\n"
@ -209,10 +212,10 @@ void export_map()
">>> m.srs\n"
"'+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs'\n"
))
.def_pickle(map_pickle_suite()
)
.def("append_style",&Map::insert_style,
(arg("style_name"),arg("style_object")),
"Insert a Mapnik Style onto the map by appending it.\n"
@ -278,7 +281,7 @@ void export_map()
">>> m.has_metawriter()\n"
"False\n"
)
.def("pan",&Map::pan,
(arg("x"),arg("y")),
"Set the Map center at a given x,y location\n"
@ -292,7 +295,7 @@ void export_map()
">>> m.envelope().center()\n"
"Coord(0.00166666666667,-0.835)\n"
)
.def("pan_and_zoom",&Map::pan_and_zoom,
(arg("x"),arg("y"),arg("factor")),
"Set the Map center at a given x,y location\n"
@ -308,7 +311,7 @@ void export_map()
">>> m.scale()\n"
"0.00062500000000000001\n"
)
.def("query_map_point",query_map_point,
(arg("layer_idx"),arg("pixel_x"),arg("pixel_y")),
"Query a Map Layer (by layer index) for features \n"
@ -325,7 +328,7 @@ void export_map()
">>> featureset.features\n"
">>> [<mapnik.Feature object at 0x3995630>]\n"
)
.def("query_point",query_point,
(arg("layer idx"),arg("x"),arg("y")),
"Query a Map Layer (by layer index) for features \n"
@ -349,7 +352,7 @@ void export_map()
"Usage:\n"
">>> m.remove_all()\n"
)
.def("remove_style",&Map::remove_style,
(arg("style_name")),
"Remove a Mapnik Style from the map.\n"
@ -365,7 +368,7 @@ void export_map()
"Usage:\n"
">>> m.resize(64,64)\n"
)
.def("scale", &Map::scale,
"Return the Map Scale.\n"
"Usage:\n"
@ -379,16 +382,16 @@ void export_map()
"\n"
">>> m.scale_denominator()\n"
)
.def("view_transform",&Map::view_transform,
"Return the map ViewTransform object\n"
"which is used internally to convert between\n"
"geographic coordinates and screen coordinates.\n"
"\n"
"Usage:\n"
">>> m.view_transform()\n"
">>> m.view_transform()\n"
)
.def("zoom",&Map::zoom,
(arg("factor")),
"Zoom in or out by a given factor.\n"
@ -399,7 +402,7 @@ void export_map()
"\n"
">>> m.zoom(0.25)\n"
)
.def("zoom_all",&Map::zoom_all,
"Set the geographical extent of the map\n"
"to the combined extents of all active layers.\n"
@ -407,7 +410,7 @@ void export_map()
"Usage:\n"
">>> m.zoom_all()\n"
)
.def("zoom_to_box",&Map::zoom_to_box,
(arg("Boxd2")),
"Set the geographical extent of the map\n"
@ -418,38 +421,39 @@ void export_map()
">>> m.zoom_to_box(extent)\n"
)
.def("get_metawriter_property", &Map::get_metawriter_property,
(arg("name")),
"Reads a metawriter property.\n"
"These properties are completely user-defined and can be used to"
"create filenames, etc.\n"
"\n"
"Usage:\n"
">>> map.set_metawriter_property(\"x\", \"10\")\n"
">>> map.get_metawriter_property(\"x\")\n"
"10\n"
)
(arg("name")),
"Reads a metawriter property.\n"
"These properties are completely user-defined and can be used to"
"create filenames, etc.\n"
"\n"
"Usage:\n"
">>> map.set_metawriter_property(\"x\", \"10\")\n"
">>> map.get_metawriter_property(\"x\")\n"
"10\n"
)
.def("set_metawriter_property", &Map::set_metawriter_property,
(arg("name"),arg("value")),
"Sets a metawriter property.\n"
"These properties are completely user-defined and can be used to"
"create filenames, etc.\n"
"\n"
"Usage:\n"
">>> map.set_metawriter_property(\"x\", str(x))\n"
">>> map.set_metawriter_property(\"y\", str(y))\n"
">>> map.set_metawriter_property(\"z\", str(z))\n"
"\n"
"Use a path like \"[z]/[x]/[y].json\" to create filenames.\n"
)
(arg("name"),arg("value")),
"Sets a metawriter property.\n"
"These properties are completely user-defined and can be used to"
"create filenames, etc.\n"
"\n"
"Usage:\n"
">>> map.set_metawriter_property(\"x\", str(x))\n"
">>> map.set_metawriter_property(\"y\", str(y))\n"
">>> map.set_metawriter_property(\"z\", str(z))\n"
"\n"
"Use a path like \"[z]/[x]/[y].json\" to create filenames.\n"
)
.def("find_inmem_metawriter", find_inmem_metawriter,
(arg("name")),
"Gets an inmem metawriter, or None if no such metawriter "
"exists.\n"
"Use this after the map has been rendered to retrieve information "
"about the hit areas rendered on the map.\n"
)
.def("extra_attributes",&Map::get_extra_attributes,return_value_policy<copy_const_reference>(),"TODO")
(arg("name")),
"Gets an inmem metawriter, or None if no such metawriter "
"exists.\n"
"Use this after the map has been rendered to retrieve information "
"about the hit areas rendered on the map.\n"
)
.add_property("extra_attributes",make_function(attr_nonconst,return_value_policy<reference_existing_object>()),"TODO")
.add_property("parameters",make_function(params_nonconst,return_value_policy<reference_existing_object>()),"TODO")
.add_property("aspect_fix_mode",
&Map::get_aspect_fix_mode,
@ -460,8 +464,8 @@ void export_map()
"Usage:\n"
"\n"
">>> m.aspect_fix_mode = aspect_fix_mode.GROW_BBOX\n"
)
)
.add_property("background",make_function
(&Map::background,return_value_policy<copy_const_reference>()),
&Map::set_background,
@ -480,7 +484,7 @@ void export_map()
"Usage:\n"
">>> m.base_path = '.'\n"
)
.add_property("buffer_size",
&Map::buffer_size,
&Map::set_buffer_size,
@ -493,7 +497,7 @@ void export_map()
">>> m.buffer_size\n"
"2\n"
)
.add_property("height",
&Map::height,
&Map::set_height,
@ -507,9 +511,9 @@ void export_map()
">>> m.height\n"
"600\n"
)
.add_property("layers",make_function
(layers_nonconst,return_value_policy<reference_existing_object>()),
(layers_nonconst,return_value_policy<reference_existing_object>()),
"The list of map layers.\n"
"\n"
"Usage:\n"
@ -548,7 +552,7 @@ void export_map()
"... \n"
">>> m.srs = '+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0 +k=1.0 +units=m +nadgrids=@null +no_defs +over'\n"
)
.add_property("width",
&Map::width,
&Map::set_width,

View file

@ -1,5 +1,5 @@
/*****************************************************************************
*
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2010 Artem Pavlenko
@ -33,18 +33,18 @@ using mapnik::symbolizer_with_image;
using mapnik::path_processor_type;
using mapnik::parse_path;
namespace {
namespace {
using namespace boost::python;
std::string get_filename(mapnik::markers_symbolizer const& symbolizer)
{
return path_processor_type::to_string(*symbolizer.get_filename());
}
std::string get_filename(mapnik::markers_symbolizer const& symbolizer)
{
return path_processor_type::to_string(*symbolizer.get_filename());
}
void set_filename(mapnik::markers_symbolizer & symbolizer, std::string const& file_expr)
{
symbolizer.set_filename(parse_path(file_expr));
}
void set_filename(mapnik::markers_symbolizer & symbolizer, std::string const& file_expr)
{
symbolizer.set_filename(parse_path(file_expr));
}
}
@ -75,10 +75,10 @@ struct markers_symbolizer_pickle_suite : boost::python::pickle_suite
);
throw_error_already_set();
}
p.set_allow_overlap(extract<bool>(state[0]));
//p.set_opacity(extract<float>(state[1]));
}
};
@ -87,14 +87,14 @@ struct markers_symbolizer_pickle_suite : boost::python::pickle_suite
void export_markers_symbolizer()
{
using namespace boost::python;
class_<markers_symbolizer>("MarkersSymbolizer",
init<>("Default Markers Symbolizer - blue arrow"))
init<>("Default Markers Symbolizer - blue arrow"))
.def (init<mapnik::path_expression_ptr>("<path expression ptr>"))
//.def_pickle(markers_symbolizer_pickle_suite())
.add_property("filename",
&get_filename,
&set_filename)
&set_filename)
.add_property("allow_overlap",
&markers_symbolizer::get_allow_overlap,
&markers_symbolizer::set_allow_overlap)

View file

@ -1,5 +1,5 @@
/*****************************************************************************
*
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2011 Artem Pavlenko
@ -40,14 +40,14 @@ static boost::shared_ptr<mapnik::rgba_palette> make_palette( const std::string&
return boost::make_shared<mapnik::rgba_palette>(palette, type);
}
void export_palette ()
void export_palette ()
{
using namespace boost::python;
class_<boost::shared_ptr<mapnik::rgba_palette> >("Palette",no_init)
/*, init<std::string,std::string>(
( arg("palette"), arg("type")),
"Creates a new color palette from a file\n"
)*/
.def( "__init__", boost::python::make_constructor( &make_palette))
;
/*, init<std::string,std::string>(
( arg("palette"), arg("type")),
"Creates a new color palette from a file\n"
)*/
.def( "__init__", boost::python::make_constructor(make_palette))
;
}

View file

@ -1,8 +1,8 @@
/*****************************************************************************
*
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2006 Artem Pavlenko, Jean-Francois Doyon
* Copyright (C) 2011 Artem Pavlenko
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@ -19,50 +19,26 @@
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*****************************************************************************/
//$Id: mapnik_parameters.cpp 17 2005-03-08 23:58:43Z pavlenko $
// boost
#include <boost/python.hpp>
#include <boost/make_shared.hpp>
// mapnik
#include <mapnik/params.hpp>
#include <mapnik/unicode.hpp>
#include <mapnik/value.hpp>
using mapnik::parameter;
using mapnik::parameters;
struct pickle_value : public boost::static_visitor<>
{
public:
pickle_value( boost::python::list vals):
vals_(vals) {}
void operator () ( int val )
{
vals_.append(val);
}
void operator () ( double val )
{
vals_.append(val);
}
void operator () ( std::string val )
{
vals_.append(val);
}
private:
boost::python::list vals_;
};
struct parameter_pickle_suite : boost::python::pickle_suite
{
static boost::python::tuple
getinitargs(const parameter& p)
{
using namespace boost::python;
return boost::python::make_tuple(p.first,boost::get<std::string>(p.second));
return boost::python::make_tuple(p.first,p.second);
}
};
@ -76,11 +52,7 @@ struct parameters_pickle_suite : boost::python::pickle_suite
parameters::const_iterator pos=p.begin();
while(pos!=p.end())
{
boost::python::list vals;
pickle_value serializer( vals );
mapnik::value_holder val = pos->second;
boost::apply_visitor( serializer, val );
d[pos->first] = vals[0];
d[pos->first] = pos->second;
++pos;
}
return boost::python::make_tuple(d);
@ -97,7 +69,7 @@ struct parameters_pickle_suite : boost::python::pickle_suite
);
throw_error_already_set();
}
dict d = extract<dict>(state[0]);
boost::python::list keys = d.keys();
for (int i=0; i<len(keys); ++i)
@ -107,7 +79,9 @@ struct parameters_pickle_suite : boost::python::pickle_suite
extract<std::string> ex0(obj);
extract<int> ex1(obj);
extract<double> ex2(obj);
extract<UnicodeString> ex3(obj);
// TODO - this is never hit - we need proper python string -> std::string to get invoked here
if (ex0.check())
{
p[key] = ex0();
@ -119,73 +93,132 @@ struct parameters_pickle_suite : boost::python::pickle_suite
else if (ex2.check())
{
p[key] = ex2();
}
/*
extract_value serializer( p, key );
mapnik::value_holder val = extract<mapnik::value_holder>(d[key]);
boost::apply_visitor( serializer, val );
*/
}
}
else if (ex3.check())
{
std::string buffer;
mapnik::to_utf8(ex3(),buffer);
p[key] = buffer;
}
else
{
std::clog << "could not unpickle key: " << key << "\n";
}
}
}
};
boost::python::dict dict_params(parameters& p)
mapnik::value_holder get_params_by_key1(mapnik::parameters const& p, std::string const& key)
{
boost::python::dict d;
parameters::const_iterator pos=p.begin();
while(pos!=p.end())
parameters::const_iterator pos = p.find(key);
if (pos != p.end())
{
boost::python::list vals;
pickle_value serializer( vals );
mapnik::value_holder val = pos->second;
boost::apply_visitor( serializer, val );
d[pos->first] = vals[0];
++pos;
// will be auto-converted to proper python type by `mapnik_params_to_python`
return pos->second;
}
return d;
return mapnik::value_null();
}
boost::python::list list_params(parameters& p)
mapnik::value_holder get_params_by_key2(mapnik::parameters const& p, std::string const& key)
{
boost::python::list l;
parameters::const_iterator pos=p.begin();
while(pos!=p.end())
parameters::const_iterator pos = p.find(key);
if (pos == p.end())
{
boost::python::list vals;
pickle_value serializer( vals );
mapnik::value_holder val = pos->second;
boost::apply_visitor( serializer, val );
l.append(boost::python::make_tuple(pos->first,vals[0]));
++pos;
PyErr_SetString(PyExc_KeyError, key.c_str());
boost::python::throw_error_already_set();
}
return l;
// will be auto-converted to proper python type by `mapnik_params_to_python`
return pos->second;
}
boost::python::dict dict_param(parameter& p)
mapnik::parameter get_params_by_index(mapnik::parameters const& p, int index)
{
boost::python::dict d;
d[p.first] = boost::get<std::string>(p.second);
return d;
if (index < 0 || index > p.size())
{
PyErr_SetString(PyExc_IndexError, "Index is out of range");
throw boost::python::error_already_set();
}
parameters::const_iterator itr = p.begin();
parameters::const_iterator end = p.end();
unsigned idx = 0;
while (itr != p.end())
{
if (idx == index)
{
return *itr;
}
++idx;
++itr;
}
PyErr_SetString(PyExc_IndexError, "Index is out of range");
throw boost::python::error_already_set();
}
boost::python::tuple tuple_param(parameter& p)
void add_parameter(mapnik::parameters & p, mapnik::parameter const& param)
{
return boost::python::make_tuple(p.first,boost::get<std::string>(p.second));
p[param.first] = param.second;
}
mapnik::value_holder get_param(mapnik::parameter const& p, int index)
{
if (index == 0)
{
return p.first;
}
else if (index == 1)
{
return p.second;
}
else
{
PyErr_SetString(PyExc_IndexError, "Index is out of range");
throw boost::python::error_already_set();
}
}
boost::shared_ptr<mapnik::parameter> create_parameter_from_string(std::string const& key, std::string const& value)
{
return boost::make_shared<mapnik::parameter>(key,mapnik::value_holder(value));
}
boost::shared_ptr<mapnik::parameter> create_parameter_from_int(std::string const& key, int value)
{
return boost::make_shared<mapnik::parameter>(key,mapnik::value_holder(value));
}
boost::shared_ptr<mapnik::parameter> create_parameter_from_float(std::string const& key, double value)
{
return boost::make_shared<mapnik::parameter>(key,mapnik::value_holder(value));
}
void export_parameters()
{
using namespace boost::python;
class_<parameter>("Parameter",init<std::string,std::string>())
class_<parameter,boost::shared_ptr<parameter> >("Parameter",no_init)
.def("__init__", make_constructor(create_parameter_from_string),
"Create a mapnik.Parameter from a pair of values, the first being a string\n"
"and the second being either a string, and integer, or a float")
.def("__init__", make_constructor(create_parameter_from_int),
"Create a mapnik.Parameter from a pair of values, the first being a string\n"
"and the second being either a string, and integer, or a float")
.def("__init__", make_constructor(create_parameter_from_float),
"Create a mapnik.Parameter from a pair of values, the first being a string\n"
"and the second being either a string, and integer, or a float")
.def_pickle(parameter_pickle_suite())
.def("as_dict",dict_param)
.def("as_tuple",tuple_param)
.def("__getitem__",get_param)
;
class_<parameters>("Parameters",init<>())
.def_pickle(parameters_pickle_suite())
.def("as_dict",dict_params)
.def("as_list",list_params)
.def("get",get_params_by_key1)
.def("__getitem__",get_params_by_key2)
.def("__getitem__",get_params_by_index)
.def("__len__",&parameters::size)
.def("append",add_parameter)
.def("iteritems",iterator<parameters>())
;
}

View file

@ -1,5 +1,5 @@
/*****************************************************************************
*
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2006 Artem Pavlenko, Jean-Francois Doyon
@ -39,14 +39,14 @@ using mapnik::parse_path;
namespace {
using namespace boost::python;
const std::string get_filename(point_symbolizer const& t)
{
return path_processor_type::to_string(*t.get_filename());
const std::string get_filename(point_symbolizer const& t)
{
return path_processor_type::to_string(*t.get_filename());
}
void set_filename(point_symbolizer & t, std::string const& file_expr)
{
t.set_filename(parse_path(file_expr));
void set_filename(point_symbolizer & t, std::string const& file_expr)
{
t.set_filename(parse_path(file_expr));
}
}
@ -81,12 +81,12 @@ struct point_symbolizer_pickle_suite : boost::python::pickle_suite
);
throw_error_already_set();
}
p.set_allow_overlap(extract<bool>(state[0]));
p.set_opacity(extract<float>(state[1]));
p.set_ignore_placement(extract<bool>(state[2]));
p.set_point_placement(extract<point_placement_e>(state[3]));
}
};
@ -100,7 +100,7 @@ void export_point_symbolizer()
.value("CENTROID",CENTROID_POINT_PLACEMENT)
.value("INTERIOR",INTERIOR_POINT_PLACEMENT)
;
class_<point_symbolizer>("PointSymbolizer",
init<>("Default Point Symbolizer - 4x4 black square"))
.def (init<mapnik::path_expression_ptr>("<path expression ptr>"))

View file

@ -1,5 +1,5 @@
/*****************************************************************************
*
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2006 Artem Pavlenko, Jean-Francois Doyon
@ -38,14 +38,14 @@ using mapnik::guess_type;
namespace {
using namespace boost::python;
const std::string get_filename(polygon_pattern_symbolizer const& t)
{
return path_processor_type::to_string(*t.get_filename());
const std::string get_filename(polygon_pattern_symbolizer const& t)
{
return path_processor_type::to_string(*t.get_filename());
}
void set_filename(polygon_pattern_symbolizer & t, std::string const& file_expr)
{
t.set_filename(parse_path(file_expr));
void set_filename(polygon_pattern_symbolizer & t, std::string const& file_expr)
{
t.set_filename(parse_path(file_expr));
}
}
@ -77,7 +77,7 @@ struct polygon_pattern_symbolizer_pickle_suite : boost::python::pickle_suite
);
throw_error_already_set();
}
p.set_alignment(extract<pattern_alignment_e>(state[0]));
p.set_gamma(extract<float>(state[1]));
}
@ -92,22 +92,22 @@ void export_polygon_pattern_symbolizer()
.value("LOCAL",LOCAL_ALIGNMENT)
.value("GLOBAL",GLOBAL_ALIGNMENT)
;
class_<polygon_pattern_symbolizer>("PolygonPatternSymbolizer",
init<path_expression_ptr>("<path_expression_ptr>"))
.def_pickle(polygon_pattern_symbolizer_pickle_suite())
.add_property("alignment",
&polygon_pattern_symbolizer::get_alignment,
&polygon_pattern_symbolizer::set_alignment,
"Set/get the alignment of the pattern")
&polygon_pattern_symbolizer::get_alignment,
&polygon_pattern_symbolizer::set_alignment,
"Set/get the alignment of the pattern")
.add_property("transform",
mapnik::get_svg_transform<polygon_pattern_symbolizer>,
mapnik::set_svg_transform<polygon_pattern_symbolizer>)
mapnik::get_svg_transform<polygon_pattern_symbolizer>,
mapnik::set_svg_transform<polygon_pattern_symbolizer>)
.add_property("filename",
&get_filename,
&set_filename)
.add_property("gamma",
&polygon_pattern_symbolizer::get_gamma,
&polygon_pattern_symbolizer::set_gamma)
;
;
}

View file

@ -1,5 +1,5 @@
/*****************************************************************************
*
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2006 Artem Pavlenko, Jean-Francois Doyon
@ -32,7 +32,7 @@ struct polygon_symbolizer_pickle_suite : boost::python::pickle_suite
static boost::python::tuple
getinitargs(const polygon_symbolizer& p)
{
return boost::python::make_tuple(p.get_fill());
return boost::python::make_tuple(p.get_fill());
}
static boost::python::tuple
@ -53,7 +53,7 @@ struct polygon_symbolizer_pickle_suite : boost::python::pickle_suite
);
throw_error_already_set();
}
p.set_opacity(extract<float>(state[0]));
p.set_gamma(extract<float>(state[1]));
}
@ -63,7 +63,7 @@ struct polygon_symbolizer_pickle_suite : boost::python::pickle_suite
void export_polygon_symbolizer()
{
using namespace boost::python;
class_<polygon_symbolizer>("PolygonSymbolizer",
init<>("Default PolygonSymbolizer - solid fill grey"))
.def(init<color const&>("TODO"))
@ -78,6 +78,6 @@ void export_polygon_symbolizer()
.add_property("gamma",
&polygon_symbolizer::get_gamma,
&polygon_symbolizer::set_gamma)
;
;
}

View file

@ -1,5 +1,5 @@
/*****************************************************************************
*
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2009 Artem Pavlenko
@ -25,7 +25,7 @@
#include <mapnik/proj_transform.hpp>
// boost
#include <boost/python.hpp>
using mapnik::proj_transform;
using mapnik::projection;
@ -54,7 +54,7 @@ mapnik::coord2d forward_transform_c(mapnik::proj_transform& t, mapnik::coord2d c
}
return mapnik::coord2d(x,y);
}
mapnik::coord2d backward_transform_c(mapnik::proj_transform& t, mapnik::coord2d const& c)
{
double x = c.x;
@ -122,7 +122,7 @@ mapnik::box2d<double> backward_transform_env_p(mapnik::proj_transform& t, mapnik
void export_proj_transform ()
{
using namespace boost::python;
class_<proj_transform, boost::noncopyable>("ProjTransform", init< projection const&, projection const& >())
.def_pickle(proj_transform_pickle_suite())
.def("forward", forward_transform_c)
@ -132,5 +132,5 @@ void export_proj_transform ()
.def("forward", forward_transform_env_p)
.def("backward",backward_transform_env_p)
;
}

View file

@ -1,5 +1,5 @@
/*****************************************************************************
*
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2006 Artem Pavlenko, Jean-Francois Doyon
@ -41,7 +41,7 @@ struct projection_pickle_suite : boost::python::pickle_suite
};
namespace {
mapnik::coord2d forward_pt(mapnik::coord2d const& pt,
mapnik::coord2d forward_pt(mapnik::coord2d const& pt,
mapnik::projection const& prj)
{
double x = pt.x;
@ -49,8 +49,8 @@ mapnik::coord2d forward_pt(mapnik::coord2d const& pt,
prj.forward(x,y);
return mapnik::coord2d(x,y);
}
mapnik::coord2d inverse_pt(mapnik::coord2d const& pt,
mapnik::coord2d inverse_pt(mapnik::coord2d const& pt,
mapnik::projection const& prj)
{
double x = pt.x;
@ -58,7 +58,7 @@ mapnik::coord2d inverse_pt(mapnik::coord2d const& pt,
prj.inverse(x,y);
return mapnik::coord2d(x,y);
}
mapnik::box2d<double> forward_env(mapnik::box2d<double> const & box,
mapnik::projection const& prj)
{
@ -70,7 +70,7 @@ mapnik::box2d<double> forward_env(mapnik::box2d<double> const & box,
prj.forward(maxx,maxy);
return mapnik::box2d<double>(minx,miny,maxx,maxy);
}
mapnik::box2d<double> inverse_env(mapnik::box2d<double> const & box,
mapnik::projection const& prj)
{
@ -82,18 +82,18 @@ mapnik::box2d<double> inverse_env(mapnik::box2d<double> const & box,
prj.inverse(maxx,maxy);
return mapnik::box2d<double>(minx,miny,maxx,maxy);
}
}
void export_projection ()
{
using namespace boost::python;
using namespace boost::python;
class_<projection>("Projection", "Represents a map projection.",init<optional<std::string const&> >(
(arg("proj4_string")),
"Constructs a new projection from its PROJ.4 string representation.\n"
"\n"
"The parameterless version of this constructor is equivalent to\n"
"The parameterless version of this constructor is equivalent to\n"
" Projection('+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs')\n"
"\n"
"The constructor will throw a RuntimeError in case the projection\n"
@ -110,10 +110,10 @@ void export_projection ()
"This property is True if the projection is a geographic projection\n"
"(i.e. it uses lon/lat coordinates)\n")
;
def("forward_",&forward_pt);
def("inverse_",&inverse_pt);
def("forward_",&forward_env);
def("inverse_",&inverse_env);
}

View file

@ -1,5 +1,5 @@
/*****************************************************************************
*
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2006 Artem Pavlenko, Jean-Francois Doyon
@ -66,6 +66,7 @@ void export_view_transform();
void export_raster_colorizer();
void export_glyph_symbolizer();
void export_inmem_metawriter();
void export_label_collision_detector();
#include <mapnik/version.hpp>
#include <mapnik/value_error.hpp>
@ -82,47 +83,58 @@ void export_inmem_metawriter();
#include <mapnik/value_error.hpp>
#include <mapnik/save_map.hpp>
#include "python_grid_utils.hpp"
#include "mapnik_value_converter.hpp"
#if defined(HAVE_CAIRO) && defined(HAVE_PYCAIRO)
#include <pycairo.h>
static Pycairo_CAPI_t *Pycairo_CAPI;
#endif
namespace boost { namespace python {
struct mapnik_value_to_python
{
static PyObject* convert(mapnik::value const& v)
{
return boost::apply_visitor(value_converter(),v.base());
}
};
}}
void render(const mapnik::Map& map,
mapnik::image_32& image,
mapnik::image_32& image,
double scale_factor = 1.0,
unsigned offset_x = 0u,
unsigned offset_y = 0u)
{
Py_BEGIN_ALLOW_THREADS
try
{
mapnik::agg_renderer<mapnik::image_32> ren(map,image,scale_factor,offset_x, offset_y);
ren.apply();
}
catch (...)
{
Py_BLOCK_THREADS
throw;
}
Py_END_ALLOW_THREADS
}
void render_with_detector(
const mapnik::Map &map,
mapnik::image_32 &image,
boost::shared_ptr<mapnik::label_collision_detector4> detector,
double scale_factor = 1.0,
unsigned offset_x = 0u,
unsigned offset_y = 0u)
{
Py_BEGIN_ALLOW_THREADS
try
{
mapnik::agg_renderer<mapnik::image_32> ren(map,image,scale_factor,offset_x, offset_y);
ren.apply();
}
catch (...)
{
Py_BLOCK_THREADS
throw;
}
try
{
mapnik::agg_renderer<mapnik::image_32> ren(map,image,detector);
ren.apply();
}
catch (...)
{
Py_BLOCK_THREADS
throw;
}
Py_END_ALLOW_THREADS
}
}
void render_layer2(const mapnik::Map& map,
mapnik::image_32& image,
unsigned layer_idx)
mapnik::image_32& image,
unsigned layer_idx)
{
std::vector<mapnik::layer> const& layers = map.layers();
std::size_t layer_num = layers.size();
@ -134,101 +146,101 @@ void render_layer2(const mapnik::Map& map,
}
Py_BEGIN_ALLOW_THREADS
try
{
mapnik::layer const& layer = layers[layer_idx];
mapnik::agg_renderer<mapnik::image_32> ren(map,image,1.0,0,0);
std::set<std::string> names;
ren.apply(layer,names);
}
catch (...)
{
Py_BLOCK_THREADS
throw;
}
try
{
mapnik::layer const& layer = layers[layer_idx];
mapnik::agg_renderer<mapnik::image_32> ren(map,image,1.0,0,0);
std::set<std::string> names;
ren.apply(layer,names);
}
catch (...)
{
Py_BLOCK_THREADS
throw;
}
Py_END_ALLOW_THREADS
}
}
#if defined(HAVE_CAIRO) && defined(HAVE_PYCAIRO)
void render3(const mapnik::Map& map,
PycairoSurface* surface,
unsigned offset_x = 0,
unsigned offset_y = 0)
PycairoSurface* surface,
unsigned offset_x = 0,
unsigned offset_y = 0)
{
Py_BEGIN_ALLOW_THREADS
try
{
Cairo::RefPtr<Cairo::Surface> s(new Cairo::Surface(surface->surface));
mapnik::cairo_renderer<Cairo::Surface> ren(map,s,offset_x, offset_y);
ren.apply();
}
catch (...)
{
Py_BLOCK_THREADS
throw;
}
try
{
Cairo::RefPtr<Cairo::Surface> s(new Cairo::Surface(surface->surface));
mapnik::cairo_renderer<Cairo::Surface> ren(map,s,offset_x, offset_y);
ren.apply();
}
catch (...)
{
Py_BLOCK_THREADS
throw;
}
Py_END_ALLOW_THREADS
}
}
void render4(const mapnik::Map& map, PycairoSurface* surface)
{
Py_BEGIN_ALLOW_THREADS
try
{
Cairo::RefPtr<Cairo::Surface> s(new Cairo::Surface(surface->surface));
mapnik::cairo_renderer<Cairo::Surface> ren(map,s);
ren.apply();
}
catch (...)
{
Py_BLOCK_THREADS
throw;
}
try
{
Cairo::RefPtr<Cairo::Surface> s(new Cairo::Surface(surface->surface));
mapnik::cairo_renderer<Cairo::Surface> ren(map,s);
ren.apply();
}
catch (...)
{
Py_BLOCK_THREADS
throw;
}
Py_END_ALLOW_THREADS
}
}
void render5(const mapnik::Map& map,
PycairoContext* context,
unsigned offset_x = 0,
unsigned offset_y = 0)
PycairoContext* context,
unsigned offset_x = 0,
unsigned offset_y = 0)
{
Py_BEGIN_ALLOW_THREADS
try
{
Cairo::RefPtr<Cairo::Context> c(new Cairo::Context(context->ctx));
mapnik::cairo_renderer<Cairo::Context> ren(map,c,offset_x, offset_y);
ren.apply();
}
catch (...)
{
Py_BLOCK_THREADS
throw;
}
try
{
Cairo::RefPtr<Cairo::Context> c(new Cairo::Context(context->ctx));
mapnik::cairo_renderer<Cairo::Context> ren(map,c,offset_x, offset_y);
ren.apply();
}
catch (...)
{
Py_BLOCK_THREADS
throw;
}
Py_END_ALLOW_THREADS
}
}
void render6(const mapnik::Map& map, PycairoContext* context)
{
Py_BEGIN_ALLOW_THREADS
try
{
Cairo::RefPtr<Cairo::Context> c(new Cairo::Context(context->ctx));
mapnik::cairo_renderer<Cairo::Context> ren(map,c);
ren.apply();
}
catch (...)
{
Py_BLOCK_THREADS
throw;
}
try
{
Cairo::RefPtr<Cairo::Context> c(new Cairo::Context(context->ctx));
mapnik::cairo_renderer<Cairo::Context> ren(map,c);
ren.apply();
}
catch (...)
{
Py_BLOCK_THREADS
throw;
}
Py_END_ALLOW_THREADS
}
}
#endif
void render_tile_to_file(const mapnik::Map& map,
void render_tile_to_file(const mapnik::Map& map,
unsigned offset_x, unsigned offset_y,
unsigned width, unsigned height,
const std::string& file,
@ -251,11 +263,11 @@ void render_to_file1(const mapnik::Map& map,
throw mapnik::ImageWriterException("Cairo backend not available, cannot write to format: " + format);
#endif
}
else
else
{
mapnik::image_32 image(map.width(),map.height());
render(map,image,1.0,0,0);
mapnik::save_to_file(image,filename,format);
mapnik::save_to_file(image,filename,format);
}
}
@ -270,11 +282,11 @@ void render_to_file2(const mapnik::Map& map,const std::string& filename)
throw mapnik::ImageWriterException("Cairo backend not available, cannot write to format: " + format);
#endif
}
else
else
{
mapnik::image_32 image(map.width(),map.height());
render(map,image,1.0,0,0);
mapnik::save_to_file(image,filename);
mapnik::save_to_file(image,filename);
}
}
@ -282,7 +294,7 @@ void render_to_file3(const mapnik::Map& map,
const std::string& filename,
const std::string& format,
double scale_factor = 1.0
)
)
{
if (format == "pdf" || format == "svg" || format =="ps" || format == "ARGB32" || format == "RGB24")
{
@ -292,11 +304,11 @@ void render_to_file3(const mapnik::Map& map,
throw mapnik::ImageWriterException("Cairo backend not available, cannot write to format: " + format);
#endif
}
else
else
{
mapnik::image_32 image(map.width(),map.height());
render(map,image,scale_factor,0,0);
mapnik::save_to_file(image,filename,format);
mapnik::save_to_file(image,filename,format);
}
}
@ -319,22 +331,13 @@ unsigned mapnik_version()
return MAPNIK_VERSION;
}
unsigned mapnik_svn_revision()
{
#if defined(SVN_REVISION)
return SVN_REVISION;
#else
return 0;
#endif
}
// indicator for jpeg read/write support within libmapnik
bool has_jpeg()
{
#if defined(HAVE_JPEG)
return true;
return true;
#else
return false;
return false;
#endif
}
@ -356,10 +359,10 @@ bool has_pycairo()
if (Pycairo_CAPI == NULL){
/*
Case where pycairo support has been compiled into
mapnik but at runtime the cairo python module
is unable to be imported and therefore Pycairo surfaces
and contexts cannot be passed to mapnik.render()
*/
mapnik but at runtime the cairo python module
is unable to be imported and therefore Pycairo surfaces
and contexts cannot be passed to mapnik.render()
*/
return false;
}
return true;
@ -374,10 +377,11 @@ BOOST_PYTHON_FUNCTION_OVERLOADS(load_map_string_overloads, load_map_string, 2, 4
BOOST_PYTHON_FUNCTION_OVERLOADS(save_map_overloads, save_map, 2, 3)
BOOST_PYTHON_FUNCTION_OVERLOADS(save_map_to_string_overloads, save_map_to_string, 1, 2)
BOOST_PYTHON_FUNCTION_OVERLOADS(render_overloads, render, 2, 5)
BOOST_PYTHON_FUNCTION_OVERLOADS(render_with_detector_overloads, render_with_detector, 3, 6)
BOOST_PYTHON_MODULE(_mapnik2)
BOOST_PYTHON_MODULE(_mapnik)
{
using namespace boost::python;
using mapnik::load_map;
@ -385,7 +389,7 @@ BOOST_PYTHON_MODULE(_mapnik2)
using mapnik::save_map;
using mapnik::save_map_to_string;
using mapnik::render_grid;
register_exception_translator<mapnik::config_error>(&config_error_translator);
register_exception_translator<mapnik::value_error>(&value_error_translator);
register_cairo();
@ -395,8 +399,8 @@ BOOST_PYTHON_MODULE(_mapnik2)
export_featureset();
export_datasource();
export_parameters();
export_color();
export_envelope();
export_color();
export_envelope();
export_palette();
export_image();
export_image_view();
@ -404,7 +408,7 @@ BOOST_PYTHON_MODULE(_mapnik2)
export_grid_view();
export_expression();
export_rule();
export_style();
export_style();
export_layer();
export_stroke();
export_datasource_cache();
@ -427,16 +431,17 @@ BOOST_PYTHON_MODULE(_mapnik2)
export_raster_colorizer();
export_glyph_symbolizer();
export_inmem_metawriter();
export_label_collision_detector();
def("render_grid",&render_grid,
( arg("map"),
arg("layer"),
args("key")="__id__",
arg("resolution")=4,
arg("fields")=boost::python::list()
)
);
( arg("map"),
arg("layer"),
args("key")="__id__",
arg("resolution")=4,
arg("fields")=boost::python::list()
)
);
def("render_to_file",&render_to_file1,
"\n"
"Render Map to file using explicit image type.\n"
@ -478,16 +483,16 @@ BOOST_PYTHON_MODULE(_mapnik2)
">>> render_to_file(m,'image.jpeg',scale_factor)\n"
"\n"
);
def("render_tile_to_file",&render_tile_to_file,
"\n"
"TODO\n"
"\n"
);
);
def("render", &render, render_overloads(
"\n"
"\n"
"Render Map to an AGG image_32 using offsets\n"
"\n"
"Usage:\n"
@ -501,16 +506,29 @@ BOOST_PYTHON_MODULE(_mapnik2)
">>> render(m,im,scale_factor)\n"
">>> render(m,im,scale_factor,offset[0],offset[1])\n"
"\n"
));
));
def("render_with_detector", &render_with_detector, render_with_detector_overloads(
"\n"
"Render Map to an AGG image_32 using a pre-constructed detector.\n"
"\n"
"Usage:\n"
">>> from mapnik import Map, Image, LabelCollisionDetector, render_with_detector, load_map\n"
">>> m = Map(256,256)\n"
">>> load_map(m,'mapfile.xml')\n"
">>> im = Image(m.width,m.height)\n"
">>> detector = LabelCollisionDetector(m)\n"
">>> render_with_detector(m, im, detector)\n"
));
def("render_layer", &render_layer2,
(arg("map"),arg("image"),args("layer"))
);
(arg("map"),arg("image"),args("layer"))
);
def("render_layer", &mapnik::render_layer_for_grid,
(arg("map"),arg("grid"),args("layer"),arg("fields")=boost::python::list())
);
(arg("map"),arg("grid"),args("layer"),arg("fields")=boost::python::list())
);
#if defined(HAVE_CAIRO) && defined(HAVE_PYCAIRO)
def("render",&render3,
"\n"
@ -549,7 +567,7 @@ BOOST_PYTHON_MODULE(_mapnik2)
">>> from cairo import SVGSurface, Context\n"
">>> surface = SVGSurface('image.svg', m.width, m.height)\n"
">>> ctx = Context(surface)\n"
">>> load_map(m,'mapfile.xml')\n"
">>> load_map(m,'mapfile.xml')\n"
">>> render(m,context,1,1)\n"
"\n"
);
@ -582,7 +600,7 @@ BOOST_PYTHON_MODULE(_mapnik2)
">>> scale_denominator(m,Projection(m.srs).geographic)\n"
"\n"
);
def("load_map", &load_map, load_map_overloads());
def("load_map_from_string", &load_map_string, load_map_string_overloads());
@ -603,15 +621,15 @@ BOOST_PYTHON_MODULE(_mapnik2)
"\n"
);
*/
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_svn_revision", &mapnik_svn_revision,"Get the Mapnik svn revision");
def("has_jpeg", &has_jpeg, "Get jpeg read/write support status");
def("has_cairo", &has_cairo, "Get cairo library status");
def("has_pycairo", &has_pycairo, "Get pycairo module status");
register_ptr_to_python<mapnik::expression_ptr>();
register_ptr_to_python<mapnik::path_expression_ptr>();
to_python_converter<mapnik::value_holder,mapnik_param_to_python>();
to_python_converter<mapnik::value,mapnik_value_to_python>();
}

View file

@ -1,5 +1,5 @@
/*****************************************************************************
*
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2006 Artem Pavlenko, Jean-Francois Doyon
@ -32,7 +32,7 @@ struct query_pickle_suite : boost::python::pickle_suite
static boost::python::tuple
getinitargs(query const& q)
{
return boost::python::make_tuple(q.get_bbox(),q.resolution());
return boost::python::make_tuple(q.get_bbox(),q.resolution());
}
};
@ -40,7 +40,7 @@ void export_query()
{
using namespace boost::python;
class_<query>("Query", "a spatial query data object",
class_<query>("Query", "a spatial query data object",
init<box2d<double>,query::resolution_type const&,double>() )
.def(init<box2d<double> >())
.def_pickle(query_pickle_suite())

View file

@ -1,5 +1,5 @@
/*****************************************************************************
*
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2010 Artem Pavlenko
@ -69,98 +69,98 @@ void export_raster_colorizer()
using namespace boost::python;
class_<raster_colorizer,raster_colorizer_ptr>("RasterColorizer",
"A Raster Colorizer object.",
init<colorizer_mode_enum, color>(args("default_mode","default_color"))
)
"A Raster Colorizer object.",
init<colorizer_mode_enum, color>(args("default_mode","default_color"))
)
.def(init<>())
.add_property("default_color",
make_function(&raster_colorizer::get_default_color, return_value_policy<reference_existing_object>()),
&raster_colorizer::set_default_color,
"The default color for stops added without a color (mapnik.Color).\n")
.add_property("default_mode",
&raster_colorizer::get_default_mode_enum,
&raster_colorizer::set_default_mode_enum,
"The default mode (mapnik.ColorizerMode).\n"
"\n"
"If a stop is added without a mode, then it will inherit this default mode\n")
.add_property("default_color",
make_function(&raster_colorizer::get_default_color, return_value_policy<reference_existing_object>()),
&raster_colorizer::set_default_color,
"The default color for stops added without a color (mapnik.Color).\n")
.add_property("default_mode",
&raster_colorizer::get_default_mode_enum,
&raster_colorizer::set_default_mode_enum,
"The default mode (mapnik.ColorizerMode).\n"
"\n"
"If a stop is added without a mode, then it will inherit this default mode\n")
.add_property("stops",
make_function(get_stops,return_value_policy<reference_existing_object>()),
"The list of stops this RasterColorizer contains\n")
make_function(get_stops,return_value_policy<reference_existing_object>()),
"The list of stops this RasterColorizer contains\n")
.add_property("epsilon",
&raster_colorizer::get_epsilon,
&raster_colorizer::set_epsilon,
"Comparison epsilon value for exact mode\n"
"\n"
"When comparing values in exact mode, values need only be within epsilon to match.\n")
&raster_colorizer::get_epsilon,
&raster_colorizer::set_epsilon,
"Comparison epsilon value for exact mode\n"
"\n"
"When comparing values in exact mode, values need only be within epsilon to match.\n")
.def("add_stop", add_stop,
(arg("ColorizerStop")),
"Add a colorizer stop to the raster colorizer.\n"
"\n"
"Usage:\n"
">>> colorizer = mapnik.RasterColorizer()\n"
">>> color = mapnik.Color(\"#0044cc\")\n"
">>> stop = mapnik.ColorizerStop(3, mapnik.COLORIZER_INHERIT, color)\n"
">>> colorizer.add_stop(stop)\n"
(arg("ColorizerStop")),
"Add a colorizer stop to the raster colorizer.\n"
"\n"
"Usage:\n"
">>> colorizer = mapnik.RasterColorizer()\n"
">>> color = mapnik.Color(\"#0044cc\")\n"
">>> stop = mapnik.ColorizerStop(3, mapnik.COLORIZER_INHERIT, color)\n"
">>> colorizer.add_stop(stop)\n"
)
.def("add_stop", add_stop2,
(arg("value")),
"Add a colorizer stop to the raster colorizer, using the default mode and color.\n"
"\n"
"Usage:\n"
">>> default_color = mapnik.Color(\"#0044cc\")\n"
">>> colorizer = mapnik.RasterColorizer(mapnik2.COLORIZER_LINEAR, default_color)\n"
">>> colorizer.add_stop(100)\n"
(arg("value")),
"Add a colorizer stop to the raster colorizer, using the default mode and color.\n"
"\n"
"Usage:\n"
">>> default_color = mapnik.Color(\"#0044cc\")\n"
">>> colorizer = mapnik.RasterColorizer(mapnik.COLORIZER_LINEAR, default_color)\n"
">>> colorizer.add_stop(100)\n"
)
.def("add_stop", add_stop3,
(arg("value")),
"Add a colorizer stop to the raster colorizer, using the default mode.\n"
"\n"
"Usage:\n"
">>> default_color = mapnik.Color(\"#0044cc\")\n"
">>> colorizer = mapnik.RasterColorizer(mapnik2.COLORIZER_LINEAR, default_color)\n"
">>> colorizer.add_stop(100, mapnik.Color(\"#123456\"))\n"
(arg("value")),
"Add a colorizer stop to the raster colorizer, using the default mode.\n"
"\n"
"Usage:\n"
">>> default_color = mapnik.Color(\"#0044cc\")\n"
">>> colorizer = mapnik.RasterColorizer(mapnik.COLORIZER_LINEAR, default_color)\n"
">>> colorizer.add_stop(100, mapnik.Color(\"#123456\"))\n"
)
.def("add_stop", add_stop4,
(arg("value")),
"Add a colorizer stop to the raster colorizer, using the default color.\n"
"\n"
"Usage:\n"
">>> default_color = mapnik.Color(\"#0044cc\")\n"
">>> colorizer = mapnik.RasterColorizer(mapnik2.COLORIZER_LINEAR, default_color)\n"
">>> colorizer.add_stop(100, mapnik2.COLORIZER_EXACT)\n"
(arg("value")),
"Add a colorizer stop to the raster colorizer, using the default color.\n"
"\n"
"Usage:\n"
">>> default_color = mapnik.Color(\"#0044cc\")\n"
">>> colorizer = mapnik.RasterColorizer(mapnik.COLORIZER_LINEAR, default_color)\n"
">>> colorizer.add_stop(100, mapnik.COLORIZER_EXACT)\n"
)
.def("add_stop", add_stop5,
(arg("value")),
"Add a colorizer stop to the raster colorizer.\n"
"\n"
"Usage:\n"
">>> default_color = mapnik.Color(\"#0044cc\")\n"
">>> colorizer = mapnik.RasterColorizer(mapnik2.COLORIZER_LINEAR, default_color)\n"
">>> colorizer.add_stop(100, mapnik.COLORIZER_DISCRETE, mapnik.Color(\"#112233\"))\n"
(arg("value")),
"Add a colorizer stop to the raster colorizer.\n"
"\n"
"Usage:\n"
">>> default_color = mapnik.Color(\"#0044cc\")\n"
">>> colorizer = mapnik.RasterColorizer(mapnik.COLORIZER_LINEAR, default_color)\n"
">>> colorizer.add_stop(100, mapnik.COLORIZER_DISCRETE, mapnik.Color(\"#112233\"))\n"
)
.def("get_color", &raster_colorizer::get_color,
"Get the color assigned to a certain value in raster data.\n"
"\n"
"Usage:\n"
">>> colorizer = mapnik.RasterColorizer()\n"
">>> color = mapnik.Color(\"#0044cc\")\n"
">>> colorizer.add_stop(0, mapnik2.COLORIZER_DISCRETE, mapnik.Color(\"#000000\"))\n"
">>> colorizer.add_stop(100, mapnik2.COLORIZER_DISCRETE, mapnik.Color(\"#0E0A06\"))\n"
">>> colorizer.get_color(50)\n"
"Color('#070503')\n"
.def("get_color", &raster_colorizer::get_color,
"Get the color assigned to a certain value in raster data.\n"
"\n"
"Usage:\n"
">>> colorizer = mapnik.RasterColorizer()\n"
">>> color = mapnik.Color(\"#0044cc\")\n"
">>> colorizer.add_stop(0, mapnik.COLORIZER_DISCRETE, mapnik.Color(\"#000000\"))\n"
">>> colorizer.add_stop(100, mapnik.COLORIZER_DISCRETE, mapnik.Color(\"#0E0A06\"))\n"
">>> colorizer.get_color(50)\n"
"Color('#070503')\n"
)
;
;
class_<colorizer_stops>("ColorizerStops",
"A RasterColorizer's collection of ordered color stops.\n"
"This class is not meant to be instantiated from python. However, "
"it can be accessed at a RasterColorizer's \"stops\" attribute for "
"introspection purposes",
no_init)
"A RasterColorizer's collection of ordered color stops.\n"
"This class is not meant to be instantiated from python. However, "
"it can be accessed at a RasterColorizer's \"stops\" attribute for "
"introspection purposes",
no_init)
.def(vector_indexing_suite<colorizer_stops>())
;
@ -174,32 +174,32 @@ void export_raster_colorizer()
class_<colorizer_stop>("ColorizerStop",init<float, colorizer_mode_enum, color const&>(
"A Colorizer Stop object.\n"
"Create with a value, ColorizerMode, and Color\n"
"\n"
"Usage:"
">>> color = mapnik.Color(\"#fff000\")\n"
">>> stop= mapnik.ColorizerStop(42.42, mapnik.COLORIZER_LINEAR, color)\n"
))
.add_property("color",
make_function(&colorizer_stop::get_color, return_value_policy<reference_existing_object>()),
&colorizer_stop::set_color,
"The stop color (mapnik.Color).\n")
.add_property("value",
&colorizer_stop::get_value,
&colorizer_stop::set_value,
"The stop value.\n")
.add_property("label",
make_function(&colorizer_stop::get_label, return_value_policy<copy_const_reference>()),
&colorizer_stop::set_label,
"The stop label.\n")
.add_property("mode",
&colorizer_stop::get_mode_enum,
&colorizer_stop::set_mode_enum,
"The stop mode (mapnik.ColorizerMode).\n"
"\n"
"If this is COLORIZER_INHERIT then it will inherit the default mode\n"
" from the RasterColorizer it is added to.\n")
"A Colorizer Stop object.\n"
"Create with a value, ColorizerMode, and Color\n"
"\n"
"Usage:"
">>> color = mapnik.Color(\"#fff000\")\n"
">>> stop= mapnik.ColorizerStop(42.42, mapnik.COLORIZER_LINEAR, color)\n"
))
.add_property("color",
make_function(&colorizer_stop::get_color, return_value_policy<reference_existing_object>()),
&colorizer_stop::set_color,
"The stop color (mapnik.Color).\n")
.add_property("value",
&colorizer_stop::get_value,
&colorizer_stop::set_value,
"The stop value.\n")
.add_property("label",
make_function(&colorizer_stop::get_label, return_value_policy<copy_const_reference>()),
&colorizer_stop::set_label,
"The stop label.\n")
.add_property("mode",
&colorizer_stop::get_mode_enum,
&colorizer_stop::set_mode_enum,
"The stop mode (mapnik.ColorizerMode).\n"
"\n"
"If this is COLORIZER_INHERIT then it will inherit the default mode\n"
" from the RasterColorizer it is added to.\n")
.def(self == self)
.def("__str__",&colorizer_stop::to_string)
;

View file

@ -1,5 +1,5 @@
/*****************************************************************************
*
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2006 Artem Pavlenko, Jean-Francois Doyon
@ -32,7 +32,7 @@ struct raster_symbolizer_pickle_suite : boost::python::pickle_suite
static boost::python::tuple
getinitargs(const raster_symbolizer& r)
{
return boost::python::make_tuple();
return boost::python::make_tuple();
}
*/
@ -54,7 +54,7 @@ struct raster_symbolizer_pickle_suite : boost::python::pickle_suite
);
throw_error_already_set();
}
r.set_mode(extract<std::string>(state[0]));
r.set_scaling(extract<std::string>(state[1]));
r.set_opacity(extract<float>(state[2]));
@ -70,9 +70,9 @@ void export_raster_symbolizer()
class_<raster_symbolizer>("RasterSymbolizer",
init<>("Default ctor"))
.def_pickle(raster_symbolizer_pickle_suite())
.add_property("mode",
make_function(&raster_symbolizer::get_mode,return_value_policy<copy_const_reference>()),
&raster_symbolizer::set_mode,
@ -87,7 +87,7 @@ void export_raster_symbolizer()
">>> r = RasterSymbolizer()\n"
">>> r.mode = 'grain_merge2'\n"
)
.add_property("scaling",
make_function(&raster_symbolizer::get_scaling,return_value_policy<copy_const_reference>()),
&raster_symbolizer::set_scaling,
@ -101,7 +101,7 @@ void export_raster_symbolizer()
">>> r = RasterSymbolizer()\n"
">>> r.scaling = 'bilinear8'\n"
)
.add_property("opacity",
&raster_symbolizer::get_opacity,
&raster_symbolizer::set_opacity,
@ -162,5 +162,5 @@ void export_raster_symbolizer()
">>> r = RasterSymbolizer()\n"
">>> r.mesh_size = 32\n"
)
;
;
}

View file

@ -1,5 +1,5 @@
/*****************************************************************************
*
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2006 Artem Pavlenko, Jean-Francois Doyon
@ -51,7 +51,7 @@ using mapnik::to_expression_string;
struct pickle_symbolizer : public boost::static_visitor<>
{
public:
pickle_symbolizer( boost::python::list syms):
pickle_symbolizer( boost::python::list syms):
syms_(syms) {}
template <typename T>
@ -59,7 +59,7 @@ public:
{
syms_.append(sym);
}
private:
boost::python::list syms_;
};
@ -68,9 +68,9 @@ private:
struct extract_symbolizer : public boost::static_visitor<>
{
public:
extract_symbolizer( rule& r):
extract_symbolizer( rule& r):
r_(r) {}
template <typename T>
void operator () ( T const& sym )
{
@ -78,7 +78,7 @@ public:
}
private:
rule& r_;
};
struct rule_pickle_suite : boost::python::pickle_suite
@ -93,15 +93,15 @@ struct rule_pickle_suite : boost::python::pickle_suite
getstate(const rule& r)
{
boost::python::list syms;
rule::symbolizers::const_iterator begin = r.get_symbolizers().begin();
rule::symbolizers::const_iterator end = r.get_symbolizers().end();
rule::symbolizers::const_iterator end = r.get_symbolizers().end();
pickle_symbolizer serializer( syms );
std::for_each( begin, end , boost::apply_visitor( serializer ));
// We serialize filter expressions AST as strings
std::string filter_expr = to_expression_string(*r.get_filter());
return boost::python::make_tuple(r.get_abstract(),filter_expr,r.has_else_filter(),r.has_also_filter(),syms);
}
@ -117,11 +117,11 @@ struct rule_pickle_suite : boost::python::pickle_suite
);
throw_error_already_set();
}
if (state[0])
{
r.set_title(extract<std::string>(state[0]));
}
}
if (state[1])
{
@ -132,25 +132,25 @@ struct rule_pickle_suite : boost::python::pickle_suite
{
r.set_filter(mapnik::parse_expression(filter,"utf8"));
}
}
}
if (state[2])
{
r.set_else(true);
}
}
if (state[3])
{
r.set_also(true);
}
boost::python::list syms=extract<boost::python::list>(state[4]);
extract_symbolizer serializer( r );
for (int i=0;i<len(syms);++i)
{
symbolizer symbol = extract<symbolizer>(syms[i]);
boost::apply_visitor( serializer, symbol );
}
//symbolizer symbol = extract<symbolizer>(syms[i]);
//boost::apply_visitor( serializer, symbol );
}
}
};
@ -169,11 +169,11 @@ void export_rule()
implicitly_convertible<text_symbolizer,symbolizer>();
implicitly_convertible<glyph_symbolizer,symbolizer>();
implicitly_convertible<markers_symbolizer,symbolizer>();
class_<rule::symbolizers>("Symbolizers",init<>("TODO"))
.def(vector_indexing_suite<rule::symbolizers>())
;
class_<rule>("Rule",init<>("default constructor"))
.def(init<std::string const&,
boost::python::optional<std::string const&,double,double> >())

View file

@ -1,5 +1,5 @@
/*****************************************************************************
*
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2006 Artem Pavlenko, Jean-Francois Doyon
@ -63,7 +63,7 @@ void set_text_displacement(shield_symbolizer & t, boost::python::tuple arg)
{
t.set_displacement(extract<double>(arg[0]),extract<double>(arg[1]));
}
tuple get_anchor(const shield_symbolizer& t)
{
boost::tuple<double,double> pos = t.get_anchor();
@ -75,15 +75,15 @@ void set_anchor(shield_symbolizer & t, boost::python::tuple arg)
t.set_anchor(extract<double>(arg[0]),extract<double>(arg[1]));
}
const std::string get_filename(shield_symbolizer const& t)
{
return path_processor_type::to_string(*t.get_filename());
const std::string get_filename(shield_symbolizer const& t)
{
return path_processor_type::to_string(*t.get_filename());
}
void set_filename(shield_symbolizer & t, std::string const& file_expr)
{
t.set_filename(parse_path(file_expr));
}
void set_filename(shield_symbolizer & t, std::string const& file_expr)
{
t.set_filename(parse_path(file_expr));
}
}
@ -96,7 +96,7 @@ struct shield_symbolizer_pickle_suite : boost::python::pickle_suite
//(name, font name, font size, font color, image file, image type, width, height)
return boost::python::make_tuple( "TODO",//s.get_name(),
s.get_face_name(),s.get_text_size(),s.get_fill(),filename,guess_type(filename));
}
static boost::python::tuple
@ -118,10 +118,10 @@ struct shield_symbolizer_pickle_suite : boost::python::pickle_suite
);
throw_error_already_set();
}*/
s.set_halo_fill(extract<color>(state[0]));
s.set_halo_radius(extract<float>(state[1]));
}
};
@ -131,10 +131,10 @@ void export_shield_symbolizer()
{
using namespace boost::python;
class_< shield_symbolizer, bases<text_symbolizer> >("ShieldSymbolizer",
init<expression_ptr,
std::string const&,
unsigned, mapnik::color const&,
path_expression_ptr>("TODO")
init<expression_ptr,
std::string const&,
unsigned, mapnik::color const&,
path_expression_ptr>("TODO")
)
//.def_pickle(shield_symbolizer_pickle_suite())
.add_property("anchor",
@ -159,7 +159,7 @@ void export_shield_symbolizer()
make_function(&shield_symbolizer::get_face_name,return_value_policy<copy_const_reference>()),
&shield_symbolizer::set_face_name,
"Set/get the face_name property of the label")
.add_property("fill",
.add_property("fill",
make_function(&shield_symbolizer::get_fill,return_value_policy<copy_const_reference>()),
&shield_symbolizer::set_fill)
.add_property("fontset",
@ -172,7 +172,7 @@ void export_shield_symbolizer()
make_function(&shield_symbolizer::get_halo_fill,return_value_policy<copy_const_reference>()),
&shield_symbolizer::set_halo_fill)
.add_property("halo_radius",
&shield_symbolizer::get_halo_radius,
&shield_symbolizer::get_halo_radius,
&shield_symbolizer::set_halo_radius)
.add_property("horizontal_alignment",
&shield_symbolizer::get_horizontal_alignment,

View file

@ -1,5 +1,5 @@
/*****************************************************************************
*
*
* This file is part of Mapnik (c+mapping toolkit)
*
* Copyright (C) 2006 Artem Pavlenko, Jean-Francois Doyon
@ -57,7 +57,7 @@ struct stroke_pickle_suite : boost::python::pickle_suite
{
return boost::python::make_tuple(s.get_color(),s.get_width());
}
static boost::python::tuple
@ -140,15 +140,15 @@ void export_stroke ()
.add_property("width",
&stroke::get_width,
&stroke::set_width,
"Gets or sets the stroke width in pixels.\n")
"Gets or sets the stroke width in pixels.\n")
.add_property("opacity",
&stroke::get_opacity,
&stroke::set_opacity,
&stroke::set_opacity,
"Gets or sets the opacity of this stroke.\n"
"The value is a float between 0 and 1.\n")
.add_property("gamma",
&stroke::get_gamma,
&stroke::set_gamma,
&stroke::set_gamma,
"Gets or sets the gamma of this stroke.\n"
"The value is a float between 0 and 1.\n")
.add_property("line_cap",

View file

@ -1,5 +1,5 @@
/*****************************************************************************
*
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2006 Artem Pavlenko, Jean-Francois Doyon
@ -42,7 +42,7 @@ struct style_pickle_suite : boost::python::pickle_suite
rules::const_iterator end = s.get_rules().end();
for (; it != end; ++it)
{
rule_list.append( *it );
rule_list.append( *it );
}
return boost::python::make_tuple(rule_list);
@ -60,14 +60,14 @@ struct style_pickle_suite : boost::python::pickle_suite
);
throw_error_already_set();
}
boost::python::list rules = extract<boost::python::list>(state[0]);
for (int i=0; i<len(rules); ++i)
{
s.add_rule(extract<rule>(rules[i]));
}
}
};
void export_style()
@ -95,14 +95,14 @@ void export_style()
"Usage:\n"
">>> for r in m.find_style('style 1').rules:\n"
">>> print r\n"
"<mapnik2._mapnik2.Rule object at 0x100549910>\n"
"<mapnik2._mapnik2.Rule object at 0x100549980>\n"
)
"<mapnik._mapnik.Rule object at 0x100549910>\n"
"<mapnik._mapnik.Rule object at 0x100549980>\n"
)
.add_property("filter_mode",
&feature_type_style::get_filter_mode,
&feature_type_style::set_filter_mode,
"Set/get the placement of the label")
;
}

View file

@ -1,5 +1,5 @@
/*****************************************************************************
*
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2010 Robert Coup
@ -43,11 +43,11 @@ template <class T>
void set_svg_transform(T& symbolizer, std::string const& transform_wkt)
{
agg::trans_affine tr;
if (!mapnik::svg::parse_transform(transform_wkt, tr))
if (!mapnik::svg::parse_transform(transform_wkt.c_str(), tr))
{
std::stringstream ss;
ss << "Could not parse transform from '" << transform_wkt << "', expected string like: 'matrix(1, 0, 0, 1, 0, 0)'";
throw mapnik::value_error(ss.str());
throw mapnik::value_error(ss.str());
}
mapnik::transform_type matrix;
tr.store_to(&matrix[0]);

View file

@ -1,5 +1,5 @@
/*****************************************************************************
*
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2006 Artem Pavlenko, Jean-Francois Doyon
@ -45,52 +45,52 @@ struct get_symbolizer_type : public boost::static_visitor<std::string>
{
public:
get_symbolizer_type() {}
std::string operator () ( const point_symbolizer & /*sym*/ )
{
return "point";
}
std::string operator () ( const line_symbolizer & /*sym*/ )
{
return "line";
}
std::string operator () ( const line_pattern_symbolizer & /*sym*/ )
{
return "line_pattern";
}
std::string operator () ( const polygon_symbolizer & /*sym*/ )
{
return "polygon";
}
std::string operator () ( const polygon_pattern_symbolizer & /*sym*/ )
{
return "polygon_pattern";
}
std::string operator () ( const raster_symbolizer & /*sym*/ )
{
return "raster";
}
std::string operator () ( const shield_symbolizer & /*sym*/ )
{
return "shield";
}
std::string operator () ( const text_symbolizer & /*sym*/ )
{
return "text";
}
std::string operator () ( const building_symbolizer & /*sym*/ )
{
return "building";
}
std::string operator () ( const markers_symbolizer & /*sym*/ )
{
return "markers";

View file

@ -1,5 +1,5 @@
/*****************************************************************************
*
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2006 Artem Pavlenko, Jean-Francois Doyon
@ -69,7 +69,7 @@ struct text_symbolizer_pickle_suite : boost::python::pickle_suite
return boost::python::make_tuple("TODO",//t.get_name(),
t.get_face_name(),t.get_text_size(),t.get_fill());
}
static boost::python::tuple
@ -77,7 +77,7 @@ struct text_symbolizer_pickle_suite : boost::python::pickle_suite
{
boost::python::tuple disp = get_text_displacement(t);
boost::python::tuple anchor = get_anchor(t);
// so we do not exceed max args accepted by make_tuple,
// lets put the increasing list of parameters in a list
boost::python::list extras;
@ -91,11 +91,11 @@ struct text_symbolizer_pickle_suite : boost::python::pickle_suite
extras.append(t.get_text_opacity());
extras.append(t.get_minimum_padding());
extras.append(t.get_minimum_path_length());
return boost::python::make_tuple(disp,t.get_label_placement(),
t.get_vertical_alignment(),t.get_halo_radius(),t.get_halo_fill(),t.get_text_ratio(),
t.get_wrap_width(),t.get_label_spacing(),t.get_minimum_distance(),t.get_allow_overlap(),
anchor,t.get_force_odd_labels(),t.get_max_char_angle_delta(),extras
t.get_vertical_alignment(),t.get_halo_radius(),t.get_halo_fill(),t.get_text_ratio(),
t.get_wrap_width(),t.get_label_spacing(),t.get_minimum_distance(),t.get_allow_overlap(),
anchor,t.get_force_odd_labels(),t.get_max_char_angle_delta(),extras
);
}
@ -103,7 +103,7 @@ struct text_symbolizer_pickle_suite : boost::python::pickle_suite
setstate (text_symbolizer& t, boost::python::tuple state)
{
using namespace boost::python;
if (len(state) != 14)
{
PyErr_SetObject(PyExc_ValueError,
@ -112,16 +112,16 @@ struct text_symbolizer_pickle_suite : boost::python::pickle_suite
);
throw_error_already_set();
}
tuple disp = extract<tuple>(state[0]);
double dx = extract<double>(disp[0]);
double dy = extract<double>(disp[1]);
t.set_displacement(dx,dy);
t.set_label_placement(extract<label_placement_e>(state[1]));
t.set_vertical_alignment(extract<vertical_alignment_e>(state[2]));
t.set_halo_radius(extract<unsigned>(state[3]));
t.set_halo_fill(extract<color>(state[4]));
@ -135,14 +135,14 @@ struct text_symbolizer_pickle_suite : boost::python::pickle_suite
t.set_minimum_distance(extract<double>(state[8]));
t.set_allow_overlap(extract<bool>(state[9]));
tuple anch = extract<tuple>(state[10]);
double x = extract<double>(anch[0]);
double y = extract<double>(anch[1]);
t.set_anchor(x,y);
t.set_force_odd_labels(extract<bool>(state[11]));
t.set_max_char_angle_delta(extract<double>(state[12]));
list extras = extract<list>(state[13]);
t.set_wrap_char_from_string(extract<std::string>(extras[0]));
@ -187,7 +187,7 @@ void export_text_symbolizer()
.value("MIDDLE",J_MIDDLE)
.value("RIGHT",J_RIGHT)
;
enumeration_<text_transform_e>("text_transform")
.value("NONE",NONE)
.value("UPPERCASE",UPPERCASE)
@ -196,19 +196,19 @@ void export_text_symbolizer()
;
class_<text_symbolizer>("TextSymbolizer",init<expression_ptr,std::string const&, unsigned,color const&>())
/*
// todo - all python classes can have kwargs and default constructors
class_<text_symbolizer>("TextSymbolizer",
/*
// todo - all python classes can have kwargs and default constructors
class_<text_symbolizer>("TextSymbolizer",
init<expression_ptr,std::string const&, unsigned,color const&>(
(
arg("name"),
arg("font_face")="DejaVu Sans Book",
arg("size")=10,
arg("color")=color("black")
),
(
arg("name"),
arg("font_face")="DejaVu Sans Book",
arg("size")=10,
arg("color")=color("black")
),
"Create a TextSymbolizer\n"
))
*/
*/
//.def_pickle(text_symbolizer_pickle_suite())
.add_property("anchor",
@ -233,7 +233,7 @@ void export_text_symbolizer()
make_function(&text_symbolizer::get_face_name,return_value_policy<copy_const_reference>()),
&text_symbolizer::set_face_name,
"Set/get the face_name property of the label")
.add_property("fill",
.add_property("fill",
make_function(&text_symbolizer::get_fill,return_value_policy<copy_const_reference>()),
&text_symbolizer::set_fill)
.add_property("fontset",
@ -246,7 +246,7 @@ void export_text_symbolizer()
make_function(&text_symbolizer::get_halo_fill,return_value_policy<copy_const_reference>()),
&text_symbolizer::set_halo_fill)
.add_property("halo_radius",
&text_symbolizer::get_halo_radius,
&text_symbolizer::get_halo_radius,
&text_symbolizer::set_halo_radius)
.add_property("horizontal_alignment",
&text_symbolizer::get_horizontal_alignment,

View file

@ -1,5 +1,5 @@
/*****************************************************************************
*
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2011 Artem Pavlenko
@ -27,6 +27,7 @@
#include <boost/implicit_cast.hpp>
namespace boost { namespace python {
struct value_converter : public boost::static_visitor<PyObject*>
{
PyObject * operator() (int val) const
@ -47,23 +48,49 @@ namespace boost { namespace python {
{
return ::PyBool_FromLong(val);
}
PyObject * operator() (std::string const& s) const
{
PyObject *obj = Py_None;
obj = ::PyUnicode_DecodeUTF8(s.c_str(),implicit_cast<ssize_t>(s.length()),0);
return obj;
}
PyObject * operator() (UnicodeString const& s) const
{
std::string buffer;
mapnik::to_utf8(s,buffer);
PyObject *obj = Py_None;
obj = ::PyUnicode_DecodeUTF8(buffer.c_str(),implicit_cast<ssize_t>(buffer.length()),0);
obj = ::PyUnicode_DecodeUTF8(buffer.c_str(),implicit_cast<ssize_t>(buffer.length()),0);
return obj;
}
PyObject * operator() (mapnik::value_null const& /*s*/) const
{
return Py_None;
}
};
}
struct mapnik_value_to_python
{
static PyObject* convert(mapnik::value const& v)
{
return boost::apply_visitor(value_converter(),v.base());
}
};
struct mapnik_param_to_python
{
static PyObject* convert(mapnik::value_holder const& v)
{
return boost::apply_visitor(value_converter(),v);
}
};
}
}
#endif // MAPNIK_PYTHON_BINDING_VALUE_CONVERTER_INCLUDED

View file

@ -1,5 +1,5 @@
/*****************************************************************************
*
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2009 Artem Pavlenko, Jean-Francois Doyon
@ -47,31 +47,31 @@ mapnik::coord2d forward_point(mapnik::CoordTransform const& t, mapnik::coord2d c
t.forward(out);
return out;
}
mapnik::coord2d backward_point(mapnik::CoordTransform const& t, mapnik::coord2d const& in)
{
mapnik::coord2d out(in);
t.backward(out);
return out;
}
mapnik::box2d<double> forward_envelope(mapnik::CoordTransform const& t, mapnik::box2d<double> const& in)
{
return t.forward(in);
}
mapnik::box2d<double> backward_envelope(mapnik::CoordTransform const& t, mapnik::box2d<double> const& in)
{
return t.backward(in);
}
}
void export_view_transform()
void export_view_transform()
{
using namespace boost::python;
using mapnik::box2d;
using mapnik::coord2d;
class_<CoordTransform>("ViewTransform",init<int,int,box2d<double> const& > (
"Create a ViewTransform with a width and height as integers and extent"))
.def_pickle(view_transform_pickle_suite())

View file

@ -1,5 +1,5 @@
/*****************************************************************************
*
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2011 Artem Pavlenko
@ -40,9 +40,9 @@ namespace mapnik {
template <typename T>
static void grid2utf(T const& grid_type,
boost::python::list& l,
std::vector<grid::lookup_type>& key_order)
static void grid2utf(T const& grid_type,
boost::python::list& l,
std::vector<grid::lookup_type>& key_order)
{
typename T::data_type const& data = grid_type.data();
typename T::feature_key_type const& feature_keys = grid_type.get_feature_keys();
@ -50,12 +50,12 @@ static void grid2utf(T const& grid_type,
typename T::key_type::const_iterator key_pos;
typename T::feature_key_type::const_iterator feature_pos;
// start counting at utf8 codepoint 32, aka space character
uint16_t codepoint = 32;
boost::uint16_t codepoint = 32;
unsigned array_size = data.width();
for (unsigned y = 0; y < data.height(); ++y)
{
uint16_t idx = 0;
boost::uint16_t idx = 0;
boost::scoped_array<Py_UNICODE> line(new Py_UNICODE[array_size]);
typename T::value_type const* row = data.getRow(y);
for (unsigned x = 0; x < data.width(); ++x)
@ -71,7 +71,7 @@ static void grid2utf(T const& grid_type,
// can't be encoded directly in JSON.
if (codepoint == 34) ++codepoint; // Skip "
else if (codepoint == 92) ++codepoint; // Skip backslash
keys[val] = codepoint;
key_order.push_back(val);
line[idx++] = static_cast<Py_UNICODE>(codepoint);
@ -85,17 +85,17 @@ static void grid2utf(T const& grid_type,
// else, shouldn't get here...
}
l.append(boost::python::object(
boost::python::handle<>(
PyUnicode_FromUnicode(line.get(), array_size))));
boost::python::handle<>(
PyUnicode_FromUnicode(line.get(), array_size))));
}
}
template <typename T>
static void grid2utf(T const& grid_type,
boost::python::list& l,
std::vector<typename T::lookup_type>& key_order,
unsigned int resolution)
static void grid2utf(T const& grid_type,
boost::python::list& l,
std::vector<typename T::lookup_type>& key_order,
unsigned int resolution)
{
//typename T::data_type const& data = grid_type.data();
typename T::feature_key_type const& feature_keys = grid_type.get_feature_keys();
@ -103,13 +103,13 @@ static void grid2utf(T const& grid_type,
typename T::key_type::const_iterator key_pos;
typename T::feature_key_type::const_iterator feature_pos;
// start counting at utf8 codepoint 32, aka space character
uint16_t codepoint = 32;
boost::uint16_t codepoint = 32;
// TODO - use double?
unsigned array_size = static_cast<unsigned int>(grid_type.width()/resolution);
for (unsigned y = 0; y < grid_type.height(); y=y+resolution)
{
uint16_t idx = 0;
boost::uint16_t idx = 0;
boost::scoped_array<Py_UNICODE> line(new Py_UNICODE[array_size]);
mapnik::grid::value_type const* row = grid_type.getRow(y);
for (unsigned x = 0; x < grid_type.width(); x=x+resolution)
@ -138,17 +138,17 @@ static void grid2utf(T const& grid_type,
// else, shouldn't get here...
}
l.append(boost::python::object(
boost::python::handle<>(
PyUnicode_FromUnicode(line.get(), array_size))));
boost::python::handle<>(
PyUnicode_FromUnicode(line.get(), array_size))));
}
}
template <typename T>
static void grid2utf2(T const& grid_type,
boost::python::list& l,
std::vector<typename T::lookup_type>& key_order,
unsigned int resolution)
static void grid2utf2(T const& grid_type,
boost::python::list& l,
std::vector<typename T::lookup_type>& key_order,
unsigned int resolution)
{
typename T::data_type const& data = grid_type.data();
typename T::feature_key_type const& feature_keys = grid_type.get_feature_keys();
@ -194,16 +194,16 @@ static void grid2utf2(T const& grid_type,
// else, shouldn't get here...
}
l.append(boost::python::object(
boost::python::handle<>(
PyUnicode_FromUnicode(line.get(), array_size))));
boost::python::handle<>(
PyUnicode_FromUnicode(line.get(), array_size))));
}
}
template <typename T>
static void write_features(T const& grid_type,
boost::python::dict& feature_data,
std::vector<typename T::lookup_type> const& key_order)
boost::python::dict& feature_data,
std::vector<typename T::lookup_type> const& key_order)
{
std::string const& key = grid_type.get_key();
std::set<std::string> const& attributes = grid_type.property_names();
@ -218,7 +218,7 @@ static void write_features(T const& grid_type,
if (itr != props.end())
{
typename T::lookup_type const& join_value = itr->second.to_string();
// only serialize features visible in the grid
if(std::find(key_order.begin(), key_order.end(), join_value) != key_order.end()) {
boost::python::dict feat;
@ -236,7 +236,7 @@ static void write_features(T const& grid_type,
boost::python::handle<>(
boost::apply_visitor(
boost::python::value_converter(),
it->second.base())));
it->second.base())));
}
}
else if ( (attributes.find(key_name) != attributes.end()) )
@ -246,7 +246,7 @@ static void write_features(T const& grid_type,
boost::python::handle<>(
boost::apply_visitor(
boost::python::value_converter(),
it->second.base())));
it->second.base())));
}
}
if (found)
@ -264,14 +264,14 @@ static void write_features(T const& grid_type,
template <typename T>
static void grid_encode_utf(T const& grid_type,
boost::python::dict & json,
bool add_features,
unsigned int resolution)
boost::python::dict & json,
bool add_features,
unsigned int resolution)
{
// convert buffer to utf and gather key order
boost::python::list l;
std::vector<typename T::lookup_type> key_order;
if (resolution != 1) {
// resample on the fly - faster, less accurate
mapnik::grid2utf<T>(grid_type,l,key_order,resolution);
@ -281,7 +281,7 @@ static void grid_encode_utf(T const& grid_type,
}
else
{
mapnik::grid2utf<T>(grid_type,l,key_order);
mapnik::grid2utf<T>(grid_type,l,key_order);
}
// convert key order to proper python list
@ -325,9 +325,9 @@ static boost::python::dict grid_encode( T const& grid, std::string format, bool
* whether features are dumped is determined by argument not 'fields'
*/
static void render_layer_for_grid(const mapnik::Map& map,
mapnik::grid& grid,
unsigned layer_idx, // TODO - layer by name or index
boost::python::list const& fields)
mapnik::grid& grid,
unsigned layer_idx, // TODO - layer by name or index
boost::python::list const& fields)
{
std::vector<mapnik::layer> const& layers = map.layers();
std::size_t layer_num = layers.size();
@ -347,9 +347,9 @@ static void render_layer_for_grid(const mapnik::Map& map,
}
else
{
std::stringstream s;
s << "list of field names must be strings";
throw mapnik::value_error(s.str());
std::stringstream s;
s << "list of field names must be strings";
throw mapnik::value_error(s.str());
}
}
@ -358,10 +358,10 @@ static void render_layer_for_grid(const mapnik::Map& map,
std::string const& key = grid.get_key();
// if key is special __id__ keyword
if (key == grid.id_name_)
if (key == grid.id_name_)
{
// TODO - should feature.id() be a first class attribute?
// if __id__ is requested to be dumped out
// remove it so that datasource queries will not break
if (attributes.find(key) != attributes.end())
@ -375,7 +375,7 @@ static void render_layer_for_grid(const mapnik::Map& map,
// them make sure the datasource query includes this field
attributes.insert(key);
}
mapnik::grid_renderer<mapnik::grid> ren(map,grid,1.0,0,0);
mapnik::layer const& layer = layers[layer_idx];
ren.apply(layer,attributes);
@ -385,10 +385,10 @@ static void render_layer_for_grid(const mapnik::Map& map,
* grid object is created on the fly at potentially reduced size
*/
static boost::python::dict render_grid(const mapnik::Map& map,
unsigned layer_idx, // layer
std::string const& key, // key_name
unsigned int step, // resolution
boost::python::list const& fields)
unsigned layer_idx, // layer
std::string const& key, // key_name
unsigned int step, // resolution
boost::python::list const& fields)
{
std::vector<mapnik::layer> const& layers = map.layers();
@ -405,7 +405,7 @@ static boost::python::dict render_grid(const mapnik::Map& map,
// TODO - no need to pass step here
mapnik::grid grid(grid_width,grid_height,key,step);
// convert python list to std::vector
boost::python::ssize_t num_fields = boost::python::len(fields);
for(boost::python::ssize_t i=0; i<num_fields; i++) {
@ -415,20 +415,20 @@ static boost::python::dict render_grid(const mapnik::Map& map,
}
else
{
std::stringstream s;
s << "list of field names must be strings";
throw mapnik::value_error(s.str());
std::stringstream s;
s << "list of field names must be strings";
throw mapnik::value_error(s.str());
}
}
// copy property names
std::set<std::string> attributes = grid.property_names();
// if key is special __id__ keyword
if (key == grid.id_name_)
if (key == grid.id_name_)
{
// TODO - should feature.id() be a first class attribute?
// if __id__ is requested to be dumped out
// remove it so that datasource queries will not break
if (attributes.find(key) != attributes.end())
@ -442,7 +442,7 @@ static boost::python::dict render_grid(const mapnik::Map& map,
// them make sure the datasource query includes this field
attributes.insert(key);
}
try
{
mapnik::grid_renderer<mapnik::grid> ren(map,grid,1.0,0,0);
@ -453,7 +453,7 @@ static boost::python::dict render_grid(const mapnik::Map& map,
{
throw;
}
bool add_features = false;
if (num_fields > 0)
add_features = true;

View file

@ -1,5 +1,5 @@
/*****************************************************************************
*
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2007 Artem Pavlenko
@ -68,7 +68,7 @@ struct python_optional : public boost::noncopyable
const registration& converters(registered<T>::converters);
if (implicit_rvalue_convertible_from_python(source,
if (implicit_rvalue_convertible_from_python(source,
converters)) {
rvalue_from_python_stage1_data data =
rvalue_from_python_stage1(source, converters);
@ -82,7 +82,7 @@ struct python_optional : public boost::noncopyable
{
using namespace boost::python::converter;
void * const storage = ((rvalue_from_python_storage<T> *)
void * const storage = ((rvalue_from_python_storage<T> *)
data)->storage.bytes;
if (data->convertible == source) // == None

View file

@ -41,7 +41,7 @@ if env['HAS_CAIRO']:
libraries = copy(env['LIBMAPNIK_LIBS'])
boost_program_options = 'boost_program_options%s' % env['BOOST_APPEND']
libraries.extend([boost_program_options,'mapnik2'])
libraries.extend([boost_program_options,'mapnik'])
rundemo = demo_env.Program('rundemo', source, LIBS=libraries, LINKFLAGS=env["CUSTOM_LDFLAGS"])
@ -50,4 +50,4 @@ Depends(rundemo, env.subst('../../src/%s' % env['MAPNIK_LIB_NAME']))
# we don't install this app because the datasource paths are relative
# and we're not going to install the sample data.
#env.Install(install_prefix + '/bin', rundemo)
#env.Alias('install', install_prefix + '/bin')
#env.Alias('install', install_prefix + '/bin')

View file

@ -1,8 +1,8 @@
/*****************************************************************************
*
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2006 Artem Pavlenko
* Copyright (C) 2011 Artem Pavlenko
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@ -40,69 +40,69 @@
int main ( int argc , char** argv)
{
{
if (argc != 2)
{
std::cout << "usage: ./rundemo <mapnik_install_dir>\nUsually /usr/local/lib/mapnik2\n";
std::cout << "usage: ./rundemo <mapnik_install_dir>\nUsually /usr/local/lib/mapnik\n";
std::cout << "Warning: ./rundemo looks for data in ../data/,\nTherefore must be run from within the demo/c++ folder.\n";
return EXIT_SUCCESS;
}
using namespace mapnik;
try {
std::cout << " running demo ... \n";
std::string mapnik_dir(argv[1]);
std::cout << " looking for 'shape.input' plugin in... " << mapnik_dir << "/input/" << "\n";
datasource_cache::instance()->register_datasources(mapnik_dir + "/input/");
datasource_cache::instance()->register_datasources(mapnik_dir + "/input/");
std::cout << " looking for DejaVuSans font in... " << mapnik_dir << "/fonts/DejaVuSans.ttf" << "\n";
freetype_engine::register_font(mapnik_dir + "/fonts/DejaVuSans.ttf");
Map m(800,600);
m.set_background(color_factory::from_string("white"));
// create styles
// Provinces (polygon)
feature_type_style provpoly_style;
rule provpoly_rule_on;
provpoly_rule_on.set_filter(parse_expression("[NAME_EN] = 'Ontario'"));
provpoly_rule_on.append(polygon_symbolizer(color(250, 190, 183)));
provpoly_style.add_rule(provpoly_rule_on);
rule provpoly_rule_qc;
provpoly_rule_qc.set_filter(parse_expression("[NOM_FR] = 'Québec'"));
provpoly_rule_qc.set_filter(parse_expression("[NOM_FR] = 'Québec'"));
provpoly_rule_qc.append(polygon_symbolizer(color(217, 235, 203)));
provpoly_style.add_rule(provpoly_rule_qc);
m.insert_style("provinces",provpoly_style);
// Provinces (polyline)
feature_type_style provlines_style;
stroke provlines_stk (color(0,0,0),1.0);
provlines_stk.add_dash(8, 4);
provlines_stk.add_dash(2, 2);
provlines_stk.add_dash(2, 2);
rule provlines_rule;
provlines_rule.append(line_symbolizer(provlines_stk));
provlines_style.add_rule(provlines_rule);
m.insert_style("provlines",provlines_style);
// Drainage
// Drainage
feature_type_style qcdrain_style;
rule qcdrain_rule;
qcdrain_rule.set_filter(parse_expression("[HYC] = 8"));
qcdrain_rule.append(polygon_symbolizer(color(153, 204, 255)));
qcdrain_style.add_rule(qcdrain_rule);
m.insert_style("drainage",qcdrain_style);
// Roads 3 and 4 (The "grey" roads)
feature_type_style roads34_style;
feature_type_style roads34_style;
rule roads34_rule;
roads34_rule.set_filter(parse_expression("[CLASS] = 3 or [CLASS] = 4"));
stroke roads34_rule_stk(color(171,158,137),2.0);
@ -110,9 +110,9 @@ int main ( int argc , char** argv)
roads34_rule_stk.set_line_join(ROUND_JOIN);
roads34_rule.append(line_symbolizer(roads34_rule_stk));
roads34_style.add_rule(roads34_rule);
m.insert_style("smallroads",roads34_style);
// Roads 2 (The thin yellow ones)
feature_type_style roads2_style_1;
@ -123,9 +123,9 @@ int main ( int argc , char** argv)
roads2_rule_stk_1.set_line_join(ROUND_JOIN);
roads2_rule_1.append(line_symbolizer(roads2_rule_stk_1));
roads2_style_1.add_rule(roads2_rule_1);
m.insert_style("road-border", roads2_style_1);
feature_type_style roads2_style_2;
rule roads2_rule_2;
roads2_rule_2.set_filter(parse_expression("[CLASS] = 2"));
@ -134,9 +134,9 @@ int main ( int argc , char** argv)
roads2_rule_stk_2.set_line_join(ROUND_JOIN);
roads2_rule_2.append(line_symbolizer(roads2_rule_stk_2));
roads2_style_2.add_rule(roads2_rule_2);
m.insert_style("road-fill", roads2_style_2);
// Roads 1 (The big orange ones, the highways)
feature_type_style roads1_style_1;
rule roads1_rule_1;
@ -147,7 +147,7 @@ int main ( int argc , char** argv)
roads1_rule_1.append(line_symbolizer(roads1_rule_stk_1));
roads1_style_1.add_rule(roads1_rule_1);
m.insert_style("highway-border", roads1_style_1);
feature_type_style roads1_style_2;
rule roads1_rule_2;
roads1_rule_2.set_filter(parse_expression("[CLASS] = 1"));
@ -157,9 +157,9 @@ int main ( int argc , char** argv)
roads1_rule_2.append(line_symbolizer(roads1_rule_stk_2));
roads1_style_2.add_rule(roads1_rule_2);
m.insert_style("highway-fill", roads1_style_2);
// Populated Places
feature_type_style popplaces_style;
rule popplaces_rule;
text_symbolizer popplaces_text_symbolizer(parse_expression("[GEONAME]"),"DejaVu Sans Book",10,color(0,0,0));
@ -167,22 +167,22 @@ int main ( int argc , char** argv)
popplaces_text_symbolizer.set_halo_radius(1);
popplaces_rule.append(popplaces_text_symbolizer);
popplaces_style.add_rule(popplaces_rule);
m.insert_style("popplaces",popplaces_style );
// layers
// Provincial polygons
{
parameters p;
p["type"]="shape";
p["file"]="../data/boundaries";
layer lyr("Provinces");
layer lyr("Provinces");
lyr.set_datasource(datasource_cache::instance()->create(p));
lyr.add_style("provinces");
lyr.add_style("provinces");
m.addLayer(lyr);
}
// Drainage
{
parameters p;
@ -190,38 +190,38 @@ int main ( int argc , char** argv)
p["file"]="../data/qcdrainage";
layer lyr("Quebec Hydrography");
lyr.set_datasource(datasource_cache::instance()->create(p));
lyr.add_style("drainage");
lyr.add_style("drainage");
m.addLayer(lyr);
}
{
parameters p;
p["type"]="shape";
p["file"]="../data/ontdrainage";
layer lyr("Ontario Hydrography");
layer lyr("Ontario Hydrography");
lyr.set_datasource(datasource_cache::instance()->create(p));
lyr.add_style("drainage");
lyr.add_style("drainage");
m.addLayer(lyr);
}
// Provincial boundaries
{
parameters p;
p["type"]="shape";
p["file"]="../data/boundaries_l";
layer lyr("Provincial borders");
layer lyr("Provincial borders");
lyr.set_datasource(datasource_cache::instance()->create(p));
lyr.add_style("provlines");
lyr.add_style("provlines");
m.addLayer(lyr);
}
// Roads
{
parameters p;
p["type"]="shape";
p["file"]="../data/roads";
layer lyr("Roads");
p["file"]="../data/roads";
layer lyr("Roads");
lyr.set_datasource(datasource_cache::instance()->create(p));
lyr.add_style("smallroads");
lyr.add_style("road-border");
@ -229,7 +229,7 @@ int main ( int argc , char** argv)
lyr.add_style("highway-border");
lyr.add_style("highway-fill");
m.addLayer(lyr);
m.addLayer(lyr);
}
// popplaces
{
@ -239,27 +239,30 @@ int main ( int argc , char** argv)
p["encoding"] = "latin1";
layer lyr("Populated Places");
lyr.set_datasource(datasource_cache::instance()->create(p));
lyr.add_style("popplaces");
lyr.add_style("popplaces");
m.addLayer(lyr);
}
m.zoom_to_box(box2d<double>(1405120.04127408,-247003.813399447,
1706357.31328276,-25098.593149577));
1706357.31328276,-25098.593149577));
image_32 buf(m.width(),m.height());
agg_renderer<image_32> ren(m,buf);
ren.apply();
save_to_file<image_data_32>(buf.data(),"demo.jpg","jpeg");
save_to_file<image_data_32>(buf.data(),"demo.png","png");
save_to_file<image_data_32>(buf.data(),"demo256.png","png256");
save_to_file<image_data_32>(buf.data(),"demo.tif","tiff");
std::cout << "Three maps have been rendered using AGG in the current directory:\n"
"- demo.jpg\n"
"- demo.png\n"
"- demo256.png\n"
"Have a look!\n";
#if defined(HAVE_CAIRO)
"- demo.jpg\n"
"- demo.png\n"
"- demo256.png\n"
"- demo.tif\n"
"Have a look!\n";
#if defined(HAVE_CAIRO)
Cairo::RefPtr<Cairo::ImageSurface> image_surface;
image_surface = Cairo::ImageSurface::create(Cairo::FORMAT_ARGB32, m.width(),m.height());
@ -280,12 +283,12 @@ int main ( int argc , char** argv)
svg_render.apply();
std::cout << "Three maps have been rendered using Cairo in the current directory:\n"
"- cairo-demo.png\n"
"- cairo-demo256.png\n"
"- cairo-demo.pdf\n"
"- cairo-demo.svg\n"
"Have a look!\n";
#endif
"- cairo-demo.png\n"
"- cairo-demo256.png\n"
"- cairo-demo.pdf\n"
"- cairo-demo.svg\n"
"Have a look!\n";
#endif
}
catch ( const mapnik::config_error & ex )

View file

@ -26,7 +26,7 @@
import sys
try:
import mapnik2
import mapnik
except:
print '\n\nThe mapnik library and python bindings must have been compiled and \
installed successfully before running this script.\n\n'
@ -41,11 +41,11 @@ except ImportError:
# Instanciate a map, giving it a width and height. Remember: the word "map" is
# reserved in Python! :)
m = mapnik2.Map(800,600,"+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0 +k=1.0 +units=m +nadgrids=@null +no_defs")
m = mapnik.Map(800,600,"+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0 +k=1.0 +units=m +nadgrids=@null +no_defs")
# Set its background colour. More on colours later ...
m.background = mapnik2.Color('white')
m.background = mapnik.Color('white')
# Now we can start adding layers, in stacking order (i.e. bottom layer first)
@ -66,9 +66,9 @@ m.background = mapnik2.Color('white')
# password='mypassword'
# table= TODO
provpoly_lyr = mapnik2.Layer('Provinces')
provpoly_lyr = mapnik.Layer('Provinces')
provpoly_lyr.srs = "+proj=lcc +ellps=GRS80 +lat_0=49 +lon_0=-95 +lat+1=49 +lat_2=77 +datum=NAD83 +units=m +no_defs"
provpoly_lyr.datasource = mapnik2.Shapefile(file='../data/boundaries', encoding='latin1')
provpoly_lyr.datasource = mapnik.Shapefile(file='../data/boundaries', encoding='latin1')
# We then define a style for the layer. A layer can have one or many styles.
# Styles are named, so they can be shared across different layers.
@ -78,18 +78,18 @@ provpoly_lyr.datasource = mapnik2.Shapefile(file='../data/boundaries', encoding=
# multiple styles in one layer is the same has having multiple layers.
# The paradigm is useful mostly as a convenience.
provpoly_style = mapnik2.Style()
provpoly_style = mapnik.Style()
# A Style needs one or more rules. A rule will normally consist of a filter
# for feature selection, and one or more symbolizers.
provpoly_rule_on = mapnik2.Rule()
provpoly_rule_on = mapnik.Rule()
# A Expression() allows the selection of features to which the symbology will
# be applied. More on Mapnik expressions can be found in Tutorial #2.
# A given feature can only match one filter per rule per style.
provpoly_rule_on.filter = mapnik2.Expression("[NAME_EN] = 'Ontario'")
provpoly_rule_on.filter = mapnik.Expression("[NAME_EN] = 'Ontario'")
# Here a symbolizer is defined. Available are:
# - LineSymbolizer(Color(),<width>)
@ -103,12 +103,12 @@ provpoly_rule_on.filter = mapnik2.Expression("[NAME_EN] = 'Ontario'")
# - Color(<string>) where <string> will be something like '#00FF00'
# or '#0f0' or 'green'
provpoly_rule_on.symbols.append(mapnik2.PolygonSymbolizer(mapnik2.Color(250, 190, 183)))
provpoly_rule_on.symbols.append(mapnik.PolygonSymbolizer(mapnik.Color(250, 190, 183)))
provpoly_style.rules.append(provpoly_rule_on)
provpoly_rule_qc = mapnik2.Rule()
provpoly_rule_qc.filter = mapnik2.Expression("[NOM_FR] = 'Québec'")
provpoly_rule_qc.symbols.append(mapnik2.PolygonSymbolizer(mapnik2.Color(217, 235, 203)))
provpoly_rule_qc = mapnik.Rule()
provpoly_rule_qc.filter = mapnik.Expression("[NOM_FR] = 'Québec'")
provpoly_rule_qc.symbols.append(mapnik.PolygonSymbolizer(mapnik.Color(217, 235, 203)))
provpoly_style.rules.append(provpoly_rule_qc)
# Add the style to the map, giving it a name. This is the name that will be
@ -131,14 +131,14 @@ m.layers.append(provpoly_lyr)
# A simple example ...
qcdrain_lyr = mapnik2.Layer('Quebec Hydrography')
qcdrain_lyr = mapnik.Layer('Quebec Hydrography')
qcdrain_lyr.srs = "+proj=lcc +ellps=GRS80 +lat_0=49 +lon_0=-95 +lat+1=49 +lat_2=77 +datum=NAD83 +units=m +no_defs"
qcdrain_lyr.datasource = mapnik2.Shapefile(file='../data/qcdrainage')
qcdrain_lyr.datasource = mapnik.Shapefile(file='../data/qcdrainage')
qcdrain_style = mapnik2.Style()
qcdrain_rule = mapnik2.Rule()
qcdrain_rule.filter = mapnik2.Expression('[HYC] = 8')
qcdrain_rule.symbols.append(mapnik2.PolygonSymbolizer(mapnik2.Color(153, 204, 255)))
qcdrain_style = mapnik.Style()
qcdrain_rule = mapnik.Rule()
qcdrain_rule.filter = mapnik.Expression('[HYC] = 8')
qcdrain_rule.symbols.append(mapnik.PolygonSymbolizer(mapnik.Color(153, 204, 255)))
qcdrain_style.rules.append(qcdrain_rule)
m.append_style('drainage', qcdrain_style)
@ -149,31 +149,31 @@ m.layers.append(qcdrain_lyr)
# attributes, and same desired style), so we're going to
# re-use the style defined in the above layer for the next one.
ondrain_lyr = mapnik2.Layer('Ontario Hydrography')
ondrain_lyr = mapnik.Layer('Ontario Hydrography')
ondrain_lyr.srs = "+proj=lcc +ellps=GRS80 +lat_0=49 +lon_0=-95 +lat+1=49 +lat_2=77 +datum=NAD83 +units=m +no_defs"
ondrain_lyr.datasource = mapnik2.Shapefile(file='../data/ontdrainage')
ondrain_lyr.datasource = mapnik.Shapefile(file='../data/ontdrainage')
ondrain_lyr.styles.append('drainage')
m.layers.append(ondrain_lyr)
# Provincial boundaries
provlines_lyr = mapnik2.Layer('Provincial borders')
provlines_lyr = mapnik.Layer('Provincial borders')
provlines_lyr.srs = "+proj=lcc +ellps=GRS80 +lat_0=49 +lon_0=-95 +lat+1=49 +lat_2=77 +datum=NAD83 +units=m +no_defs"
provlines_lyr.datasource = mapnik2.Shapefile(file='../data/boundaries_l')
provlines_lyr.datasource = mapnik.Shapefile(file='../data/boundaries_l')
# Here we define a "dash dot dot dash" pattern for the provincial boundaries.
provlines_stk = mapnik2.Stroke()
provlines_stk = mapnik.Stroke()
provlines_stk.add_dash(8, 4)
provlines_stk.add_dash(2, 2)
provlines_stk.add_dash(2, 2)
provlines_stk.color = mapnik2.Color('black')
provlines_stk.color = mapnik.Color('black')
provlines_stk.width = 1.0
provlines_style = mapnik2.Style()
provlines_rule = mapnik2.Rule()
provlines_rule.symbols.append(mapnik2.LineSymbolizer(provlines_stk))
provlines_style = mapnik.Style()
provlines_rule = mapnik.Rule()
provlines_rule.symbols.append(mapnik.LineSymbolizer(provlines_stk))
provlines_style.rules.append(provlines_rule)
m.append_style('provlines', provlines_style)
@ -182,22 +182,22 @@ m.layers.append(provlines_lyr)
# Roads 3 and 4 (The "grey" roads)
roads34_lyr = mapnik2.Layer('Roads')
roads34_lyr = mapnik.Layer('Roads')
roads34_lyr.srs = "+proj=lcc +ellps=GRS80 +lat_0=49 +lon_0=-95 +lat+1=49 +lat_2=77 +datum=NAD83 +units=m +no_defs"
# create roads datasource (we're going to re-use it later)
roads34_lyr.datasource = mapnik2.Shapefile(file='../data/roads')
roads34_lyr.datasource = mapnik.Shapefile(file='../data/roads')
roads34_style = mapnik2.Style()
roads34_rule = mapnik2.Rule()
roads34_rule.filter = mapnik2.Expression('([CLASS] = 3) or ([CLASS] = 4)')
roads34_style = mapnik.Style()
roads34_rule = mapnik.Rule()
roads34_rule.filter = mapnik.Expression('([CLASS] = 3) or ([CLASS] = 4)')
# With lines of a certain width, you can control how the ends
# are closed off using line_cap as below.
roads34_rule_stk = mapnik2.Stroke()
roads34_rule_stk.color = mapnik2.Color(171,158,137)
roads34_rule_stk.line_cap = mapnik2.line_cap.ROUND_CAP
roads34_rule_stk = mapnik.Stroke()
roads34_rule_stk.color = mapnik.Color(171,158,137)
roads34_rule_stk.line_cap = mapnik.line_cap.ROUND_CAP
# Available options are:
# line_cap: BUTT_CAP, SQUARE_CAP, ROUND_CAP
@ -207,7 +207,7 @@ roads34_rule_stk.line_cap = mapnik2.line_cap.ROUND_CAP
# can be set to a numerical value.
roads34_rule_stk.width = 2.0
roads34_rule.symbols.append(mapnik2.LineSymbolizer(roads34_rule_stk))
roads34_rule.symbols.append(mapnik.LineSymbolizer(roads34_rule_stk))
roads34_style.rules.append(roads34_rule)
m.append_style('smallroads', roads34_style)
@ -216,31 +216,31 @@ m.layers.append(roads34_lyr)
# Roads 2 (The thin yellow ones)
roads2_lyr = mapnik2.Layer('Roads')
roads2_lyr = mapnik.Layer('Roads')
roads2_lyr.srs = "+proj=lcc +ellps=GRS80 +lat_0=49 +lon_0=-95 +lat+1=49 +lat_2=77 +datum=NAD83 +units=m +no_defs"
# Just get a copy from roads34_lyr
roads2_lyr.datasource = roads34_lyr.datasource
roads2_style_1 = mapnik2.Style()
roads2_rule_1 = mapnik2.Rule()
roads2_rule_1.filter = mapnik2.Expression('[CLASS] = 2')
roads2_rule_stk_1 = mapnik2.Stroke()
roads2_rule_stk_1.color = mapnik2.Color(171,158,137)
roads2_rule_stk_1.line_cap = mapnik2.line_cap.ROUND_CAP
roads2_style_1 = mapnik.Style()
roads2_rule_1 = mapnik.Rule()
roads2_rule_1.filter = mapnik.Expression('[CLASS] = 2')
roads2_rule_stk_1 = mapnik.Stroke()
roads2_rule_stk_1.color = mapnik.Color(171,158,137)
roads2_rule_stk_1.line_cap = mapnik.line_cap.ROUND_CAP
roads2_rule_stk_1.width = 4.0
roads2_rule_1.symbols.append(mapnik2.LineSymbolizer(roads2_rule_stk_1))
roads2_rule_1.symbols.append(mapnik.LineSymbolizer(roads2_rule_stk_1))
roads2_style_1.rules.append(roads2_rule_1)
m.append_style('road-border', roads2_style_1)
roads2_style_2 = mapnik2.Style()
roads2_rule_2 = mapnik2.Rule()
roads2_rule_2.filter = mapnik2.Expression('[CLASS] = 2')
roads2_rule_stk_2 = mapnik2.Stroke()
roads2_rule_stk_2.color = mapnik2.Color(255,250,115)
roads2_rule_stk_2.line_cap = mapnik2.line_cap.ROUND_CAP
roads2_style_2 = mapnik.Style()
roads2_rule_2 = mapnik.Rule()
roads2_rule_2.filter = mapnik.Expression('[CLASS] = 2')
roads2_rule_stk_2 = mapnik.Stroke()
roads2_rule_stk_2.color = mapnik.Color(255,250,115)
roads2_rule_stk_2.line_cap = mapnik.line_cap.ROUND_CAP
roads2_rule_stk_2.width = 2.0
roads2_rule_2.symbols.append(mapnik2.LineSymbolizer(roads2_rule_stk_2))
roads2_rule_2.symbols.append(mapnik.LineSymbolizer(roads2_rule_stk_2))
roads2_style_2.rules.append(roads2_rule_2)
m.append_style('road-fill', roads2_style_2)
@ -252,29 +252,29 @@ m.layers.append(roads2_lyr)
# Roads 1 (The big orange ones, the highways)
roads1_lyr = mapnik2.Layer('Roads')
roads1_lyr = mapnik.Layer('Roads')
roads1_lyr.srs = "+proj=lcc +ellps=GRS80 +lat_0=49 +lon_0=-95 +lat+1=49 +lat_2=77 +datum=NAD83 +units=m +no_defs"
roads1_lyr.datasource = roads34_lyr.datasource
roads1_style_1 = mapnik2.Style()
roads1_rule_1 = mapnik2.Rule()
roads1_rule_1.filter = mapnik2.Expression('[CLASS] = 1')
roads1_rule_stk_1 = mapnik2.Stroke()
roads1_rule_stk_1.color = mapnik2.Color(188,149,28)
roads1_rule_stk_1.line_cap = mapnik2.line_cap.ROUND_CAP
roads1_style_1 = mapnik.Style()
roads1_rule_1 = mapnik.Rule()
roads1_rule_1.filter = mapnik.Expression('[CLASS] = 1')
roads1_rule_stk_1 = mapnik.Stroke()
roads1_rule_stk_1.color = mapnik.Color(188,149,28)
roads1_rule_stk_1.line_cap = mapnik.line_cap.ROUND_CAP
roads1_rule_stk_1.width = 7.0
roads1_rule_1.symbols.append(mapnik2.LineSymbolizer(roads1_rule_stk_1))
roads1_rule_1.symbols.append(mapnik.LineSymbolizer(roads1_rule_stk_1))
roads1_style_1.rules.append(roads1_rule_1)
m.append_style('highway-border', roads1_style_1)
roads1_style_2 = mapnik2.Style()
roads1_rule_2 = mapnik2.Rule()
roads1_rule_2.filter = mapnik2.Expression('[CLASS] = 1')
roads1_rule_stk_2 = mapnik2.Stroke()
roads1_rule_stk_2.color = mapnik2.Color(242,191,36)
roads1_rule_stk_2.line_cap = mapnik2.line_cap.ROUND_CAP
roads1_style_2 = mapnik.Style()
roads1_rule_2 = mapnik.Rule()
roads1_rule_2.filter = mapnik.Expression('[CLASS] = 1')
roads1_rule_stk_2 = mapnik.Stroke()
roads1_rule_stk_2.color = mapnik.Color(242,191,36)
roads1_rule_stk_2.line_cap = mapnik.line_cap.ROUND_CAP
roads1_rule_stk_2.width = 5.0
roads1_rule_2.symbols.append(mapnik2.LineSymbolizer(roads1_rule_stk_2))
roads1_rule_2.symbols.append(mapnik.LineSymbolizer(roads1_rule_stk_2))
roads1_style_2.rules.append(roads1_rule_2)
m.append_style('highway-fill', roads1_style_2)
@ -286,25 +286,25 @@ m.layers.append(roads1_lyr)
# Populated Places
popplaces_lyr = mapnik2.Layer('Populated Places')
popplaces_lyr = mapnik.Layer('Populated Places')
popplaces_lyr.srs = "+proj=lcc +ellps=GRS80 +lat_0=49 +lon_0=-95 +lat+1=49 +lat_2=77 +datum=NAD83 +units=m +no_defs"
popplaces_lyr.datasource = mapnik2.Shapefile(file='../data/popplaces',encoding='latin1')
popplaces_lyr.datasource = mapnik.Shapefile(file='../data/popplaces',encoding='latin1')
popplaces_style = mapnik2.Style()
popplaces_rule = mapnik2.Rule()
popplaces_style = mapnik.Style()
popplaces_rule = mapnik.Rule()
# And here we have a TextSymbolizer, used for labeling.
# The first parameter is the name of the attribute to use as the source of the
# text to label with. Then there is font size in points (I think?), and colour.
popplaces_text_symbolizer = mapnik2.TextSymbolizer(mapnik2.Expression("[GEONAME]"),
popplaces_text_symbolizer = mapnik.TextSymbolizer(mapnik.Expression("[GEONAME]"),
'DejaVu Sans Book',
10, mapnik2.Color('black'))
10, mapnik.Color('black'))
# We set a "halo" around the text, which looks like an outline if thin enough,
# or an outright background if large enough.
popplaces_text_symbolizer.label_placement= mapnik2.label_placement.POINT_PLACEMENT
popplaces_text_symbolizer.halo_fill = mapnik2.Color('white')
popplaces_text_symbolizer.label_placement= mapnik.label_placement.POINT_PLACEMENT
popplaces_text_symbolizer.halo_fill = mapnik.Color('white')
popplaces_text_symbolizer.halo_radius = 1
popplaces_text_symbolizer.avoid_edges = True
#popplaces_text_symbolizer.minimum_padding = 30
@ -320,11 +320,11 @@ m.layers.append(popplaces_lyr)
# Draw map
# Set the initial extent of the map in 'master' spherical Mercator projection
m.zoom_to_box(mapnik2.Box2d(-8024477.28459,5445190.38849,-7381388.20071,5662941.44855))
m.zoom_to_box(mapnik.Box2d(-8024477.28459,5445190.38849,-7381388.20071,5662941.44855))
# Render two maps, two PNGs, one JPEG.
im = mapnik2.Image(m.width,m.height)
mapnik2.render(m, im)
# Render map
im = mapnik.Image(m.width,m.height)
mapnik.render(m, im)
# Save image to files
images_ = []
@ -347,38 +347,41 @@ images_.append('demo_high.jpg')
im.save('demo_low.jpg', 'jpeg50')
images_.append('demo_low.jpg')
im.save('demo.tif', 'tiff')
images_.append('demo.tif')
# Render cairo examples
if HAS_PYCAIRO_MODULE and mapnik2.has_pycairo():
if HAS_PYCAIRO_MODULE and mapnik.has_pycairo():
svg_surface = cairo.SVGSurface('demo.svg', m.width,m.height)
mapnik2.render(m, svg_surface)
mapnik.render(m, svg_surface)
svg_surface.finish()
images_.append('demo.svg')
pdf_surface = cairo.PDFSurface('demo.pdf', m.width,m.height)
mapnik2.render(m, pdf_surface)
mapnik.render(m, pdf_surface)
images_.append('demo.pdf')
pdf_surface.finish()
postscript_surface = cairo.PSSurface('demo.ps', m.width,m.height)
mapnik2.render(m, postscript_surface)
mapnik.render(m, postscript_surface)
images_.append('demo.ps')
postscript_surface.finish()
else:
print '\n\nPycairo not available...',
if mapnik2.has_cairo():
if mapnik.has_cairo():
print ' will render Cairo formats using alternative method'
mapnik2.render_to_file(m,'demo.pdf')
mapnik.render_to_file(m,'demo.pdf')
images_.append('demo.pdf')
mapnik2.render_to_file(m,'demo.ps')
mapnik.render_to_file(m,'demo.ps')
images_.append('demo.ps')
mapnik2.render_to_file(m,'demo.svg')
mapnik.render_to_file(m,'demo.svg')
images_.append('demo.svg')
mapnik2.render_to_file(m,'demo_cairo_rgb.png','RGB24')
mapnik.render_to_file(m,'demo_cairo_rgb.png','RGB24')
images_.append('demo_cairo_rgb.png')
mapnik2.render_to_file(m,'demo_cairo_argb.png','ARGB32')
mapnik.render_to_file(m,'demo_cairo_argb.png','ARGB32')
images_.append('demo_cairo_argb.png')
print "\n\n", len(images_), "maps have been rendered in the current directory:"
@ -388,4 +391,4 @@ for im_ in images_:
print "\n\nHave a look!\n\n"
mapnik2.save_map(m,"map.xml")
mapnik.save_map(m,"map.xml")

View file

@ -1,5 +1,6 @@
/* This file is part of Mapnik (c++ mapping toolkit)
* Copyright (C) 2007 Artem Pavlenko
*
* Copyright (C) 2011 Artem Pavlenko
*
* Mapnik is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License

View file

@ -1,5 +1,6 @@
/* This file is part of Mapnik (c++ mapping toolkit)
* Copyright (C) 2007 Artem Pavlenko
*
* Copyright (C) 2011 Artem Pavlenko
*
* Mapnik is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License

View file

@ -23,7 +23,7 @@ Import ('env')
import os
import platform
lib_dir = os.path.normpath(env['DESTDIR'] + '/' + env['PREFIX'] + '/' + env['LIBDIR_SCHEMA'] + '/mapnik2')
lib_dir = os.path.normpath(env['DESTDIR'] + '/' + env['PREFIX'] + '/' + env['LIBDIR_SCHEMA'] + '/mapnik')
fonts = 1
ini_template = '''

View file

@ -1,5 +1,6 @@
/* This file is part of Mapnik (c++ mapping toolkit)
* Copyright (C) 2007 Artem Pavlenko
/* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2011 Artem Pavlenko
*
* Mapnik is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@ -35,6 +36,6 @@ info_dialog::info_dialog(QVector<QPair<QString,QString> > const& info, QWidget *
QTableWidgetItem *keyItem = new QTableWidgetItem(info[i].first);
QTableWidgetItem *valueItem = new QTableWidgetItem(info[i].second);
ui.tableWidget->setItem(i,0,keyItem);
ui.tableWidget->setItem(i,1,valueItem);
ui.tableWidget->setItem(i,1,valueItem);
}
}

View file

@ -1,5 +1,6 @@
/* This file is part of Mapnik (c++ mapping toolkit)
* Copyright (C) 2007 Artem Pavlenko
*
* Copyright (C) 2011 Artem Pavlenko
*
* Mapnik is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License

View file

@ -1,5 +1,6 @@
/* This file is part of Mapnik (c++ mapping toolkit)
* Copyright (C) 2007 Artem Pavlenko
*
* Copyright (C) 2011 Artem Pavlenko
*
* Mapnik is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@ -28,15 +29,15 @@ layer_info_dialog::layer_info_dialog(mapnik::layer& lay, QWidget *parent)
: QDialog(parent)
{
ui.setupUi(this);
ui.tableWidget->setHorizontalHeaderItem(0,new QTableWidgetItem("Name"));
ui.tableWidget->setHorizontalHeaderItem(1,new QTableWidgetItem("Value"));
// Layer name
ui.layerNameEdit->setText(QString(lay.name().c_str()));
// Named Styles : TODO!!!
// Datasource
mapnik::datasource_ptr ds = lay.datasource();
if (ds)
@ -57,10 +58,10 @@ layer_info_dialog::layer_info_dialog(mapnik::layer& lay, QWidget *parent)
QTableWidgetItem *keyItem = new QTableWidgetItem(QString(pos->first.c_str()));
QTableWidgetItem *valueItem = new QTableWidgetItem(QString((*result).c_str()));
ui.tableWidget->setItem(index,0,keyItem);
ui.tableWidget->setItem(index,1,valueItem);
ui.tableWidget->setItem(index,1,valueItem);
++index;
}
}
}
}
}

View file

@ -1,5 +1,6 @@
/* This file is part of Mapnik (c++ mapping toolkit)
* Copyright (C) 2007 Artem Pavlenko
*
* Copyright (C) 2011 Artem Pavlenko
*
* Mapnik is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License

View file

@ -1,5 +1,6 @@
/* This file is part of Mapnik (c++ mapping toolkit)
* Copyright (C) 2007 Artem Pavlenko
*
* Copyright (C) 2011 Artem Pavlenko
*
* Mapnik is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@ -37,7 +38,7 @@ void LayerDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option,
else
painter->setBrush(QBrush(QColor(255, 0, 0, 64)));
painter->drawRoundRect(option.rect,4,4);
if (option.state & QStyle::State_Selected)

View file

@ -1,5 +1,6 @@
/* This file is part of Mapnik (c++ mapping toolkit)
* Copyright (C) 2007 Artem Pavlenko
*
* Copyright (C) 2011 Artem Pavlenko
*
* Mapnik is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@ -32,11 +33,11 @@ class QPainter;
class LayerDelegate : public QAbstractItemDelegate
{
Q_OBJECT
public:
LayerDelegate(QObject *parent = 0);
void paint(QPainter *painter, const QStyleOptionViewItem &option,
const QModelIndex &index) const;
const QModelIndex &index) const;
QSize sizeHint(const QStyleOptionViewItem &option,
const QModelIndex &index ) const;
};

View file

@ -1,5 +1,6 @@
/* This file is part of Mapnik (c++ mapping toolkit)
* Copyright (C) 2007 Artem Pavlenko
*
* Copyright (C) 2011 Artem Pavlenko
*
* Mapnik is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@ -61,7 +62,7 @@ QVariant LayerListModel::data(QModelIndex const& index,int role) const
{
if (map_->layers().at(index.row()).isActive())
return QVariant(Qt::Checked);
else
else
return QVariant(Qt::Unchecked);
}
else
@ -75,7 +76,7 @@ QVariant LayerListModel::headerData(int section, Qt::Orientation orientation,
{
if (role != Qt::DisplayRole)
return QVariant();
if (orientation == Qt::Horizontal)
return QString("TODO Column %1").arg(section);
else
@ -86,22 +87,22 @@ bool LayerListModel::setData(const QModelIndex &index,
const QVariant &value, int role)
{
if (!map_) return false;
if (index.isValid() && role == Qt::CheckStateRole)
{
int status = value.toInt();
int status = value.toInt();
std::vector<mapnik::layer> & layers = const_cast<std::vector<mapnik::layer>& >(map_->layers());
layers.at(index.row()).setActive(status);
emit dataChanged(index, index);
return true;
}
}
return false;
}
Qt::ItemFlags LayerListModel::flags(QModelIndex const& index) const
{
Qt::ItemFlags flags = QAbstractItemModel::flags(index);
if (index.isValid())
flags |= Qt::ItemIsUserCheckable;
return flags;
@ -121,4 +122,4 @@ boost::optional<mapnik::layer&> LayerListModel::map_layer(int i)

View file

@ -1,5 +1,6 @@
/* This file is part of Mapnik (c++ mapping toolkit)
* Copyright (C) 2007 Artem Pavlenko
*
* Copyright (C) 2011 Artem Pavlenko
*
* Mapnik is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@ -36,10 +37,10 @@ class LayerListModel : public QAbstractListModel
int rowCount(const QModelIndex &parent = QModelIndex()) const;
QVariant data(const QModelIndex &index, int role) const;
QVariant headerData(int section, Qt::Orientation orientation,
int role = Qt::DisplayRole) const;
int role = Qt::DisplayRole) const;
bool setData(const QModelIndex &index, const QVariant &value,
int role = Qt::EditRole);
Qt::ItemFlags flags(QModelIndex const& index) const;
Qt::ItemFlags flags(QModelIndex const& index) const;
boost::optional<mapnik::layer&> map_layer(int i);
private:

View file

@ -1,5 +1,6 @@
/* This file is part of Mapnik (c++ mapping toolkit)
* Copyright (C) 2007 Artem Pavlenko
*
* Copyright (C) 2011 Artem Pavlenko
*
* Mapnik is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@ -41,7 +42,7 @@ LayerTab::LayerTab(QWidget* parent)
void LayerTab::paintEvent(QPaintEvent *e)
{
QListView::paintEvent(e);
QListView::paintEvent(e);
}
void LayerTab::dataChanged(const QModelIndex &topLeft,
@ -55,7 +56,7 @@ void LayerTab::dataChanged(const QModelIndex &topLeft,
void LayerTab::selectionChanged(const QItemSelection & selected, const QItemSelection &)
{
QModelIndexList list = selected.indexes();
if (list.size() != 0)
if (list.size() != 0)
{
std::cout << "SELECTED LAYER ->" << list[0].row() << "\n";
emit layerSelected(list[0].row());
@ -69,7 +70,7 @@ void LayerTab::layerInfo()
if (indexes.size() > 0)
{
qDebug("id = %d",indexes[0].row());
}
}
@ -81,7 +82,7 @@ void LayerTab::layerInfo2(QModelIndex const& index)
unsigned i = index.row();
LayerListModel * model = static_cast<LayerListModel*>(this->model());
boost::optional<mapnik::layer&> layer = model->map_layer(i);
if (layer)
{
layer_info_dialog dlg(*layer,this);
@ -91,7 +92,7 @@ void LayerTab::layerInfo2(QModelIndex const& index)
StyleTab::StyleTab(QWidget*)
{
}
void StyleTab::contextMenuEvent(QContextMenuEvent * event )

View file

@ -1,5 +1,6 @@
/* This file is part of Mapnik (c++ mapping toolkit)
* Copyright (C) 2006 Artem Pavlenko
*
* Copyright (C) 2011 Artem Pavlenko
*
* Mapnik is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@ -33,10 +34,10 @@ class LayerTab : public QListView
void paintEvent(QPaintEvent *e);
signals:
void update_mapwidget();
void layerSelected(int) const;
void layerSelected(int) const;
public slots:
void layerInfo();
void layerInfo2(QModelIndex const&);
void layerInfo();
void layerInfo2(QModelIndex const&);
protected slots:
void dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight);
void selectionChanged(const QItemSelection & selected, const QItemSelection &);
@ -51,4 +52,4 @@ protected:
void contextMenuEvent(QContextMenuEvent * event );
};
#endif
#endif

View file

@ -1,5 +1,6 @@
/* This file is part of Mapnik (c++ mapping toolkit)
* Copyright (C) 2006 Artem Pavlenko
*
* Copyright (C) 2011 Artem Pavlenko
*
* Mapnik is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@ -34,16 +35,16 @@ int main( int argc, char **argv )
{
using mapnik::datasource_cache;
using mapnik::freetype_engine;
QCoreApplication::setOrganizationName("Mapnik");
QCoreApplication::setOrganizationDomain("mapnik.org");
QCoreApplication::setApplicationName("Viewer");
QSettings settings("viewer.ini",QSettings::IniFormat);
// register input plug-ins
QString plugins_dir = settings.value("mapnik/plugins_dir",
QVariant("/usr/local/lib/mapnik2/input/")).toString();
QVariant("/usr/local/lib/mapnik/input/")).toString();
datasource_cache::instance()->register_datasources(plugins_dir.toStdString());
// register fonts
int count = settings.beginReadArray("mapnik/fonts");
@ -54,8 +55,8 @@ int main( int argc, char **argv )
freetype_engine::register_fonts(font_dir.toStdString());
}
settings.endArray();
QApplication app( argc, argv );
QApplication app( argc, argv );
MainWindow window;
window.show();
if (argc > 1) window.open(argv[1]);
@ -82,5 +83,5 @@ int main( int argc, char **argv )
double scaling_factor = QString(argv[3]).toDouble(&ok);
if (ok) window.set_scaling_factor(scaling_factor);
}
return app.exec();
return app.exec();
}

View file

@ -1,5 +1,6 @@
/* This file is part of Mapnik (c++ mapping toolkit)
* Copyright (C) 2006 Artem Pavlenko
*
* Copyright (C) 2011 Artem Pavlenko
*
* Mapnik is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@ -47,42 +48,42 @@
MainWindow::MainWindow()
: filename_(),
default_extent_(-20037508.3428,-20037508.3428,20037508.3428,20037508.3428)
{
{
mapWidget_ = new MapWidget(this);
QSplitter *splitter = new QSplitter(this);
QSplitter *splitter = new QSplitter(this);
QTabWidget *tabWidget=new QTabWidget;
layerTab_ = new LayerTab;
layerTab_->setFocusPolicy(Qt::NoFocus);
layerTab_->setIconSize(QSize(16,16));
//LayerDelegate *delegate = new LayerDelegate(this);
//LayerDelegate *delegate = new LayerDelegate(this);
//layerTab_->setItemDelegate(delegate);
//layerTab_->setItemDelegate(new QItemDelegate(this));
//layerTab_->setViewMode(QListView::IconMode);
layerTab_->setFlow(QListView::TopToBottom);
tabWidget->addTab(layerTab_,tr("Layers"));
// Styles tab
styleTab_ = new StyleTab;
tabWidget->addTab(styleTab_,tr("Styles"));
tabWidget->addTab(styleTab_,tr("Styles"));
splitter->addWidget(tabWidget);
splitter->addWidget(mapWidget_);
QList<int> list;
list.push_back(200);
list.push_back(600);
splitter->setSizes(list);
mapWidget_->setFocusPolicy(Qt::StrongFocus);
mapWidget_->setFocus();
//setCentralWidget(mapWidget_);
setCentralWidget(splitter);
createActions();
createMenus();
createToolBars();
createContextMenu();
setWindowTitle(tr("Mapnik Viewer"));
status=new QStatusBar(this);
status->showMessage(tr(""));
@ -91,11 +92,11 @@ MainWindow::MainWindow()
//connect mapview to layerlist
connect(mapWidget_, SIGNAL(mapViewChanged()),layerTab_, SLOT(update()));
// slider
// slider
connect(slider_,SIGNAL(valueChanged(int)),mapWidget_,SLOT(zoomToLevel(int)));
//
//
connect(layerTab_,SIGNAL(update_mapwidget()),mapWidget_,SLOT(updateMap()));
connect(layerTab_,SIGNAL(layerSelected(int)),
connect(layerTab_,SIGNAL(layerSelected(int)),
mapWidget_,SLOT(layerSelected(int)));
}
@ -128,21 +129,21 @@ void MainWindow::open(QString const& path)
{
filename_ = path;
}
if (!filename_.isEmpty())
{
load_map_file(filename_);
setWindowTitle(tr("%1 - Mapnik Viewer").arg(filename_));
}
}
void MainWindow::reload()
{
if (!filename_.isEmpty())
{
mapnik::box2d<double> bbox = mapWidget_->getMap()->get_current_extent();
load_map_file(filename_);
mapWidget_->zoomToBox(bbox);
@ -157,7 +158,7 @@ void MainWindow::save()
initialPath,
tr("%1 Files (*.xml)")
.arg(QString("Mapnik definition")));
if (!filename.isEmpty())
if (!filename.isEmpty())
{
std::cout<<"saving "<< filename.toStdString() << std::endl;
mapnik::save_map(*mapWidget_->getMap(),filename.toStdString());
@ -166,16 +167,16 @@ void MainWindow::save()
void MainWindow::load_map_file(QString const& filename)
{
std::cout<<"loading "<< filename.toStdString() << std::endl;
std::cout<<"loading "<< filename.toStdString() << std::endl;
unsigned width = mapWidget_->width();
unsigned height = mapWidget_->height();
boost::shared_ptr<mapnik::Map> map(new mapnik::Map(width,height));
boost::shared_ptr<mapnik::Map> map(new mapnik::Map(width,height));
mapWidget_->setMap(map);
try
{
try
{
mapnik::load_map(*map,filename.toStdString());
}
catch (mapnik::config_error & ex)
catch (mapnik::config_error & ex)
{
std::cout << ex.what() << "\n";
}
@ -195,7 +196,7 @@ void MainWindow::zoom_to_box()
void MainWindow::pan()
{
mapWidget_->setTool(MapWidget::Pan);
mapWidget_->setTool(MapWidget::Pan);
}
void MainWindow::info()
@ -240,7 +241,7 @@ void MainWindow::export_as()
tr("%1 Files (*.%2);;All Files (*)")
.arg(QString(fileFormat.toUpper()))
.arg(QString(fileFormat)));
if (!fileName.isEmpty())
if (!fileName.isEmpty())
{
QPixmap const& pix = mapWidget_->pixmap();
pix.save(fileName);
@ -248,8 +249,8 @@ void MainWindow::export_as()
}
void MainWindow::print()
{
{
//Q_ASSERT(mapWidget_->pixmap());
//QPrintDialog dialog(&printer, this);
//if (dialog.exec()) {
@ -264,31 +265,31 @@ void MainWindow::print()
}
void MainWindow::createActions()
{
{
//exportAct = new QAction(tr("&Export as ..."),this);
//exportAct->setShortcut(tr("Ctrl+E"));
//connect(exportAct, SIGNAL(triggered()), this, SLOT(export_as()));
zoomAllAct = new QAction(QIcon(":/images/home.png"),tr("Zoom All"),this);
connect(zoomAllAct, SIGNAL(triggered()), this, SLOT(zoom_all()));
zoomBoxAct = new QAction(QIcon(":/images/zoombox.png"),tr("Zoom To Box"),this);
zoomBoxAct->setCheckable(true);
connect(zoomBoxAct, SIGNAL(triggered()), this, SLOT(zoom_to_box()));
panAct = new QAction(QIcon(":/images/pan.png"),tr("Pan"),this);
panAct->setCheckable(true);
connect(panAct, SIGNAL(triggered()), this, SLOT(pan()));
infoAct = new QAction(QIcon(":/images/info.png"),tr("Info"),this);
infoAct->setCheckable(true);
connect(infoAct, SIGNAL(triggered()), this, SLOT(info()));
toolsGroup=new QActionGroup(this);
toolsGroup->addAction(zoomBoxAct);
toolsGroup->addAction(panAct);
toolsGroup->addAction(infoAct);
zoomBoxAct->setChecked(true);
openAct=new QAction(tr("Open Map definition"),this);
connect(openAct,SIGNAL(triggered()),this,SLOT(open()));
saveAct=new QAction(tr("Save Map definition"),this);
@ -302,27 +303,27 @@ void MainWindow::createActions()
connect(panUpAct, SIGNAL(triggered()), this, SLOT(pan_up()));
panDownAct = new QAction(QIcon(":/images/down.png"),tr("&Pan Down"),this);
connect(panDownAct, SIGNAL(triggered()), this, SLOT(pan_down()));
reloadAct = new QAction(QIcon(":/images/reload.png"),tr("Reload"),this);
connect(reloadAct, SIGNAL(triggered()), this, SLOT(reload()));
layerInfo = new QAction(QIcon(":/images/info.png"),tr("&Layer info"),layerTab_);
connect(layerInfo, SIGNAL(triggered()), layerTab_,SLOT(layerInfo()));
connect(layerTab_, SIGNAL(doubleClicked(QModelIndex const&)), layerTab_,SLOT(layerInfo2(QModelIndex const&)));
foreach (QByteArray format, QImageWriter::supportedImageFormats())
foreach (QByteArray format, QImageWriter::supportedImageFormats())
{
QString text = tr("%1...").arg(QString(format).toUpper());
QAction *action = new QAction(text, this);
action->setData(format);
connect(action, SIGNAL(triggered()), this, SLOT(export_as()));
exportAsActs.append(action);
}
printAct = new QAction(QIcon(":/images/print.png"),tr("&Print ..."),this);
printAct->setShortcut(tr("Ctrl+E"));
connect(printAct, SIGNAL(triggered()), this, SLOT(print()));
exitAct = new QAction(tr("E&xit"), this);
exitAct->setShortcut(tr("Ctrl+Q"));
connect(exitAct, SIGNAL(triggered()), this, SLOT(close()));
@ -335,8 +336,8 @@ void MainWindow::createMenus()
{
exportMenu = new QMenu(tr("&Export As"), this);
foreach (QAction *action, exportAsActs)
exportMenu->addAction(action);
exportMenu->addAction(action);
fileMenu = new QMenu(tr("&File"),this);
fileMenu->addAction(openAct);
fileMenu->addAction(saveAct);
@ -345,7 +346,7 @@ void MainWindow::createMenus()
fileMenu->addSeparator();
fileMenu->addAction(exitAct);
menuBar()->addMenu(fileMenu);
helpMenu = new QMenu(tr("&Help"), this);
helpMenu->addAction(aboutAct);
menuBar()->addMenu(helpMenu);
@ -377,10 +378,10 @@ void MainWindow::createToolBars()
void MainWindow::set_default_extent(double x0,double y0, double x1, double y1)
{
try
try
{
boost::shared_ptr<mapnik::Map> map_ptr = mapWidget_->getMap();
if (map_ptr)
if (map_ptr)
{
mapnik::projection prj(map_ptr->srs());
prj.forward(x0,y0);
@ -401,7 +402,7 @@ void MainWindow::set_scaling_factor(double scaling_factor)
void MainWindow::zoom_all()
{
boost::shared_ptr<mapnik::Map> map_ptr = mapWidget_->getMap();
if (map_ptr)
if (map_ptr)
{
map_ptr->zoom_all();
mapnik::box2d<double> const& ext = map_ptr->get_current_extent();

View file

@ -1,5 +1,6 @@
/* This file is part of Mapnik (c++ mapping toolkit)
* Copyright (C) 2006 Artem Pavlenko
*
* Copyright (C) 2011 Artem Pavlenko
*
* Mapnik is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@ -67,7 +68,7 @@ private:
void createToolBars();
void createContextMenu();
void load_map_file(QString const& filename);
QString currentPath;
QString filename_;

View file

@ -1,5 +1,6 @@
/* This file is part of Mapnik (c++ mapping toolkit)
* Copyright (C) 2006 Artem Pavlenko
*
* Copyright (C) 2011 Artem Pavlenko
*
* Mapnik is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@ -63,7 +64,7 @@ double scales [] = {279541132.014,
1066.36479192,
533.182395962};
MapWidget::MapWidget(QWidget *parent)
MapWidget::MapWidget(QWidget *parent)
: QWidget(parent),
map_(),
selected_(1),
@ -90,9 +91,9 @@ void MapWidget::setTool(eTool tool)
}
void MapWidget::paintEvent(QPaintEvent*)
{
{
QPainter painter(this);
if (drag_)
{
if (cur_tool_ == ZoomToBox)
@ -119,7 +120,7 @@ void MapWidget::paintEvent(QPaintEvent*)
}
painter.end();
}
void MapWidget::resizeEvent(QResizeEvent * ev)
{
if (map_)
@ -128,10 +129,10 @@ void MapWidget::resizeEvent(QResizeEvent * ev)
updateMap();
}
}
void MapWidget::mousePressEvent(QMouseEvent* e)
{
if (e->button()==Qt::LeftButton)
if (e->button()==Qt::LeftButton)
{
if (cur_tool_ == ZoomToBox || cur_tool_==Pan)
{
@ -142,17 +143,17 @@ void MapWidget::mousePressEvent(QMouseEvent* e)
else if (cur_tool_==Info)
{
if (map_)
{
{
QVector<QPair<QString,QString> > info;
projection map_proj(map_->srs()); // map projection
double scale_denom = scale_denominator(*map_,map_proj.is_geographic());
CoordTransform t(map_->width(),map_->height(),map_->get_current_extent());
for (unsigned index = 0; index < map_->layer_count();++index)
{
if (int(index) != selectedLayer_) continue;
layer & layer = map_->layers()[index];
if (!layer.isVisible(scale_denom)) continue;
std::string name = layer.name();
@ -163,11 +164,11 @@ void MapWidget::mousePressEvent(QMouseEvent* e)
mapnik::proj_transform prj_trans(map_proj,layer_proj);
//std::auto_ptr<mapnik::memory_datasource> data(new mapnik::memory_datasource);
mapnik::featureset_ptr fs = map_->query_map_point(index,x,y);
if (fs)
{
feature_ptr feat = fs->next();
if (feat)
if (feat)
{
std::map<std::string,mapnik::value> const& props = feat->props();
std::map<std::string,mapnik::value>::const_iterator itr=props.begin();
@ -180,10 +181,10 @@ void MapWidget::mousePressEvent(QMouseEvent* e)
}
}
typedef mapnik::coord_transform2<mapnik::CoordTransform,mapnik::geometry_type> path_type;
for (unsigned i=0; i<feat->num_geometries();++i)
{
mapnik::geometry_type & geom = feat->get_geometry(i);
mapnik::geometry_type & geom = feat->get_geometry(i);
path_type path(t,geom,prj_trans);
if (geom.num_points() > 0)
{
@ -208,7 +209,7 @@ void MapWidget::mousePressEvent(QMouseEvent* e)
}
}
}
if (info.size() > 0)
{
info_dialog info_dlg(info,this);
@ -216,34 +217,34 @@ void MapWidget::mousePressEvent(QMouseEvent* e)
break;
}
}
// remove annotation layer
map_->layers().erase(remove_if(map_->layers().begin(),
map_->layers().end(),
bind(&layer::name,_1) == "*annotations*")
, map_->layers().end());
}
}
}
}
else if (e->button()==Qt::RightButton)
{
else if (e->button()==Qt::RightButton)
{
//updateMap();
}
}
void MapWidget::mouseMoveEvent(QMouseEvent* e)
{
{
if (cur_tool_ == ZoomToBox || cur_tool_==Pan)
{
end_x_ = e->x();
end_y_ = e->y();
update();
}
}
}
void MapWidget::mouseReleaseEvent(QMouseEvent* e)
{
if (e->button()==Qt::LeftButton)
if (e->button()==Qt::LeftButton)
{
end_x_ = e->x();
end_y_ = e->y();
@ -252,7 +253,7 @@ void MapWidget::mouseReleaseEvent(QMouseEvent* e)
drag_=false;
if (map_)
{
CoordTransform t(map_->width(),map_->height(),map_->get_current_extent());
CoordTransform t(map_->width(),map_->height(),map_->get_current_extent());
box2d<double> box = t.backward(box2d<double>(start_x_,start_y_,end_x_,end_y_));
map_->zoom_to_box(box);
updateMap();
@ -267,7 +268,7 @@ void MapWidget::mouseReleaseEvent(QMouseEvent* e)
int cy = int(0.5 * map_->height());
int dx = end_x_ - start_x_;
int dy = end_y_ - start_y_;
map_->pan(cx - dx ,cy - dy);
map_->pan(cx - dx ,cy - dy);
updateMap();
}
}
@ -275,10 +276,10 @@ void MapWidget::mouseReleaseEvent(QMouseEvent* e)
}
void MapWidget::keyPressEvent(QKeyEvent *e)
void MapWidget::keyPressEvent(QKeyEvent *e)
{
std::cout << "key pressed:"<< e->key()<<"\n";
switch (e->key()) {
switch (e->key()) {
case Qt::Key_Minus:
zoomOut();
break;
@ -294,10 +295,10 @@ void MapWidget::keyPressEvent(QKeyEvent *e)
break;
case Qt::Key_Down:
panDown();
break;
break;
case Qt::Key_Left:
panLeft();
break;
break;
case Qt::Key_Right:
panRight();
break;
@ -309,7 +310,7 @@ void MapWidget::keyPressEvent(QKeyEvent *e)
break;
case 51:
zoomToLevel(12);
break;
break;
case 52:
zoomToLevel(13);
break;
@ -318,7 +319,7 @@ void MapWidget::keyPressEvent(QKeyEvent *e)
break;
case 54:
zoomToLevel(15);
break;
break;
case 55:
zoomToLevel(16);
break;
@ -327,12 +328,12 @@ void MapWidget::keyPressEvent(QKeyEvent *e)
break;
case 57:
zoomToLevel(18);
break;
break;
default:
QWidget::keyPressEvent(e);
}
}
void MapWidget::zoomToBox(mapnik::box2d<double> const& bbox)
@ -344,7 +345,7 @@ void MapWidget::zoomToBox(mapnik::box2d<double> const& bbox)
}
}
void MapWidget::defaultView()
void MapWidget::defaultView()
{
if (map_)
{
@ -354,7 +355,7 @@ void MapWidget::defaultView()
}
}
void MapWidget::zoomIn()
void MapWidget::zoomIn()
{
if (map_)
{
@ -363,7 +364,7 @@ void MapWidget::zoomIn()
}
}
void MapWidget::zoomOut()
void MapWidget::zoomOut()
{
if (map_)
{
@ -406,12 +407,12 @@ void MapWidget::panLeft()
}
void MapWidget::panRight()
{
{
if (map_)
{
double cx = 0.5*map_->width();
double cy = 0.5*map_->height();
map_->pan(int(cx + cx * 0.25),int(cy));
map_->pan(int(cx + cx * 0.25),int(cy));
updateMap();
}
}
@ -425,11 +426,11 @@ void MapWidget::zoomToLevel(int level)
std::cerr << "scale denominator = " << scale_denom << "\n";
mapnik::box2d<double> ext = map_->get_current_extent();
double width = static_cast<double>(map_->width());
double height= static_cast<double>(map_->height());
double height= static_cast<double>(map_->height());
mapnik::coord2d pt = ext.center();
double res = scale_denom * 0.00028;
mapnik::box2d<double> box(pt.x - 0.5 * width * res,
pt.y - 0.5 * height*res,
pt.x + 0.5 * width * res,
@ -439,37 +440,37 @@ void MapWidget::zoomToLevel(int level)
}
}
void MapWidget::export_to_file(unsigned ,unsigned ,std::string const&,std::string const&)
void MapWidget::export_to_file(unsigned ,unsigned ,std::string const&,std::string const&)
{
//image_32 image(width,height);
//agg_renderer renderer(map,image);
//renderer.apply();
//image.saveToFile(filename,type);
}
void MapWidget::set_scaling_factor(double scaling_factor)
{
scaling_factor_ = scaling_factor;
}
void MapWidget::updateMap()
{
void MapWidget::updateMap()
{
if (map_)
{
unsigned width=map_->width();
unsigned height=map_->height();
image_32 buf(width,height);
try
try
{
mapnik::agg_renderer<image_32> ren(*map_,buf,scaling_factor_);
ren.apply();
QImage image((uchar*)buf.raw_data(),width,height,QImage::Format_ARGB32);
pix_=QPixmap::fromImage(image.rgbSwapped());
projection prj(map_->srs()); // map projection
box2d<double> ext = map_->get_current_extent();
double x0 = ext.minx();
double y0 = ext.miny();

View file

@ -1,5 +1,6 @@
/* This file is part of Mapnik (c++ mapping toolkit)
* Copyright (C) 2007 Artem Pavlenko
*
* Copyright (C) 2011 Artem Pavlenko
*
* Mapnik is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@ -32,19 +33,19 @@
#include <boost/scoped_ptr.hpp>
#include <mapnik/map.hpp>
class MapWidget : public QWidget
class MapWidget : public QWidget
{
Q_OBJECT
public:
enum eTool
public:
enum eTool
{
ZoomToBox = 1,
Pan,
Info,
};
private:
private:
boost::shared_ptr<mapnik::Map> map_;
int selected_;
QPixmap pix_;
@ -64,7 +65,7 @@ public:
void setTool(eTool tool);
boost::shared_ptr<mapnik::Map> getMap();
inline QPixmap const& pixmap() const { return pix_;}
void setMap(boost::shared_ptr<mapnik::Map> map);
void setMap(boost::shared_ptr<mapnik::Map> map);
void defaultView();
void zoomToBox(mapnik::box2d<double> const& box);
void zoomIn();
@ -80,7 +81,7 @@ public slots:
void layerSelected(int);
signals:
void mapViewChanged();
protected:
protected:
void paintEvent(QPaintEvent* ev);
void resizeEvent(QResizeEvent* ev);
void mousePressEvent(QMouseEvent* e);
@ -89,8 +90,8 @@ protected:
void keyPressEvent(QKeyEvent *e);
void export_to_file(unsigned width,
unsigned height,
std::string const& filename,
std::string const& type);
std::string const& filename,
std::string const& type);
};
#endif // MAP_WIDGET_HPP

View file

@ -1,5 +1,6 @@
/* This file is part of Mapnik (c++ mapping toolkit)
* Copyright (C) 2007 Artem Pavlenko
*
* Copyright (C) 2011 Artem Pavlenko
*
* Mapnik is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@ -38,60 +39,60 @@ class node : private boost::noncopyable
virtual QIcon icon() const=0;
virtual ~node_base() {}
};
template <typename T>
struct wrap : public node_base
{
wrap(T const& obj)
: obj_(obj) {}
~wrap() {}
QString name () const
{
return obj_.name();
}
QIcon icon() const
{
return obj_.icon();
}
T obj_;
};
public:
template <typename T>
template <typename T>
node ( T const& obj, node * parent=0)
: impl_(new wrap<T>(obj)),
parent_(parent)
{}
QString name() const
{
return impl_->name();
}
QIcon icon() const
{
return impl_->icon();
}
unsigned num_children() const
{
return children_.count();
}
node * child(unsigned row) const
{
return children_.value(row);
}
node * parent() const
{
return parent_;
}
node * add_child(node * child)
{
children_.push_back(child);
@ -104,12 +105,12 @@ public:
else
return 0;
}
~node()
~node()
{
qDeleteAll(children_);
}
private:
boost::scoped_ptr<node_base> impl_;
QList<node*> children_;
@ -124,7 +125,7 @@ struct symbolizer_info : public boost::static_visitor<QString>
boost::ignore_unused_variable_warning(sym);
return QString("PointSymbolizer");
}
QString operator() (mapnik::line_symbolizer const& sym) const
{
boost::ignore_unused_variable_warning(sym);
@ -148,19 +149,19 @@ struct symbolizer_info : public boost::static_visitor<QString>
boost::ignore_unused_variable_warning(sym);
return QString("PolygonSymbolizer");
}
QString operator() (mapnik::text_symbolizer const& sym) const
{
boost::ignore_unused_variable_warning(sym);
return QString("TextSymbolizer");
}
QString operator() (mapnik::shield_symbolizer const& sym) const
{
boost::ignore_unused_variable_warning(sym);
return QString("ShieldSymbolizer");
}
template <typename T>
QString operator() (T const& ) const
{
@ -200,14 +201,14 @@ struct symbolizer_icon : public boost::static_visitor<QIcon>
QPixmap pix(48,16);
pix.fill();
QPainter painter(&pix);
mapnik::stroke const& strk = sym.get_stroke();
mapnik::stroke const& strk = sym.get_stroke();
mapnik::color const& col = strk.get_color();
QPen pen(QColor(col.red(),col.green(),col.blue(),col.alpha()));
pen.setWidth(strk.get_width());
painter.setPen(pen);
painter.drawLine(0,7,47,7);
//painter.drawLine(7,15,12,0);
//painter.drawLine(12,0,8,15);
//painter.drawLine(12,0,8,15);
return QIcon(pix);
}
@ -224,13 +225,13 @@ public:
symbolizer_node(mapnik::symbolizer const & sym)
: sym_(sym) {}
~symbolizer_node(){}
QString name() const
QString name() const
{
//return QString("Symbolizer:fixme");
return boost::apply_visitor(symbolizer_info(),sym_);
}
QIcon icon() const
{
return boost::apply_visitor(symbolizer_icon(),sym_);//QIcon(":/images/filter.png");
@ -248,15 +249,15 @@ public:
QString name() const
{
mapnik::expression_ptr filter = rule_.get_filter();
return QString(mapnik::to_expression_string(*filter).c_str());
}
}
QIcon icon() const
{
return QIcon(":/images/filter.png");
}
private:
QString name_;
mapnik::rule const& rule_;
@ -268,19 +269,19 @@ public:
style_node(QString name, mapnik::feature_type_style const& style)
: name_(name),
style_(style) {}
~style_node() {}
QString name() const
{
return name_;
}
QIcon icon() const
{
return QIcon(":/images/style.png");
}
private:
QString name_;
mapnik::feature_type_style const& style_;
@ -292,26 +293,26 @@ public:
explicit map_node(boost::shared_ptr<mapnik::Map> map)
: map_(map) {}
~map_node() {}
QString name() const
{
return QString("Map");
}
QIcon icon() const
{
return QIcon(":/images/map.png");
}
private:
boost::shared_ptr<mapnik::Map> map_;
};
StyleModel::StyleModel(boost::shared_ptr<mapnik::Map> map, QObject * parent)
: QAbstractItemModel(parent),
root_(new node(map_node(map)))
root_(new node(map_node(map)))
{
typedef std::map<std::string,mapnik::feature_type_style> style_type;
typedef std::map<std::string,mapnik::feature_type_style> style_type;
style_type const & styles = map->styles();
style_type::const_iterator itr = styles.begin();
style_type::const_iterator end = styles.end();
@ -329,22 +330,22 @@ StyleModel::StyleModel(boost::shared_ptr<mapnik::Map> map, QObject * parent)
rule_n->add_child(new node(symbolizer_node(*itr3),rule_n));
}
}
}
}
}
StyleModel::~StyleModel() {}
// interface
// interface
QModelIndex StyleModel::index (int row, int col, QModelIndex const& parent) const
{
// qDebug("index() row=%d col=%d parent::internalId() = %lld", row,col,parent.internalId());
node * parent_node;
if (!parent.isValid())
parent_node = root_.get();
else
parent_node = static_cast<node*>(parent.internalPointer());
node * child_node = parent_node->child(row);
if (child_node)
return createIndex(row,col,child_node);
@ -358,7 +359,7 @@ QModelIndex StyleModel::parent (QModelIndex const& index) const
node * parent_node = child_node->parent();
if (parent_node == root_.get())
return QModelIndex();
return createIndex(parent_node->row(),0,parent_node);
}
@ -389,7 +390,7 @@ QVariant StyleModel::data(const QModelIndex & index, int role) const
{
if (role == Qt::DisplayRole)
{
return QVariant(cur_node->name());
}
else if ( role == Qt::DecorationRole)

View file

@ -1,5 +1,6 @@
/* This file is part of Mapnik (c++ mapping toolkit)
* Copyright (C) 2007 Artem Pavlenko
*
* Copyright (C) 2011 Artem Pavlenko
*
* Mapnik is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@ -32,11 +33,11 @@ class StyleModel : public QAbstractItemModel
public:
StyleModel(boost::shared_ptr<mapnik::Map> map, QObject * parent=0);
~StyleModel();
// interface
// interface
QModelIndex index (int row, int col, QModelIndex const& parent = QModelIndex()) const;
QModelIndex parent (QModelIndex const& child) const;
int rowCount( QModelIndex const& parent = QModelIndex()) const;
int columnCount( QModelIndex const& parent = QModelIndex()) const;
int columnCount( QModelIndex const& parent = QModelIndex()) const;
QVariant data(const QModelIndex & index, int role = Qt::DisplayRole) const;
private:
//boost::shared_ptr<mapnik::Map> map_;

View file

@ -11,7 +11,7 @@ INCLUDEPATH += /usr/X11/include/freetype2
INCLUDEPATH += .
QMAKE_CXXFLAGS +=' -DDARWIN -Wno-missing-field-initializers -ansi'
unix:LIBS = -L/usr/local/lib -L/usr/X11/lib -lmapnik2 -lfreetype
unix:LIBS = -L/usr/local/lib -L/usr/X11/lib -lmapnik -lfreetype
unix:LIBS += -lboost_system -licuuc -lboost_filesystem -lboost_regex
# Input

View file

@ -736,7 +736,7 @@ namespace agg
template<class VertexSource>
void join_path(VertexSource& vs, unsigned path_id = 0)
{
double x, y;
double x=0.0, y=0.0;
unsigned cmd;
vs.rewind(path_id);
cmd = vs.vertex(&x, &y);

View file

@ -323,68 +323,65 @@ namespace agg
int y2;
int lprev;
if(close_polygon)
if(close_polygon && (m_src_vertices.size() >= 3))
{
if(m_src_vertices.size() >= 3)
dv.idx = 2;
v = &m_src_vertices[m_src_vertices.size() - 1];
x1 = v->x;
y1 = v->y;
lprev = v->len;
v = &m_src_vertices[0];
x2 = v->x;
y2 = v->y;
dv.lcurr = v->len;
line_parameters prev(x1, y1, x2, y2, lprev);
v = &m_src_vertices[1];
dv.x1 = v->x;
dv.y1 = v->y;
dv.lnext = v->len;
dv.curr = line_parameters(x2, y2, dv.x1, dv.y1, dv.lcurr);
v = &m_src_vertices[dv.idx];
dv.x2 = v->x;
dv.y2 = v->y;
dv.next = line_parameters(dv.x1, dv.y1, dv.x2, dv.y2, dv.lnext);
dv.xb1 = 0;
dv.yb1 = 0;
dv.xb2 = 0;
dv.yb2 = 0;
switch(m_line_join)
{
dv.idx = 2;
case outline_no_join:
dv.flags = 3;
break;
v = &m_src_vertices[m_src_vertices.size() - 1];
x1 = v->x;
y1 = v->y;
lprev = v->len;
case outline_miter_join:
case outline_round_join:
dv.flags =
(prev.diagonal_quadrant() == dv.curr.diagonal_quadrant()) |
((dv.curr.diagonal_quadrant() == dv.next.diagonal_quadrant()) << 1);
break;
v = &m_src_vertices[0];
x2 = v->x;
y2 = v->y;
dv.lcurr = v->len;
line_parameters prev(x1, y1, x2, y2, lprev);
v = &m_src_vertices[1];
dv.x1 = v->x;
dv.y1 = v->y;
dv.lnext = v->len;
dv.curr = line_parameters(x2, y2, dv.x1, dv.y1, dv.lcurr);
v = &m_src_vertices[dv.idx];
dv.x2 = v->x;
dv.y2 = v->y;
dv.next = line_parameters(dv.x1, dv.y1, dv.x2, dv.y2, dv.lnext);
dv.xb1 = 0;
dv.yb1 = 0;
dv.xb2 = 0;
dv.yb2 = 0;
switch(m_line_join)
{
case outline_no_join:
dv.flags = 3;
break;
case outline_miter_join:
case outline_round_join:
dv.flags =
(prev.diagonal_quadrant() == dv.curr.diagonal_quadrant()) |
((dv.curr.diagonal_quadrant() == dv.next.diagonal_quadrant()) << 1);
break;
case outline_miter_accurate_join:
dv.flags = 0;
break;
}
if((dv.flags & 1) == 0 && m_line_join != outline_round_join)
{
bisectrix(prev, dv.curr, &dv.xb1, &dv.yb1);
}
if((dv.flags & 2) == 0 && m_line_join != outline_round_join)
{
bisectrix(dv.curr, dv.next, &dv.xb2, &dv.yb2);
}
draw(dv, 0, m_src_vertices.size());
case outline_miter_accurate_join:
dv.flags = 0;
break;
}
if((dv.flags & 1) == 0 && m_line_join != outline_round_join)
{
bisectrix(prev, dv.curr, &dv.xb1, &dv.yb1);
}
if((dv.flags & 2) == 0 && m_line_join != outline_round_join)
{
bisectrix(dv.curr, dv.next, &dv.xb2, &dv.yb2);
}
draw(dv, 0, m_src_vertices.size());
}
else
{

View file

@ -78,8 +78,8 @@ namespace agg
//--------------------------------------------------------------------
void rounded_rect::normalize_radius()
{
double dx = fabs(m_y2 - m_y1);
double dy = fabs(m_x2 - m_x1);
double dx = fabs(m_x2 - m_x1);
double dy = fabs(m_y2 - m_y1);
double k = 1.0;
double t;

View file

@ -15,11 +15,33 @@ Look through the code to get an idea, and do not hesitate to ask questions.
Also read the design philosophy page for the motivations that lead to code decisions.
Templates are good, within reason. We seek to use templates were possible for flexible code, but not in cases where functional
patterns would be just as concise and clear.
In general we use Boost, it makes more possible in C++. It is a big build time dependency (as in time to compile against and # of headers) but ultimately compiles to small object code and is very fast (particularly spirit). It also has no dependencies itself (it's really an extension to the C++ language) so requiring it is much easier than requiring a hard dependency that itself has other dependencies. This is a big reason that we prefer AGG to Cairo as our primary renderer. Also AGG, besides producing the best visual output, strikes an excellent balance between speed and thread safety by using very lightweight objects. Cairo not so much.
You will also notice that we don't use many of the standard geo libraries when we could. For instance we don't use GDAL, OGR, or GEOS anywhere in core, and only leverage them in optional plugins. We feel we can often write code that is faster and more thread safe than these libraries but that still does the job. If this ever changes we can adapt and start using these libraries or others as dependencies - nothing is nicer than standing on the shoulders of giants when it makes sense.
## Code commits best practices.
#### Big changes - awesome as pull requests
We love big, aggressive refactoring - but ideally in branches. Even if the changes should go directly into the mainline code and are stable, very big changes are useful to see as a group and branches are cheap. So, branch and commit then create a pull request against master so that other developers can take a quick look. This is a great way for informal code review when a full issue is not warrented.
#### Commits that fix issues should note the issue #
git commit plugins/input/ogr/ -m "implemented sql query in OGR plugin (closes #472)"
#### Commits that relate to issues should reference them:
git commit tests/python_tests/sqlite_test.py -m "more robust sqlite tests - refs #928"
#### Commits that add a new feature or fix should be added to the CHANGELOG
Ideally the CHANGELOG can be a very concise place to look for the most important recent development and should not read like a full commit log. So, some developers may prefer to weekly or monthly look back over their commits and summarize all at once with additions to the CHANGELOG. Other developers may prefer to add as they go.
## License
Mapnik is licensed LGPL, which means that you are a free to use the code in any of your applications whether they be open source or not. It also means that if you contribute code to Mapnik that others are free to continue using Mapnik in the same way, even with your new additions. If you choose to redistribute an application using Mapnik just make sure to provide any source code modifications you make back to the community. For the actual details see the full LGPL license in the COPYING doc.
@ -67,13 +89,19 @@ If you see bits of code around that do not follow these please don't hesitate to
#### Indentation is four spaces
#### Use C++ style casts
static_cast<int>(value); // yes
(int)value; // no
#### Shared pointers should be created with [boost::make_shared](http://www.boost.org/doc/libs/1_47_0/libs/smart_ptr/make_shared.html) where possible
#### Function definitions should not be separated from their arguments:
void foo(int a) { ... } // please
void foo(int a) // please
void foo (int a) { ... } // no
void foo (int a) // no
#### Separate arguments by a single space:
@ -87,7 +115,18 @@ If you see bits of code around that do not follow these please don't hesitate to
if(a==b) // no
#### Braces should ideally be on a separate line:
#### Braces should always be used:
if (!file)
{
throw mapnik::datasource_exception("not found"); // please
}
if (!file)
throw mapnik::datasource_exception("not found"); // no
#### Braces should be on a separate line:
if (a == b)
{

View file

@ -2,7 +2,7 @@
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2010 Artem Pavlenko
* Copyright (C) 2011 Artem Pavlenko
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@ -19,15 +19,16 @@
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*****************************************************************************/
//$Id$
#ifndef MAPNIK_AGG_PATTERN_SOURCE_HPP
#define MAPNIK_AGG_PATTERN_SOURCE_HPP
// mapnik
#include <mapnik/image_data.hpp>
// boost
#include <boost/utility.hpp>
// agg
#include "agg_color_rgba.h"
@ -61,4 +62,4 @@ private:
};
}
#endif //MAPNIK_AGG_PATTERN_SOURCE_HPP
#endif // MAPNIK_AGG_PATTERN_SOURCE_HPP

View file

@ -2,7 +2,7 @@
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2010 Artem Pavlenko
* Copyright (C) 2011 Artem Pavlenko
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@ -19,12 +19,14 @@
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*****************************************************************************/
//$Id$
#ifndef MAPNIK_AGG_RASTERIZER_HPP
#define MAPNIK_AGG_RASTERIZER_HPP
// boost
#include <boost/utility.hpp>
// agg
#include "agg_rasterizer_scanline_aa.h"
namespace mapnik {
@ -33,4 +35,4 @@ struct rasterizer : agg::rasterizer_scanline_aa<>, boost::noncopyable {};
}
#endif //MAPNIK_AGG_RASTERIZER_HPP
#endif // MAPNIK_AGG_RASTERIZER_HPP

View file

@ -2,7 +2,7 @@
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2006 Artem Pavlenko
* Copyright (C) 2011 Artem Pavlenko
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@ -20,10 +20,8 @@
*
*****************************************************************************/
//$Id$
#ifndef AGG_RENDERER_HPP
#define AGG_RENDERER_HPP
#ifndef MAPNIK_AGG_RENDERER_HPP
#define MAPNIK_AGG_RENDERER_HPP
// mapnik
#include <mapnik/config.hpp>
@ -40,6 +38,7 @@
// boost
#include <boost/utility.hpp>
#include <boost/scoped_ptr.hpp>
#include <boost/shared_ptr.hpp>
// FIXME
// forward declare so that
@ -61,7 +60,11 @@ class MAPNIK_DECL agg_renderer : public feature_style_processor<agg_renderer<T>
{
public:
// create with default, empty placement detector
agg_renderer(Map const& m, T & pixmap, double scale_factor=1.0, unsigned offset_x=0, unsigned offset_y=0);
// create with external placement detector, possibly non-empty
agg_renderer(Map const &m, T & pixmap, boost::shared_ptr<label_collision_detector4> detector,
double scale_factor=1.0, unsigned offset_x=0, unsigned offset_y=0);
~agg_renderer();
void start_map_processing(Map const& map);
void end_map_processing(Map const& map);
@ -122,9 +125,11 @@ private:
CoordTransform t_;
freetype_engine font_engine_;
face_manager<freetype_engine> font_manager_;
label_collision_detector4 detector_;
boost::shared_ptr<label_collision_detector4> detector_;
boost::scoped_ptr<rasterizer> ras_ptr;
void setup(Map const &m);
};
}
#endif //AGG_RENDERER_HPP
#endif // MAPNIK_AGG_RENDERER_HPP

View file

@ -2,7 +2,7 @@
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2006 Artem Pavlenko
* Copyright (C) 2011 Artem Pavlenko
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@ -20,10 +20,8 @@
*
*****************************************************************************/
//$Id$
#ifndef ARROW_HPP
#define ARROW_HPP
#ifndef MAPNIK_ARROW_HPP
#define MAPNIK_ARROW_HPP
#include <mapnik/box2d.hpp>
@ -44,4 +42,4 @@ private:
};
}
#endif // ARROW_HPP
#endif // MAPNIK_ARROW_HPP

View file

@ -2,7 +2,7 @@
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2010 Artem Pavlenko
* Copyright (C) 2011 Artem Pavlenko
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@ -20,15 +20,18 @@
*
*****************************************************************************/
//$Id$
#ifndef MAPNIK_ATTRIBUTE_HPP
#define MAPNIK_ATTRIBUTE_HPP
// mapnik
#include <mapnik/value.hpp>
// stl
#include <string>
namespace mapnik {
static mapnik::value _null_value;
struct attribute
{
std::string name_;
@ -38,7 +41,13 @@ struct attribute
template <typename V ,typename F>
V value(F const& f) const
{
return f[name_];
typedef typename F::const_iterator const_iterator;
const_iterator itr = f.find(name_);
if (itr != f.end())
{
return itr->second;
}
return _null_value;
}
std::string const& name() const { return name_;}
};

View file

@ -2,7 +2,7 @@
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2006 Artem Pavlenko
* Copyright (C) 2011 Artem Pavlenko
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@ -20,20 +20,20 @@
*
*****************************************************************************/
//$Id$
#ifndef ATTRIBUTE_COLLECTOR_HPP
#define ATTRIBUTE_COLLECTOR_HPP
#ifndef MAPNIK_ATTRIBUTE_COLLECTOR_HPP
#define MAPNIK_ATTRIBUTE_COLLECTOR_HPP
// mapnik
#include <mapnik/feature_layer_desc.hpp>
#include <mapnik/rule.hpp>
#include <mapnik/path_expression_grammar.hpp>
#include <mapnik/parse_path.hpp>
// boost
#include <boost/utility.hpp>
#include <boost/variant.hpp>
#include <boost/concept_check.hpp>
// stl
#include <set>
#include <iostream>
@ -271,4 +271,4 @@ private:
} // namespace mapnik
#endif //ATTRIBUTE_COLLECTOR_HPP
#endif // MAPNIK_ATTRIBUTE_COLLECTOR_HPP

View file

@ -2,7 +2,7 @@
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2006 Artem Pavlenko
* Copyright (C) 2011 Artem Pavlenko
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@ -20,10 +20,8 @@
*
*****************************************************************************/
//$Id$
#ifndef ATTRIBUTE_DESCRIPTOR
#define ATTRIBUTE_DESCRIPTOR
#ifndef MAPNIK_ATTRIBUTE_DESCRIPTOR_HPP
#define MAPNIK_ATTRIBUTE_DESCRIPTOR_HPP
#include <string>
@ -118,4 +116,4 @@ operator << (std::basic_ostream<charT,traits>& out,
}
#endif // ATTRIBUTE_DESCRIPTOR_HPP
#endif // MAPNIK_ATTRIBUTE_DESCRIPTOR_HPP

View file

@ -2,7 +2,7 @@
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2010 Artem Pavlenko
* Copyright (C) 2011 Artem Pavlenko
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@ -20,16 +20,16 @@
*
*****************************************************************************/
//$Id: box2d.hpp 39 2005-04-10 20:39:53Z pavlenko $
#ifndef MAPNIK_BOX2D_HPP
#define MAPNIK_BOX2D_HPP
// mapnik
#include <mapnik/config.hpp>
#include <mapnik/coord.hpp>
// boost
#include <boost/operators.hpp>
// stl
#include <iomanip>
@ -41,9 +41,8 @@ namespace mapnik {
template <typename T> class MAPNIK_DECL box2d
: boost::equality_comparable<box2d<T> ,
boost::addable<box2d<T>,
boost::subtractable<box2d<T>,
boost::dividable2<box2d<T>, T,
boost::multipliable2<box2d<T>, T > > > > >
boost::dividable2<box2d<T>, T,
boost::multipliable2<box2d<T>, T > > > >
{
public:
typedef box2d<T> box2d_type;
@ -86,7 +85,6 @@ public:
// define some operators
box2d_type& operator+=(box2d_type const& other);
box2d_type& operator-=(box2d_type const& other);
box2d_type& operator*=(T);
box2d_type& operator/=(T);
T operator[](int index) const;

View file

@ -2,7 +2,7 @@
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2008 Tom Hughes
* Copyright (C) 2011 Artem Pavlenko
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@ -20,14 +20,10 @@
*
*****************************************************************************/
//$Id$
#if defined(HAVE_CAIRO)
#ifndef CAIRO_RENDERER_HPP
#define CAIRO_RENDERER_HPP
#ifndef MAPNIK_CAIRO_RENDERER_HPP
#define MAPNIK_CAIRO_RENDERER_HPP
// mapnik
#include <mapnik/config.hpp>
@ -152,6 +148,6 @@ public:
};
}
#endif
#endif // MAPNIK_CAIRO_RENDERER_HPP
#endif //CAIRO_RENDERER_HPP
#endif

View file

@ -2,7 +2,7 @@
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2006 Artem Pavlenko
* Copyright (C) 2011 Artem Pavlenko
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@ -20,10 +20,8 @@
*
*****************************************************************************/
//$Id: color.hpp 39 2005-04-10 20:39:53Z pavlenko $
#ifndef COLOR_HPP
#define COLOR_HPP
#ifndef MAPNIK_COLOR_HPP
#define MAPNIK_COLOR_HPP
// mapnik
#include <mapnik/config.hpp>
@ -32,6 +30,7 @@
//boost
#include <boost/cstdint.hpp>
#include <boost/operators.hpp>
// stl
#include <sstream>
@ -141,4 +140,4 @@ public:
}
#endif //COLOR_HPP
#endif // MAPNIK_COLOR_HPP

Some files were not shown because too many files have changed in this diff Show more