Merge pull request #2776 from mapnik/split-python

Split python
This commit is contained in:
Dane Springmeyer 2015-04-25 06:01:36 +02:00
commit a8b4793642
2531 changed files with 624 additions and 103541 deletions

View file

@ -28,8 +28,6 @@ install:
script:
- source bootstrap.sh
- wget https://gist.githubusercontent.com/springmeyer/0833fa43794838889139/raw/build_pycairo.sh && chmod +x build_pycairo.sh && ./build_pycairo.sh
- export PYTHONPATH=$(pwd)/mason_packages/.link/lib/python2.7/site-packages:${PYTHONPATH}
- if [[ ${COVERAGE} == true ]]; then ./configure CUSTOM_LDFLAGS='--coverage' CUSTOM_CXXFLAGS='--coverage' CUSTOM_CFLAGS='--coverage' DEBUG=True; else ./configure; fi;
- make
- git clone --depth=1 https://github.com/mapbox/mapnik-test-data tests/data/mapnik-test-data

View file

@ -46,7 +46,6 @@ clean:
@find ./ -name "*.so" -exec rm {} \;
@find ./ -name "*.o" -exec rm {} \;
@find ./ -name "*.a" -exec rm {} \;
@if test -e "bindings/python/mapnik/paths.py"; then rm "bindings/python/mapnik/paths.py"; fi
distclean:
if test -e "config.py"; then mv "config.py" "config.py.backup"; fi
@ -65,12 +64,6 @@ test:
test-local:
make test
test-visual:
bash -c "source ./localize.sh && python tests/visual_tests/test.py -q"
test-python:
bash -c "source ./localize.sh && python tests/run_tests.py -q"
test-cpp:
./tests/cpp_tests/run

View file

@ -78,7 +78,6 @@ pretty_dep_names = {
'gdal':'GDAL C++ library | configured using gdal-config program | try setting GDAL_CONFIG SCons option | more info: https://github.com/mapnik/mapnik/wiki/GDAL',
'ogr':'OGR-enabled GDAL C++ Library | configured using gdal-config program | try setting GDAL_CONFIG SCons option | more info: https://github.com/mapnik/mapnik/wiki/OGR',
'cairo':'Cairo C library | configured using pkg-config | try setting PKG_CONFIG_PATH SCons option',
'pycairo':'Python bindings to Cairo library | configured using pkg-config | try setting PKG_CONFIG_PATH SCons option',
'proj':'Proj.4 C Projections library | configure with PROJ_LIBS & PROJ_INCLUDES | more info: http://trac.osgeo.org/proj/',
'pg':'Postgres C Library required for PostGIS plugin | configure with pg_config program or configure with PG_LIBS & PG_INCLUDES | more info: https://github.com/mapnik/mapnik/wiki/PostGIS',
'sqlite3':'SQLite3 C Library | configure with SQLITE_LIBS & SQLITE_INCLUDES | more info: https://github.com/mapnik/mapnik/wiki/SQLite',
@ -320,7 +319,6 @@ opts.AddVariables(
# Install Variables
('PREFIX', 'The install path "prefix"', '/usr/local'),
('LIBDIR_SCHEMA', 'The library sub-directory appended to the "prefix", sometimes lib64 on 64bit linux systems', LIBDIR_SCHEMA_DEFAULT),
('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', '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 (create multiple excludes separated by :)', ''),
@ -335,7 +333,6 @@ 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 to specific Boost Python lib (e.g. "boost_python-py26")','boost_python'),
# Variables for required dependencies
('FREETYPE_CONFIG', 'The path to the freetype-config executable.', 'freetype-config'),
@ -403,12 +400,8 @@ opts.AddVariables(
('SYSTEM_FONTS','Provide location for python bindings to register fonts (if provided then the bundled DejaVu fonts are not installed)',''),
('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'),
('FRAMEWORK_SEARCH_PATH','Custom framework search path on Mac OS X', ''),
BoolVariable('FULL_LIB_PATH', 'Embed the full and absolute path to libmapnik when linking ("install_name" on OS X/rpath on Linux)', 'True'),
BoolVariable('ENABLE_SONAME', 'Embed a soname in libmapnik on Linux', 'True'),
ListVariable('BINDINGS','Language bindings to build','all',['python']),
EnumVariable('THREADING','Set threading support','multi', ['multi','single']),
EnumVariable('XMLPARSER','Set xml parser','libxml2', ['libxml2','ptree']),
BoolVariable('DEMO', 'Compile demo c++ application', 'True'),
@ -452,17 +445,12 @@ pickle_store = [# Scons internal variables
'BOOST_APPEND',
'LIBDIR_SCHEMA',
'REQUESTED_PLUGINS',
'PYTHON_VERSION',
'PYTHON_INCLUDES',
'PYTHON_INSTALL_LOCATION',
'PYTHON_SYS_PREFIX',
'COLOR_PRINT',
'HAS_CAIRO',
'MAPNIK_HAS_DLFCN',
'HAS_PYCAIRO',
'PYCAIRO_PATHS',
'HAS_LIBXML2',
'PYTHON_IS_64BIT',
'SAMPLE_INPUT_PLUGINS',
'PKG_CONFIG_PATH',
'PATH',
@ -1145,7 +1133,6 @@ if not preconfigured:
env['PLUGINS'] = PLUGINS
env['EXTRA_FREETYPE_LIBS'] = []
env['SQLITE_LINKFLAGS'] = []
env['PYTHON_INCLUDES'] = []
# 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):
@ -1646,94 +1633,6 @@ if not preconfigured:
env['SKIPPED_DEPS'].append('cairo')
env['HAS_CAIRO'] = False
if 'python' in env['BINDINGS']:
if not os.access(env['PYTHON'], os.X_OK):
color_print(1,"Cannot run python interpreter at '%s', make sure that you have the permissions to execute it." % env['PYTHON'])
Exit(1)
py3 = 'True' in os.popen('''%s -c "import sys as s;s.stdout.write(str(s.version_info[0] == 3))"''' % env['PYTHON']).read().strip()
if py3:
sys_prefix = '''%s -c "import sys; print(sys.prefix)"''' % env['PYTHON']
else:
sys_prefix = '''%s -c "import sys; print sys.prefix"''' % env['PYTHON']
env['PYTHON_SYS_PREFIX'] = call(sys_prefix)
if HAS_DISTUTILS:
if py3:
sys_version = '''%s -c "from distutils.sysconfig import get_python_version; print(get_python_version())"''' % env['PYTHON']
else:
sys_version = '''%s -c "from distutils.sysconfig import get_python_version; print get_python_version()"''' % env['PYTHON']
env['PYTHON_VERSION'] = call(sys_version)
if py3:
py_includes = '''%s -c "from distutils.sysconfig import get_python_inc; print(get_python_inc())"''' % env['PYTHON']
else:
py_includes = '''%s -c "from distutils.sysconfig import get_python_inc; print get_python_inc()"''' % env['PYTHON']
env['PYTHON_INCLUDES'].append(call(py_includes))
# also append platform specific includes
if py3:
py_plat_includes = '''%s -c "from distutils.sysconfig import get_python_inc; print(get_python_inc(plat_specific=True))"''' % env['PYTHON']
else:
py_plat_includes = '''%s -c "from distutils.sysconfig import get_python_inc; print get_python_inc(plat_specific=True)"''' % env['PYTHON']
env['PYTHON_INCLUDES'].append(call(py_plat_includes))
# Note: we use the plat_specific argument here to make sure to respect the arch-specific site-packages location
if py3:
site_packages = '''%s -c "from distutils.sysconfig import get_python_lib; print(get_python_lib(plat_specific=True))"''' % env['PYTHON']
else:
site_packages = '''%s -c "from distutils.sysconfig import get_python_lib; print get_python_lib(plat_specific=True)"''' % env['PYTHON']
env['PYTHON_SITE_PACKAGES'] = call(site_packages)
else:
env['PYTHON_SYS_PREFIX'] = os.popen('''%s -c "import sys; print sys.prefix"''' % env['PYTHON']).read().strip()
env['PYTHON_VERSION'] = os.popen('''%s -c "import sys; print sys.version"''' % env['PYTHON']).read()[0:3]
env['PYTHON_INCLUDES'] = [env['PYTHON_SYS_PREFIX'] + '/include/python' + env['PYTHON_VERSION']]
env['PYTHON_SITE_PACKAGES'] = env['DESTDIR'] + os.path.sep + env['PYTHON_SYS_PREFIX'] + os.path.sep + env['LIBDIR_SCHEMA'] + '/python' + env['PYTHON_VERSION'] + '/site-packages/'
# if user-requested custom prefix fall back to manual concatenation for building subdirectories
if env['PYTHON_PREFIX']:
py_relative_install = env['LIBDIR_SCHEMA'] + '/python' + env['PYTHON_VERSION'] + '/site-packages/'
env['PYTHON_INSTALL_LOCATION'] = env['DESTDIR'] + os.path.sep + env['PYTHON_PREFIX'] + os.path.sep + py_relative_install
else:
env['PYTHON_INSTALL_LOCATION'] = env['DESTDIR'] + os.path.sep + env['PYTHON_SITE_PACKAGES']
if py3:
is_64_bit = '''%s -c "import sys; print(sys.maxsize == 9223372036854775807)"''' % env['PYTHON']
else:
is_64_bit = '''%s -c "import sys; print sys.maxint == 9223372036854775807"''' % env['PYTHON']
if is_64_bit:
env['PYTHON_IS_64BIT'] = True
else:
env['PYTHON_IS_64BIT'] = False
if has_boost_devel and 'python' in env['BINDINGS']:
if py3 and env['BOOST_PYTHON_LIB'] == 'boost_python':
env['BOOST_PYTHON_LIB'] = 'boost_python3%s' % env['BOOST_APPEND']
elif env['BOOST_PYTHON_LIB'] == 'boost_python':
env['BOOST_PYTHON_LIB'] = 'boost_python%s' % env['BOOST_APPEND']
if not env['HOST']:
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 CHECK_PKG_CONFIG and conf.CheckPKG('pycairo'):
env['HAS_PYCAIRO'] = True
temp_env = env.Clone()
temp_env['CPPPATH'] = []
temp_env.ParseConfig('pkg-config --cflags pycairo')
if temp_env['CPPPATH']:
env['PYCAIRO_PATHS'] = copy(temp_env['CPPPATH'])
else:
print temp_env['CPPPATH']
else:
env['SKIPPED_DEPS'].extend(['pycairo'])
else:
color_print(4,'Not building with pycairo support, pass CAIRO=True to enable')
#### End Config Stage for Required Dependencies ####
if env['MISSING_DEPS']:
@ -1864,29 +1763,6 @@ if not preconfigured:
if env['DEBUG_UNDEFINED']:
env.Append(CXXFLAGS = '-fsanitize=undefined-trap -fsanitize-undefined-trap-on-error -ftrapv -fwrapv')
if 'python' in env['BINDINGS']:
majver, minver = env['PYTHON_VERSION'].split('.')
# we don't want the includes it in the main environment...
# as they are later set in the python build.py
# ugly hack needed until we have env specific conf
backup = env.Clone().Dictionary()
for pyinc in env['PYTHON_INCLUDES']:
env.AppendUnique(CPPPATH = fix_path(pyinc))
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'])
Exit(1)
if (int(majver), int(minver)) < (2, 2):
color_print(1,"Python version 2.2 or greater required")
Exit(1)
if 'python' in env['BINDINGS']:
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']))
env.Replace(**backup)
# if requested, sort LIBPATH and CPPPATH one last time before saving...
if env['PRIORITIZE_LINKING']:
conf.prioritize_paths(silent=True)
@ -2070,16 +1946,6 @@ if not HELP_REQUESTED:
else :
color_print(1,"WARNING: Cannot find boost_program_options. 'shapeindex' and other command line programs will not be available")
# Build the Python bindings
if 'python' in env['BINDINGS']:
SConscript('bindings/python/build.py')
# Install the python speed testing scripts if python bindings will be available
SConscript('utils/performance/build.py')
# Install the mapnik upgrade script
SConscript('utils/upgrade_map_xml/build.py')
# Configure fonts and if requested install the bundled DejaVu fonts
SConscript('fonts/build.py')

View file

@ -1,49 +0,0 @@
/*****************************************************************************
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2014 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
*
*****************************************************************************/
#ifndef MAPNIK_PYTHON_BOOST_STD_SHARED_SHIM
#define MAPNIK_PYTHON_BOOST_STD_SHARED_SHIM
// boost
#include <boost/version.hpp>
#include <boost/config.hpp>
#if BOOST_VERSION < 105300 || defined BOOST_NO_CXX11_SMART_PTR
// https://github.com/mapnik/mapnik/issues/2022
#include <memory>
namespace boost {
template<class T> const T* get_pointer(std::shared_ptr<T> const& p)
{
return p.get();
}
template<class T> T* get_pointer(std::shared_ptr<T>& p)
{
return p.get();
}
} // namespace boost
#endif
#endif // MAPNIK_PYTHON_BOOST_STD_SHARED_SHIM

View file

@ -1,212 +0,0 @@
#
# This file is part of Mapnik (c++ mapping toolkit)
#
# Copyright (C) 2014 Artem Pavlenko
#
# 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
#
#
import glob
import os
from subprocess import Popen, PIPE
Import('env')
def call(cmd, silent=True):
stdin, stderr = Popen(cmd, shell=True, stdout=PIPE, stderr=PIPE).communicate()
if not stderr:
return stdin.strip()
elif not silent:
print stderr
def run_2to3(*args,**kwargs):
call('2to3 -w %s' % os.path.dirname(kwargs['target'][0].path))
def is_py3():
return 'True' in os.popen('''%s -c "import sys as s;s.stdout.write(str(s.version_info[0] == 3))"''' % env['PYTHON']).read().strip()
prefix = env['PREFIX']
target_path = os.path.normpath(env['PYTHON_INSTALL_LOCATION'] + os.path.sep + env['MAPNIK_NAME'])
target_path_deprecated = os.path.normpath(env['PYTHON_INSTALL_LOCATION'] + os.path.sep + 'mapnik2')
py_env = env.Clone()
py_env.Append(CPPPATH = env['PYTHON_INCLUDES'])
py_env.Append(CPPDEFINES = env['LIBMAPNIK_DEFINES'])
py_env['LIBS'] = [env['MAPNIK_NAME'],env['BOOST_PYTHON_LIB']]
link_all_libs = env['LINKING'] == 'static' or env['RUNTIME_LINK'] == 'static' or (env['PLATFORM'] == 'Darwin' and not env['PYTHON_DYNAMIC_LOOKUP'])
# even though boost_thread is no longer used in mapnik core
# we need to link in for boost_python to avoid missing symbol: _ZN5boost6detail12get_tss_dataEPKv / boost::detail::get_tss_data
py_env.AppendUnique(LIBS = 'boost_thread%s' % env['BOOST_APPEND'])
if link_all_libs:
py_env.AppendUnique(LIBS=env['LIBMAPNIK_LIBS'])
# note: on linux -lrt must be linked after thread to avoid: undefined symbol: clock_gettime
if env['RUNTIME_LINK'] == 'static' and env['PLATFORM'] == 'Linux':
py_env.AppendUnique(LIBS='rt')
# TODO - do solaris/fedora need direct linking too?
if env['PLATFORM'] == 'Darwin':
##### Python linking on OS X is tricky ###
# Confounding problems are:
# 1) likelyhood of multiple python installs of the same major.minor version
# because apple supplies python built-in and many users may have installed
# further versions using macports
# 2) boost python directly links to a python version
# 3) the below will directly link _mapnik.so to a python version
# 4) _mapnik.so must link to the same python lib as boost_python.dylib otherwise
# python will Abort with a Version Mismatch error.
# See https://github.com/mapnik/mapnik/issues/453 for the seeds of a better approach
# for now we offer control over method of direct linking...
# The default below is to link against the python dylib in the form of
#/path/to/Python.framework/Python instead of -lpython
# http://developer.apple.com/mac/library/DOCUMENTATION/Darwin/Reference/ManPages/man1/ld.1.html
if env['PYTHON_DYNAMIC_LOOKUP']:
python_link_flag = '-undefined dynamic_lookup'
elif env['FRAMEWORK_PYTHON']:
if env['FRAMEWORK_SEARCH_PATH']:
# if the user has supplied a custom root path to search for
# a given Python framework, then use that to direct the linker
python_link_flag = '-F%s -framework Python -Z' % env['FRAMEWORK_SEARCH_PATH']
else:
# otherwise be as explicit as possible for linking to the same Framework
# as the executable we are building with (or is pointed to by the PYTHON variable)
# otherwise we may accidentally link against either:
# /System/Library/Frameworks/Python.framework/Python/Versions/
# or
# /Library/Frameworks/Python.framework/Python/Versions/
# See: https://github.com/mapnik/mapnik/issues/380
link_prefix = env['PYTHON_SYS_PREFIX']
if '.framework' in link_prefix:
python_link_flag = '-F%s -framework Python -Z' % os.path.dirname(link_prefix.split('.')[0])
elif '/System' in link_prefix:
python_link_flag = '-F/System/Library/Frameworks/ -framework Python -Z'
else:
# should we fall back to -lpython here?
python_link_flag = '-F/ -framework Python'
# if we are not linking to a framework then use the *nix standard approach
else:
# TODO - do we need to pass -L/?
python_link_flag = '-lpython%s' % env['PYTHON_VERSION']
elif env['PLATFORM'] == 'SunOS':
# make sure to explicitly link mapnik.so against
# libmapnik in its installed location
python_link_flag = '-R%s' % env['MAPNIK_LIB_BASE']
else:
# all other platforms we don't directly link python
python_link_flag = ''
paths = '''
"""Configuration paths of Mapnik fonts and input plugins (auto-generated by SCons)."""
from os.path import normpath,join,dirname
mapniklibpath = '%s'
mapniklibpath = normpath(join(dirname(__file__),mapniklibpath))
'''
paths += "inputpluginspath = join(mapniklibpath,'input')\n"
if env['SYSTEM_FONTS']:
paths += "fontscollectionpath = normpath('%s')\n" % env['SYSTEM_FONTS']
else:
paths += "fontscollectionpath = join(mapniklibpath,'fonts')\n"
paths += "__all__ = [mapniklibpath,inputpluginspath,fontscollectionpath]\n"
if not os.path.exists(env['MAPNIK_NAME']):
os.mkdir(env['MAPNIK_NAME'])
file('mapnik/paths.py','w').write(paths % (env['MAPNIK_LIB_DIR']))
# force open perms temporarily so that `sudo scons install`
# does not later break simple non-install non-sudo rebuild
try:
os.chmod('mapnik/paths.py',0666)
except: pass
# install the shared object beside the module directory
sources = glob.glob('*.cpp')
if 'install' in COMMAND_LINE_TARGETS:
# install the core mapnik python files, including '__init__.py'
init_files = glob.glob('mapnik/*.py')
if 'mapnik/paths.py' in init_files:
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
init_mapnik2 = env.Install(target_path_deprecated, 'mapnik2/__init__.py')
env.Alias(target='install', source=init_mapnik2)
# fix perms and install the custom generated 'paths.py'
targetp = os.path.join(target_path,'paths.py')
env.Alias("install", targetp)
# use env.Command rather than env.Install
# to enable setting proper perms on `paths.py`
env.Command( targetp, 'mapnik/paths.py',
[
Copy("$TARGET","$SOURCE"),
Chmod("$TARGET", 0644),
])
if 'uninstall' not in COMMAND_LINE_TARGETS:
if env['HAS_CAIRO']:
py_env.Append(CPPPATH = env['CAIRO_CPPPATHS'])
py_env.Append(CPPDEFINES = '-DHAVE_CAIRO')
if link_all_libs:
py_env.Append(LIBS=env['CAIRO_ALL_LIBS'])
if env['HAS_PYCAIRO']:
py_env.Append(CPPDEFINES = '-DHAVE_PYCAIRO')
py_env.Append(CPPPATH = env['PYCAIRO_PATHS'])
py_env.Append(LINKFLAGS=python_link_flag)
py_env.AppendUnique(LIBS='mapnik-json')
py_env.AppendUnique(LIBS='mapnik-wkt')
_mapnik = py_env.LoadableModule('mapnik/_mapnik', sources, LDMODULEPREFIX='', LDMODULESUFFIX='.so')
Depends(_mapnik, env.subst('../../src/%s' % env['MAPNIK_LIB_NAME']))
Depends(_mapnik, env.subst('../../src/json/libmapnik-json${LIBSUFFIX}'))
Depends(_mapnik, env.subst('../../src/wkt/libmapnik-wkt${LIBSUFFIX}'))
if env['PLATFORM'] == 'SunOS' and env['PYTHON_IS_64BIT']:
# http://mail.python.org/pipermail/python-dev/2006-August/068528.html
cxx_module_path = os.path.join(target_path,'64')
else:
cxx_module_path = target_path
if 'uninstall' not in COMMAND_LINE_TARGETS:
pymapniklib = env.Install(cxx_module_path,_mapnik)
py_env.Alias(target='install',source=pymapniklib)
if 'install' in COMMAND_LINE_TARGETS:
if is_py3():
env.AddPostAction(pymapniklib, run_2to3)
env['create_uninstall_target'](env, target_path)
env['create_uninstall_target'](env, target_path_deprecated)

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -1,27 +0,0 @@
#
# This file is part of Mapnik (C++/Python mapping toolkit)
# Copyright (C) 2014 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,130 +0,0 @@
/*****************************************************************************
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2014 Artem Pavlenko, Jean-Francois Doyon
*
* 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 <mapnik/config.hpp>
#include "boost_std_shared_shim.hpp"
// boost
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-parameter"
#pragma GCC diagnostic ignored "-Wunused-local-typedef"
#pragma GCC diagnostic ignored "-Wmissing-field-initializers"
#include <boost/python.hpp>
#pragma GCC diagnostic pop
//mapnik
#include <mapnik/color.hpp>
using mapnik::color;
struct color_pickle_suite : boost::python::pickle_suite
{
static boost::python::tuple
getinitargs(const color& c)
{
using namespace boost::python;
return boost::python::make_tuple(c.red(),c.green(),c.blue(),c.alpha());
}
};
void export_color ()
{
using namespace boost::python;
class_<color>("Color", init<int,int,int,int>(
( arg("r"), arg("g"), arg("b"), arg("a") ),
"Creates a new color from its RGB components\n"
"and an alpha value.\n"
"All values between 0 and 255.\n")
)
.def(init<int,int,int,int,bool>(
( arg("r"), arg("g"), arg("b"), arg("a"), arg("premultiplied") ),
"Creates a new color from its RGB components\n"
"and an alpha value.\n"
"All values between 0 and 255.\n")
)
.def(init<int,int,int>(
( arg("r"), arg("g"), arg("b") ),
"Creates a new color from its RGB components.\n"
"All values between 0 and 255.\n")
)
.def(init<uint32_t>(
( arg("val") ),
"Creates a new color from an unsigned integer.\n"
"All values between 0 and 2^32-1\n")
)
.def(init<uint32_t, bool>(
( arg("val"), arg("premultiplied") ),
"Creates a new color from an unsigned integer.\n"
"All values between 0 and 2^32-1\n")
)
.def(init<std::string>(
( arg("color_string") ),
"Creates a new color from its CSS string representation.\n"
"The string may be a CSS color name (e.g. 'blue')\n"
"or a hex color string (e.g. '#0000ff').\n")
)
.def(init<std::string, bool>(
( arg("color_string"), arg("premultiplied") ),
"Creates a new color from its CSS string representation.\n"
"The string may be a CSS color name (e.g. 'blue')\n"
"or a hex color string (e.g. '#0000ff').\n")
)
.add_property("r",
&color::red,
&color::set_red,
"Gets or sets the red component.\n"
"The value is between 0 and 255.\n")
.add_property("g",
&color::green,
&color::set_green,
"Gets or sets the green component.\n"
"The value is between 0 and 255.\n")
.add_property("b",
&color::blue,
&color::set_blue,
"Gets or sets the blue component.\n"
"The value is between 0 and 255.\n")
.add_property("a",
&color::alpha,
&color::set_alpha,
"Gets or sets the alpha component.\n"
"The value is between 0 and 255.\n")
.def(self == self)
.def(self != self)
.def_pickle(color_pickle_suite())
.def("__str__",&color::to_string)
.def("set_premultiplied",&color::set_premultiplied)
.def("get_premultiplied",&color::get_premultiplied)
.def("premultiply",&color::premultiply)
.def("demultiply",&color::demultiply)
.def("packed",&color::rgba)
.def("to_hex_string",&color::to_hex_string,
"Returns the hexadecimal representation of this color.\n"
"\n"
"Example:\n"
">>> c = Color('blue')\n"
">>> c.to_hex_string()\n"
"'#0000ff'\n")
;
}

View file

@ -1,73 +0,0 @@
/*****************************************************************************
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2014 Artem Pavlenko, Jean-Francois Doyon
*
* 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 <mapnik/config.hpp>
#include "boost_std_shared_shim.hpp"
// boost
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-parameter"
#pragma GCC diagnostic ignored "-Wunused-local-typedef"
#pragma GCC diagnostic ignored "-Wmissing-field-initializers"
#include <boost/python.hpp>
#pragma GCC diagnostic pop
// mapnik
#include <mapnik/coord.hpp>
using mapnik::coord;
struct coord_pickle_suite : boost::python::pickle_suite
{
static boost::python::tuple
getinitargs(const coord<double,2>& c)
{
using namespace boost::python;
return boost::python::make_tuple(c.x,c.y);
}
};
void export_coord()
{
using namespace boost::python;
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")
)
.def_pickle(coord_pickle_suite())
.def_readwrite("x", &coord<double,2>::x,
"Gets or sets the x/lon coordinate of the point.\n")
.def_readwrite("y", &coord<double,2>::y,
"Gets or sets the y/lat coordinate of the point.\n")
.def(self == self) // __eq__
.def(self + self) // __add__
.def(self + float())
.def(float() + self)
.def(self - self) // __sub__
.def(self - float())
.def(self * float()) //__mult__
.def(float() * self)
.def(self / float()) // __div__
;
}

View file

@ -1,217 +0,0 @@
/*****************************************************************************
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2014 Artem Pavlenko, Jean-Francois Doyon
*
* 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 <mapnik/config.hpp>
// boost
#include "boost_std_shared_shim.hpp"
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-parameter"
#pragma GCC diagnostic ignored "-Wunused-local-typedef"
#pragma GCC diagnostic ignored "-Wmissing-field-initializers"
#include <boost/python.hpp>
#include <boost/noncopyable.hpp>
#include <boost/version.hpp>
#pragma GCC diagnostic pop
// stl
#include <vector>
// mapnik
#include <mapnik/box2d.hpp>
#include <mapnik/datasource.hpp>
#include <mapnik/datasource_cache.hpp>
#include <mapnik/feature_layer_desc.hpp>
#include <mapnik/memory_datasource.hpp>
using mapnik::datasource;
using mapnik::memory_datasource;
using mapnik::layer_descriptor;
using mapnik::attribute_descriptor;
using mapnik::parameters;
namespace
{
//user-friendly wrapper that uses Python dictionary
using namespace boost::python;
std::shared_ptr<mapnik::datasource> create_datasource(dict const& d)
{
mapnik::parameters params;
boost::python::list keys=d.keys();
for (int i=0; i < len(keys); ++i)
{
std::string key = extract<std::string>(keys[i]);
object obj = d[key];
if (PyUnicode_Check(obj.ptr()))
{
PyObject* temp = PyUnicode_AsUTF8String(obj.ptr());
if (temp)
{
#if PY_VERSION_HEX >= 0x03000000
char* c_str = PyBytes_AsString(temp);
#else
char* c_str = PyString_AsString(temp);
#endif
params[key] = std::string(c_str);
Py_DecRef(temp);
}
continue;
}
extract<std::string> ex0(obj);
extract<mapnik::value_integer> ex1(obj);
extract<double> ex2(obj);
if (ex0.check())
{
params[key] = ex0();
}
else if (ex1.check())
{
params[key] = ex1();
}
else if (ex2.check())
{
params[key] = ex2();
}
}
return mapnik::datasource_cache::instance().create(params);
}
boost::python::dict describe(std::shared_ptr<mapnik::datasource> const& ds)
{
boost::python::dict description;
mapnik::layer_descriptor ld = ds->get_descriptor();
description["type"] = ds->type();
description["name"] = ld.get_name();
description["geometry_type"] = ds->get_geometry_type();
description["encoding"] = ld.get_encoding();
for (auto const& param : ld.get_extra_parameters())
{
description[param.first] = param.second;
}
return description;
}
boost::python::list fields(std::shared_ptr<mapnik::datasource> const& ds)
{
boost::python::list flds;
if (ds)
{
layer_descriptor ld = ds->get_descriptor();
std::vector<attribute_descriptor> const& desc_ar = ld.get_descriptors();
std::vector<attribute_descriptor>::const_iterator it = desc_ar.begin();
std::vector<attribute_descriptor>::const_iterator end = desc_ar.end();
for (; it != end; ++it)
{
flds.append(it->get_name());
}
}
return flds;
}
boost::python::list field_types(std::shared_ptr<mapnik::datasource> const& ds)
{
boost::python::list fld_types;
if (ds)
{
layer_descriptor ld = ds->get_descriptor();
std::vector<attribute_descriptor> const& desc_ar = ld.get_descriptors();
std::vector<attribute_descriptor>::const_iterator it = desc_ar.begin();
std::vector<attribute_descriptor>::const_iterator end = desc_ar.end();
for (; it != end; ++it)
{
unsigned type = it->get_type();
if (type == mapnik::Integer)
// this crashes, so send back strings instead
//fld_types.append(boost::python::object(boost::python::handle<>(&PyInt_Type)));
fld_types.append(boost::python::str("int"));
else if (type == mapnik::Float)
fld_types.append(boost::python::str("float"));
else if (type == mapnik::Double)
fld_types.append(boost::python::str("float"));
else if (type == mapnik::String)
fld_types.append(boost::python::str("str"));
else if (type == mapnik::Boolean)
fld_types.append(boost::python::str("bool"));
else if (type == mapnik::Geometry)
fld_types.append(boost::python::str("geometry"));
else if (type == mapnik::Object)
fld_types.append(boost::python::str("object"));
else
fld_types.append(boost::python::str("unknown"));
}
}
return fld_types;
}}
mapnik::parameters const& (mapnik::datasource::*params_const)() const = &mapnik::datasource::params;
void export_datasource()
{
using namespace boost::python;
enum_<mapnik::datasource::datasource_t>("DataType")
.value("Vector",mapnik::datasource::Vector)
.value("Raster",mapnik::datasource::Raster)
;
enum_<mapnik::datasource_geometry_t>("DataGeometryType")
.value("Point",mapnik::datasource_geometry_t::Point)
.value("LineString",mapnik::datasource_geometry_t::LineString)
.value("Polygon",mapnik::datasource_geometry_t::Polygon)
.value("Collection",mapnik::datasource_geometry_t::Collection)
;
class_<datasource,std::shared_ptr<datasource>,
boost::noncopyable>("Datasource",no_init)
.def("type",&datasource::type)
.def("geometry_type",&datasource::get_geometry_type)
.def("describe",&describe)
.def("envelope",&datasource::envelope)
.def("features",&datasource::features)
.def("fields",&fields)
.def("field_types",&field_types)
.def("features_at_point",&datasource::features_at_point, (arg("coord"),arg("tolerance")=0))
.def("params",make_function(params_const,return_value_policy<copy_const_reference>()),
"The configuration parameters of the data source. "
"These vary depending on the type of data source.")
.def(self == self)
;
def("CreateDatasource",&create_datasource);
class_<memory_datasource,
bases<datasource>, std::shared_ptr<memory_datasource>,
boost::noncopyable>("MemoryDatasourceBase", init<parameters>())
.def("add_feature",&memory_datasource::push,
"Adds a Feature:\n"
">>> ms = MemoryDatasource()\n"
">>> feature = Feature(1)\n"
">>> ms.add_feature(Feature(1))\n")
.def("num_features",&memory_datasource::size)
;
implicitly_convertible<std::shared_ptr<memory_datasource>,std::shared_ptr<datasource> >();
}

View file

@ -1,104 +0,0 @@
/*****************************************************************************
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2014 Artem Pavlenko, Jean-Francois Doyon
*
* 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 <mapnik/config.hpp>
// boost
#include "boost_std_shared_shim.hpp"
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-parameter"
#pragma GCC diagnostic ignored "-Wunused-local-typedef"
#pragma GCC diagnostic ignored "-Wmissing-field-initializers"
#include <boost/python.hpp>
#include <boost/noncopyable.hpp>
#pragma GCC diagnostic pop
#include <mapnik/value_types.hpp>
#include <mapnik/params.hpp>
#include <mapnik/datasource.hpp>
#include <mapnik/datasource_cache.hpp>
namespace {
using namespace boost::python;
std::shared_ptr<mapnik::datasource> create_datasource(const dict& d)
{
mapnik::parameters params;
boost::python::list keys=d.keys();
for (int i=0; i<len(keys); ++i)
{
std::string key = extract<std::string>(keys[i]);
object obj = d[key];
extract<std::string> ex0(obj);
extract<mapnik::value_integer> ex1(obj);
extract<double> ex2(obj);
if (ex0.check())
{
params[key] = ex0();
}
else if (ex1.check())
{
params[key] = ex1();
}
else if (ex2.check())
{
params[key] = ex2();
}
}
return mapnik::datasource_cache::instance().create(params);
}
void register_datasources(std::string const& path)
{
mapnik::datasource_cache::instance().register_datasources(path);
}
std::vector<std::string> plugin_names()
{
return mapnik::datasource_cache::instance().plugin_names();
}
std::string plugin_directories()
{
return mapnik::datasource_cache::instance().plugin_directories();
}
}
void export_datasource_cache()
{
using mapnik::datasource_cache;
class_<datasource_cache,
boost::noncopyable>("DatasourceCache",no_init)
.def("create",&create_datasource)
.staticmethod("create")
.def("register_datasources",&register_datasources)
.staticmethod("register_datasources")
.def("plugin_names",&plugin_names)
.staticmethod("plugin_names")
.def("plugin_directories",&plugin_directories)
.staticmethod("plugin_directories")
;
}

View file

@ -1,88 +0,0 @@
/*****************************************************************************
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2014 Artem Pavlenko, Jean-Francois Doyon
*
* 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
*
*****************************************************************************/
#ifndef MAPNIK_PYTHON_BINDING_ENUMERATION_INCLUDED
#define MAPNIK_PYTHON_BINDING_ENUMERATION_INCLUDED
#include <boost/python/converter/registered.hpp> // for registered
#include <boost/python/enum.hpp> // for enum_
#include <boost/python/implicit.hpp> // for implicitly_convertible
#include <boost/python/to_python_converter.hpp>
namespace mapnik {
template <typename EnumWrapper>
class enumeration_ :
public boost::python::enum_<typename EnumWrapper::native_type>
{
// some short cuts
using base_type = boost::python::enum_<typename EnumWrapper::native_type>;
using native_type = typename EnumWrapper::native_type;
public:
enumeration_() :
base_type( EnumWrapper::get_name().c_str() )
{
init();
}
enumeration_(const char * python_alias) :
base_type( python_alias )
{
init();
}
enumeration_(const char * python_alias, const char * doc) :
base_type( python_alias, doc )
{
init();
}
private:
struct converter
{
static PyObject* convert(EnumWrapper const& v)
{
// Redirect conversion to a static method of our base class's
// base class. A free template converter will not work because
// the base_type::base typedef is protected.
// Lets hope MSVC agrees that this is legal C++
using namespace boost::python::converter;
return base_type::base::to_python(
registered<native_type>::converters.m_class_object
, static_cast<long>( v ));
}
};
void init() {
boost::python::implicitly_convertible<native_type, EnumWrapper>();
boost::python::to_python_converter<EnumWrapper, converter >();
for (unsigned i = 0; i < EnumWrapper::MAX; ++i)
{
// Register the strings already defined for this enum.
base_type::value( EnumWrapper::get_string( i ), native_type( i ) );
}
}
};
} // end of namespace mapnik
#endif // MAPNIK_PYTHON_BINDING_ENUMERATION_INCLUDED

View file

@ -1,45 +0,0 @@
/*****************************************************************************
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2014 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
*
*****************************************************************************/
#ifndef MAPNIK_BINDINGS_PYTHON_ENUMERATION_WRAPPPER
#define MAPNIK_BINDINGS_PYTHON_ENUMERATION_WRAPPPER
// mapnik
#include <mapnik/symbolizer.hpp>
// boost
#include <boost/python.hpp>
namespace boost { namespace python {
struct mapnik_enumeration_wrapper_to_python
{
static PyObject* convert(mapnik::enumeration_wrapper const& v)
{
return ::PyLong_FromLongLong(v.value); // FIXME: this is a temp hack!!
}
};
}}
#endif // MAPNIK_BINDINGS_PYTHON_ENUMERATION_WRAPPPER

View file

@ -1,301 +0,0 @@
/*****************************************************************************
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2014 Artem Pavlenko, Jean-Francois Doyon
*
* 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 <mapnik/config.hpp>
// boost
#include "boost_std_shared_shim.hpp"
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-parameter"
#pragma GCC diagnostic ignored "-Wunused-local-typedef"
#pragma GCC diagnostic ignored "-Wmissing-field-initializers"
#include <boost/python.hpp>
#pragma GCC diagnostic pop
// mapnik
#include <mapnik/box2d.hpp>
#include <mapnik/value_error.hpp>
using mapnik::coord;
using mapnik::box2d;
struct envelope_pickle_suite : boost::python::pickle_suite
{
static boost::python::tuple
getinitargs(const box2d<double>& e)
{
using namespace boost::python;
return boost::python::make_tuple(e.minx(),e.miny(),e.maxx(),e.maxy());
}
};
box2d<double> from_string(std::string const& s)
{
box2d<double> bbox;
bool success = bbox.from_string(s);
if (success)
{
return bbox;
}
else
{
std::stringstream ss;
ss << "Could not parse bbox from string: '" << s << "'";
throw mapnik::value_error(ss.str());
}
}
//define overloads here
void (box2d<double>::*width_p1)(double) = &box2d<double>::width;
double (box2d<double>::*width_p2)() const = &box2d<double>::width;
void (box2d<double>::*height_p1)(double) = &box2d<double>::height;
double (box2d<double>::*height_p2)() const = &box2d<double>::height;
void (box2d<double>::*expand_to_include_p1)(double,double) = &box2d<double>::expand_to_include;
void (box2d<double>::*expand_to_include_p2)(coord<double,2> const& ) = &box2d<double>::expand_to_include;
void (box2d<double>::*expand_to_include_p3)(box2d<double> const& ) = &box2d<double>::expand_to_include;
bool (box2d<double>::*contains_p1)(double,double) const = &box2d<double>::contains;
bool (box2d<double>::*contains_p2)(coord<double,2> const&) const = &box2d<double>::contains;
bool (box2d<double>::*contains_p3)(box2d<double> const&) const = &box2d<double>::contains;
//intersects
bool (box2d<double>::*intersects_p1)(double,double) const = &box2d<double>::intersects;
bool (box2d<double>::*intersects_p2)(coord<double,2> const&) const = &box2d<double>::intersects;
bool (box2d<double>::*intersects_p3)(box2d<double> const&) const = &box2d<double>::intersects;
// intersect
box2d<double> (box2d<double>::*intersect)(box2d<double> const&) const = &box2d<double>::intersect;
// re_center
void (box2d<double>::*re_center_p1)(double,double) = &box2d<double>::re_center;
void (box2d<double>::*re_center_p2)(coord<double,2> const& ) = &box2d<double>::re_center;
// clip
void (box2d<double>::*clip)(box2d<double> const&) = &box2d<double>::clip;
// pad
void (box2d<double>::*pad)(double) = &box2d<double>::pad;
// deepcopy
box2d<double> box2d_deepcopy(box2d<double> & obj, boost::python::dict const&)
{
// FIXME::ignore memo for now
box2d<double> result(obj);
return result;
}
void export_envelope()
{
using namespace boost::python;
class_<box2d<double> >("Box2d",
// class docstring is in mapnik/__init__.py, class _Coord
init<double,double,double,double>(
(arg("minx"),arg("miny"),arg("maxx"),arg("maxy")),
"Constructs a new envelope from the coordinates\n"
"of its lower left and upper right corner points.\n"))
.def(init<>("Equivalent to Box2d(0, 0, -1, -1).\n"))
.def(init<const coord<double,2>&, const coord<double,2>&>(
(arg("ll"),arg("ur")),
"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,
"X coordinate for the lower left corner")
.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,
"Y coordinate for the upper right corner")
.def("center", &box2d<double>::center,
"Returns the coordinates of the center of the bounding box.\n"
"\n"
"Example:\n"
">>> e = Box2d(0, 0, 100, 100)\n"
">>> e.center()\n"
"Coord(50, 50)\n")
.def("center", re_center_p1,
(arg("x"), arg("y")),
"Moves the envelope so that the given coordinates become its new center.\n"
"The width and the height are preserved.\n"
"\n "
"Example:\n"
">>> e = Box2d(0, 0, 100, 100)\n"
">>> e.center(60, 60)\n"
">>> e.center()\n"
"Coord(60.0,60.0)\n"
">>> (e.width(), e.height())\n"
"(100.0, 100.0)\n"
">>> e\n"
"Box2d(10.0, 10.0, 110.0, 110.0)\n"
)
.def("center", re_center_p2,
(arg("Coord")),
"Moves the envelope so that the given coordinates become its new center.\n"
"The width and the height are preserved.\n"
"\n "
"Example:\n"
">>> e = Box2d(0, 0, 100, 100)\n"
">>> e.center(Coord60, 60)\n"
">>> e.center()\n"
"Coord(60.0,60.0)\n"
">>> (e.width(), e.height())\n"
"(100.0, 100.0)\n"
">>> e\n"
"Box2d(10.0, 10.0, 110.0, 110.0)\n"
)
.def("clip", clip,
(arg("other")),
"Clip the envelope based on the bounds of another envelope.\n"
"\n "
"Example:\n"
">>> e = Box2d(0, 0, 100, 100)\n"
">>> c = Box2d(-50, -50, 50, 50)\n"
">>> e.clip(c)\n"
">>> e\n"
"Box2d(0.0,0.0,50.0,50.0\n"
)
.def("pad", pad,
(arg("padding")),
"Pad the envelope based on a padding value.\n"
"\n "
"Example:\n"
">>> e = Box2d(0, 0, 100, 100)\n"
">>> e.pad(10)\n"
">>> e\n"
"Box2d(-10.0,-10.0,110.0,110.0\n"
)
.def("width", width_p1,
(arg("new_width")),
"Sets the width to new_width of the envelope preserving its center.\n"
"\n "
"Example:\n"
">>> e = Box2d(0, 0, 100, 100)\n"
">>> e.width(120)\n"
">>> e.center()\n"
"Coord(50.0,50.0)\n"
">>> e\n"
"Box2d(-10.0, 0.0, 110.0, 100.0)\n"
)
.def("width", width_p2,
"Returns the width of this envelope.\n"
)
.def("height", height_p1,
(arg("new_height")),
"Sets the height to new_height of the envelope preserving its center.\n"
"\n "
"Example:\n"
">>> e = Box2d(0, 0, 100, 100)\n"
">>> e.height(120)\n"
">>> e.center()\n"
"Coord(50.0,50.0)\n"
">>> e\n"
"Box2d(0.0, -10.0, 100.0, 110.0)\n"
)
.def("height", height_p2,
"Returns the height of this envelope.\n"
)
.def("expand_to_include",expand_to_include_p1,
(arg("x"),arg("y")),
"Expands this envelope to include the point given by x and y.\n"
"\n"
"Example:\n",
">>> e = Box2d(0, 0, 100, 100)\n"
">>> e.expand_to_include(110, 110)\n"
">>> e\n"
"Box2d(0.0, 00.0, 110.0, 110.0)\n"
)
.def("expand_to_include",expand_to_include_p2,
(arg("p")),
"Equivalent to expand_to_include(p.x, p.y)\n"
)
.def("expand_to_include",expand_to_include_p3,
(arg("other")),
"Equivalent to:\n"
" expand_to_include(other.minx, other.miny)\n"
" expand_to_include(other.maxx, other.maxy)\n"
)
.def("contains",contains_p1,
(arg("x"),arg("y")),
"Returns True iff this envelope contains the point\n"
"given by x and y.\n"
)
.def("contains",contains_p2,
(arg("p")),
"Equivalent to contains(p.x, p.y)\n"
)
.def("contains",contains_p3,
(arg("other")),
"Equivalent to:\n"
" contains(other.minx, other.miny) and contains(other.maxx, other.maxy)\n"
)
.def("intersects",intersects_p1,
(arg("x"),arg("y")),
"Returns True iff this envelope intersects the point\n"
"given by x and y.\n"
"\n"
"Note: For points, intersection is equivalent\n"
"to containment, i.e. the following holds:\n"
" e.contains(x, y) == e.intersects(x, y)\n"
)
.def("intersects",intersects_p2,
(arg("p")),
"Equivalent to contains(p.x, p.y)\n")
.def("intersects",intersects_p3,
(arg("other")),
"Returns True iff this envelope intersects the other envelope,\n"
"This relationship is symmetric."
"\n"
"Example:\n"
">>> e1 = Box2d(0, 0, 100, 100)\n"
">>> e2 = Box2d(50, 50, 150, 150)\n"
">>> e1.intersects(e2)\n"
"True\n"
">>> e1.contains(e2)\n"
"False\n"
)
.def("intersect",intersect,
(arg("other")),
"Returns the overlap of this envelope and the other envelope\n"
"as a new envelope.\n"
"\n"
"Example:\n"
">>> 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"
)
.def(self == self) // __eq__
.def(self != self) // __neq__
.def(self + self) // __add__
.def(self * float()) // __mult__
.def(float() * self)
.def(self / float()) // __div__
.def("__getitem__",&box2d<double>::operator[])
.def("valid",&box2d<double>::valid)
.def_pickle(envelope_pickle_suite())
.def("__deepcopy__", &box2d_deepcopy)
;
}

View file

@ -1,111 +0,0 @@
/*****************************************************************************
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2014 Artem Pavlenko, Jean-Francois Doyon
*
* 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 <mapnik/config.hpp>
#include "python_to_value.hpp"
// boost
#include "boost_std_shared_shim.hpp"
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-parameter"
#pragma GCC diagnostic ignored "-Wunused-local-typedef"
#pragma GCC diagnostic ignored "-Wmissing-field-initializers"
#include <boost/python.hpp>
#include <boost/noncopyable.hpp>
#pragma GCC diagnostic pop
// mapnik
#include <mapnik/util/variant.hpp>
#include <mapnik/feature.hpp>
#include <mapnik/expression.hpp>
#include <mapnik/expression_string.hpp>
#include <mapnik/expression_evaluator.hpp>
#include <mapnik/parse_path.hpp>
#include <mapnik/value.hpp>
using mapnik::expression_ptr;
using mapnik::parse_expression;
using mapnik::to_expression_string;
using mapnik::path_expression_ptr;
// expression
expression_ptr parse_expression_(std::string const& wkt)
{
return parse_expression(wkt);
}
std::string expression_to_string_(mapnik::expr_node const& expr)
{
return mapnik::to_expression_string(expr);
}
mapnik::value expression_evaluate_(mapnik::expr_node const& expr, mapnik::feature_impl const& f, boost::python::dict const& d)
{
// will be auto-converted to proper python type by `mapnik_value_to_python`
return mapnik::util::apply_visitor(mapnik::evaluate<mapnik::feature_impl,mapnik::value,mapnik::attributes>(f,mapnik::dict2attr(d)),expr);
}
bool expression_evaluate_to_bool_(mapnik::expr_node const& expr, mapnik::feature_impl const& f, boost::python::dict const& d)
{
return mapnik::util::apply_visitor(mapnik::evaluate<mapnik::feature_impl,mapnik::value,mapnik::attributes>(f,mapnik::dict2attr(d)),expr).to_bool();
}
// path expression
path_expression_ptr parse_path_(std::string const& path)
{
return mapnik::parse_path(path);
}
std::string path_to_string_(mapnik::path_expression const& expr)
{
return mapnik::path_processor_type::to_string(expr);
}
std::string path_evaluate_(mapnik::path_expression const& expr, mapnik::feature_impl const& f)
{
return mapnik::path_processor_type::evaluate(expr, f);
}
void export_expression()
{
using namespace boost::python;
class_<mapnik::expr_node ,boost::noncopyable>("Expression",
"TODO"
"",no_init)
.def("evaluate", &expression_evaluate_,(arg("feature"),arg("variables")=boost::python::dict()))
.def("to_bool", &expression_evaluate_to_bool_,(arg("feature"),arg("variables")=boost::python::dict()))
.def("__str__",&expression_to_string_);
;
def("Expression",&parse_expression_,(arg("expr")),"Expression string");
class_<mapnik::path_expression ,boost::noncopyable>("PathExpression",
"TODO"
"",no_init)
.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,237 +0,0 @@
/*****************************************************************************
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2014 Artem Pavlenko, Jean-Francois Doyon
*
* 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 <mapnik/config.hpp>
// boost
#include "boost_std_shared_shim.hpp"
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-parameter"
#pragma GCC diagnostic ignored "-Wunused-local-typedef"
#pragma GCC diagnostic ignored "-Wmissing-field-initializers"
#include <boost/python.hpp>
#include <boost/python/iterator.hpp>
#include <boost/python/call_method.hpp>
#include <boost/python/tuple.hpp>
#include <boost/python/to_python_converter.hpp>
#include <boost/noncopyable.hpp>
#pragma GCC diagnostic pop
// mapnik
#include <mapnik/value_types.hpp>
#include <mapnik/feature.hpp>
#include <mapnik/feature_factory.hpp>
#include <mapnik/feature_kv_iterator.hpp>
#include <mapnik/datasource.hpp>
#include <mapnik/wkb.hpp>
//#include <mapnik/wkt/wkt_factory.hpp>
#include <mapnik/json/feature_parser.hpp>
#include <mapnik/json/feature_generator.hpp>
// stl
#include <stdexcept>
namespace {
using mapnik::geometry_utils;
using mapnik::context_type;
using mapnik::context_ptr;
using mapnik::feature_kv_iterator;
mapnik::feature_ptr from_geojson_impl(std::string const& json, mapnik::context_ptr const& ctx)
{
mapnik::feature_ptr feature(mapnik::feature_factory::create(ctx,1));
if (!mapnik::json::from_geojson(json,*feature))
{
throw std::runtime_error("Failed to parse geojson feature");
}
return feature;
}
std::string feature_to_geojson(mapnik::feature_impl const& feature)
{
std::string json;
if (!mapnik::json::to_geojson(json,feature))
{
throw std::runtime_error("Failed to generate GeoJSON");
}
return json;
}
mapnik::value __getitem__(mapnik::feature_impl const& feature, std::string const& name)
{
return feature.get(name);
}
mapnik::value __getitem2__(mapnik::feature_impl const& feature, std::size_t index)
{
return feature.get(index);
}
void __setitem__(mapnik::feature_impl & feature, std::string const& name, mapnik::value const& val)
{
feature.put_new(name,val);
}
boost::python::dict attributes(mapnik::feature_impl const& f)
{
boost::python::dict attributes;
feature_kv_iterator itr = f.begin();
feature_kv_iterator end = f.end();
for ( ;itr!=end; ++itr)
{
attributes[std::get<0>(*itr)] = std::get<1>(*itr);
}
return attributes;
}
} // end anonymous namespace
struct unicode_string_from_python_str
{
unicode_string_from_python_str()
{
boost::python::converter::registry::push_back(
&convertible,
&construct,
boost::python::type_id<mapnik::value_unicode_string>());
}
static void* convertible(PyObject* obj_ptr)
{
if (!(
#if PY_VERSION_HEX >= 0x03000000
PyBytes_Check(obj_ptr)
#else
PyString_Check(obj_ptr)
#endif
|| PyUnicode_Check(obj_ptr)))
return 0;
return obj_ptr;
}
static void construct(
PyObject* obj_ptr,
boost::python::converter::rvalue_from_python_stage1_data* data)
{
char * value=0;
if (PyUnicode_Check(obj_ptr)) {
PyObject *encoded = PyUnicode_AsEncodedString(obj_ptr, "utf8", "replace");
if (encoded) {
#if PY_VERSION_HEX >= 0x03000000
value = PyBytes_AsString(encoded);
#else
value = PyString_AsString(encoded);
#endif
Py_DecRef(encoded);
}
} else {
#if PY_VERSION_HEX >= 0x03000000
value = PyBytes_AsString(obj_ptr);
#else
value = PyString_AsString(obj_ptr);
#endif
}
if (value == 0) boost::python::throw_error_already_set();
void* storage = (
(boost::python::converter::rvalue_from_python_storage<mapnik::value_unicode_string>*)
data)->storage.bytes;
new (storage) mapnik::value_unicode_string(value);
data->convertible = storage;
}
};
struct value_null_from_python
{
value_null_from_python()
{
boost::python::converter::registry::push_back(
&convertible,
&construct,
boost::python::type_id<mapnik::value_null>());
}
static void* convertible(PyObject* obj_ptr)
{
if (obj_ptr == Py_None) return obj_ptr;
return 0;
}
static void construct(
PyObject* obj_ptr,
boost::python::converter::rvalue_from_python_stage1_data* data)
{
if (obj_ptr != Py_None) boost::python::throw_error_already_set();
void* storage = (
(boost::python::converter::rvalue_from_python_storage<mapnik::value_null>*)
data)->storage.bytes;
new (storage) mapnik::value_null();
data->convertible = storage;
}
};
void export_feature()
{
using namespace boost::python;
// Python to mapnik::value converters
// NOTE: order matters here. For example value_null must be listed before
// bool otherwise Py_None will be interpreted as bool (false)
implicitly_convertible<mapnik::value_unicode_string,mapnik::value>();
implicitly_convertible<mapnik::value_null,mapnik::value>();
implicitly_convertible<mapnik::value_integer,mapnik::value>();
implicitly_convertible<mapnik::value_double,mapnik::value>();
implicitly_convertible<mapnik::value_bool,mapnik::value>();
// http://misspent.wordpress.com/2009/09/27/how-to-write-boost-python-converters/
unicode_string_from_python_str();
value_null_from_python();
class_<context_type,context_ptr,boost::noncopyable>
("Context",init<>("Default ctor."))
.def("push", &context_type::push)
;
class_<mapnik::feature_impl,std::shared_ptr<mapnik::feature_impl>,
boost::noncopyable>("Feature",init<context_ptr,mapnik::value_integer>("Default ctor."))
.def("id",&mapnik::feature_impl::id)
.add_property("geometry",
make_function(&mapnik::feature_impl::get_geometry,return_value_policy<reference_existing_object>()),
&mapnik::feature_impl::set_geometry_copy)
.def("envelope", &mapnik::feature_impl::envelope)
.def("has_key", &mapnik::feature_impl::has_key)
.add_property("attributes",&attributes)
.def("__setitem__",&__setitem__)
.def("__contains__",&__getitem__)
.def("__getitem__",&__getitem__)
.def("__getitem__",&__getitem2__)
.def("__len__", &mapnik::feature_impl::size)
.def("context",&mapnik::feature_impl::context)
.def("to_geojson",&feature_to_geojson)
.def("from_geojson",from_geojson_impl)
.staticmethod("from_geojson")
;
}

View file

@ -1,93 +0,0 @@
/*****************************************************************************
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2014 Artem Pavlenko, Jean-Francois Doyon
*
* 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 <mapnik/config.hpp>
// boost
#include "boost_std_shared_shim.hpp"
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-parameter"
#pragma GCC diagnostic ignored "-Wunused-local-typedef"
#pragma GCC diagnostic ignored "-Wmissing-field-initializers"
#include <boost/python.hpp>
#include <boost/noncopyable.hpp>
#pragma GCC diagnostic pop
// mapnik
#include <mapnik/feature.hpp>
#include <mapnik/datasource.hpp>
namespace {
using namespace boost::python;
inline list features(mapnik::featureset_ptr const& itr)
{
list l;
while (true)
{
mapnik::feature_ptr fp = itr->next();
if (!fp)
{
break;
}
l.append(fp);
}
return l;
}
inline object pass_through(object const& o) { return o; }
inline mapnik::feature_ptr next(mapnik::featureset_ptr const& itr)
{
mapnik::feature_ptr f = itr->next();
if (!f)
{
PyErr_SetString(PyExc_StopIteration, "No more features.");
boost::python::throw_error_already_set();
}
return f;
}
}
void export_featureset()
{
using namespace boost::python;
class_<mapnik::Featureset,std::shared_ptr<mapnik::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"
"<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,60 +0,0 @@
/*****************************************************************************
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2014 Artem Pavlenko, Jean-Francois Doyon
*
* 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 <mapnik/config.hpp>
// boost
#include "boost_std_shared_shim.hpp"
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-parameter"
#pragma GCC diagnostic ignored "-Wunused-local-typedef"
#pragma GCC diagnostic ignored "-Wmissing-field-initializers"
#include <boost/python.hpp>
#include <boost/noncopyable.hpp>
#pragma GCC diagnostic pop
#include <mapnik/font_engine_freetype.hpp>
#include <mapnik/utils.hpp>
void export_font_engine()
{
using mapnik::freetype_engine;
using mapnik::singleton;
using mapnik::CreateStatic;
using namespace boost::python;
class_<singleton<freetype_engine,CreateStatic>,boost::noncopyable>("Singleton",no_init)
.def("instance",&singleton<freetype_engine,CreateStatic>::instance,
return_value_policy<reference_existing_object>())
.staticmethod("instance")
;
class_<freetype_engine,bases<singleton<freetype_engine,CreateStatic> >,
boost::noncopyable>("FontEngine",no_init)
.def("register_font",&freetype_engine::register_font)
.def("register_fonts",&freetype_engine::register_fonts)
.def("face_names",&freetype_engine::face_names)
.staticmethod("register_font")
.staticmethod("register_fonts")
.staticmethod("face_names")
;
}

View file

@ -1,64 +0,0 @@
/*****************************************************************************
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2014 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 <mapnik/config.hpp>
// boost
#include "boost_std_shared_shim.hpp"
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-parameter"
#pragma GCC diagnostic ignored "-Wunused-local-typedef"
#pragma GCC diagnostic ignored "-Wmissing-field-initializers"
#include <boost/python.hpp>
#pragma GCC diagnostic pop
//mapnik
#include <mapnik/font_set.hpp>
using mapnik::font_set;
void export_fontset ()
{
using namespace boost::python;
class_<font_set>("FontSet", init<std::string const&>("default fontset constructor")
)
.add_property("name",
make_function(&font_set::get_name,return_value_policy<copy_const_reference>()),
&font_set::set_name,
"Get/Set the name of the FontSet.\n"
)
.def("add_face_name",&font_set::add_face_name,
(arg("name")),
"Add a face-name to the fontset.\n"
"\n"
"Example:\n"
">>> fs = Fontset('book-fonts')\n"
">>> fs.add_face_name('DejaVu Sans Book')\n")
.add_property("names",make_function
(&font_set::get_face_names,
return_value_policy<reference_existing_object>()),
"List of face names belonging to a FontSet.\n"
)
;
}

View file

@ -1,49 +0,0 @@
/*****************************************************************************
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2014 Artem Pavlenko, Jean-Francois Doyon
*
* 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 <mapnik/config.hpp>
// boost
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-parameter"
#pragma GCC diagnostic ignored "-Wunused-local-typedef"
#pragma GCC diagnostic ignored "-Wmissing-field-initializers"
#include <boost/python.hpp>
#pragma GCC diagnostic pop
#include <mapnik/symbolizer_enumerations.hpp>
#include "mapnik_enumeration.hpp"
void export_gamma_method()
{
using namespace boost::python;
mapnik::enumeration_<mapnik::gamma_method_e>("gamma_method")
.value("POWER", mapnik::GAMMA_POWER)
.value("LINEAR",mapnik::GAMMA_LINEAR)
.value("NONE", mapnik::GAMMA_NONE)
.value("THRESHOLD", mapnik::GAMMA_THRESHOLD)
.value("MULTIPLY", mapnik::GAMMA_MULTIPLY)
;
}

View file

@ -1,296 +0,0 @@
/*****************************************************************************
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2015 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 <mapnik/config.hpp>
// boost
#include "boost_std_shared_shim.hpp"
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-parameter"
#pragma GCC diagnostic ignored "-Wunused-local-typedef"
#pragma GCC diagnostic ignored "-Wmissing-field-initializers"
#include <boost/python.hpp>
#include <boost/python/def.hpp>
#include <boost/python/exception_translator.hpp>
#include <boost/python/manage_new_object.hpp>
#include <boost/python/iterator.hpp>
#include <boost/noncopyable.hpp>
#include <boost/version.hpp>
#pragma GCC diagnostic pop
// mapnik
#include <mapnik/geometry.hpp>
#include <mapnik/geometry_type.hpp>
#include <mapnik/geometry_envelope.hpp>
#include <mapnik/geometry_is_valid.hpp>
#include <mapnik/geometry_is_simple.hpp>
#include <mapnik/geometry_is_empty.hpp>
#include <mapnik/geometry_correct.hpp>
#include <mapnik/geometry_centroid.hpp>
#include <mapnik/wkt/wkt_factory.hpp> // from_wkt
#include <mapnik/json/geometry_parser.hpp> // from_geojson
#include <mapnik/util/geometry_to_geojson.hpp> // to_geojson
#include <mapnik/util/geometry_to_wkb.hpp> // to_wkb
#include <mapnik/util/geometry_to_wkt.hpp> // to_wkt
//#include <mapnik/util/geometry_to_svg.hpp>
#include <mapnik/wkb.hpp>
// stl
#include <stdexcept>
namespace {
std::shared_ptr<mapnik::geometry::geometry<double> > from_wkb_impl(std::string const& wkb)
{
std::shared_ptr<mapnik::geometry::geometry<double> > geom = std::make_shared<mapnik::geometry::geometry<double> >();
try
{
*geom = std::move(mapnik::geometry_utils::from_wkb(wkb.c_str(), wkb.size()));
}
catch (...)
{
throw std::runtime_error("Failed to parse WKB");
}
return geom;
}
std::shared_ptr<mapnik::geometry::geometry<double> > from_wkt_impl(std::string const& wkt)
{
std::shared_ptr<mapnik::geometry::geometry<double> > geom = std::make_shared<mapnik::geometry::geometry<double> >();
if (!mapnik::from_wkt(wkt, *geom))
throw std::runtime_error("Failed to parse WKT geometry");
return geom;
}
std::shared_ptr<mapnik::geometry::geometry<double> > from_geojson_impl(std::string const& json)
{
std::shared_ptr<mapnik::geometry::geometry<double> > geom = std::make_shared<mapnik::geometry::geometry<double> >();
if (!mapnik::json::from_geojson(json, *geom))
throw std::runtime_error("Failed to parse geojson geometry");
return geom;
}
}
inline std::string boost_version()
{
std::ostringstream s;
s << BOOST_VERSION/100000 << "." << BOOST_VERSION/100 % 1000 << "." << BOOST_VERSION % 100;
return s.str();
}
PyObject* to_wkb_impl(mapnik::geometry::geometry<double> const& geom, mapnik::wkbByteOrder byte_order)
{
mapnik::util::wkb_buffer_ptr wkb = mapnik::util::to_wkb(geom,byte_order);
if (wkb)
{
return
#if PY_VERSION_HEX >= 0x03000000
::PyBytes_FromStringAndSize
#else
::PyString_FromStringAndSize
#endif
((const char*)wkb->buffer(),wkb->size());
}
else
{
Py_RETURN_NONE;
}
}
std::string to_geojson_impl(mapnik::geometry::geometry<double> const& geom)
{
std::string wkt;
if (!mapnik::util::to_geojson(wkt, geom))
{
throw std::runtime_error("Generate JSON failed");
}
return wkt;
}
std::string to_wkt_impl(mapnik::geometry::geometry<double> const& geom)
{
std::string wkt;
if (!mapnik::util::to_wkt(wkt,geom))
{
throw std::runtime_error("Generate WKT failed");
}
return wkt;
}
mapnik::geometry::geometry_types geometry_type_impl(mapnik::geometry::geometry<double> const& geom)
{
return mapnik::geometry::geometry_type(geom);
}
mapnik::box2d<double> geometry_envelope_impl(mapnik::geometry::geometry<double> const& geom)
{
return mapnik::geometry::envelope(geom);
}
// only Boost >= 1.56 has is_valid and is_simple
#if BOOST_VERSION >= 105600
bool geometry_is_valid_impl(mapnik::geometry::geometry<double> const& geom)
{
return mapnik::geometry::is_valid(geom);
}
bool geometry_is_simple_impl(mapnik::geometry::geometry<double> const& geom)
{
return mapnik::geometry::is_simple(geom);
}
#endif // BOOST_VERSION >= 1.56
bool geometry_is_empty_impl(mapnik::geometry::geometry<double> const& geom)
{
return mapnik::geometry::is_empty(geom);
}
void geometry_correct_impl(mapnik::geometry::geometry<double> & geom)
{
mapnik::geometry::correct(geom);
}
void polygon_set_exterior_impl(mapnik::geometry::polygon<double> & poly, mapnik::geometry::linear_ring<double> const& ring)
{
poly.exterior_ring = ring; // copy
}
void polygon_add_hole_impl(mapnik::geometry::polygon<double> & poly, mapnik::geometry::linear_ring<double> const& ring)
{
poly.interior_rings.push_back(ring); // copy
}
mapnik::geometry::point<double> geometry_centroid_impl(mapnik::geometry::geometry<double> const& geom)
{
mapnik::geometry::point<double> pt;
mapnik::geometry::centroid(geom, pt);
return pt;
}
void export_geometry()
{
using namespace boost::python;
implicitly_convertible<mapnik::geometry::point<double>, mapnik::geometry::geometry<double> >();
implicitly_convertible<mapnik::geometry::line_string<double>, mapnik::geometry::geometry<double> >();
implicitly_convertible<mapnik::geometry::polygon<double>, mapnik::geometry::geometry<double> >();
enum_<mapnik::geometry::geometry_types>("GeometryType")
.value("Unknown",mapnik::geometry::geometry_types::Unknown)
.value("Point",mapnik::geometry::geometry_types::Point)
.value("LineString",mapnik::geometry::geometry_types::LineString)
.value("Polygon",mapnik::geometry::geometry_types::Polygon)
.value("MultiPoint",mapnik::geometry::geometry_types::MultiPoint)
.value("MultiLineString",mapnik::geometry::geometry_types::MultiLineString)
.value("MultiPolygon",mapnik::geometry::geometry_types::MultiPolygon)
.value("GeometryCollection",mapnik::geometry::geometry_types::GeometryCollection)
;
enum_<mapnik::wkbByteOrder>("wkbByteOrder")
.value("XDR",mapnik::wkbXDR)
.value("NDR",mapnik::wkbNDR)
;
using mapnik::geometry::geometry;
using mapnik::geometry::point;
using mapnik::geometry::line_string;
using mapnik::geometry::linear_ring;
using mapnik::geometry::polygon;
class_<point<double> >("Point", init<double, double>((arg("x"), arg("y")),
"Constructs a new Point object\n"))
.add_property("x", &point<double>::x, "X coordinate")
.add_property("y", &point<double>::y, "Y coordinate")
// only Boost >= 1.56 has is_valid and is_simple
#if BOOST_VERSION >= 105600
.def("is_valid", &geometry_is_valid_impl)
.def("is_simple", &geometry_is_simple_impl)
#endif // BOOST_VERSION >= 1.56
.def("to_geojson",&to_geojson_impl)
.def("to_wkb",&to_wkb_impl)
.def("to_wkt",&to_wkt_impl)
;
class_<line_string<double> >("LineString", init<>(
"Constructs a new LineString object\n"))
.def("add_coord", &line_string<double>::add_coord, "Adds coord")
// only Boost >= 1.56 has is_valid and is_simple
#if BOOST_VERSION >= 105600
.def("is_valid", &geometry_is_valid_impl)
.def("is_simple", &geometry_is_simple_impl)
#endif // BOOST_VERSION >= 1.56
.def("to_geojson",&to_geojson_impl)
.def("to_wkb",&to_wkb_impl)
.def("to_wkt",&to_wkt_impl)
;
class_<linear_ring<double> >("LinearRing", init<>(
"Constructs a new LinearRtring object\n"))
.def("add_coord", &linear_ring<double>::add_coord, "Adds coord")
;
class_<polygon<double> >("Polygon", init<>(
"Constructs a new Polygon object\n"))
.add_property("exterior_ring", &polygon<double>::exterior_ring , "Exterior ring")
.def("add_hole", &polygon_add_hole_impl, "Add interior ring")
.def("num_rings", polygon_set_exterior_impl, "Number of rings (at least 1)")
// only Boost >= 1.56 has is_valid and is_simple
#if BOOST_VERSION >= 105600
.def("is_valid", &geometry_is_valid_impl)
.def("is_simple", &geometry_is_simple_impl)
#endif // BOOST_VERSION >= 1.56
.def("to_geojson",&to_geojson_impl)
.def("to_wkb",&to_wkb_impl)
.def("to_wkt",&to_wkt_impl)
;
class_<geometry<double>, std::shared_ptr<geometry<double> >, boost::noncopyable>("Geometry",no_init)
.def("envelope",&geometry_envelope_impl)
.def("from_geojson", from_geojson_impl)
.def("from_wkt", from_wkt_impl)
.def("from_wkb", from_wkb_impl)
.staticmethod("from_geojson")
.staticmethod("from_wkt")
.staticmethod("from_wkb")
.def("__str__",&to_wkt_impl)
.def("type",&geometry_type_impl)
// only Boost >= 1.56 has is_valid and is_simple
#if BOOST_VERSION >= 105600
.def("is_valid", &geometry_is_valid_impl)
.def("is_simple", &geometry_is_simple_impl)
#endif // BOOST_VERSION >= 1.56
.def("is_empty", &geometry_is_empty_impl)
.def("correct", &geometry_correct_impl)
.def("centroid",&geometry_centroid_impl)
.def("to_wkb",&to_wkb_impl)
.def("to_wkt",&to_wkt_impl)
.def("to_geojson",&to_geojson_impl)
//.def("to_svg",&to_svg)
// TODO add other geometry_type methods
;
}

View file

@ -1,95 +0,0 @@
/*****************************************************************************
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2014 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
*
*****************************************************************************/
#if defined(GRID_RENDERER)
#include <mapnik/config.hpp>
// boost
#include "boost_std_shared_shim.hpp"
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-parameter"
#pragma GCC diagnostic ignored "-Wunused-local-typedef"
#pragma GCC diagnostic ignored "-Wmissing-field-initializers"
#include <boost/python.hpp>
#include <boost/python/module.hpp>
#include <boost/python/def.hpp>
#pragma GCC diagnostic pop
// mapnik
#include <mapnik/grid/grid.hpp>
#include "python_grid_utils.hpp"
using namespace boost::python;
// help compiler see template definitions
static dict (*encode)( mapnik::grid const&, std::string const& , bool, unsigned int) = mapnik::grid_encode;
bool painted(mapnik::grid const& grid)
{
return grid.painted();
}
mapnik::grid::value_type get_pixel(mapnik::grid const& grid, int x, int y)
{
if (x < static_cast<int>(grid.width()) && y < static_cast<int>(grid.height()))
{
mapnik::grid::data_type const & data = grid.data();
return data(x,y);
}
PyErr_SetString(PyExc_IndexError, "invalid x,y for grid dimensions");
boost::python::throw_error_already_set();
return 0;
}
void export_grid()
{
class_<mapnik::grid,std::shared_ptr<mapnik::grid> >(
"Grid",
"This class represents a feature hitgrid.",
init<int,int,std::string>(
( boost::python::arg("width"), boost::python::arg("height"),boost::python::arg("key")="__id__"),
"Create a mapnik.Grid object\n"
))
.def("painted",&painted)
.def("width",&mapnik::grid::width)
.def("height",&mapnik::grid::height)
.def("view",&mapnik::grid::get_view)
.def("get_pixel",&get_pixel)
.def("clear",&mapnik::grid::clear)
.def("encode",encode,
( 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"
)
;
}
#endif

View file

@ -1,64 +0,0 @@
/*****************************************************************************
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2014 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
*
*****************************************************************************/
#if defined(GRID_RENDERER)
#include <mapnik/config.hpp>
// boost
#include "boost_std_shared_shim.hpp"
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-parameter"
#pragma GCC diagnostic ignored "-Wunused-local-typedef"
#pragma GCC diagnostic ignored "-Wmissing-field-initializers"
#include <boost/python.hpp>
#include <boost/python/module.hpp>
#include <boost/python/def.hpp>
#pragma GCC diagnostic pop
// mapnik
#include <string>
#include <mapnik/grid/grid_view.hpp>
#include <mapnik/grid/grid.hpp>
#include "python_grid_utils.hpp"
using namespace boost::python;
// help compiler see template definitions
static dict (*encode)( mapnik::grid_view const&, std::string const& , bool, unsigned int) = mapnik::grid_encode;
void export_grid_view()
{
class_<mapnik::grid_view,
std::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,
( boost::python::arg("encoding")="utf",boost::python::arg("add_features")=true,boost::python::arg("resolution")=4 ),
"Encode the grid as as optimized json\n"
)
;
}
#endif

View file

@ -1,471 +0,0 @@
/*****************************************************************************
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2014 Artem Pavlenko, Jean-Francois Doyon
*
* 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 <mapnik/config.hpp>
// boost
#include "boost_std_shared_shim.hpp"
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-parameter"
#pragma GCC diagnostic ignored "-Wunused-local-typedef"
#pragma GCC diagnostic ignored "-Wmissing-field-initializers"
#include <boost/python.hpp>
#include <boost/python/module.hpp>
#include <boost/python/def.hpp>
#pragma GCC diagnostic pop
// mapnik
#include <mapnik/color.hpp>
#include <mapnik/palette.hpp>
#include <mapnik/image_util.hpp>
#include <mapnik/image_copy.hpp>
#include <mapnik/image_reader.hpp>
#include <mapnik/image_compositing.hpp>
#include <mapnik/image_view_any.hpp>
// cairo
#if defined(HAVE_CAIRO) && defined(HAVE_PYCAIRO)
#include <mapnik/cairo/cairo_context.hpp>
#include <mapnik/cairo/cairo_image_util.hpp>
#include <pycairo.h>
#include <cairo.h>
#endif
using mapnik::image_any;
using mapnik::image_reader;
using mapnik::get_image_reader;
using mapnik::type_from_filename;
using mapnik::save_to_file;
using namespace boost::python;
// output 'raw' pixels
PyObject* tostring1( image_any const& im)
{
return
#if PY_VERSION_HEX >= 0x03000000
::PyBytes_FromStringAndSize
#else
::PyString_FromStringAndSize
#endif
((const char*)im.getBytes(),im.getSize());
}
// encode (png,jpeg)
PyObject* tostring2(image_any const & im, std::string const& format)
{
std::string s = mapnik::save_to_string(im, format);
return
#if PY_VERSION_HEX >= 0x03000000
::PyBytes_FromStringAndSize
#else
::PyString_FromStringAndSize
#endif
(s.data(),s.size());
}
PyObject* tostring3(image_any const & im, std::string const& format, mapnik::rgba_palette const& pal)
{
std::string s = mapnik::save_to_string(im, format, pal);
return
#if PY_VERSION_HEX >= 0x03000000
::PyBytes_FromStringAndSize
#else
::PyString_FromStringAndSize
#endif
(s.data(),s.size());
}
void save_to_file1(mapnik::image_any const& im, std::string const& filename)
{
save_to_file(im,filename);
}
void save_to_file2(mapnik::image_any const& im, std::string const& filename, std::string const& type)
{
save_to_file(im,filename,type);
}
void save_to_file3(mapnik::image_any const& im, std::string const& filename, std::string const& type, mapnik::rgba_palette const& pal)
{
save_to_file(im,filename,type,pal);
}
mapnik::image_view_any get_view(mapnik::image_any const& data,unsigned x,unsigned y, unsigned w,unsigned h)
{
return mapnik::create_view(data,x,y,w,h);
}
bool is_solid(mapnik::image_any const& im)
{
return mapnik::is_solid(im);
}
void fill_color(mapnik::image_any & im, mapnik::color const& c)
{
mapnik::fill(im, c);
}
void fill_int(mapnik::image_any & im, int val)
{
mapnik::fill(im, val);
}
void fill_double(mapnik::image_any & im, double val)
{
mapnik::fill(im, val);
}
std::shared_ptr<image_any> copy(mapnik::image_any const& im, mapnik::image_dtype type, double offset, double scaling)
{
return std::make_shared<image_any>(std::move(mapnik::image_copy(im, type, offset, scaling)));
}
unsigned compare(mapnik::image_any const& im1, mapnik::image_any const& im2, double threshold, bool alpha)
{
return mapnik::compare(im1, im2, threshold, alpha);
}
struct get_pixel_visitor
{
get_pixel_visitor(unsigned x, unsigned y)
: x_(x), y_(y) {}
object operator() (mapnik::image_null const&)
{
throw std::runtime_error("Can not return a null image from a pixel (shouldn't have reached here)");
}
template <typename T>
object operator() (T const& im)
{
using pixel_type = typename T::pixel_type;
return object(mapnik::get_pixel<pixel_type>(im, x_, y_));
}
private:
unsigned x_;
unsigned y_;
};
object get_pixel(mapnik::image_any const& im, unsigned x, unsigned y, bool get_color)
{
if (x < static_cast<unsigned>(im.width()) && y < static_cast<unsigned>(im.height()))
{
if (get_color)
{
return object(
mapnik::get_pixel<mapnik::color>(im, x, y)
);
}
else
{
return mapnik::util::apply_visitor(get_pixel_visitor(x, y), im);
}
}
PyErr_SetString(PyExc_IndexError, "invalid x,y for image dimensions");
boost::python::throw_error_already_set();
return object();
}
void set_pixel_color(mapnik::image_any & im, unsigned x, unsigned y, mapnik::color const& c)
{
if (x >= static_cast<int>(im.width()) && y >= static_cast<int>(im.height()))
{
PyErr_SetString(PyExc_IndexError, "invalid x,y for image dimensions");
boost::python::throw_error_already_set();
return;
}
mapnik::set_pixel(im, x, y, c);
}
void set_pixel_double(mapnik::image_any & im, unsigned x, unsigned y, double val)
{
if (x >= static_cast<int>(im.width()) && y >= static_cast<int>(im.height()))
{
PyErr_SetString(PyExc_IndexError, "invalid x,y for image dimensions");
boost::python::throw_error_already_set();
return;
}
mapnik::set_pixel(im, x, y, val);
}
void set_pixel_int(mapnik::image_any & im, unsigned x, unsigned y, int val)
{
if (x >= static_cast<int>(im.width()) && y >= static_cast<int>(im.height()))
{
PyErr_SetString(PyExc_IndexError, "invalid x,y for image dimensions");
boost::python::throw_error_already_set();
return;
}
mapnik::set_pixel(im, x, y, val);
}
unsigned get_type(mapnik::image_any & im)
{
return im.get_dtype();
}
std::shared_ptr<image_any> open_from_file(std::string const& filename)
{
boost::optional<std::string> type = type_from_filename(filename);
if (type)
{
std::unique_ptr<image_reader> reader(get_image_reader(filename,*type));
if (reader.get())
{
return std::make_shared<image_any>(std::move(reader->read(0,0,reader->width(),reader->height())));
}
throw mapnik::image_reader_exception("Failed to load: " + filename);
}
throw mapnik::image_reader_exception("Unsupported image format:" + filename);
}
std::shared_ptr<image_any> fromstring(std::string const& str)
{
std::unique_ptr<image_reader> reader(get_image_reader(str.c_str(),str.size()));
if (reader.get())
{
return std::make_shared<image_any>(std::move(reader->read(0,0,reader->width(), reader->height())));
}
throw mapnik::image_reader_exception("Failed to load image from buffer" );
}
std::shared_ptr<image_any> frombuffer(PyObject * obj)
{
void const* buffer=0;
Py_ssize_t buffer_len;
if (PyObject_AsReadBuffer(obj, &buffer, &buffer_len) == 0)
{
std::unique_ptr<image_reader> reader(get_image_reader(reinterpret_cast<char const*>(buffer),buffer_len));
if (reader.get())
{
return std::make_shared<image_any>(reader->read(0,0,reader->width(),reader->height()));
}
}
throw mapnik::image_reader_exception("Failed to load image from buffer" );
}
void set_grayscale_to_alpha(image_any & im)
{
mapnik::set_grayscale_to_alpha(im);
}
void set_grayscale_to_alpha_c(image_any & im, mapnik::color const& c)
{
mapnik::set_grayscale_to_alpha(im, c);
}
void set_color_to_alpha(image_any & im, mapnik::color const& c)
{
mapnik::set_color_to_alpha(im, c);
}
void set_alpha(image_any & im, float opacity)
{
mapnik::set_alpha(im, opacity);
}
bool premultiplied(image_any &im)
{
return im.get_premultiplied();
}
bool premultiply(image_any & im)
{
return mapnik::premultiply_alpha(im);
}
bool demultiply(image_any & im)
{
return mapnik::demultiply_alpha(im);
}
void clear(image_any & im)
{
mapnik::fill(im, 0);
}
void composite(image_any & dst, image_any & src, mapnik::composite_mode_e mode, float opacity, int dx, int dy)
{
bool demultiply_dst = mapnik::premultiply_alpha(dst);
bool demultiply_src = mapnik::premultiply_alpha(src);
mapnik::composite(dst,src,mode,opacity,dx,dy);
if (demultiply_dst)
{
mapnik::demultiply_alpha(dst);
}
if (demultiply_src)
{
mapnik::demultiply_alpha(src);
}
}
#if defined(HAVE_CAIRO) && defined(HAVE_PYCAIRO)
std::shared_ptr<image_any> from_cairo(PycairoSurface* py_surface)
{
mapnik::cairo_surface_ptr surface(cairo_surface_reference(py_surface->surface), mapnik::cairo_surface_closer());
mapnik::image_rgba8 image = mapnik::image_rgba8(cairo_image_surface_get_width(&*surface), cairo_image_surface_get_height(&*surface));
cairo_image_to_rgba8(image, surface);
return std::make_shared<image_any>(std::move(image));
}
#endif
void export_image()
{
using namespace boost::python;
// NOTE: must match list in include/mapnik/image_compositing.hpp
enum_<mapnik::composite_mode_e>("CompositeOp")
.value("clear", mapnik::clear)
.value("src", mapnik::src)
.value("dst", mapnik::dst)
.value("src_over", mapnik::src_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)
.value("dst_out", mapnik::dst_out)
.value("src_atop", mapnik::src_atop)
.value("dst_atop", mapnik::dst_atop)
.value("xor", mapnik::_xor)
.value("plus", mapnik::plus)
.value("minus", mapnik::minus)
.value("multiply", mapnik::multiply)
.value("screen", mapnik::screen)
.value("overlay", mapnik::overlay)
.value("darken", mapnik::darken)
.value("lighten", mapnik::lighten)
.value("color_dodge", mapnik::color_dodge)
.value("color_burn", mapnik::color_burn)
.value("hard_light", mapnik::hard_light)
.value("soft_light", mapnik::soft_light)
.value("difference", mapnik::difference)
.value("exclusion", mapnik::exclusion)
.value("contrast", mapnik::contrast)
.value("invert", mapnik::invert)
.value("grain_merge", mapnik::grain_merge)
.value("grain_extract", mapnik::grain_extract)
.value("hue", mapnik::hue)
.value("saturation", mapnik::saturation)
.value("color", mapnik::_color)
.value("value", mapnik::_value)
.value("linear_dodge", mapnik::linear_dodge)
.value("linear_burn", mapnik::linear_burn)
.value("divide", mapnik::divide)
;
enum_<mapnik::image_dtype>("ImageType")
.value("rgba8", mapnik::image_dtype_rgba8)
.value("gray8", mapnik::image_dtype_gray8)
.value("gray8s", mapnik::image_dtype_gray8s)
.value("gray16", mapnik::image_dtype_gray16)
.value("gray16s", mapnik::image_dtype_gray16s)
.value("gray32", mapnik::image_dtype_gray32)
.value("gray32s", mapnik::image_dtype_gray32s)
.value("gray32f", mapnik::image_dtype_gray32f)
.value("gray64", mapnik::image_dtype_gray64)
.value("gray64s", mapnik::image_dtype_gray64s)
.value("gray64f", mapnik::image_dtype_gray64f)
;
class_<image_any,std::shared_ptr<image_any>, boost::noncopyable >("Image","This class represents a image.",init<int,int>())
.def(init<int,int,mapnik::image_dtype>())
.def(init<int,int,mapnik::image_dtype,bool>())
.def(init<int,int,mapnik::image_dtype,bool,bool>())
.def(init<int,int,mapnik::image_dtype,bool,bool,bool>())
.def("width",&image_any::width)
.def("height",&image_any::height)
.def("view",&get_view)
.def("painted",&image_any::painted)
.def("is_solid",&is_solid)
.def("fill",&fill_color)
.def("fill",&fill_int)
.def("fill",&fill_double)
.def("set_grayscale_to_alpha",&set_grayscale_to_alpha, "Set the grayscale values to the alpha channel of the Image")
.def("set_grayscale_to_alpha",&set_grayscale_to_alpha_c, "Set the grayscale values to the alpha channel of the Image")
.def("set_color_to_alpha",&set_color_to_alpha, "Set a given color to the alpha channel of the Image")
.def("set_alpha",&set_alpha, "Set the overall alpha channel of the Image")
.def("composite",&composite,
( arg("self"),
arg("image"),
arg("mode")=mapnik::src_over,
arg("opacity")=1.0f,
arg("dx")=0,
arg("dy")=0
))
.def("compare",&compare,
( arg("self"),
arg("image"),
arg("threshold")=0.0,
arg("alpha")=true
))
.def("copy",&copy,
( arg("self"),
arg("type"),
arg("offset")=0.0,
arg("scaling")=1.0
))
.add_property("offset",
&image_any::get_offset,
&image_any::set_offset,
"Gets or sets the offset component.\n")
.add_property("scaling",
&image_any::get_scaling,
&image_any::set_scaling,
"Gets or sets the offset component.\n")
.def("premultiplied",&premultiplied)
.def("premultiply",&premultiply)
.def("demultiply",&demultiply)
.def("set_pixel",&set_pixel_color)
.def("set_pixel",&set_pixel_double)
.def("set_pixel",&set_pixel_int)
.def("get_pixel",&get_pixel,
( arg("self"),
arg("x"),
arg("y"),
arg("get_color")=false
))
.def("get_type",&get_type)
.def("clear",&clear)
//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)
.def("save", &save_to_file1)
.def("save", &save_to_file2)
.def("save", &save_to_file3)
.def("open",open_from_file)
.staticmethod("open")
.def("frombuffer",&frombuffer)
.staticmethod("frombuffer")
.def("fromstring",&fromstring)
.staticmethod("fromstring")
#if defined(HAVE_CAIRO) && defined(HAVE_PYCAIRO)
.def("from_cairo",&from_cairo)
.staticmethod("from_cairo")
#endif
;
}

View file

@ -1,128 +0,0 @@
/*****************************************************************************
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2014 Artem Pavlenko, Jean-Francois Doyon
*
* 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 <mapnik/config.hpp>
// boost
#include "boost_std_shared_shim.hpp"
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-parameter"
#pragma GCC diagnostic ignored "-Wunused-local-typedef"
#pragma GCC diagnostic ignored "-Wmissing-field-initializers"
#include <boost/python.hpp>
#include <boost/python/module.hpp>
#include <boost/python/def.hpp>
#pragma GCC diagnostic pop
// mapnik
#include <mapnik/image.hpp>
#include <mapnik/image_view.hpp>
#include <mapnik/image_view_any.hpp>
#include <mapnik/image_util.hpp>
#include <mapnik/palette.hpp>
#include <sstream>
using mapnik::image_view_any;
using mapnik::save_to_file;
// output 'raw' pixels
PyObject* view_tostring1(image_view_any const& view)
{
std::ostringstream ss(std::ios::out|std::ios::binary);
mapnik::view_to_string(view, ss);
return
#if PY_VERSION_HEX >= 0x03000000
::PyBytes_FromStringAndSize
#else
::PyString_FromStringAndSize
#endif
((const char*)ss.str().c_str(),ss.str().size());
}
// encode (png,jpeg)
PyObject* view_tostring2(image_view_any const & view, std::string const& format)
{
std::string s = save_to_string(view, format);
return
#if PY_VERSION_HEX >= 0x03000000
::PyBytes_FromStringAndSize
#else
::PyString_FromStringAndSize
#endif
(s.data(),s.size());
}
PyObject* view_tostring3(image_view_any const & view, std::string const& format, mapnik::rgba_palette const& pal)
{
std::string s = save_to_string(view, format, pal);
return
#if PY_VERSION_HEX >= 0x03000000
::PyBytes_FromStringAndSize
#else
::PyString_FromStringAndSize
#endif
(s.data(),s.size());
}
bool is_solid(image_view_any const& view)
{
return mapnik::is_solid(view);
}
void save_view1(image_view_any const& view,
std::string const& filename)
{
save_to_file(view,filename);
}
void save_view2(image_view_any const& view,
std::string const& filename,
std::string const& type)
{
save_to_file(view,filename,type);
}
void save_view3(image_view_any const& view,
std::string const& filename,
std::string const& type,
mapnik::rgba_palette const& pal)
{
save_to_file(view,filename,type,pal);
}
void export_image_view()
{
using namespace boost::python;
class_<image_view_any>("ImageView","A view into an image.",no_init)
.def("width",&image_view_any::width)
.def("height",&image_view_any::height)
.def("is_solid",&is_solid)
.def("tostring",&view_tostring1)
.def("tostring",&view_tostring2)
.def("tostring",&view_tostring3)
.def("save",&save_view1)
.def("save",&save_view2)
.def("save",&save_view3)
;
}

View file

@ -1,131 +0,0 @@
/*****************************************************************************
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2014 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 <mapnik/config.hpp>
// boost
#include "boost_std_shared_shim.hpp"
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-parameter"
#pragma GCC diagnostic ignored "-Wunused-local-typedef"
#pragma GCC diagnostic ignored "-Wmissing-field-initializers"
#include <boost/python.hpp>
#include <boost/python/module.hpp>
#include <boost/python/def.hpp>
#pragma GCC diagnostic pop
#include <mapnik/label_collision_detector.hpp>
#include <mapnik/map.hpp>
#include <list>
using mapnik::label_collision_detector4;
using mapnik::box2d;
using mapnik::Map;
namespace
{
std::shared_ptr<label_collision_detector4>
create_label_collision_detector_from_extent(box2d<double> const &extent)
{
return std::make_shared<label_collision_detector4>(extent);
}
std::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 std::make_shared<label_collision_detector4>(extent);
}
boost::python::list
make_label_boxes(std::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, std::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,388 +0,0 @@
/*****************************************************************************
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2014 Artem Pavlenko, Jean-Francois Doyon
*
* 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 <mapnik/config.hpp>
// boost
#include "boost_std_shared_shim.hpp"
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-parameter"
#pragma GCC diagnostic ignored "-Wunused-local-typedef"
#pragma GCC diagnostic ignored "-Wmissing-field-initializers"
#include <boost/python.hpp>
#include <boost/python/suite/indexing/vector_indexing_suite.hpp>
#pragma GCC diagnostic pop
// mapnik
#include <mapnik/layer.hpp>
#include <mapnik/datasource.hpp>
#include <mapnik/datasource_cache.hpp>
using mapnik::layer;
using mapnik::parameters;
using mapnik::datasource_cache;
struct layer_pickle_suite : boost::python::pickle_suite
{
static boost::python::tuple
getinitargs(const layer& l)
{
return boost::python::make_tuple(l.name(),l.srs());
}
static boost::python::tuple
getstate(const layer& l)
{
boost::python::list s;
std::vector<std::string> const& style_names = l.styles();
for (unsigned i = 0; i < style_names.size(); ++i)
{
s.append(style_names[i]);
}
return boost::python::make_tuple(l.clear_label_cache(),l.min_zoom(),l.max_zoom(),l.queryable(),l.datasource()->params(),l.cache_features(),s);
}
static void
setstate (layer& l, boost::python::tuple state)
{
using namespace boost::python;
if (len(state) != 9)
{
PyErr_SetObject(PyExc_ValueError,
("expected 9-item tuple in call to __setstate__; got %s"
% state).ptr()
);
throw_error_already_set();
}
l.set_clear_label_cache(extract<bool>(state[0]));
l.set_min_zoom(extract<double>(state[1]));
l.set_max_zoom(extract<double>(state[2]));
l.set_queryable(extract<bool>(state[3]));
mapnik::parameters params = extract<parameters>(state[4]);
l.set_datasource(datasource_cache::instance().create(params));
boost::python::list s = extract<boost::python::list>(state[5]);
for (int i=0;i<len(s);++i)
{
l.add_style(extract<std::string>(s[i]));
}
l.set_cache_features(extract<bool>(state[6]));
}
};
std::vector<std::string> & (mapnik::layer::*_styles_)() = &mapnik::layer::styles;
void set_maximum_extent(mapnik::layer & l, boost::optional<mapnik::box2d<double> > const& box)
{
if (box)
{
l.set_maximum_extent(*box);
}
else
{
l.reset_maximum_extent();
}
}
void set_buffer_size(mapnik::layer & l, boost::optional<int> const& buffer_size)
{
if (buffer_size)
{
l.set_buffer_size(*buffer_size);
}
else
{
l.reset_buffer_size();
}
}
PyObject * get_buffer_size(mapnik::layer & l)
{
boost::optional<int> buffer_size = l.buffer_size();
if (buffer_size)
{
#if PY_VERSION_HEX >= 0x03000000
return PyLong_FromLong(*buffer_size);
#else
return PyInt_FromLong(*buffer_size);
#endif
}
else
{
Py_RETURN_NONE;
}
}
void export_layer()
{
using namespace boost::python;
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"
"The srs can be either a Proj.4 epsg code ('+init=epsg:<code>') or\n"
"of a Proj.4 literal ('+proj=<literal>').\n"
"If no srs is specified it will default to '+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs'\n"
"\n"
"Usage:\n"
">>> from mapnik import Layer\n"
">>> lyr = Layer('My Layer','+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs')\n"
">>> lyr\n"
"<mapnik._mapnik.Layer object at 0x6a270>\n"
))
.def_pickle(layer_pickle_suite())
.def("envelope",&layer::envelope,
"Return the geographic envelope/bounding box."
"\n"
"Determined based on the layer datasource.\n"
"\n"
"Usage:\n"
">>> from mapnik import Layer\n"
">>> lyr = Layer('My Layer','+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs')\n"
">>> lyr.envelope()\n"
"box2d(-1.0,-1.0,0.0,0.0) # default until a datasource is loaded\n"
)
.def("visible", &layer::visible,
"Return True if this layer's data is active and visible at a given scale.\n"
"\n"
"Otherwise returns False.\n"
"Accepts a scale value as an integer or float input.\n"
"Will return False if:\n"
"\tscale >= minzoom - 1e-6\n"
"\tor:\n"
"\tscale < maxzoom + 1e-6\n"
"\n"
"Usage:\n"
">>> from mapnik import Layer\n"
">>> lyr = Layer('My Layer','+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs')\n"
">>> lyr.visible(1.0/1000000)\n"
"True\n"
">>> lyr.active = False\n"
">>> lyr.visible(1.0/1000000)\n"
"False\n"
)
.add_property("active",
&layer::active,
&layer::set_active,
"Get/Set whether this layer is active and will be rendered (same as status property).\n"
"\n"
"Usage:\n"
">>> from mapnik import Layer\n"
">>> lyr = Layer('My Layer','+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs')\n"
">>> lyr.active\n"
"True # Active by default\n"
">>> lyr.active = False # set False to disable layer rendering\n"
">>> lyr.active\n"
"False\n"
)
.add_property("status",
&layer::active,
&layer::set_active,
"Get/Set whether this layer is active and will be rendered.\n"
"\n"
"Usage:\n"
">>> from mapnik import Layer\n"
">>> lyr = Layer('My Layer','+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs')\n"
">>> lyr.status\n"
"True # Active by default\n"
">>> lyr.status = False # set False to disable layer rendering\n"
">>> lyr.status\n"
"False\n"
)
.add_property("clear_label_cache",
&layer::clear_label_cache,
&layer::set_clear_label_cache,
"Get/Set whether to clear the label collision detector cache for this layer during rendering\n"
"\n"
"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"
)
.add_property("cache_features",
&layer::cache_features,
&layer::set_cache_features,
"Get/Set whether features should be cached during rendering if used between multiple styles\n"
"\n"
"Usage:\n"
">>> lyr.cache_features\n"
"False # False by default\n"
">>> lyr.cache_features = True # set to True to enable feature caching\n"
)
.add_property("datasource",
&layer::datasource,
&layer::set_datasource,
"The datasource attached to this layer.\n"
"\n"
"Usage:\n"
">>> from mapnik import Layer, Datasource\n"
">>> lyr = Layer('My Layer','+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs')\n"
">>> lyr.datasource = Datasource(type='shape',file='world_borders')\n"
">>> lyr.datasource\n"
"<mapnik.Datasource object at 0x65470>\n"
)
.add_property("buffer_size",
&get_buffer_size,
&set_buffer_size,
"Get/Set the size of buffer around layer in pixels.\n"
"\n"
"Usage:\n"
">>> print(l.buffer_size)\n"
"None # None by default\n"
">>> l.buffer_size = 2\n"
">>> l.buffer_size\n"
"2\n"
)
.add_property("maximum_extent",make_function
(&layer::maximum_extent,return_value_policy<copy_const_reference>()),
&set_maximum_extent,
"The maximum extent of the map.\n"
"\n"
"Usage:\n"
">>> m.maximum_extent = Box2d(-180,-90,180,90)\n"
)
.add_property("maxzoom",
&layer::max_zoom,
&layer::set_max_zoom,
"Get/Set the maximum zoom lever of the layer.\n"
"\n"
"Usage:\n"
">>> from mapnik import Layer\n"
">>> lyr = Layer('My Layer','+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs')\n"
">>> lyr.maxzoom\n"
"1.7976931348623157e+308 # default is the numerical maximum\n"
">>> lyr.maxzoom = 1.0/1000000\n"
">>> lyr.maxzoom\n"
"9.9999999999999995e-07\n"
)
.add_property("minzoom",
&layer::min_zoom,
&layer::set_min_zoom,
"Get/Set the minimum zoom lever of the layer.\n"
"\n"
"Usage:\n"
">>> from mapnik import Layer\n"
">>> lyr = Layer('My Layer','+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs')\n"
">>> lyr.minzoom # default is 0\n"
"0.0\n"
">>> lyr.minzoom = 1.0/1000000\n"
">>> lyr.minzoom\n"
"9.9999999999999995e-07\n"
)
.add_property("name",
make_function(&layer::name, return_value_policy<copy_const_reference>()),
&layer::set_name,
"Get/Set the name of the layer.\n"
"\n"
"Usage:\n"
">>> from mapnik import Layer\n"
">>> lyr = Layer('My Layer','+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs')\n"
">>> lyr.name\n"
"'My Layer'\n"
">>> lyr.name = 'New Name'\n"
">>> lyr.name\n"
"'New Name'\n"
)
.add_property("queryable",
&layer::queryable,
&layer::set_queryable,
"Get/Set whether this layer is queryable.\n"
"\n"
"Usage:\n"
">>> from mapnik import layer\n"
">>> lyr = layer('My layer','+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs')\n"
">>> lyr.queryable\n"
"False # Not queryable by default\n"
">>> lyr.queryable = True\n"
">>> lyr.queryable\n"
"True\n"
)
.add_property("srs",
make_function(&layer::srs,return_value_policy<copy_const_reference>()),
&layer::set_srs,
"Get/Set the SRS of the layer.\n"
"\n"
"Usage:\n"
">>> from mapnik import layer\n"
">>> lyr = layer('My layer','+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs')\n"
">>> lyr.srs\n"
"'+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs' # The default srs if not initialized with custom srs\n"
">>> # set to google mercator with Proj.4 literal\n"
"... \n"
">>> lyr.srs = '+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0.0 +k=1.0 +units=m +nadgrids=@null +wktext +no_defs +over'\n"
)
.add_property("group_by",
make_function(&layer::group_by,return_value_policy<copy_const_reference>()),
&layer::set_group_by,
"Get/Set the optional layer group name.\n"
"\n"
"More details at https://github.com/mapnik/mapnik/wiki/Grouped-rendering:\n"
)
.add_property("styles",
make_function(_styles_,return_value_policy<reference_existing_object>()),
"The styles list attached to this layer.\n"
"\n"
"Usage:\n"
">>> from mapnik import layer\n"
">>> lyr = layer('My layer','+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs')\n"
">>> lyr.styles\n"
"<mapnik._mapnik.Names object at 0x6d3e8>\n"
">>> len(lyr.styles)\n"
"0\n # no styles until you append them\n"
"lyr.styles.append('My Style') # mapnik uses named styles for flexibility\n"
">>> len(lyr.styles)\n"
"1\n"
">>> lyr.styles[0]\n"
"'My Style'\n"
)
// comparison
.def(self == self)
;
}

View file

@ -1,83 +0,0 @@
/*****************************************************************************
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2014 Artem Pavlenko, Jean-Francois Doyon
*
* 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 <mapnik/config.hpp>
// boost
#include "boost_std_shared_shim.hpp"
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-parameter"
#pragma GCC diagnostic ignored "-Wunused-local-typedef"
#pragma GCC diagnostic ignored "-Wmissing-field-initializers"
#include <boost/python.hpp>
#include <boost/noncopyable.hpp>
#pragma GCC diagnostic pop
#include <mapnik/debug.hpp>
#include <mapnik/utils.hpp>
#include "mapnik_enumeration.hpp"
void export_logger()
{
using mapnik::logger;
using mapnik::singleton;
using mapnik::CreateStatic;
using namespace boost::python;
class_<singleton<logger,CreateStatic>,boost::noncopyable>("Singleton",no_init)
.def("instance",&singleton<logger,CreateStatic>::instance,
return_value_policy<reference_existing_object>())
.staticmethod("instance")
;
enum_<mapnik::logger::severity_type>("severity_type")
.value("Debug", logger::debug)
.value("Warn", logger::warn)
.value("Error", logger::error)
.value("None", logger::none)
;
class_<logger,bases<singleton<logger,CreateStatic> >,
boost::noncopyable>("logger",no_init)
.def("get_severity", &logger::get_severity)
.def("set_severity", &logger::set_severity)
.def("get_object_severity", &logger::get_object_severity)
.def("set_object_severity", &logger::set_object_severity)
.def("clear_object_severity", &logger::clear_object_severity)
.def("get_format", &logger::get_format)
.def("set_format", &logger::set_format)
.def("str", &logger::str)
.def("use_file", &logger::use_file)
.def("use_console", &logger::use_console)
.staticmethod("get_severity")
.staticmethod("set_severity")
.staticmethod("get_object_severity")
.staticmethod("set_object_severity")
.staticmethod("clear_object_severity")
.staticmethod("get_format")
.staticmethod("set_format")
.staticmethod("str")
.staticmethod("use_file")
.staticmethod("use_console")
;
}

View file

@ -1,543 +0,0 @@
/*****************************************************************************
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2014 Artem Pavlenko, Jean-Francois Doyon
*
* 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 <mapnik/config.hpp>
// boost
#include "boost_std_shared_shim.hpp"
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-parameter"
#pragma GCC diagnostic ignored "-Wunused-local-typedef"
#pragma GCC diagnostic ignored "-Wmissing-field-initializers"
#include <boost/python.hpp>
#include <boost/noncopyable.hpp>
#include <boost/python/suite/indexing/vector_indexing_suite.hpp>
#include <boost/python/iterator.hpp>
#include <boost/iterator/transform_iterator.hpp>
#pragma GCC diagnostic pop
// mapnik
#include <mapnik/rule.hpp>
#include <mapnik/layer.hpp>
#include <mapnik/map.hpp>
#include <mapnik/projection.hpp>
#include <mapnik/view_transform.hpp>
#include <mapnik/feature_type_style.hpp>
#include "mapnik_enumeration.hpp"
using mapnik::color;
using mapnik::coord;
using mapnik::box2d;
using mapnik::layer;
using mapnik::Map;
std::vector<layer>& (Map::*layers_nonconst)() = &Map::layers;
std::vector<layer> const& (Map::*layers_const)() const = &Map::layers;
mapnik::parameters& (Map::*params_nonconst)() = &Map::get_extra_parameters;
void insert_style(mapnik::Map & m, std::string const& name, mapnik::feature_type_style const& style)
{
m.insert_style(name,style);
}
void insert_fontset(mapnik::Map & m, std::string const& name, mapnik::font_set const& fontset)
{
m.insert_fontset(name,fontset);
}
mapnik::feature_type_style find_style(mapnik::Map const& m, std::string const& name)
{
boost::optional<mapnik::feature_type_style const&> style = m.find_style(name);
if (!style)
{
PyErr_SetString(PyExc_KeyError, "Invalid style name");
boost::python::throw_error_already_set();
}
return *style;
}
mapnik::font_set find_fontset(mapnik::Map const& m, std::string const& name)
{
boost::optional<mapnik::font_set const&> fontset = m.find_fontset(name);
if (!fontset)
{
PyErr_SetString(PyExc_KeyError, "Invalid font_set name");
boost::python::throw_error_already_set();
}
return *fontset;
}
// TODO - we likely should allow indexing by negative number from python
// for now, protect against negative values and kindly throw
mapnik::featureset_ptr query_point(mapnik::Map const& m, int index, double x, double y)
{
if (index < 0){
PyErr_SetString(PyExc_IndexError, "Please provide a layer index >= 0");
boost::python::throw_error_already_set();
}
unsigned idx = index;
return m.query_point(idx, x, y);
}
mapnik::featureset_ptr query_map_point(mapnik::Map const& m, int index, double x, double y)
{
if (index < 0){
PyErr_SetString(PyExc_IndexError, "Please provide a layer index >= 0");
boost::python::throw_error_already_set();
}
unsigned idx = index;
return m.query_map_point(idx, x, y);
}
void set_maximum_extent(mapnik::Map & m, boost::optional<mapnik::box2d<double> > const& box)
{
if (box)
{
m.set_maximum_extent(*box);
}
else
{
m.reset_maximum_extent();
}
}
struct extract_style
{
using result_type = boost::python::tuple;
result_type operator() (std::map<std::string, mapnik::feature_type_style>::value_type const& val) const
{
return boost::python::make_tuple(val.first,val.second);
}
};
using style_extract_iterator = boost::transform_iterator<extract_style, Map::const_style_iterator>;
using style_range = std::pair<style_extract_iterator,style_extract_iterator>;
style_range _styles_ (mapnik::Map const& m)
{
return style_range(
boost::make_transform_iterator<extract_style>(m.begin_styles(), extract_style()),
boost::make_transform_iterator<extract_style>(m.end_styles(), extract_style()));
}
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)
.value("GROW_CANVAS",mapnik::Map::GROW_CANVAS)
.value("SHRINK_BBOX",mapnik::Map::SHRINK_BBOX)
.value("SHRINK_CANVAS",mapnik::Map::SHRINK_CANVAS)
.value("ADJUST_BBOX_WIDTH",mapnik::Map::ADJUST_BBOX_WIDTH)
.value("ADJUST_BBOX_HEIGHT",mapnik::Map::ADJUST_BBOX_HEIGHT)
.value("ADJUST_CANVAS_WIDTH",mapnik::Map::ADJUST_CANVAS_WIDTH)
.value("ADJUST_CANVAS_HEIGHT", mapnik::Map::ADJUST_CANVAS_HEIGHT)
.value("RESPECT", mapnik::Map::RESPECT)
;
class_<std::vector<layer> >("Layers")
.def(vector_indexing_suite<std::vector<layer> >())
;
class_<style_range>("StyleRange")
.def("__iter__",
boost::python::range(&style_range::first, &style_range::second))
;
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"
"an srs string either with a Proj.4 epsg code ('+init=epsg:<code>')\n"
"or with a Proj.4 literal ('+proj=<literal>').\n"
"If no srs is specified the map will default to '+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs'\n"
"\n"
"Usage:\n"
">>> from mapnik import Map\n"
">>> m = Map(600,400)\n"
">>> m\n"
"<mapnik._mapnik.Map object at 0x6a240>\n"
">>> m.srs\n"
"'+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs'\n"
))
.def("append_style",insert_style,
(arg("style_name"),arg("style_object")),
"Insert a Mapnik Style onto the map by appending it.\n"
"\n"
"Usage:\n"
">>> sty\n"
"<mapnik._mapnik.Style object at 0x6a330>\n"
">>> m.append_style('Style Name', sty)\n"
"True # style object added to map by name\n"
">>> m.append_style('Style Name', sty)\n"
"False # you can only append styles with unique names\n"
)
.def("append_fontset",insert_fontset,
(arg("fontset")),
"Add a FontSet to the map."
)
.def("buffered_envelope",
&Map::get_buffered_extent,
"Get the Box2d() of the Map given\n"
"the Map.buffer_size.\n"
"\n"
"Usage:\n"
">>> m = Map(600,400)\n"
">>> m.envelope()\n"
"Box2d(-1.0,-1.0,0.0,0.0)\n"
">>> m.buffered_envelope()\n"
"Box2d(-1.0,-1.0,0.0,0.0)\n"
">>> m.buffer_size = 1\n"
">>> m.buffered_envelope()\n"
"Box2d(-1.02222222222,-1.02222222222,0.0222222222222,0.0222222222222)\n"
)
.def("envelope",
make_function(&Map::get_current_extent,
return_value_policy<copy_const_reference>()),
"Return the Map Box2d object\n"
"and print the string representation\n"
"of the current extent of the map.\n"
"\n"
"Usage:\n"
">>> m.envelope()\n"
"Box2d(-0.185833333333,-0.96,0.189166666667,-0.71)\n"
">>> dir(m.envelope())\n"
"...'center', 'contains', 'expand_to_include', 'forward',\n"
"...'height', 'intersect', 'intersects', 'inverse', 'maxx',\n"
"...'maxy', 'minx', 'miny', 'width'\n"
)
.def("find_fontset",find_fontset,
(arg("name")),
"Find a fontset by name."
)
.def("find_style",
find_style,
(arg("name")),
"Query the Map for a style by name and return\n"
"a style object if found or raise KeyError\n"
"style if not found.\n"
"\n"
"Usage:\n"
">>> m.find_style('Style Name')\n"
"<mapnik._mapnik.Style object at 0x654f0>\n"
)
.add_property("styles", _styles_)
.def("pan",&Map::pan,
(arg("x"),arg("y")),
"Set the Map center at a given x,y location\n"
"as integers in the coordinates of the pixmap or map surface.\n"
"\n"
"Usage:\n"
">>> m = Map(600,400)\n"
">>> m.envelope().center()\n"
"Coord(-0.5,-0.5) # default Map center\n"
">>> m.pan(-1,-1)\n"
">>> 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"
"and zoom factor as a float.\n"
"\n"
"Usage:\n"
">>> m = Map(600,400)\n"
">>> m.envelope().center()\n"
"Coord(-0.5,-0.5) # default Map center\n"
">>> m.scale()\n"
"-0.0016666666666666668\n"
">>> m.pan_and_zoom(-1,-1,0.25)\n"
">>> 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"
"intersecting the given x,y location in the pixel\n"
"coordinates of the rendered map image.\n"
"Layer index starts at 0 (first layer in map).\n"
"Will return a Mapnik Featureset if successful\n"
"otherwise will return None.\n"
"\n"
"Usage:\n"
">>> featureset = m.query_map_point(0,200,200)\n"
">>> featureset\n"
"<mapnik._mapnik.Featureset object at 0x23b0b0>\n"
">>> featureset.features\n"
">>> [<mapnik.Feature object at 0x3995630>]\n"
)
.def("query_point",query_point,
(arg("layer idx"),arg("x"),arg("y")),
"Query a Map Layer (by layer index) for features \n"
"intersecting the given x,y location in the coordinates\n"
"of map projection.\n"
"Layer index starts at 0 (first layer in map).\n"
"Will return a Mapnik Featureset if successful\n"
"otherwise will return None.\n"
"\n"
"Usage:\n"
">>> featureset = m.query_point(0,-122,48)\n"
">>> featureset\n"
"<mapnik._mapnik.Featureset object at 0x23b0b0>\n"
">>> featureset.features\n"
">>> [<mapnik.Feature object at 0x3995630>]\n"
)
.def("remove_all",&Map::remove_all,
"Remove all Mapnik Styles and layers from the Map.\n"
"\n"
"Usage:\n"
">>> m.remove_all()\n"
)
.def("remove_style",&Map::remove_style,
(arg("style_name")),
"Remove a Mapnik Style from the map.\n"
"\n"
"Usage:\n"
">>> m.remove_style('Style Name')\n"
)
.def("resize",&Map::resize,
(arg("width"),arg("height")),
"Resize a Mapnik Map.\n"
"\n"
"Usage:\n"
">>> m.resize(64,64)\n"
)
.def("scale", &Map::scale,
"Return the Map Scale.\n"
"Usage:\n"
"\n"
">>> m.scale()\n"
)
.def("scale_denominator", &Map::scale_denominator,
"Return the Map Scale Denominator.\n"
"Usage:\n"
"\n"
">>> m.scale_denominator()\n"
)
.def("view_transform",&Map::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"
)
.def("zoom",&Map::zoom,
(arg("factor")),
"Zoom in or out by a given factor.\n"
"positive number larger than 1, zooms out\n"
"positive number smaller than 1, zooms in\n"
"\n"
"Usage:\n"
"\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"
"\n"
"Usage:\n"
">>> m.zoom_all()\n"
)
.def("zoom_to_box",&Map::zoom_to_box,
(arg("Boxd2")),
"Set the geographical extent of the map\n"
"by specifying a Mapnik Box2d.\n"
"\n"
"Usage:\n"
">>> extext = Box2d(-180.0, -90.0, 180.0, 90.0)\n"
">>> m.zoom_to_box(extent)\n"
)
.add_property("parameters",make_function(params_nonconst,return_value_policy<reference_existing_object>()),"TODO")
.add_property("aspect_fix_mode",
&Map::get_aspect_fix_mode,
&Map::set_aspect_fix_mode,
// TODO - how to add arg info to properties?
//(arg("aspect_fix_mode")),
"Get/Set aspect fix mode.\n"
"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,
"The background color of the map (same as background_color property).\n"
"\n"
"Usage:\n"
">>> m.background = Color('steelblue')\n"
)
.add_property("background_color",make_function
(&Map::background,return_value_policy<copy_const_reference>()),
&Map::set_background,
"The background color of the map.\n"
"\n"
"Usage:\n"
">>> m.background_color = Color('steelblue')\n"
)
.add_property("background_image",make_function
(&Map::background_image,return_value_policy<copy_const_reference>()),
&Map::set_background_image,
"The optional background image of the map.\n"
"\n"
"Usage:\n"
">>> m.background_image = '/path/to/image.png'\n"
)
.add_property("background_image_comp_op",&Map::background_image_comp_op,
&Map::set_background_image_comp_op,
"The background image compositing operation.\n"
"\n"
"Usage:\n"
">>> m.background_image_comp_op = mapnik.CompositeOp.src_over\n"
)
.add_property("background_image_opacity",&Map::background_image_opacity,
&Map::set_background_image_opacity,
"The background image opacity.\n"
"\n"
"Usage:\n"
">>> m.background_image_opacity = 1.0\n"
)
.add_property("base",
make_function(&Map::base_path,return_value_policy<copy_const_reference>()),
&Map::set_base_path,
"The base path of the map where any files using relative \n"
"paths will be interpreted as relative to.\n"
"\n"
"Usage:\n"
">>> m.base_path = '.'\n"
)
.add_property("buffer_size",
&Map::buffer_size,
&Map::set_buffer_size,
"Get/Set the size of buffer around map in pixels.\n"
"\n"
"Usage:\n"
">>> m.buffer_size\n"
"0 # zero by default\n"
">>> m.buffer_size = 2\n"
">>> m.buffer_size\n"
"2\n"
)
.add_property("height",
&Map::height,
&Map::set_height,
"Get/Set the height of the map in pixels.\n"
"Minimum settable size is 16 pixels.\n"
"\n"
"Usage:\n"
">>> m.height\n"
"400\n"
">>> m.height = 600\n"
">>> m.height\n"
"600\n"
)
.add_property("layers",make_function
(layers_nonconst,return_value_policy<reference_existing_object>()),
"The list of map layers.\n"
"\n"
"Usage:\n"
">>> m.layers\n"
"<mapnik._mapnik.layers object at 0x6d458>"
">>> m.layers[0]\n"
"<mapnik._mapnik.layer object at 0x5fe130>\n"
)
.add_property("maximum_extent",make_function
(&Map::maximum_extent,return_value_policy<copy_const_reference>()),
&set_maximum_extent,
"The maximum extent of the map.\n"
"\n"
"Usage:\n"
">>> m.maximum_extent = Box2d(-180,-90,180,90)\n"
)
.add_property("srs",
make_function(&Map::srs,return_value_policy<copy_const_reference>()),
&Map::set_srs,
"Spatial reference in Proj.4 format.\n"
"Either an epsg code or proj literal.\n"
"For example, a proj literal:\n"
"\t'+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs'\n"
"and a proj epsg code:\n"
"\t'+init=epsg:4326'\n"
"\n"
"Note: using epsg codes requires the installation of\n"
"the Proj.4 'epsg' data file normally found in '/usr/local/share/proj'\n"
"\n"
"Usage:\n"
">>> m.srs\n"
"'+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs' # The default srs if not initialized with custom srs\n"
">>> # set to google mercator with Proj.4 literal\n"
"... \n"
">>> m.srs = '+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0.0 +k=1.0 +units=m +nadgrids=@null +wktext +no_defs +over'\n"
)
.add_property("width",
&Map::width,
&Map::set_width,
"Get/Set the width of the map in pixels.\n"
"Minimum settable size is 16 pixels.\n"
"\n"
"Usage:\n"
">>> m.width\n"
"600\n"
">>> m.width = 800\n"
">>> m.width\n"
"800\n"
)
// comparison
.def(self == self)
;
}

View file

@ -1,70 +0,0 @@
/*****************************************************************************
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2014 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 <mapnik/config.hpp>
// boost
#include "boost_std_shared_shim.hpp"
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-parameter"
#pragma GCC diagnostic ignored "-Wunused-local-typedef"
#pragma GCC diagnostic ignored "-Wmissing-field-initializers"
#include <boost/python.hpp>
#include <boost/noncopyable.hpp>
#pragma GCC diagnostic pop
//mapnik
#include <mapnik/palette.hpp>
// stl
#include <stdexcept>
static std::shared_ptr<mapnik::rgba_palette> make_palette( std::string const& palette, std::string const& format )
{
mapnik::rgba_palette::palette_type type = mapnik::rgba_palette::PALETTE_RGBA;
if (format == "rgb")
type = mapnik::rgba_palette::PALETTE_RGB;
else if (format == "act")
type = mapnik::rgba_palette::PALETTE_ACT;
else
throw std::runtime_error("invalid type passed for mapnik.Palette: must be either rgba, rgb, or act");
return std::make_shared<mapnik::rgba_palette>(palette, type);
}
void export_palette ()
{
using namespace boost::python;
class_<mapnik::rgba_palette,
std::shared_ptr<mapnik::rgba_palette>,
boost::noncopyable >("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))
.def("to_string", &mapnik::rgba_palette::to_string,
"Returns the palette as a string.\n"
)
;
}

View file

@ -1,246 +0,0 @@
/*****************************************************************************
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2014 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 <mapnik/config.hpp>
// boost
#include "boost_std_shared_shim.hpp"
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-parameter"
#pragma GCC diagnostic ignored "-Wunused-local-typedef"
#pragma GCC diagnostic ignored "-Wmissing-field-initializers"
#include <boost/python.hpp>
#pragma GCC diagnostic pop
// mapnik
#include <mapnik/debug.hpp>
#include <mapnik/params.hpp>
#include <mapnik/unicode.hpp>
#include <mapnik/value_types.hpp>
#include <mapnik/value.hpp>
// stl
#include <iterator>
using mapnik::parameter;
using mapnik::parameters;
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,p.second);
}
};
struct parameters_pickle_suite : boost::python::pickle_suite
{
static boost::python::tuple
getstate(const parameters& p)
{
using namespace boost::python;
dict d;
parameters::const_iterator pos=p.begin();
while(pos!=p.end())
{
d[pos->first] = pos->second;
++pos;
}
return boost::python::make_tuple(d);
}
static void setstate(parameters& p, boost::python::tuple state)
{
using namespace boost::python;
if (len(state) != 1)
{
PyErr_SetObject(PyExc_ValueError,
("expected 1-item tuple in call to __setstate__; got %s"
% state).ptr()
);
throw_error_already_set();
}
dict d = extract<dict>(state[0]);
boost::python::list keys = d.keys();
for (int i=0; i<len(keys); ++i)
{
std::string key = extract<std::string>(keys[i]);
object obj = d[key];
extract<std::string> ex0(obj);
extract<mapnik::value_integer> ex1(obj);
extract<double> ex2(obj);
extract<mapnik::value_unicode_string> ex3(obj);
// TODO - this is never hit - we need proper python string -> std::string to get invoked here
if (ex0.check())
{
p[key] = ex0();
}
else if (ex1.check())
{
p[key] = ex1();
}
else if (ex2.check())
{
p[key] = ex2();
}
else if (ex3.check())
{
std::string buffer;
mapnik::to_utf8(ex3(),buffer);
p[key] = buffer;
}
else
{
MAPNIK_LOG_DEBUG(bindings) << "parameters_pickle_suite: Could not unpickle key=" << key;
}
}
}
};
mapnik::value_holder get_params_by_key1(mapnik::parameters const& p, std::string const& key)
{
parameters::const_iterator pos = p.find(key);
if (pos != p.end())
{
// will be auto-converted to proper python type by `mapnik_params_to_python`
return pos->second;
}
return mapnik::value_null();
}
mapnik::value_holder get_params_by_key2(mapnik::parameters const& p, std::string const& key)
{
parameters::const_iterator pos = p.find(key);
if (pos == p.end())
{
PyErr_SetString(PyExc_KeyError, key.c_str());
boost::python::throw_error_already_set();
}
// will be auto-converted to proper python type by `mapnik_params_to_python`
return pos->second;
}
mapnik::parameter get_params_by_index(mapnik::parameters const& p, int index)
{
if (index < 0 || static_cast<unsigned>(index) > p.size())
{
PyErr_SetString(PyExc_IndexError, "Index is out of range");
throw boost::python::error_already_set();
}
parameters::const_iterator itr = p.begin();
std::advance(itr, index);
if (itr != p.end())
{
return *itr;
}
PyErr_SetString(PyExc_IndexError, "Index is out of range");
throw boost::python::error_already_set();
}
unsigned get_params_size(mapnik::parameters const& p)
{
return p.size();
}
void add_parameter(mapnik::parameters & p, mapnik::parameter const& param)
{
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();
}
}
std::shared_ptr<mapnik::parameter> create_parameter(mapnik::value_unicode_string const& key, mapnik::value_holder const& value)
{
std::string key_utf8;
mapnik::to_utf8(key, key_utf8);
return std::make_shared<mapnik::parameter>(key_utf8,value);
}
bool contains(mapnik::parameters const& p, std::string const& key)
{
parameters::const_iterator pos = p.find(key);
return pos != p.end();
}
// needed for Python_Unicode to std::string (utf8) conversion
std::shared_ptr<mapnik::parameter> create_parameter_from_string(mapnik::value_unicode_string const& key, mapnik::value_unicode_string const& ustr)
{
std::string key_utf8;
std::string ustr_utf8;
mapnik::to_utf8(key, key_utf8);
mapnik::to_utf8(ustr,ustr_utf8);
return std::make_shared<mapnik::parameter>(key_utf8, ustr_utf8);
}
void export_parameters()
{
using namespace boost::python;
implicitly_convertible<std::string,mapnik::value_holder>();
implicitly_convertible<mapnik::value_null,mapnik::value_holder>();
implicitly_convertible<mapnik::value_integer,mapnik::value_holder>();
implicitly_convertible<mapnik::value_double,mapnik::value_holder>();
class_<parameter,std::shared_ptr<parameter> >("Parameter",no_init)
.def("__init__", make_constructor(create_parameter),
"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_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_pickle(parameter_pickle_suite())
.def("__getitem__",get_param)
;
class_<parameters>("Parameters",init<>())
.def_pickle(parameters_pickle_suite())
.def("get",get_params_by_key1)
.def("__getitem__",get_params_by_key2)
.def("__getitem__",get_params_by_index)
.def("__len__",get_params_size)
.def("__contains__",contains)
.def("append",add_parameter)
.def("iteritems",iterator<parameters>())
;
}

View file

@ -1,154 +0,0 @@
/*****************************************************************************
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2014 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 <mapnik/config.hpp>
// boost
#include "boost_std_shared_shim.hpp"
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-parameter"
#pragma GCC diagnostic ignored "-Wunused-local-typedef"
#pragma GCC diagnostic ignored "-Wmissing-field-initializers"
#include <boost/python.hpp>
#include <boost/noncopyable.hpp>
#pragma GCC diagnostic pop
// mapnik
#include <mapnik/proj_transform.hpp>
#include <mapnik/projection.hpp>
#include <mapnik/coord.hpp>
#include <mapnik/box2d.hpp>
// stl
#include <stdexcept>
using mapnik::proj_transform;
using mapnik::projection;
struct proj_transform_pickle_suite : boost::python::pickle_suite
{
static boost::python::tuple
getinitargs(const proj_transform& p)
{
using namespace boost::python;
return boost::python::make_tuple(p.source(),p.dest());
}
};
namespace {
mapnik::coord2d forward_transform_c(mapnik::proj_transform& t, mapnik::coord2d const& c)
{
double x = c.x;
double y = c.y;
double z = 0.0;
if (!t.forward(x,y,z)) {
std::ostringstream s;
s << "Failed to forward project "
<< "from " << t.source().params() << " to: " << t.dest().params();
throw std::runtime_error(s.str());
}
return mapnik::coord2d(x,y);
}
mapnik::coord2d backward_transform_c(mapnik::proj_transform& t, mapnik::coord2d const& c)
{
double x = c.x;
double y = c.y;
double z = 0.0;
if (!t.backward(x,y,z)) {
std::ostringstream s;
s << "Failed to back project "
<< "from " << t.dest().params() << " to: " << t.source().params();
throw std::runtime_error(s.str());
}
return mapnik::coord2d(x,y);
}
mapnik::box2d<double> forward_transform_env(mapnik::proj_transform& t, mapnik::box2d<double> const & box)
{
mapnik::box2d<double> new_box = box;
if (!t.forward(new_box)) {
std::ostringstream s;
s << "Failed to forward project "
<< "from " << t.source().params() << " to: " << t.dest().params();
throw std::runtime_error(s.str());
}
return new_box;
}
mapnik::box2d<double> backward_transform_env(mapnik::proj_transform& t, mapnik::box2d<double> const & box)
{
mapnik::box2d<double> new_box = box;
if (!t.backward(new_box)){
std::ostringstream s;
s << "Failed to back project "
<< "from " << t.dest().params() << " to: " << t.source().params();
throw std::runtime_error(s.str());
}
return new_box;
}
mapnik::box2d<double> forward_transform_env_p(mapnik::proj_transform& t, mapnik::box2d<double> const & box, unsigned int points)
{
mapnik::box2d<double> new_box = box;
if (!t.forward(new_box,points)) {
std::ostringstream s;
s << "Failed to forward project "
<< "from " << t.source().params() << " to: " << t.dest().params();
throw std::runtime_error(s.str());
}
return new_box;
}
mapnik::box2d<double> backward_transform_env_p(mapnik::proj_transform& t, mapnik::box2d<double> const & box, unsigned int points)
{
mapnik::box2d<double> new_box = box;
if (!t.backward(new_box,points)){
std::ostringstream s;
s << "Failed to back project "
<< "from " << t.dest().params() << " to: " << t.source().params();
throw std::runtime_error(s.str());
}
return new_box;
}
}
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)
.def("backward",backward_transform_c)
.def("forward", forward_transform_env)
.def("backward",backward_transform_env)
.def("forward", forward_transform_env_p)
.def("backward",backward_transform_env_p)
;
}

View file

@ -1,125 +0,0 @@
/*****************************************************************************
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2014 Artem Pavlenko, Jean-Francois Doyon
*
* 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 <mapnik/config.hpp>
// boost
#include "boost_std_shared_shim.hpp"
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-parameter"
#pragma GCC diagnostic ignored "-Wunused-local-typedef"
#pragma GCC diagnostic ignored "-Wmissing-field-initializers"
#include <boost/python.hpp>
#pragma GCC diagnostic pop
// mapnik
#include <mapnik/coord.hpp>
#include <mapnik/box2d.hpp>
#include <mapnik/projection.hpp>
using mapnik::projection;
struct projection_pickle_suite : boost::python::pickle_suite
{
static boost::python::tuple
getinitargs(const projection& p)
{
using namespace boost::python;
return boost::python::make_tuple(p.params());
}
};
namespace {
mapnik::coord2d forward_pt(mapnik::coord2d const& pt,
mapnik::projection const& prj)
{
double x = pt.x;
double y = pt.y;
prj.forward(x,y);
return mapnik::coord2d(x,y);
}
mapnik::coord2d inverse_pt(mapnik::coord2d const& pt,
mapnik::projection const& prj)
{
double x = pt.x;
double y = pt.y;
prj.inverse(x,y);
return mapnik::coord2d(x,y);
}
mapnik::box2d<double> forward_env(mapnik::box2d<double> const & box,
mapnik::projection const& prj)
{
double minx = box.minx();
double miny = box.miny();
double maxx = box.maxx();
double maxy = box.maxy();
prj.forward(minx,miny);
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)
{
double minx = box.minx();
double miny = box.miny();
double maxx = box.maxx();
double maxy = box.maxy();
prj.inverse(minx,miny);
prj.inverse(maxx,maxy);
return mapnik::box2d<double>(minx,miny,maxx,maxy);
}
}
void export_projection ()
{
using namespace boost::python;
class_<projection>("Projection", "Represents a map projection.",init<std::string const&>(
(arg("proj4_string")),
"Constructs a new projection from its PROJ.4 string representation.\n"
"\n"
"The constructor will throw a RuntimeError in case the projection\n"
"cannot be initialized.\n"
)
)
.def_pickle(projection_pickle_suite())
.def ("params", make_function(&projection::params,
return_value_policy<copy_const_reference>()),
"Returns the PROJ.4 string for this projection.\n")
.def ("expanded",&projection::expanded,
"normalize PROJ.4 definition by expanding +init= syntax\n")
.add_property ("geographic", &projection::is_geographic,
"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);
}

File diff suppressed because it is too large Load diff

View file

@ -1,107 +0,0 @@
/*****************************************************************************
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2014 Artem Pavlenko, Jean-Francois Doyon
*
* 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 <mapnik/config.hpp>
// boost
#include "boost_std_shared_shim.hpp"
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-parameter"
#pragma GCC diagnostic ignored "-Wunused-local-typedef"
#pragma GCC diagnostic ignored "-Wmissing-field-initializers"
#include "python_to_value.hpp"
#include <boost/python.hpp>
#pragma GCC diagnostic pop
// mapnik
#include <mapnik/query.hpp>
#include <mapnik/box2d.hpp>
#include <string>
#include <set>
using mapnik::query;
using mapnik::box2d;
namespace python = boost::python;
struct resolution_to_tuple
{
static PyObject* convert(query::resolution_type const& x)
{
python::object tuple(python::make_tuple(std::get<0>(x), std::get<1>(x)));
return python::incref(tuple.ptr());
}
static PyTypeObject const* get_pytype()
{
return &PyTuple_Type;
}
};
struct names_to_list
{
static PyObject* convert(std::set<std::string> const& names)
{
boost::python::list l;
for ( std::string const& name : names )
{
l.append(name);
}
return python::incref(l.ptr());
}
static PyTypeObject const* get_pytype()
{
return &PyList_Type;
}
};
namespace {
void set_variables(mapnik::query & q, boost::python::dict const& d)
{
mapnik::attributes vars = mapnik::dict2attr(d);
q.set_variables(vars);
}
}
void export_query()
{
using namespace boost::python;
to_python_converter<query::resolution_type, resolution_to_tuple> ();
to_python_converter<std::set<std::string>, names_to_list> ();
class_<query>("Query", "a spatial query data object",
init<box2d<double>,query::resolution_type const&,double>() )
.def(init<box2d<double> >())
.add_property("resolution",make_function(&query::resolution,
return_value_policy<copy_const_reference>()))
.add_property("bbox", make_function(&query::get_bbox,
return_value_policy<copy_const_reference>()) )
.add_property("property_names", make_function(&query::property_names,
return_value_policy<copy_const_reference>()) )
.def("add_property_name", &query::add_property_name)
.def("set_variables",&set_variables);
}

View file

@ -1,241 +0,0 @@
/*****************************************************************************
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2014 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 <mapnik/config.hpp>
// boost
#include "boost_std_shared_shim.hpp"
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-parameter"
#pragma GCC diagnostic ignored "-Wunused-local-typedef"
#pragma GCC diagnostic ignored "-Wmissing-field-initializers"
#include <boost/python.hpp>
#include <boost/python/suite/indexing/vector_indexing_suite.hpp>
#pragma GCC diagnostic pop
// mapnik
#include <mapnik/raster_colorizer.hpp>
#include <mapnik/symbolizer.hpp>
using mapnik::raster_colorizer;
using mapnik::raster_colorizer_ptr;
using mapnik::symbolizer_base;
using mapnik::colorizer_stop;
using mapnik::colorizer_stops;
using mapnik::colorizer_mode_enum;
using mapnik::color;
using mapnik::COLORIZER_INHERIT;
using mapnik::COLORIZER_LINEAR;
using mapnik::COLORIZER_DISCRETE;
using mapnik::COLORIZER_EXACT;
namespace {
void add_stop(raster_colorizer_ptr & rc, colorizer_stop & stop)
{
rc->add_stop(stop);
}
void add_stop2(raster_colorizer_ptr & rc, float v)
{
colorizer_stop stop(v, rc->get_default_mode(), rc->get_default_color());
rc->add_stop(stop);
}
void add_stop3(raster_colorizer_ptr &rc, float v, color c)
{
colorizer_stop stop(v, rc->get_default_mode(), c);
rc->add_stop(stop);
}
void add_stop4(raster_colorizer_ptr &rc, float v, colorizer_mode_enum m)
{
colorizer_stop stop(v, m, rc->get_default_color());
rc->add_stop(stop);
}
void add_stop5(raster_colorizer_ptr &rc, float v, colorizer_mode_enum m, color c)
{
colorizer_stop stop(v, m, c);
rc->add_stop(stop);
}
mapnik::color get_color(raster_colorizer_ptr &rc, float value)
{
unsigned rgba = rc->get_color(value);
unsigned r = (rgba & 0xff);
unsigned g = (rgba >> 8 ) & 0xff;
unsigned b = (rgba >> 16) & 0xff;
unsigned a = (rgba >> 24) & 0xff;
return mapnik::color(r,g,b,a);
}
colorizer_stops const& get_stops(raster_colorizer_ptr & rc)
{
return rc->get_stops();
}
}
void export_raster_colorizer()
{
using namespace boost::python;
implicitly_convertible<raster_colorizer_ptr, mapnik::symbolizer_base::value_type>();
class_<raster_colorizer,raster_colorizer_ptr>("RasterColorizer",
"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("stops",
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")
.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"
)
.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(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(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(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(mapnik.COLORIZER_LINEAR, default_color)\n"
">>> colorizer.add_stop(100, mapnik.COLORIZER_DISCRETE, mapnik.Color(\"#112233\"))\n"
)
.def("get_color", 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)
.def(vector_indexing_suite<colorizer_stops>())
;
enum_<colorizer_mode_enum>("ColorizerMode")
.value("COLORIZER_INHERIT", COLORIZER_INHERIT)
.value("COLORIZER_LINEAR", COLORIZER_LINEAR)
.value("COLORIZER_DISCRETE", COLORIZER_DISCRETE)
.value("COLORIZER_EXACT", COLORIZER_EXACT)
.export_values()
;
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")
.def(self == self)
.def("__str__",&colorizer_stop::to_string)
;
}

View file

@ -1,100 +0,0 @@
/*****************************************************************************
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2014 Artem Pavlenko, Jean-Francois Doyon
*
* 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 <mapnik/config.hpp>
// boost
#include "boost_std_shared_shim.hpp"
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-parameter"
#pragma GCC diagnostic ignored "-Wunused-local-typedef"
#pragma GCC diagnostic ignored "-Wmissing-field-initializers"
#include <boost/python.hpp>
#include <boost/python/implicit.hpp>
#include <boost/python/suite/indexing/vector_indexing_suite.hpp>
#pragma GCC diagnostic pop
// mapnik
#include <mapnik/rule.hpp>
#include <mapnik/expression.hpp>
#include <mapnik/expression_string.hpp>
using mapnik::rule;
using mapnik::expr_node;
using mapnik::expression_ptr;
using mapnik::point_symbolizer;
using mapnik::line_symbolizer;
using mapnik::line_pattern_symbolizer;
using mapnik::polygon_symbolizer;
using mapnik::polygon_pattern_symbolizer;
using mapnik::raster_symbolizer;
using mapnik::shield_symbolizer;
using mapnik::text_symbolizer;
using mapnik::building_symbolizer;
using mapnik::markers_symbolizer;
using mapnik::group_symbolizer;
using mapnik::symbolizer;
using mapnik::to_expression_string;
void export_rule()
{
using namespace boost::python;
implicitly_convertible<point_symbolizer,symbolizer>();
implicitly_convertible<line_symbolizer,symbolizer>();
implicitly_convertible<line_pattern_symbolizer,symbolizer>();
implicitly_convertible<polygon_symbolizer,symbolizer>();
implicitly_convertible<building_symbolizer,symbolizer>();
implicitly_convertible<polygon_pattern_symbolizer,symbolizer>();
implicitly_convertible<raster_symbolizer,symbolizer>();
implicitly_convertible<shield_symbolizer,symbolizer>();
implicitly_convertible<text_symbolizer,symbolizer>();
implicitly_convertible<markers_symbolizer,symbolizer>();
implicitly_convertible<group_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<double,double> >())
.add_property("name",make_function
(&rule::get_name,
return_value_policy<copy_const_reference>()),
&rule::set_name)
.add_property("filter",make_function
(&rule::get_filter,return_value_policy<copy_const_reference>()),
&rule::set_filter)
.add_property("min_scale",&rule::get_min_scale,&rule::set_min_scale)
.add_property("max_scale",&rule::get_max_scale,&rule::set_max_scale)
.def("set_else",&rule::set_else)
.def("has_else",&rule::has_else_filter)
.def("set_also",&rule::set_also)
.def("has_also",&rule::has_also_filter)
.def("active",&rule::active)
.add_property("symbols",make_function
(&rule::get_symbolizers,return_value_policy<reference_existing_object>()))
.add_property("copy_symbols",make_function
(&rule::get_symbolizers,return_value_policy<copy_const_reference>()))
;
}

View file

@ -1,58 +0,0 @@
/*****************************************************************************
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2014 Artem Pavlenko, Jean-Francois Doyon
*
* 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 <mapnik/image_scaling.hpp>
// boost
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-parameter"
#pragma GCC diagnostic ignored "-Wunused-local-typedef"
#pragma GCC diagnostic ignored "-Wmissing-field-initializers"
#include <boost/python.hpp>
#pragma GCC diagnostic pop
void export_scaling_method()
{
using namespace boost::python;
enum_<mapnik::scaling_method_e>("scaling_method")
.value("NEAR", mapnik::SCALING_NEAR)
.value("BILINEAR", mapnik::SCALING_BILINEAR)
.value("BICUBIC", mapnik::SCALING_BICUBIC)
.value("SPLINE16", mapnik::SCALING_SPLINE16)
.value("SPLINE36", mapnik::SCALING_SPLINE36)
.value("HANNING", mapnik::SCALING_HANNING)
.value("HAMMING", mapnik::SCALING_HAMMING)
.value("HERMITE", mapnik::SCALING_HERMITE)
.value("KAISER", mapnik::SCALING_KAISER)
.value("QUADRIC", mapnik::SCALING_QUADRIC)
.value("CATROM", mapnik::SCALING_CATROM)
.value("GAUSSIAN", mapnik::SCALING_GAUSSIAN)
.value("BESSEL", mapnik::SCALING_BESSEL)
.value("MITCHELL", mapnik::SCALING_MITCHELL)
.value("SINC", mapnik::SCALING_SINC)
.value("LANCZOS", mapnik::SCALING_LANCZOS)
.value("BLACKMAN", mapnik::SCALING_BLACKMAN)
;
}

View file

@ -1,118 +0,0 @@
/*****************************************************************************
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2014 Artem Pavlenko, Jean-Francois Doyon
*
* 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 <mapnik/config.hpp>
// boost
#include "boost_std_shared_shim.hpp"
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-parameter"
#pragma GCC diagnostic ignored "-Wunused-local-typedef"
#pragma GCC diagnostic ignored "-Wmissing-field-initializers"
#include <boost/python.hpp>
#include <boost/python/suite/indexing/vector_indexing_suite.hpp>
#pragma GCC diagnostic pop
// mapnik
#include <mapnik/value_error.hpp>
#include <mapnik/rule.hpp>
#include "mapnik_enumeration.hpp"
#include <mapnik/feature_type_style.hpp>
#include <mapnik/image_filter_types.hpp> // generate_image_filters
using mapnik::feature_type_style;
using mapnik::rules;
using mapnik::rule;
std::string get_image_filters(feature_type_style & style)
{
std::string filters_str;
std::back_insert_iterator<std::string> sink(filters_str);
generate_image_filters(sink, style.image_filters());
return filters_str;
}
void set_image_filters(feature_type_style & style, std::string const& filters)
{
std::vector<mapnik::filter::filter_type> new_filters;
bool result = parse_image_filters(filters, new_filters);
if (!result)
{
throw mapnik::value_error("failed to parse image-filters: '" + filters + "'");
}
#ifdef _WINDOWS
style.image_filters() = new_filters;
// FIXME : https://svn.boost.org/trac/boost/ticket/2839
#else
style.image_filters() = std::move(new_filters);
#endif
}
void export_style()
{
using namespace boost::python;
mapnik::enumeration_<mapnik::filter_mode_e>("filter_mode")
.value("ALL",mapnik::FILTER_ALL)
.value("FIRST",mapnik::FILTER_FIRST)
;
class_<rules>("Rules",init<>("default ctor"))
.def(vector_indexing_suite<rules>())
;
class_<feature_type_style>("Style",init<>("default style constructor"))
.add_property("rules",make_function
(&feature_type_style::get_rules,
return_value_policy<reference_existing_object>()),
"List of rules belonging to a style as rule objects.\n"
"\n"
"Usage:\n"
">>> for r in m.find_style('style 1').rules:\n"
">>> print r\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 filter mode of the style")
.add_property("opacity",
&feature_type_style::get_opacity,
&feature_type_style::set_opacity,
"Set/get the opacity of the style")
.add_property("comp_op",
&feature_type_style::comp_op,
&feature_type_style::set_comp_op,
"Set/get the comp-op (composite operation) of the style")
.add_property("image_filters_inflate",
&feature_type_style::image_filters_inflate,
&feature_type_style::image_filters_inflate,
"Set/get the image_filters_inflate property of the style")
.add_property("image_filters",
get_image_filters,
set_image_filters,
"Set/get the comp-op (composite operation) of the style")
;
}

View file

@ -1,56 +0,0 @@
/*****************************************************************************
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2010 Robert Coup
*
* 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
*
*****************************************************************************/
#ifndef MAPNIK_PYTHON_BINDING_SVG_INCLUDED
#define MAPNIK_PYTHON_BINDING_SVG_INCLUDED
// mapnik
#include <mapnik/parse_transform.hpp>
#include <mapnik/symbolizer.hpp>
#include <mapnik/value_error.hpp>
namespace mapnik {
using namespace boost::python;
template <class T>
std::string get_svg_transform(T& symbolizer)
{
return symbolizer.get_image_transform_string();
}
template <class T>
void set_svg_transform(T& symbolizer, std::string const& transform_wkt)
{
transform_list_ptr trans_expr = mapnik::parse_transform(transform_wkt);
if (!trans_expr)
{
std::stringstream ss;
ss << "Could not parse transform from '"
<< transform_wkt
<< "', expected SVG transform attribute";
throw mapnik::value_error(ss.str());
}
symbolizer.set_image_transform(trans_expr);
}
} // end of namespace mapnik
#endif // MAPNIK_PYTHON_BINDING_SVG_INCLUDED

View file

@ -1,27 +0,0 @@
/*****************************************************************************
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2014 Artem Pavlenko, Jean-Francois Doyon
*
* 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 <mapnik/svg/geometry_svg_generator_impl.hpp>
#include <string>
using sink_type = std::back_insert_iterator<std::string>;
template struct mapnik::svg::svg_path_generator<sink_type, mapnik::vertex_adapter>;

View file

@ -1,422 +0,0 @@
/*****************************************************************************
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2014 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 <mapnik/config.hpp>
// boost
#include "boost_std_shared_shim.hpp"
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-parameter"
#pragma GCC diagnostic ignored "-Wunused-local-typedef"
#pragma GCC diagnostic ignored "-Wmissing-field-initializers"
#include <boost/python.hpp>
#include <boost/python/suite/indexing/map_indexing_suite.hpp>
#pragma GCC diagnostic pop
// mapnik
#include <mapnik/symbolizer.hpp>
#include <mapnik/symbolizer_hash.hpp>
#include <mapnik/symbolizer_utils.hpp>
#include <mapnik/symbolizer_keys.hpp>
#include <mapnik/image_util.hpp>
#include <mapnik/parse_path.hpp>
#include <mapnik/path_expression.hpp>
#include "mapnik_enumeration.hpp"
#include "mapnik_svg.hpp"
#include <mapnik/expression_node.hpp>
#include <mapnik/value_error.hpp>
#include <mapnik/marker_cache.hpp> // for known_svg_prefix_
#include <mapnik/group/group_layout.hpp>
#include <mapnik/group/group_rule.hpp>
#include <mapnik/group/group_symbolizer_properties.hpp>
#include <mapnik/util/variant.hpp>
// stl
#include <sstream>
using mapnik::symbolizer;
using mapnik::point_symbolizer;
using mapnik::line_symbolizer;
using mapnik::line_pattern_symbolizer;
using mapnik::polygon_symbolizer;
using mapnik::polygon_pattern_symbolizer;
using mapnik::raster_symbolizer;
using mapnik::shield_symbolizer;
using mapnik::text_symbolizer;
using mapnik::building_symbolizer;
using mapnik::markers_symbolizer;
using mapnik::debug_symbolizer;
using mapnik::group_symbolizer;
using mapnik::symbolizer_base;
using mapnik::color;
using mapnik::path_processor_type;
using mapnik::path_expression_ptr;
using mapnik::guess_type;
using mapnik::expression_ptr;
using mapnik::parse_path;
namespace {
using namespace boost::python;
void __setitem__(mapnik::symbolizer_base & sym, std::string const& name, mapnik::symbolizer_base::value_type const& val)
{
put(sym, mapnik::get_key(name), val);
}
std::shared_ptr<mapnik::symbolizer_base::value_type> numeric_wrapper(const object& arg)
{
std::shared_ptr<mapnik::symbolizer_base::value_type> result;
if (PyBool_Check(arg.ptr()))
{
mapnik::value_bool val = extract<mapnik::value_bool>(arg);
result.reset(new mapnik::symbolizer_base::value_type(val));
}
else if (PyFloat_Check(arg.ptr()))
{
mapnik::value_double val = extract<mapnik::value_double>(arg);
result.reset(new mapnik::symbolizer_base::value_type(val));
}
else
{
mapnik::value_integer val = extract<mapnik::value_integer>(arg);
result.reset(new mapnik::symbolizer_base::value_type(val));
}
return result;
}
struct extract_python_object
{
using result_type = boost::python::object;
template <typename T>
auto operator() (T const& val) const -> result_type
{
return result_type(val); // wrap into python object
}
};
boost::python::object __getitem__(mapnik::symbolizer_base const& sym, std::string const& name)
{
using const_iterator = symbolizer_base::cont_type::const_iterator;
mapnik::keys key = mapnik::get_key(name);
const_iterator itr = sym.properties.find(key);
if (itr != sym.properties.end())
{
return mapnik::util::apply_visitor(extract_python_object(), itr->second);
}
//mapnik::property_meta_type const& meta = mapnik::get_meta(key);
//return mapnik::util::apply_visitor(extract_python_object(), std::get<1>(meta));
return boost::python::object();
}
/*
std::string __str__(mapnik::symbolizer const& sym)
{
return mapnik::util::apply_visitor(mapnik::symbolizer_to_json(), sym);
}
*/
std::string get_symbolizer_type(symbolizer const& sym)
{
return mapnik::symbolizer_name(sym); // FIXME - do we need this ?
}
std::size_t hash_impl(symbolizer const& sym)
{
return mapnik::util::apply_visitor(mapnik::symbolizer_hash_visitor(), sym);
}
template <typename T>
std::size_t hash_impl_2(T const& sym)
{
return mapnik::symbolizer_hash::value<T>(sym);
}
struct extract_underlying_type_visitor
{
template <typename T>
boost::python::object operator() (T const& sym) const
{
return boost::python::object(sym);
}
};
boost::python::object extract_underlying_type(symbolizer const& sym)
{
return mapnik::util::apply_visitor(extract_underlying_type_visitor(), sym);
}
}
void export_symbolizer()
{
using namespace boost::python;
//implicitly_convertible<mapnik::value_bool, mapnik::symbolizer_base::value_type>();
implicitly_convertible<mapnik::value_integer, mapnik::symbolizer_base::value_type>();
implicitly_convertible<mapnik::value_double, mapnik::symbolizer_base::value_type>();
implicitly_convertible<std::string, mapnik::symbolizer_base::value_type>();
implicitly_convertible<mapnik::color, mapnik::symbolizer_base::value_type>();
implicitly_convertible<mapnik::expression_ptr, mapnik::symbolizer_base::value_type>();
implicitly_convertible<mapnik::enumeration_wrapper, mapnik::symbolizer_base::value_type>();
implicitly_convertible<std::shared_ptr<mapnik::group_symbolizer_properties>, mapnik::symbolizer_base::value_type>();
enum_<mapnik::keys>("keys")
.value("gamma", mapnik::keys::gamma)
.value("gamma_method",mapnik::keys::gamma_method)
;
class_<symbolizer>("Symbolizer",no_init)
.def("type",get_symbolizer_type)
.def("__hash__",hash_impl)
.def("extract", extract_underlying_type)
;
class_<symbolizer_base::value_type>("NumericWrapper")
.def("__init__", make_constructor(numeric_wrapper))
;
class_<symbolizer_base>("SymbolizerBase",no_init)
.def("__setitem__",&__setitem__)
.def("__setattr__",&__setitem__)
.def("__getitem__",&__getitem__)
.def("__getattr__",&__getitem__)
//.def("__str__", &__str__)
.def(self == self) // __eq__
;
}
void export_shield_symbolizer()
{
using namespace boost::python;
class_< shield_symbolizer, bases<text_symbolizer> >("ShieldSymbolizer",
init<>("Default ctor"))
.def("__hash__",hash_impl_2<shield_symbolizer>)
;
}
void export_polygon_symbolizer()
{
using namespace boost::python;
class_<polygon_symbolizer, bases<symbolizer_base> >("PolygonSymbolizer",
init<>("Default ctor"))
.def("__hash__",hash_impl_2<polygon_symbolizer>)
;
}
void export_polygon_pattern_symbolizer()
{
using namespace boost::python;
mapnik::enumeration_<mapnik::pattern_alignment_e>("pattern_alignment")
.value("LOCAL",mapnik::LOCAL_ALIGNMENT)
.value("GLOBAL",mapnik::GLOBAL_ALIGNMENT)
;
class_<polygon_pattern_symbolizer>("PolygonPatternSymbolizer",
init<>("Default ctor"))
.def("__hash__",hash_impl_2<polygon_pattern_symbolizer>)
;
}
void export_raster_symbolizer()
{
using namespace boost::python;
class_<raster_symbolizer, bases<symbolizer_base> >("RasterSymbolizer",
init<>("Default ctor"))
;
}
void export_point_symbolizer()
{
using namespace boost::python;
mapnik::enumeration_<mapnik::point_placement_e>("point_placement")
.value("CENTROID",mapnik::CENTROID_POINT_PLACEMENT)
.value("INTERIOR",mapnik::INTERIOR_POINT_PLACEMENT)
;
class_<point_symbolizer, bases<symbolizer_base> >("PointSymbolizer",
init<>("Default Point Symbolizer - 4x4 black square"))
.def("__hash__",hash_impl_2<point_symbolizer>)
;
}
void export_markers_symbolizer()
{
using namespace boost::python;
mapnik::enumeration_<mapnik::marker_placement_e>("marker_placement")
.value("POINT_PLACEMENT",mapnik::MARKER_POINT_PLACEMENT)
.value("INTERIOR_PLACEMENT",mapnik::MARKER_INTERIOR_PLACEMENT)
.value("LINE_PLACEMENT",mapnik::MARKER_LINE_PLACEMENT)
;
mapnik::enumeration_<mapnik::marker_multi_policy_e>("marker_multi_policy")
.value("EACH",mapnik::MARKER_EACH_MULTI)
.value("WHOLE",mapnik::MARKER_WHOLE_MULTI)
.value("LARGEST",mapnik::MARKER_LARGEST_MULTI)
;
class_<markers_symbolizer, bases<symbolizer_base> >("MarkersSymbolizer",
init<>("Default Markers Symbolizer - circle"))
.def("__hash__",hash_impl_2<markers_symbolizer>)
;
}
void export_line_symbolizer()
{
using namespace boost::python;
mapnik::enumeration_<mapnik::line_rasterizer_e>("line_rasterizer")
.value("FULL",mapnik::RASTERIZER_FULL)
.value("FAST",mapnik::RASTERIZER_FAST)
;
mapnik::enumeration_<mapnik::line_cap_e>("stroke_linecap",
"The possible values for a line cap used when drawing\n"
"with a stroke.\n")
.value("BUTT_CAP",mapnik::BUTT_CAP)
.value("SQUARE_CAP",mapnik::SQUARE_CAP)
.value("ROUND_CAP",mapnik::ROUND_CAP)
;
mapnik::enumeration_<mapnik::line_join_e>("stroke_linejoin",
"The possible values for the line joining mode\n"
"when drawing with a stroke.\n")
.value("MITER_JOIN",mapnik::MITER_JOIN)
.value("MITER_REVERT_JOIN",mapnik::MITER_REVERT_JOIN)
.value("ROUND_JOIN",mapnik::ROUND_JOIN)
.value("BEVEL_JOIN",mapnik::BEVEL_JOIN)
;
class_<line_symbolizer, bases<symbolizer_base> >("LineSymbolizer",
init<>("Default LineSymbolizer - 1px solid black"))
.def("__hash__",hash_impl_2<line_symbolizer>)
;
}
void export_line_pattern_symbolizer()
{
using namespace boost::python;
class_<line_pattern_symbolizer, bases<symbolizer_base> >("LinePatternSymbolizer",
init<> ("Default LinePatternSymbolizer"))
.def("__hash__",hash_impl_2<line_pattern_symbolizer>)
;
}
void export_debug_symbolizer()
{
using namespace boost::python;
mapnik::enumeration_<mapnik::debug_symbolizer_mode_e>("debug_symbolizer_mode")
.value("COLLISION",mapnik::DEBUG_SYM_MODE_COLLISION)
.value("VERTEX",mapnik::DEBUG_SYM_MODE_VERTEX)
;
class_<debug_symbolizer, bases<symbolizer_base> >("DebugSymbolizer",
init<>("Default debug Symbolizer"))
.def("__hash__",hash_impl_2<debug_symbolizer>)
;
}
void export_building_symbolizer()
{
using namespace boost::python;
class_<building_symbolizer, bases<symbolizer_base> >("BuildingSymbolizer",
init<>("Default BuildingSymbolizer"))
.def("__hash__",hash_impl_2<building_symbolizer>)
;
}
namespace {
void group_symbolizer_properties_set_layout_simple(mapnik::group_symbolizer_properties &p,
mapnik::simple_row_layout &s)
{
p.set_layout(s);
}
void group_symbolizer_properties_set_layout_pair(mapnik::group_symbolizer_properties &p,
mapnik::pair_layout &s)
{
p.set_layout(s);
}
std::shared_ptr<mapnik::group_rule> group_rule_construct1(mapnik::expression_ptr p)
{
return std::make_shared<mapnik::group_rule>(p, mapnik::expression_ptr());
}
} // anonymous namespace
void export_group_symbolizer()
{
using namespace boost::python;
using mapnik::group_rule;
using mapnik::simple_row_layout;
using mapnik::pair_layout;
using mapnik::group_symbolizer_properties;
class_<group_rule, std::shared_ptr<group_rule> >("GroupRule",
init<expression_ptr, expression_ptr>())
.def("__init__", boost::python::make_constructor(group_rule_construct1))
.def("append", &group_rule::append)
.def("set_filter", &group_rule::set_filter)
.def("set_repeat_key", &group_rule::set_repeat_key)
;
class_<simple_row_layout>("SimpleRowLayout")
.def("item_margin", &simple_row_layout::get_item_margin)
.def("set_item_margin", &simple_row_layout::set_item_margin)
;
class_<pair_layout>("PairLayout")
.def("item_margin", &simple_row_layout::get_item_margin)
.def("set_item_margin", &simple_row_layout::set_item_margin)
.def("max_difference", &pair_layout::get_max_difference)
.def("set_max_difference", &pair_layout::set_max_difference)
;
class_<group_symbolizer_properties, std::shared_ptr<group_symbolizer_properties> >("GroupSymbolizerProperties")
.def("add_rule", &group_symbolizer_properties::add_rule)
.def("set_layout", &group_symbolizer_properties_set_layout_simple)
.def("set_layout", &group_symbolizer_properties_set_layout_pair)
;
class_<group_symbolizer, bases<symbolizer_base> >("GroupSymbolizer",
init<>("Default GroupSymbolizer"))
.def("__hash__",hash_impl_2<group_symbolizer>)
;
}

View file

@ -1,587 +0,0 @@
/*****************************************************************************
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2014 Artem Pavlenko, Jean-Francois Doyon
*
* 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 <mapnik/config.hpp>
// boost
#include "boost_std_shared_shim.hpp"
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-parameter"
#pragma GCC diagnostic ignored "-Wunused-local-typedef"
#pragma GCC diagnostic ignored "-Wmissing-field-initializers"
#include <boost/python.hpp>
#include <boost/python/stl_iterator.hpp>
#include <boost/noncopyable.hpp>
#pragma GCC diagnostic pop
#include <mapnik/text/text_properties.hpp>
#include <mapnik/text/placements/simple.hpp>
#include <mapnik/text/placements/list.hpp>
#include <mapnik/text/formatting/text.hpp>
#include <mapnik/text/formatting/list.hpp>
#include <mapnik/text/formatting/format.hpp>
#include <mapnik/text/formatting/layout.hpp>
#include <mapnik/text/text_layout.hpp>
#include <mapnik/symbolizer.hpp>
#include "mapnik_enumeration.hpp"
#include "mapnik_threads.hpp"
using namespace mapnik;
/* Notes:
Overriding functions in inherited classes:
boost.python documentation doesn't really tell you how to do it.
But this helps:
http://www.gamedev.net/topic/446225-inheritance-in-boostpython/
register_ptr_to_python is required for wrapped classes, but not for unwrapped.
Functions don't have to be members of the class, but can also be
normal functions taking a ref to the class as first parameter.
*/
namespace {
using namespace boost::python;
// This class works around a feature in boost python.
// See http://osdir.com/ml/python.c++/2003-11/msg00158.html
template <typename T,
typename X1 = boost::python::detail::not_specified,
typename X2 = boost::python::detail::not_specified,
typename X3 = boost::python::detail::not_specified>
class class_with_converter : public boost::python::class_<T, X1, X2, X3>
{
public:
using self = class_with_converter<T,X1,X2,X3>;
// Construct with the class name, with or without docstring, and default __init__() function
class_with_converter(char const* name, char const* doc = 0) : boost::python::class_<T, X1, X2, X3>(name, doc) { }
// Construct with class name, no docstring, and an uncallable __init__ function
class_with_converter(char const* name, boost::python::no_init_t y) : boost::python::class_<T, X1, X2, X3>(name, y) { }
// Construct with class name, docstring, and an uncallable __init__ function
class_with_converter(char const* name, char const* doc, boost::python::no_init_t y) : boost::python::class_<T, X1, X2, X3>(name, doc, y) { }
// Construct with class name and init<> function
template <class DerivedT> class_with_converter(char const* name, boost::python::init_base<DerivedT> const& i)
: boost::python::class_<T, X1, X2, X3>(name, i) { }
// Construct with class name, docstring and init<> function
template <class DerivedT>
inline class_with_converter(char const* name, char const* doc, boost::python::init_base<DerivedT> const& i)
: boost::python::class_<T, X1, X2, X3>(name, doc, i) { }
template <class D>
self& def_readwrite_convert(char const* name, D const& d, char const* /*doc*/=0)
{
this->add_property(name,
boost::python::make_getter(d, boost::python::return_value_policy<boost::python::return_by_value>()),
boost::python::make_setter(d, boost::python::default_call_policies()));
return *this;
}
};
/*
boost::python::tuple get_displacement(text_layout_properties const& t)
{
return boost::python::make_tuple(0.0,0.0);// FIXME t.displacement.x, t.displacement.y);
}
void set_displacement(text_layout_properties &t, boost::python::tuple arg)
{
if (len(arg) != 2)
{
PyErr_SetObject(PyExc_ValueError,
("expected 2-item tuple in call to set_displacement; got %s"
% arg).ptr()
);
throw_error_already_set();
}
//double x = extract<double>(arg[0]);
//double y = extract<double>(arg[1]);
//t.displacement.set(x, y); FIXME
}
struct NodeWrap
: formatting::node, wrapper<formatting::node>
{
NodeWrap()
: formatting::node(), wrapper<formatting::node>() {}
void apply(evaluated_format_properties_ptr p, feature_impl const& feature, attributes const& vars, text_layout &output) const
{
python_block_auto_unblock b;
this->get_override("apply")(ptr(&p), ptr(&feature), ptr(&vars), ptr(&output));
}
virtual void add_expressions(expression_set &output) const
{
override o = this->get_override("add_expressions");
if (o)
{
python_block_auto_unblock b;
o(ptr(&output));
} else
{
formatting::node::add_expressions(output);
}
}
void default_add_expressions(expression_set &output) const
{
formatting::node::add_expressions(output);
}
};
*/
/*
struct TextNodeWrap
: formatting::text_node, wrapper<formatting::text_node>
{
TextNodeWrap(expression_ptr expr)
: formatting::text_node(expr), wrapper<formatting::text_node>() {}
TextNodeWrap(std::string expr_text)
: formatting::text_node(expr_text), wrapper<formatting::text_node>() {}
virtual void apply(evaluated_format_properties_ptr p, feature_impl const& feature, attributes const& vars, text_layout &output) const
{
if(override o = this->get_override("apply"))
{
python_block_auto_unblock b;
o(ptr(&p), ptr(&feature), ptr(&vars), ptr(&output));
}
else
{
formatting::text_node::apply(p, feature, vars, output);
}
}
void default_apply(evaluated_format_properties_ptr p, feature_impl const& feature, attributes const& vars, text_layout &output) const
{
formatting::text_node::apply(p, feature, vars, output);
}
};
*/
/*
struct FormatNodeWrap
: formatting::format_node, wrapper<formatting::format_node>
{
virtual void apply(evaluated_format_properties_ptr p, feature_impl const& feature, attributes const& vars, text_layout &output) const
{
if(override o = this->get_override("apply"))
{
python_block_auto_unblock b;
o(ptr(&p), ptr(&feature), ptr(&vars), ptr(&output));
}
else
{
formatting::format_node::apply(p, feature, vars ,output);
}
}
void default_apply(evaluated_format_properties_ptr p, feature_impl const& feature, attributes const& vars, text_layout &output) const
{
formatting::format_node::apply(p, feature, vars, output);
}
};
struct ExprFormatWrap: formatting::expression_format, wrapper<formatting::expression_format>
{
virtual void apply(evaluated_format_properties_ptr p, feature_impl const& feature, attributes const& vars, text_layout &output) const
{
if(override o = this->get_override("apply"))
{
python_block_auto_unblock b;
o(ptr(&p), ptr(&feature), ptr(&vars), ptr(&output));
}
else
{
formatting::expression_format::apply(p, feature, vars, output);
}
}
void default_apply(evaluated_format_properties_ptr p, feature_impl const& feature, attributes const& vars, text_layout &output) const
{
formatting::expression_format::apply(p, feature, vars, output);
}
};
struct LayoutNodeWrap: formatting::layout_node, wrapper<formatting::layout_node>
{
virtual void apply(evaluated_format_properties_ptr p, feature_impl const& feature, attributes const& vars, text_layout &output) const
{
if(override o = this->get_override("apply"))
{
python_block_auto_unblock b;
o(ptr(&p), ptr(&feature), ptr(&vars), ptr(&output));
}
else
{
formatting::layout_node::apply(p, feature, vars, output);
}
}
void default_apply(evaluated_format_properties_ptr p, feature_impl const& feature, attributes const& vars, text_layout &output) const
{
formatting::layout_node::apply(p, feature, vars, output);
}
};
struct ListNodeWrap: formatting::list_node, wrapper<formatting::list_node>
{
//Default constructor
ListNodeWrap() : formatting::list_node(), wrapper<formatting::list_node>()
{
}
//Special constructor: Takes a python sequence as its argument
ListNodeWrap(object l) : formatting::list_node(), wrapper<formatting::list_node>()
{
stl_input_iterator<formatting::node_ptr> begin(l), end;
while (begin != end)
{
children_.push_back(*begin);
++begin;
}
}
// TODO: Add constructor taking variable number of arguments.
http://wiki.python.org/moin/boost.python/HowTo#A.22Raw.22_function
virtual void apply(evaluated_format_properties_ptr p, feature_impl const& feature, attributes const& vars, text_layout &output) const
{
if(override o = this->get_override("apply"))
{
python_block_auto_unblock b;
o(ptr(&p), ptr(&feature), ptr(&vars), ptr(&output));
}
else
{
formatting::list_node::apply(p, feature, vars, output);
}
}
void default_apply(evaluated_format_properties_ptr p, feature_impl const& feature, attributes const& vars, text_layout &output) const
{
formatting::list_node::apply(p, feature, vars, output);
}
inline void IndexError(){
PyErr_SetString(PyExc_IndexError, "Index out of range");
throw_error_already_set();
}
unsigned get_length()
{
return children_.size();
}
formatting::node_ptr get_item(int i)
{
if (i < 0) i+= children_.size();
if (i < static_cast<int>(children_.size())) return children_[i];
IndexError();
return formatting::node_ptr(); //Avoid compiler warning
}
void set_item(int i, formatting::node_ptr ptr)
{
if (i < 0) i+= children_.size();
if (i < static_cast<int>(children_.size())) children_[i] = ptr;
IndexError();
}
void append(formatting::node_ptr ptr)
{
children_.push_back(ptr);
}
};
*/
/*
struct TextPlacementsWrap: text_placements, wrapper<text_placements>
{
text_placement_info_ptr get_placement_info(double scale_factor_) const
{
python_block_auto_unblock b;
//return this->get_override("get_placement_info")();
return text_placement_info_ptr();
}
};
struct TextPlacementInfoWrap: text_placement_info, wrapper<text_placement_info>
{
TextPlacementInfoWrap(text_placements const* parent,
double scale_factor_)
: text_placement_info(parent, scale_factor_)
{
}
bool next()
{
python_block_auto_unblock b;
return this->get_override("next")();
}
};
void insert_expression(expression_set *set, expression_ptr p)
{
set->insert(p);
}
evaluated_format_properties_ptr get_format(text_symbolizer const& sym)
{
return sym.get_placement_options()->defaults.format;
}
void set_format(text_symbolizer const& sym, evaluated_format_properties_ptr format)
{
sym.get_placement_options()->defaults.format = format;
}
text_symbolizer_properties & get_properties(text_symbolizer const& sym)
{
return sym.get_placement_options()->defaults;
}
void set_properties(text_symbolizer const& sym, text_symbolizer_properties & defaults)
{
sym.get_placement_options()->defaults = defaults;
}
*/
}
void export_text_placement()
{
/*
using namespace boost::python;
enumeration_<label_placement_e>("label_placement")
.value("LINE_PLACEMENT",LINE_PLACEMENT)
.value("POINT_PLACEMENT",POINT_PLACEMENT)
.value("VERTEX_PLACEMENT",VERTEX_PLACEMENT)
.value("INTERIOR_PLACEMENT",INTERIOR_PLACEMENT)
;
enumeration_<vertical_alignment_e>("vertical_alignment")
.value("TOP",V_TOP)
.value("MIDDLE",V_MIDDLE)
.value("BOTTOM",V_BOTTOM)
.value("AUTO",V_AUTO)
;
enumeration_<horizontal_alignment_e>("horizontal_alignment")
.value("LEFT",H_LEFT)
.value("MIDDLE",H_MIDDLE)
.value("RIGHT",H_RIGHT)
.value("AUTO",H_AUTO)
;
enumeration_<justify_alignment_e>("justify_alignment")
.value("LEFT",J_LEFT)
.value("MIDDLE",J_MIDDLE)
.value("RIGHT",J_RIGHT)
.value("AUTO", J_AUTO)
;
enumeration_<text_transform_e>("text_transform")
.value("NONE",NONE)
.value("UPPERCASE",UPPERCASE)
.value("LOWERCASE",LOWERCASE)
.value("CAPITALIZE",CAPITALIZE)
;
enumeration_<halo_rasterizer_e>("halo_rasterizer")
.value("FULL",HALO_RASTERIZER_FULL)
.value("FAST",HALO_RASTERIZER_FAST)
;
*/
class_<text_symbolizer>("TextSymbolizer",
init<>())
;
/*
class_with_converter<text_symbolizer_properties>
("TextSymbolizerProperties")
.def_readwrite_convert("label_placement", &text_symbolizer_properties::label_placement)
.def_readwrite_convert("upright", &text_symbolizer_properties::upright)
.def_readwrite("label_spacing", &text_symbolizer_properties::label_spacing)
.def_readwrite("label_position_tolerance", &text_symbolizer_properties::label_position_tolerance)
.def_readwrite("avoid_edges", &text_symbolizer_properties::avoid_edges)
.def_readwrite("margin", &text_symbolizer_properties::margin)
.def_readwrite("repeat_distance", &text_symbolizer_properties::repeat_distance)
.def_readwrite("minimum_distance", &text_symbolizer_properties::minimum_distance)
.def_readwrite("minimum_padding", &text_symbolizer_properties::minimum_padding)
.def_readwrite("minimum_path_length", &text_symbolizer_properties::minimum_path_length)
.def_readwrite("maximum_angle_char_delta", &text_symbolizer_properties::max_char_angle_delta)
.def_readwrite("allow_overlap", &text_symbolizer_properties::allow_overlap)
.def_readwrite("largest_bbox_only", &text_symbolizer_properties::largest_bbox_only)
.def_readwrite("layout_defaults", &text_symbolizer_properties::layout_defaults)
//.def_readwrite("format", &text_symbolizer_properties::format)
.add_property ("format_tree",
&text_symbolizer_properties::format_tree,
&text_symbolizer_properties::set_format_tree);
//from_xml, to_xml operate on mapnik's internal XML tree and don't make sense in python.
// add_expressions isn't useful in python either. The result is only needed by
// attribute_collector (which isn't exposed in python) and
// it just calls add_expressions of the associated formatting tree.
// set_old_style expression is just a compatibility wrapper and doesn't need to be exposed in python.
;
class_with_converter<text_layout_properties>
("TextLayoutProperties")
.def_readwrite_convert("horizontal_alignment", &text_layout_properties::halign)
.def_readwrite_convert("justify_alignment", &text_layout_properties::jalign)
.def_readwrite_convert("vertical_alignment", &text_layout_properties::valign)
.def_readwrite("text_ratio", &text_layout_properties::text_ratio)
.def_readwrite("wrap_width", &text_layout_properties::wrap_width)
.def_readwrite("wrap_before", &text_layout_properties::wrap_before)
.def_readwrite("orientation", &text_layout_properties::orientation)
.def_readwrite("rotate_displacement", &text_layout_properties::rotate_displacement)
.add_property("displacement", &get_displacement, &set_displacement);
class_with_converter<detail::evaluated_format_properties>
("CharProperties")
.def_readwrite_convert("text_transform", &detail::evaluated_format_properties::text_transform)
.def_readwrite_convert("fontset", &detail::evaluated_format_properties::fontset)
.def(init<detail::evaluated_format_properties const&>()) //Copy constructor
.def_readwrite("face_name", &detail::evaluated_format_properties::face_name)
.def_readwrite("text_size", &detail::evaluated_format_properties::text_size)
.def_readwrite("character_spacing", &detail::evaluated_format_properties::character_spacing)
.def_readwrite("line_spacing", &detail::evaluated_format_properties::line_spacing)
.def_readwrite("text_opacity", &detail::evaluated_format_properties::text_opacity)
.def_readwrite("fill", &detail::evaluated_format_properties::fill)
.def_readwrite("halo_fill", &detail::evaluated_format_properties::halo_fill)
.def_readwrite("halo_radius", &evaluated_format_properties::halo_radius)
//from_xml, to_xml operate on mapnik's internal XML tree and don't make sense in python.
;
class_<TextPlacementsWrap,
std::shared_ptr<TextPlacementsWrap>,
boost::noncopyable>
("TextPlacements")
.def_readwrite("defaults", &text_placements::defaults)
//.def("get_placement_info", pure_virtual(&text_placements::get_placement_info))
// TODO: add_expressions()
;
register_ptr_to_python<std::shared_ptr<text_placements> >();
class_<TextPlacementInfoWrap,
std::shared_ptr<TextPlacementInfoWrap>,
boost::noncopyable>
("TextPlacementInfo",
init<text_placements const*, double>())
.def("next", pure_virtual(&text_placement_info::next))
.def_readwrite("properties", &text_placement_info::properties)
.def_readwrite("scale_factor", &text_placement_info::scale_factor)
;
register_ptr_to_python<std::shared_ptr<text_placement_info> >();
class_<expression_set,std::shared_ptr<expression_set>,
boost::noncopyable>("ExpressionSet")
.def("insert", &insert_expression);
;
class_<formatting::node,std::shared_ptr<formatting::node>,
boost::noncopyable>("FormattingNode")
.def("apply", pure_virtual(&formatting::node::apply))
.def("add_expressions", pure_virtual(&formatting::node::add_expressions))
.def("to_xml", pure_virtual(&formatting::node::to_xml))
;
register_ptr_to_python<std::shared_ptr<formatting::node> >();
class_<formatting::text_node,
std::shared_ptr<formatting::text_node>,
bases<formatting::node>,boost::noncopyable>("FormattingText", init<expression_ptr>())
.def(init<std::string>())
.def("apply", &formatting::text_node::apply)//, &TextNodeWrap::default_apply)
.add_property("text",&formatting::text_node::get_text, &formatting::text_node::set_text)
;
register_ptr_to_python<std::shared_ptr<formatting::text_node> >();
class_with_converter<FormatNodeWrap,
std::shared_ptr<FormatNodeWrap>,
bases<formatting::node>,
boost::noncopyable>
("FormattingFormat")
.def_readwrite_convert("text_size", &formatting::format_node::text_size)
.def_readwrite_convert("face_name", &formatting::format_node::face_name)
.def_readwrite_convert("character_spacing", &formatting::format_node::character_spacing)
.def_readwrite_convert("line_spacing", &formatting::format_node::line_spacing)
.def_readwrite_convert("text_opacity", &formatting::format_node::text_opacity)
.def_readwrite_convert("text_transform", &formatting::format_node::text_transform)
.def_readwrite_convert("fill", &formatting::format_node::fill)
.def_readwrite_convert("halo_fill", &formatting::format_node::halo_fill)
.def_readwrite_convert("halo_radius", &formatting::format_node::halo_radius)
.def("apply", &formatting::format_node::apply, &FormatNodeWrap::default_apply)
.add_property("child",
&formatting::format_node::get_child,
&formatting::format_node::set_child)
;
register_ptr_to_python<std::shared_ptr<formatting::format_node> >();
class_<ListNodeWrap,
std::shared_ptr<ListNodeWrap>,
bases<formatting::node>,
boost::noncopyable>
("FormattingList", init<>())
.def(init<list>())
.def("append", &formatting::list_node::push_back)
.def("apply", &formatting::list_node::apply, &ListNodeWrap::default_apply)
.def("__len__", &ListNodeWrap::get_length)
.def("__getitem__", &ListNodeWrap::get_item)
.def("__setitem__", &ListNodeWrap::set_item)
.def("append", &ListNodeWrap::append)
;
register_ptr_to_python<std::shared_ptr<formatting::list_node> >();
class_<ExprFormatWrap,
std::shared_ptr<ExprFormatWrap>,
bases<formatting::node>,
boost::noncopyable>
("FormattingExpressionFormat")
.def_readwrite("text_size", &formatting::expression_format::text_size)
.def_readwrite("face_name", &formatting::expression_format::face_name)
.def_readwrite("character_spacing", &formatting::expression_format::character_spacing)
.def_readwrite("line_spacing", &formatting::expression_format::line_spacing)
.def_readwrite("text_opacity", &formatting::expression_format::text_opacity)
.def_readwrite("fill", &formatting::expression_format::fill)
.def_readwrite("halo_fill", &formatting::expression_format::halo_fill)
.def_readwrite("halo_radius", &formatting::expression_format::halo_radius)
.def("apply", &formatting::expression_format::apply, &ExprFormatWrap::default_apply)
.add_property("child",
&formatting::expression_format::get_child,
&formatting::expression_format::set_child)
;
register_ptr_to_python<std::shared_ptr<formatting::expression_format> >();
*/
//TODO: registry
}

View file

@ -1,109 +0,0 @@
/*****************************************************************************
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2014 Artem Pavlenko, Jean-Francois Doyon
*
* 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
*
*****************************************************************************/
#ifndef MAPNIK_THREADS_HPP
#define MAPNIK_THREADS_HPP
#include <boost/thread/tss.hpp> // for thread_specific_ptr
#include <Python.h>
namespace mapnik {
class python_thread
{
/* Docs:
http://docs.python.org/c-api/init.html#thread-state-and-the-global-interpreter-lock
*/
public:
static void unblock()
{
#ifdef MAPNIK_DEBUG
if (state.get())
{
std::cerr << "ERROR: Python threads are already unblocked. "
"Unblocking again will loose the current state and "
"might crash later. Aborting!\n";
abort(); //This is a serious error and can't be handled in any other sane way
}
#endif
PyThreadState *_save = 0; //Name defined by python
Py_UNBLOCK_THREADS;
state.reset(_save);
#ifdef MAPNIK_DEBUG
if (!_save) {
thread_support = false;
}
#endif
}
static void block()
{
#ifdef MAPNIK_DEBUG
if (thread_support && !state.get())
{
std::cerr << "ERROR: Trying to restore python thread state, "
"but no state is saved. Can't continue and also "
"can't raise an exception because the python "
"interpreter might be non-function. Aborting!\n";
abort();
}
#endif
PyThreadState *_save = state.release(); //Name defined by python
Py_BLOCK_THREADS;
}
private:
static boost::thread_specific_ptr<PyThreadState> state;
#ifdef MAPNIK_DEBUG
static bool thread_support;
#endif
};
class python_block_auto_unblock
{
public:
python_block_auto_unblock()
{
python_thread::block();
}
~python_block_auto_unblock()
{
python_thread::unblock();
}
};
class python_unblock_auto_block
{
public:
python_unblock_auto_block()
{
python_thread::unblock();
}
~python_unblock_auto_block()
{
python_thread::block();
}
};
} //namespace
#endif // MAPNIK_THREADS_HPP

View file

@ -1,90 +0,0 @@
/*****************************************************************************
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2014 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
*
*****************************************************************************/
#ifndef MAPNIK_PYTHON_BINDING_VALUE_CONVERTER_INCLUDED
#define MAPNIK_PYTHON_BINDING_VALUE_CONVERTER_INCLUDED
// mapnik
#include <mapnik/value.hpp>
#include <mapnik/util/variant.hpp>
// boost
#include <boost/python.hpp>
#include <boost/implicit_cast.hpp>
namespace boost { namespace python {
struct value_converter
{
PyObject * operator() (mapnik::value_integer val) const
{
return ::PyLong_FromLongLong(val);
}
PyObject * operator() (mapnik::value_double val) const
{
return ::PyFloat_FromDouble(val);
}
PyObject * operator() (mapnik::value_bool val) const
{
return ::PyBool_FromLong(val);
}
PyObject * operator() (std::string const& s) const
{
return ::PyUnicode_DecodeUTF8(s.c_str(),implicit_cast<ssize_t>(s.length()),0);
}
PyObject * operator() (mapnik::value_unicode_string const& s) const
{
std::string buffer;
mapnik::to_utf8(s,buffer);
return ::PyUnicode_DecodeUTF8(buffer.c_str(),implicit_cast<ssize_t>(buffer.length()),0);
}
PyObject * operator() (mapnik::value_null const& /*s*/) const
{
Py_RETURN_NONE;
}
};
struct mapnik_value_to_python
{
static PyObject* convert(mapnik::value const& v)
{
return mapnik::util::apply_visitor(value_converter(),v);
}
};
struct mapnik_param_to_python
{
static PyObject* convert(mapnik::value_holder const& v)
{
return mapnik::util::apply_visitor(value_converter(),v);
}
};
}}
#endif // MAPNIK_PYTHON_BINDING_VALUE_CONVERTER_INCLUDED

View file

@ -1,92 +0,0 @@
/*****************************************************************************
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2014 Artem Pavlenko, Jean-Francois Doyon
*
* 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 <mapnik/config.hpp>
// boost
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-parameter"
#pragma GCC diagnostic ignored "-Wunused-local-typedef"
#pragma GCC diagnostic ignored "-Wmissing-field-initializers"
#include <boost/python.hpp>
#pragma GCC diagnostic pop
// mapnik
#include <mapnik/view_transform.hpp>
using mapnik::view_transform;
struct view_transform_pickle_suite : boost::python::pickle_suite
{
static boost::python::tuple
getinitargs(const view_transform& c)
{
using namespace boost::python;
return boost::python::make_tuple(c.width(),c.height(),c.extent());
}
};
namespace {
mapnik::coord2d forward_point(mapnik::view_transform const& t, mapnik::coord2d const& in)
{
mapnik::coord2d out(in);
t.forward(out);
return out;
}
mapnik::coord2d backward_point(mapnik::view_transform const& t, mapnik::coord2d const& in)
{
mapnik::coord2d out(in);
t.backward(out);
return out;
}
mapnik::box2d<double> forward_envelope(mapnik::view_transform const& t, mapnik::box2d<double> const& in)
{
return t.forward(in);
}
mapnik::box2d<double> backward_envelope(mapnik::view_transform const& t, mapnik::box2d<double> const& in)
{
return t.backward(in);
}
}
void export_view_transform()
{
using namespace boost::python;
using mapnik::box2d;
using mapnik::coord2d;
class_<view_transform>("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())
.def("forward", forward_point)
.def("backward",backward_point)
.def("forward", forward_envelope)
.def("backward",backward_envelope)
.def("scale_x",&view_transform::scale_x)
.def("scale_y",&view_transform::scale_y)
;
}

View file

@ -1,405 +0,0 @@
/*****************************************************************************
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2014 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
*
*****************************************************************************/
#if defined(GRID_RENDERER)
#include <mapnik/config.hpp>
// boost
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-parameter"
#pragma GCC diagnostic ignored "-Wunused-local-typedef"
#pragma GCC diagnostic ignored "-Wmissing-field-initializers"
#include <boost/python.hpp>
#pragma GCC diagnostic pop
// mapnik
#include <mapnik/map.hpp>
#include <mapnik/layer.hpp>
#include <mapnik/debug.hpp>
#include <mapnik/grid/grid_renderer.hpp>
#include <mapnik/grid/grid.hpp>
#include <mapnik/grid/grid_util.hpp>
#include <mapnik/grid/grid_view.hpp>
#include <mapnik/value_error.hpp>
#include <mapnik/feature.hpp>
#include <mapnik/feature_kv_iterator.hpp>
#include "python_grid_utils.hpp"
// stl
#include <stdexcept>
namespace mapnik {
template <typename T>
void grid2utf(T const& grid_type,
boost::python::list& l,
std::vector<typename T::lookup_type>& key_order)
{
using keys_type = std::map< typename T::lookup_type, typename T::value_type>;
using keys_iterator = typename keys_type::iterator;
typename T::data_type const& data = grid_type.data();
typename T::feature_key_type const& feature_keys = grid_type.get_feature_keys();
typename T::feature_key_type::const_iterator feature_pos;
keys_type keys;
// start counting at utf8 codepoint 32, aka space character
std::uint16_t codepoint = 32;
unsigned array_size = data.width();
for (unsigned y = 0; y < data.height(); ++y)
{
std::uint16_t idx = 0;
const std::unique_ptr<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)
{
typename T::value_type feature_id = row[x];
feature_pos = feature_keys.find(feature_id);
if (feature_pos != feature_keys.end())
{
mapnik::grid::lookup_type val = feature_pos->second;
keys_iterator key_pos = keys.find(val);
if (key_pos == keys.end())
{
// Create a new entry for this key. Skip the codepoints that
// can't be encoded directly in JSON.
if (codepoint == 34) ++codepoint; // Skip "
else if (codepoint == 92) ++codepoint; // Skip backslash
if (feature_id == mapnik::grid::base_mask)
{
keys[""] = codepoint;
key_order.push_back("");
}
else
{
keys[val] = codepoint;
key_order.push_back(val);
}
line[idx++] = static_cast<Py_UNICODE>(codepoint);
++codepoint;
}
else
{
line[idx++] = static_cast<Py_UNICODE>(key_pos->second);
}
}
// else, shouldn't get here...
}
l.append(boost::python::object(
boost::python::handle<>(
PyUnicode_FromUnicode(line.get(), array_size))));
}
}
template <typename T>
void grid2utf(T const& grid_type,
boost::python::list& l,
std::vector<typename T::lookup_type>& key_order,
unsigned int resolution)
{
using keys_type = std::map< typename T::lookup_type, typename T::value_type>;
using keys_iterator = typename keys_type::iterator;
typename T::feature_key_type const& feature_keys = grid_type.get_feature_keys();
typename T::feature_key_type::const_iterator feature_pos;
keys_type keys;
// start counting at utf8 codepoint 32, aka space character
std::uint16_t codepoint = 32;
unsigned array_size = std::ceil(grid_type.width()/static_cast<float>(resolution));
for (unsigned y = 0; y < grid_type.height(); y=y+resolution)
{
std::uint16_t idx = 0;
const std::unique_ptr<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)
{
typename T::value_type feature_id = row[x];
feature_pos = feature_keys.find(feature_id);
if (feature_pos != feature_keys.end())
{
mapnik::grid::lookup_type val = feature_pos->second;
keys_iterator key_pos = keys.find(val);
if (key_pos == keys.end())
{
// Create a new entry for this key. Skip the codepoints that
// can't be encoded directly in JSON.
if (codepoint == 34) ++codepoint; // Skip "
else if (codepoint == 92) ++codepoint; // Skip backslash
if (feature_id == mapnik::grid::base_mask)
{
keys[""] = codepoint;
key_order.push_back("");
}
else
{
keys[val] = codepoint;
key_order.push_back(val);
}
line[idx++] = static_cast<Py_UNICODE>(codepoint);
++codepoint;
}
else
{
line[idx++] = static_cast<Py_UNICODE>(key_pos->second);
}
}
// else, shouldn't get here...
}
l.append(boost::python::object(
boost::python::handle<>(
PyUnicode_FromUnicode(line.get(), array_size))));
}
}
template <typename T>
void grid2utf2(T const& grid_type,
boost::python::list& l,
std::vector<typename T::lookup_type>& key_order,
unsigned int resolution)
{
using keys_type = std::map< typename T::lookup_type, typename T::value_type>;
using keys_iterator = typename keys_type::iterator;
typename T::data_type const& data = grid_type.data();
typename T::feature_key_type const& feature_keys = grid_type.get_feature_keys();
typename T::feature_key_type::const_iterator feature_pos;
keys_type keys;
// start counting at utf8 codepoint 32, aka space character
uint16_t codepoint = 32;
mapnik::grid::data_type target(data.width()/resolution,data.height()/resolution);
mapnik::scale_grid(target,grid_type.data(),0.0,0.0);
unsigned array_size = target.width();
for (unsigned y = 0; y < target.height(); ++y)
{
uint16_t idx = 0;
const std::unique_ptr<Py_UNICODE[]> line(new Py_UNICODE[array_size]);
mapnik::grid::value_type * row = target.getRow(y);
unsigned x;
for (x = 0; x < target.width(); ++x)
{
feature_pos = feature_keys.find(row[x]);
if (feature_pos != feature_keys.end())
{
mapnik::grid::lookup_type val = feature_pos->second;
keys_iterator key_pos = keys.find(val);
if (key_pos == keys.end())
{
// Create a new entry for this key. Skip the codepoints that
// 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);
++codepoint;
}
else
{
line[idx++] = static_cast<Py_UNICODE>(key_pos->second);
}
}
// else, shouldn't get here...
}
l.append(boost::python::object(
boost::python::handle<>(
PyUnicode_FromUnicode(line.get(), array_size))));
}
}
template <typename T>
void write_features(T const& grid_type,
boost::python::dict& feature_data,
std::vector<typename T::lookup_type> const& key_order)
{
typename T::feature_type const& g_features = grid_type.get_grid_features();
if (g_features.size() <= 0)
{
return;
}
std::set<std::string> const& attributes = grid_type.get_fields();
typename T::feature_type::const_iterator feat_end = g_features.end();
for ( std::string const& key_item :key_order )
{
if (key_item.empty())
{
continue;
}
typename T::feature_type::const_iterator feat_itr = g_features.find(key_item);
if (feat_itr == feat_end)
{
continue;
}
bool found = false;
boost::python::dict feat;
mapnik::feature_ptr feature = feat_itr->second;
for ( std::string const& attr : attributes )
{
if (attr == "__id__")
{
feat[attr.c_str()] = feature->id();
}
else if (feature->has_key(attr))
{
found = true;
feat[attr.c_str()] = feature->get(attr);
}
}
if (found)
{
feature_data[feat_itr->first] = feat;
}
}
}
template <typename T>
void grid_encode_utf(T const& grid_type,
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);
// resample first - slower, more accurate
//mapnik::grid2utf2<T>(grid_type,l,key_order,resolution);
}
else
{
mapnik::grid2utf<T>(grid_type,l,key_order);
}
// convert key order to proper python list
boost::python::list keys_a;
for ( typename T::lookup_type const& key_id : key_order )
{
keys_a.append(key_id);
}
// gather feature data
boost::python::dict feature_data;
if (add_features) {
mapnik::write_features<T>(grid_type,feature_data,key_order);
}
json["grid"] = l;
json["keys"] = keys_a;
json["data"] = feature_data;
}
template <typename T>
boost::python::dict grid_encode( T const& grid, std::string const& format, bool add_features, unsigned int resolution)
{
if (format == "utf") {
boost::python::dict json;
grid_encode_utf<T>(grid,json,add_features,resolution);
return json;
}
else
{
std::stringstream s;
s << "'utf' is currently the only supported encoding format.";
throw mapnik::value_error(s.str());
}
}
template boost::python::dict grid_encode( mapnik::grid const& grid, std::string const& format, bool add_features, unsigned int resolution);
template boost::python::dict grid_encode( mapnik::grid_view const& grid, std::string const& format, bool add_features, unsigned int resolution);
void render_layer_for_grid(mapnik::Map const& map,
mapnik::grid & grid,
unsigned layer_idx,
boost::python::list const& fields,
double scale_factor,
unsigned offset_x,
unsigned offset_y)
{
std::vector<mapnik::layer> const& layers = map.layers();
std::size_t layer_num = layers.size();
if (layer_idx >= layer_num) {
std::ostringstream s;
s << "Zero-based layer index '" << layer_idx << "' not valid, only '"
<< layer_num << "' layers are in map\n";
throw std::runtime_error(s.str());
}
// convert python list to std::set
boost::python::ssize_t num_fields = boost::python::len(fields);
for(boost::python::ssize_t i=0; i<num_fields; i++) {
boost::python::extract<std::string> name(fields[i]);
if (name.check())
{
grid.add_field(name());
}
else
{
std::stringstream s;
s << "list of field names must be strings";
throw mapnik::value_error(s.str());
}
}
// copy field names
std::set<std::string> attributes = grid.get_fields();
// todo - make this a static constant
std::string known_id_key = "__id__";
if (attributes.find(known_id_key) != attributes.end())
{
attributes.erase(known_id_key);
}
std::string join_field = grid.get_key();
if (known_id_key != join_field &&
attributes.find(join_field) == attributes.end())
{
attributes.insert(join_field);
}
mapnik::grid_renderer<mapnik::grid> ren(map,grid,scale_factor,offset_x,offset_y);
mapnik::layer const& layer = layers[layer_idx];
ren.apply(layer,attributes);
}
}
#endif

View file

@ -1,79 +0,0 @@
/*****************************************************************************
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2014 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
*
*****************************************************************************/
#ifndef MAPNIK_PYTHON_BINDING_GRID_UTILS_INCLUDED
#define MAPNIK_PYTHON_BINDING_GRID_UTILS_INCLUDED
// boost
#include <boost/python.hpp>
// mapnik
#include <mapnik/map.hpp>
#include <mapnik/grid/grid.hpp>
namespace mapnik {
template <typename T>
void grid2utf(T const& grid_type,
boost::python::list& l,
std::vector<typename T::lookup_type>& key_order);
template <typename T>
void grid2utf(T const& grid_type,
boost::python::list& l,
std::vector<typename T::lookup_type>& key_order,
unsigned int resolution);
template <typename T>
void grid2utf2(T const& grid_type,
boost::python::list& l,
std::vector<typename T::lookup_type>& key_order,
unsigned int resolution);
template <typename T>
void write_features(T const& grid_type,
boost::python::dict& feature_data,
std::vector<typename T::lookup_type> const& key_order);
template <typename T>
void grid_encode_utf(T const& grid_type,
boost::python::dict & json,
bool add_features,
unsigned int resolution);
template <typename T>
boost::python::dict grid_encode( T const& grid, std::string const& format, bool add_features, unsigned int resolution);
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,
double scale_factor,
unsigned offset_x,
unsigned offset_y);
}
#endif // MAPNIK_PYTHON_BINDING_GRID_UTILS_INCLUDED

View file

@ -1,198 +0,0 @@
/*****************************************************************************
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2014 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/optional/optional.hpp>
#include <boost/python.hpp>
#include <mapnik/util/noncopyable.hpp>
// boost::optional<T> to/from converter from John Wiegley
template <typename T, typename TfromPy>
struct object_from_python
{
object_from_python() {
boost::python::converter::registry::push_back
(&TfromPy::convertible, &TfromPy::construct,
boost::python::type_id<T>());
}
};
template <typename T, typename TtoPy, typename TfromPy>
struct register_python_conversion
{
register_python_conversion() {
boost::python::to_python_converter<T, TtoPy>();
object_from_python<T, TfromPy>();
}
};
template <typename T>
struct python_optional : public mapnik::util::noncopyable
{
struct optional_to_python
{
static PyObject * convert(const boost::optional<T>& value)
{
return (value ? boost::python::to_python_value<T>()(*value) :
boost::python::detail::none());
}
};
struct optional_from_python
{
static void * convertible(PyObject * source)
{
using namespace boost::python::converter;
if (source == Py_None)
return source;
const registration& converters(registered<T>::converters);
if (implicit_rvalue_convertible_from_python(source,
converters)) {
rvalue_from_python_stage1_data data =
rvalue_from_python_stage1(source, converters);
return rvalue_from_python_stage2(source, data, converters);
}
return 0;
}
static void construct(PyObject * source,
boost::python::converter::rvalue_from_python_stage1_data * data)
{
using namespace boost::python::converter;
void * const storage = ((rvalue_from_python_storage<T> *)
data)->storage.bytes;
if (data->convertible == source) // == None
new (storage) boost::optional<T>(); // A Boost uninitialized value
else
new (storage) boost::optional<T>(*static_cast<T *>(data->convertible));
data->convertible = storage;
}
};
explicit python_optional()
{
register_python_conversion<boost::optional<T>,
optional_to_python, optional_from_python>();
}
};
// to/from boost::optional<bool>
template <>
struct python_optional<float> : public mapnik::util::noncopyable
{
struct optional_to_python
{
static PyObject * convert(const boost::optional<float>& value)
{
return (value ? PyFloat_FromDouble(*value) :
boost::python::detail::none());
}
};
struct optional_from_python
{
static void * convertible(PyObject * source)
{
using namespace boost::python::converter;
if (source == Py_None || PyFloat_Check(source))
return source;
return 0;
}
static void construct(PyObject * source,
boost::python::converter::rvalue_from_python_stage1_data * data)
{
using namespace boost::python::converter;
void * const storage = ((rvalue_from_python_storage<boost::optional<bool> > *)
data)->storage.bytes;
if (source == Py_None) // == None
new (storage) boost::optional<float>(); // A Boost uninitialized value
else
new (storage) boost::optional<float>(PyFloat_AsDouble(source));
data->convertible = storage;
}
};
explicit python_optional()
{
register_python_conversion<boost::optional<float>,
optional_to_python, optional_from_python>();
}
};
// to/from boost::optional<float>
template <>
struct python_optional<bool> : public mapnik::util::noncopyable
{
struct optional_to_python
{
static PyObject * convert(const boost::optional<bool>& value)
{
if (value)
{
if (*value) Py_RETURN_TRUE;
else Py_RETURN_FALSE;
}
else return boost::python::detail::none();
}
};
struct optional_from_python
{
static void * convertible(PyObject * source)
{
using namespace boost::python::converter;
if (source == Py_None || PyBool_Check(source))
return source;
return 0;
}
static void construct(PyObject * source,
boost::python::converter::rvalue_from_python_stage1_data * data)
{
using namespace boost::python::converter;
void * const storage = ((rvalue_from_python_storage<boost::optional<bool> > *)
data)->storage.bytes;
if (source == Py_None) // == None
new (storage) boost::optional<bool>(); // A Boost uninitialized value
else
{
new (storage) boost::optional<bool>(source == Py_True ? true : false);
}
data->convertible = storage;
}
};
explicit python_optional()
{
register_python_conversion<boost::optional<bool>,
optional_to_python, optional_from_python>();
}
};

View file

@ -1,122 +0,0 @@
/*****************************************************************************
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2014 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
*
*****************************************************************************/
#ifndef MAPNIK_PYTHON_BINDING_PYTHON_TO_VALUE
#define MAPNIK_PYTHON_BINDING_PYTHON_TO_VALUE
// boost
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-parameter"
#pragma GCC diagnostic ignored "-Wunused-local-typedef"
#pragma GCC diagnostic ignored "-Wmissing-field-initializers"
#include <boost/python.hpp>
#pragma GCC diagnostic pop
// mapnik
#include <mapnik/value.hpp>
#include <mapnik/unicode.hpp>
#include <mapnik/attribute.hpp>
namespace mapnik {
static mapnik::attributes dict2attr(boost::python::dict const& d)
{
using namespace boost::python;
mapnik::attributes vars;
mapnik::transcoder tr_("utf8");
boost::python::list keys=d.keys();
for (int i=0; i < len(keys); ++i)
{
std::string key;
object obj_key = keys[i];
if (PyUnicode_Check(obj_key.ptr()))
{
PyObject* temp = PyUnicode_AsUTF8String(obj_key.ptr());
if (temp)
{
#if PY_VERSION_HEX >= 0x03000000
char* c_str = PyBytes_AsString(temp);
#else
char* c_str = PyString_AsString(temp);
#endif
key = c_str;
Py_DecRef(temp);
}
}
else
{
key = extract<std::string>(keys[i]);
}
object obj = d[key];
if (PyUnicode_Check(obj.ptr()))
{
PyObject* temp = PyUnicode_AsUTF8String(obj.ptr());
if (temp)
{
#if PY_VERSION_HEX >= 0x03000000
char* c_str = PyBytes_AsString(temp);
#else
char* c_str = PyString_AsString(temp);
#endif
vars[key] = tr_.transcode(c_str);
Py_DecRef(temp);
}
continue;
}
if (PyBool_Check(obj.ptr()))
{
extract<mapnik::value_bool> ex(obj);
if (ex.check())
{
vars[key] = ex();
}
}
else if (PyFloat_Check(obj.ptr()))
{
extract<mapnik::value_double> ex(obj);
if (ex.check())
{
vars[key] = ex();
}
}
else
{
extract<mapnik::value_integer> ex(obj);
if (ex.check())
{
vars[key] = ex();
}
else
{
extract<std::string> ex0(obj);
if (ex0.check())
{
vars[key] = tr_.transcode(ex0().c_str());
}
}
}
}
return vars;
}
}
#endif // MAPNIK_PYTHON_BINDING_PYTHON_TO_VALUE

View file

@ -8,7 +8,7 @@ todo
- gdal shared lib / avoid dlclose atexit crash
- clang debs to s3
- docs for base setup: sudo apt-get -y install zlib1g-dev python-dev make git python-dev
- docs for base setup: sudo apt-get -y install zlib1g-dev make git
- shrink icu data
'
@ -50,7 +50,6 @@ function install_mason_deps() {
install boost_libfilesystem 1.57.0
install boost_libprogram_options 1.57.0
install boost_libregex 1.57.0
install boost_libpython 1.57.0
install libpq 9.4.0
install sqlite 3.8.8.1
install gdal 1.11.1
@ -59,14 +58,6 @@ function install_mason_deps() {
install cairo 1.12.18
}
function setup_nose() {
if [[ ! -d $(pwd)/nose-1.3.4 ]]; then
curl -s -O https://pypi.python.org/packages/source/n/nose/nose-1.3.4.tar.gz
tar -xzf nose-1.3.4.tar.gz
fi
export PYTHONPATH=$(pwd)/nose-1.3.4:${PYTHONPATH}
}
MASON_LINKED_ABS=$(pwd)/mason_packages/.link
MASON_LINKED_REL=./mason_packages/.link
@ -114,11 +105,9 @@ CAIRO_INCLUDES = '${MASON_LINKED_REL}/include'
CAIRO_LIBS = '${MASON_LINKED_REL}/lib'
SQLITE_INCLUDES = '${MASON_LINKED_REL}/include'
SQLITE_LIBS = '${MASON_LINKED_REL}/lib'
FRAMEWORK_PYTHON = False
BENCHMARK = True
CPP_TESTS = True
PGSQL2SQLITE = True
BINDINGS = 'python'
XMLPARSER = 'ptree'
SVG2PNG = True
SAMPLE_INPUT_PLUGINS = True
@ -134,7 +123,6 @@ function setup_runtime_settings() {
function main() {
setup_mason
install_mason_deps
setup_nose
make_config
setup_runtime_settings
echo "Ready, now run:"

View file

@ -6,7 +6,6 @@ if [ ${UNAME} = 'Darwin' ]; then
else
export LD_LIBRARY_PATH="${CURRENT_DIR}/src/":${LD_LIBRARY_PATH}
fi
export PYTHONPATH="${CURRENT_DIR}/bindings/python/":$PYTHONPATH
export MAPNIK_FONT_DIRECTORY="${CURRENT_DIR}/fonts/dejavu-fonts-ttf-2.34/ttf/"
export MAPNIK_INPUT_PLUGINS_DIRECTORY="${CURRENT_DIR}/plugins/input/"
export PATH="${CURRENT_DIR}/utils/mapnik-config":${PATH}

View file

@ -3,24 +3,10 @@
failures=0
source ./localize.sh
PYTHON=${PYTHON:-python}
echo "*** Running Next Gen C++ tests..."
echo "*** Running C++ tests..."
./tests/cxx/run
failures=$((failures+$?))
echo
echo "*** Running Old C++ tests..."
./tests/cpp_tests/run
failures=$((failures+$?))
echo
echo "*** Running visual tests..."
$PYTHON tests/visual_tests/test.py -q
failures=$((failures+$?))
echo "*** Running python tests..."
$PYTHON tests/run_tests.py -q
failures=$((failures+$?))
exit $failures

View file

@ -1,207 +0,0 @@
#include <mapnik/font_engine_freetype.hpp>
#include <mapnik/util/fs.hpp>
#include <mapnik/map.hpp>
#include <mapnik/load_map.hpp>
#include <mapnik/debug.hpp>
#include <boost/detail/lightweight_test.hpp>
#include <iostream>
#include <vector>
#include <algorithm>
#include "utils.hpp"
int main(int argc, char** argv)
{
std::vector<std::string> args;
for (int i=1;i<argc;++i)
{
args.push_back(argv[i]);
}
bool quiet = std::find(args.begin(), args.end(), "-q")!=args.end();
try
{
mapnik::logger logger;
mapnik::logger::severity_type original_severity = logger.get_severity();
BOOST_TEST(set_working_dir(args));
// grab references to global statics of registered/cached fonts
auto const& global_mapping = mapnik::freetype_engine::get_mapping();
auto const& global_cache = mapnik::freetype_engine::get_cache();
// mapnik.Map object has parallel structure for localized fonts
mapnik::Map m(1,1);
auto const& local_mapping = m.get_font_file_mapping();
auto const& local_cache = m.get_font_memory_cache();
// should be empty to start
BOOST_TEST( global_mapping.empty() );
BOOST_TEST( global_cache.empty() );
BOOST_TEST( local_mapping.empty() );
BOOST_TEST( local_cache.empty() );
std::string fontdir("fonts/");
BOOST_TEST( mapnik::util::exists( fontdir ) );
BOOST_TEST( mapnik::util::is_directory( fontdir ) );
// test map cached fonts
BOOST_TEST( m.register_fonts(fontdir , false ) );
BOOST_TEST( m.get_font_memory_cache().size() == 0 );
BOOST_TEST( m.get_font_file_mapping().size() == 1 );
BOOST_TEST( m.load_fonts() );
BOOST_TEST( m.get_font_memory_cache().size() == 1 );
BOOST_TEST( m.register_fonts(fontdir , true ) );
BOOST_TEST( m.get_font_file_mapping().size() == 22 );
BOOST_TEST( m.load_fonts() );
BOOST_TEST( m.get_font_memory_cache().size() == 22 );
// copy discards memory cache but not file mapping
mapnik::Map m2(m);
BOOST_TEST( m2.get_font_memory_cache().size() == 0 );
BOOST_TEST( m2.get_font_file_mapping().size() == 22 );
BOOST_TEST( m2.load_fonts() );
BOOST_TEST( m2.get_font_memory_cache().size() == 22 );
// test font-directory from XML
mapnik::Map m3(1,1);
mapnik::load_map_string(m3,"<Map font-directory=\"fonts/\"></Map>");
BOOST_TEST( m3.get_font_memory_cache().size() == 0 );
BOOST_TEST( m3.load_fonts() );
BOOST_TEST( m3.get_font_memory_cache().size() == 1 );
std::vector<std::string> face_names;
std::string foo("foo");
// fake directories
BOOST_TEST( !mapnik::freetype_engine::register_fonts(foo , true ) );
face_names = mapnik::freetype_engine::face_names();
BOOST_TEST( face_names.size() == 0 );
BOOST_TEST( !mapnik::freetype_engine::register_fonts(foo) );
face_names = mapnik::freetype_engine::face_names();
BOOST_TEST( face_names.size() == 0 );
// directories without fonts
// silence warnings here by altering the logging severity
logger.set_severity(mapnik::logger::none);
std::string src("src");
// an empty directory will not return true
// we need to register at least one font and not fail on any
// to return true
BOOST_TEST( mapnik::freetype_engine::register_font(src) == false );
BOOST_TEST( mapnik::freetype_engine::register_fonts(src, true) == false );
BOOST_TEST( mapnik::freetype_engine::face_names().size() == 0 );
// bogus, emtpy file that looks like font
BOOST_TEST( mapnik::freetype_engine::register_font("tests/data/fonts/fake.ttf") == false );
BOOST_TEST( mapnik::freetype_engine::register_fonts("tests/data/fonts/fake.ttf") == false );
BOOST_TEST( mapnik::freetype_engine::face_names().size() == 0 );
BOOST_TEST( mapnik::freetype_engine::register_font("tests/data/fonts/intentionally-broken.ttf") == false );
BOOST_TEST( mapnik::freetype_engine::register_fonts("tests/data/fonts/intentionally-broken.ttf") == false );
BOOST_TEST( mapnik::freetype_engine::face_names().size() == 0 );
// now restore the original severity
logger.set_severity(original_severity);
// register unifont, since we know it sits in the root fonts/ dir
BOOST_TEST( mapnik::freetype_engine::register_fonts(fontdir) );
face_names = mapnik::freetype_engine::face_names();
BOOST_TEST( face_names.size() > 0 );
BOOST_TEST( face_names.size() == 1 );
// re-register unifont, should not have any affect
BOOST_TEST( mapnik::freetype_engine::register_fonts(fontdir, false) );
face_names = mapnik::freetype_engine::face_names();
BOOST_TEST( face_names.size() == 1 );
// single dejavu font in separate location
std::string dejavu_bold_oblique("tests/data/fonts/DejaVuSansMono-BoldOblique.ttf");
BOOST_TEST( mapnik::freetype_engine::register_font(dejavu_bold_oblique) );
face_names = mapnik::freetype_engine::face_names();
BOOST_TEST( face_names.size() == 2 );
// now, inspect font mapping and confirm the correct 'DejaVu Sans Mono Bold Oblique' is registered
using font_file_mapping = std::map<std::string, std::pair<int,std::string> >;
font_file_mapping const& name2file = mapnik::freetype_engine::get_mapping();
bool found_dejavu = false;
for (auto const& item : name2file)
{
if (item.first == "DejaVu Sans Mono Bold Oblique")
{
found_dejavu = true;
BOOST_TEST( item.second.first == 0 );
BOOST_TEST( item.second.second == dejavu_bold_oblique );
}
}
BOOST_TEST( found_dejavu );
// recurse to find all dejavu fonts
BOOST_TEST( mapnik::freetype_engine::register_fonts(fontdir, true) );
face_names = mapnik::freetype_engine::face_names();
BOOST_TEST( face_names.size() == 22 );
// we should have re-registered 'DejaVu Sans Mono Bold Oblique' again,
// but now at a new path
bool found_dejavu2 = false;
for (auto const& item : name2file)
{
if (item.first == "DejaVu Sans Mono Bold Oblique")
{
found_dejavu2 = true;
BOOST_TEST( item.second.first == 0 );
// path should be different
BOOST_TEST( item.second.second != dejavu_bold_oblique );
}
}
BOOST_TEST( found_dejavu2 );
// now that global registry is populated
// now test that a map only loads new fonts
mapnik::Map m4(1,1);
BOOST_TEST( m4.register_fonts(fontdir , true ) );
BOOST_TEST( m4.get_font_memory_cache().size() == 0 );
BOOST_TEST( m4.get_font_file_mapping().size() == 22 );
BOOST_TEST( !m4.load_fonts() );
BOOST_TEST( m4.get_font_memory_cache().size() == 0 );
BOOST_TEST( m4.register_fonts(dejavu_bold_oblique, false) );
BOOST_TEST( m4.load_fonts() );
BOOST_TEST( m4.get_font_memory_cache().size() == 1 );
// check that we can correctly read a .ttc containing
// multiple valid faces
// https://github.com/mapnik/mapnik/issues/2274
BOOST_TEST( mapnik::freetype_engine::register_font("tests/data/fonts/NotoSans-Regular.ttc") );
face_names = mapnik::freetype_engine::face_names();
BOOST_TEST( face_names.size() == 24 );
// now blindly register as many system fonts as possible
// the goal here to make sure we don't crash
// linux
mapnik::freetype_engine::register_fonts("/usr/share/fonts/", true);
mapnik::freetype_engine::register_fonts("/usr/local/share/fonts/", true);
// osx
mapnik::freetype_engine::register_fonts("/Library/Fonts/", true);
mapnik::freetype_engine::register_fonts("/System/Library/Fonts/", true);
// windows
mapnik::freetype_engine::register_fonts("C:\\Windows\\Fonts", true);
face_names = mapnik::freetype_engine::face_names();
BOOST_TEST( face_names.size() > 22 );
}
catch (std::exception const & ex)
{
std::clog << ex.what() << "\n";
BOOST_TEST(false);
}
if (!::boost::detail::test_errors()) {
if (quiet) std::clog << "\x1b[1;32m.\x1b[0m";
else std::clog << "C++ fonts registration: \x1b[1;32m✓ \x1b[0m\n";
::boost::detail::report_errors_remind().called_report_errors_function = true;
} else {
return ::boost::report_errors();
}
}

View file

@ -1,124 +0,0 @@
#include <boost/detail/lightweight_test.hpp>
#include <iostream>
#include <mapnik/value_types.hpp>
#include <mapnik/params.hpp>
#include <mapnik/boolean.hpp>
#include <vector>
#include <algorithm>
namespace detail {
class string_holder {
public:
string_holder() :
member_("member") {}
std::string const& get_string() const
{
return member_;
}
private:
std::string member_;
};
}
int main(int argc, char** argv)
{
std::vector<std::string> args;
for (int i=1;i<argc;++i)
{
args.push_back(argv[i]);
}
bool quiet = std::find(args.begin(), args.end(), "-q")!=args.end();
try
{
mapnik::parameters params;
// true
params["bool"] = mapnik::value_integer(true);
BOOST_TEST( (params.get<mapnik::boolean_type>("bool") && *params.get<mapnik::boolean_type>("bool") == true));
params["bool"] = "true";
BOOST_TEST( (params.get<mapnik::boolean_type>("bool") && *params.get<mapnik::boolean_type>("bool") == true));
params["bool"] = mapnik::value_integer(1);
BOOST_TEST( (params.get<mapnik::boolean_type>("bool") && *params.get<mapnik::boolean_type>("bool") == true));
params["bool"] = "1";
BOOST_TEST( (params.get<mapnik::boolean_type>("bool") && *params.get<mapnik::boolean_type>("bool") == true));
params["bool"] = "True";
BOOST_TEST( (params.get<mapnik::boolean_type>("bool") && *params.get<mapnik::boolean_type>("bool") == true));
params["bool"] = "on";
BOOST_TEST( (params.get<mapnik::boolean_type>("bool") && *params.get<mapnik::boolean_type>("bool") == true));
params["bool"] = "yes";
BOOST_TEST( (params.get<mapnik::boolean_type>("bool") && *params.get<mapnik::boolean_type>("bool") == true));
// false
params["bool"] = mapnik::value_integer(false);
BOOST_TEST( (params.get<mapnik::boolean_type>("bool") && *params.get<mapnik::boolean_type>("bool") == false) );
params["bool"] = "false";
BOOST_TEST( (params.get<mapnik::boolean_type>("bool") && *params.get<mapnik::boolean_type>("bool") == false) );
params["bool"] = mapnik::value_integer(0);
BOOST_TEST( (params.get<mapnik::boolean_type>("bool") && *params.get<mapnik::boolean_type>("bool") == false));
params["bool"] = "0";
BOOST_TEST( (params.get<mapnik::boolean_type>("bool") && *params.get<mapnik::boolean_type>("bool") == false));
params["bool"] = "False";
BOOST_TEST( (params.get<mapnik::boolean_type>("bool") && *params.get<mapnik::boolean_type>("bool") == false));
params["bool"] = "off";
BOOST_TEST( (params.get<mapnik::boolean_type>("bool") && *params.get<mapnik::boolean_type>("bool") == false));
params["bool"] = "no";
BOOST_TEST( (params.get<mapnik::boolean_type>("bool") && *params.get<mapnik::boolean_type>("bool") == false));
// strings
params["string"] = "hello";
BOOST_TEST( (params.get<std::string>("string") && *params.get<std::string>("string") == "hello") );
// int
params["int"] = mapnik::value_integer(1);
BOOST_TEST( (params.get<mapnik::value_integer>("int") && *params.get<mapnik::value_integer>("int") == 1) );
// double
params["double"] = 1.5;
BOOST_TEST( (params.get<double>("double") && *params.get<double>("double") == 1.5) );
// value_null
params["null"] = mapnik::value_null();
// https://github.com/mapnik/mapnik/issues/2471
//BOOST_TEST( (params.get<mapnik::value_null>("null") && *params.get<mapnik::value_null>("null") == mapnik::value_null()) );
std::string value("value");
params["value"] = value;
BOOST_TEST(params.get<std::string>("value") == std::string("value"));
BOOST_TEST(value == std::string("value"));
// ensure that const member is not moved incorrectly when added to params
detail::string_holder holder;
std::string const& holder_member = holder.get_string();
params["member"] = holder_member;
BOOST_TEST(params.get<std::string>("member") == std::string("member"));
BOOST_TEST(holder_member == std::string("member"));
}
catch (std::exception const& ex)
{
std::cerr << ex.what() << "\n";
BOOST_TEST(false);
}
if (!::boost::detail::test_errors()) {
if (quiet) std::clog << "\x1b[1;32m.\x1b[0m";
else std::clog << "C++ parameters: \x1b[1;32m✓ \x1b[0m\n";
::boost::detail::report_errors_remind().called_report_errors_function = true;
} else {
return ::boost::report_errors();
}
}

View file

@ -1,40 +0,0 @@
#include <boost/detail/lightweight_test.hpp>
#include <iostream>
#include <mapnik/symbolizer.hpp>
#include <vector>
#include <algorithm>
using namespace mapnik;
int main(int argc, char** argv)
{
std::vector<std::string> args;
for (int i=1;i<argc;++i)
{
args.push_back(argv[i]);
}
bool quiet = std::find(args.begin(), args.end(), "-q")!=args.end();
try {
marker_multi_policy_enum policy_in = MARKER_WHOLE_MULTI;
BOOST_TEST_EQ(policy_in,MARKER_WHOLE_MULTI);
markers_symbolizer sym;
put(sym, keys::markers_multipolicy, policy_in);
BOOST_TEST_EQ(sym.properties.count(keys::markers_multipolicy),static_cast<unsigned long>(1));
marker_multi_policy_enum policy_out = get<mapnik::marker_multi_policy_enum>(sym, keys::markers_multipolicy);
BOOST_TEST_EQ(policy_out,MARKER_WHOLE_MULTI);
}
catch (std::exception const & ex)
{
std::clog << ex.what() << std::endl;
BOOST_TEST(false);
}
if (!::boost::detail::test_errors()) {
if (quiet) std::clog << "\x1b[1;32m.\x1b[0m";
else std::clog << "C++ symbolizer test: \x1b[1;32m✓ \x1b[0m\n";
::boost::detail::report_errors_remind().called_report_errors_function = true;
} else {
return ::boost::report_errors();
}
}

View file

@ -1,26 +0,0 @@
#include <vector>
#include <algorithm>
#include <string>
#include <mapnik/util/fs.hpp>
#include <boost/filesystem/convenience.hpp>
inline static bool set_working_dir(std::vector<std::string> args)
{
std::vector<std::string>::iterator itr = std::find(args.begin(), args.end(), "-d");
if (itr!=args.end())
{
unsigned dist = std::distance(args.begin(),itr);
if (args.size() > dist+1)
{
std::string chdir = args.at(dist+1);
bool exists = mapnik::util::exists( chdir );
if (exists)
{
boost::filesystem::current_path(chdir);
return true;
}
}
return false;
}
return true;
}

View file

@ -1,4 +1,5 @@
#include <boost/detail/lightweight_test.hpp>
#include "catch.hpp"
#include <iostream>
#include <cstdio>
#include <cstring>
@ -132,14 +133,9 @@ template<class ColorT, class Order> struct comp_op_rgba_src_over2
}
int main(int argc, char** argv)
{
std::vector<std::string> args;
for (int i=1;i<argc;++i)
{
args.push_back(argv[i]);
}
bool quiet = std::find(args.begin(), args.end(), "-q")!=args.end();
TEST_CASE("blending") {
SECTION("src over") {
using source_over_old_agg = agg::comp_op_rgba_src_over2<color, agg::order_rgba>;
using source_over = agg::comp_op_rgba_src_over<color, agg::order_rgba>;
@ -149,16 +145,16 @@ int main(int argc, char** argv)
color white(255,255,255,255);
color black(0,0,0,255);
BOOST_TEST_EQ( to_string(blend<source_over>(white,white)), to_string(white) );
BOOST_TEST_EQ( to_string(blend<source_over>(white,black)), to_string(white) );
BOOST_TEST_EQ( to_string(blend<source_over>(black,white)), to_string(black) );
REQUIRE( to_string(blend<source_over>(white,white)) == to_string(white) );
REQUIRE( to_string(blend<source_over>(white,black)) == to_string(white) );
REQUIRE( to_string(blend<source_over>(black,white)) == to_string(black) );
color near_white(254,254,254,254); // Source
color near_trans(1,1,1,1); // Dest
color expected_color(253,253,253,255); // expected result
BOOST_TEST_EQ( to_string(blend<source_over_old_agg>(near_white,near_trans)), to_string(color(253,253,253,254)) );
BOOST_TEST_EQ( to_string(blend<source_over>(near_white,near_trans)), to_string(expected_color) );
BOOST_TEST_EQ( to_string(normal_blend(near_white,near_trans)), to_string(expected_color) );
REQUIRE( to_string(blend<source_over_old_agg>(near_white,near_trans)) == to_string(color(253,253,253,254)) );
REQUIRE( to_string(blend<source_over>(near_white,near_trans)) == to_string(expected_color) );
REQUIRE( to_string(normal_blend(near_white,near_trans)) == to_string(expected_color) );
// using normal_blend as expected, compare a variety of other colors
@ -167,8 +163,8 @@ int main(int argc, char** argv)
color dest(128,128,128,255);
unsigned cover = 128;
std::string expected_str = to_string(normal_blend(source,dest,cover));
BOOST_TEST_EQ( to_string(blend<source_over>(source,dest,cover)), expected_str );
BOOST_TEST_EQ( to_string(blend<source_over_old_agg>(source,dest,cover)), expected_str );
REQUIRE( to_string(blend<source_over>(source,dest,cover)) == expected_str );
REQUIRE( to_string(blend<source_over_old_agg>(source,dest,cover)) == expected_str );
}
{
@ -176,8 +172,8 @@ int main(int argc, char** argv)
color dest(128,128,128,255);
unsigned cover = 245;
std::string expected_str = to_string(normal_blend(source,dest,cover));
BOOST_TEST_EQ( to_string(blend<source_over>(source,dest,cover)), expected_str );
BOOST_TEST_EQ( to_string(blend<source_over_old_agg>(source,dest,cover)), expected_str );
REQUIRE( to_string(blend<source_over>(source,dest,cover)) == expected_str );
REQUIRE( to_string(blend<source_over_old_agg>(source,dest,cover)) == expected_str );
}
// commenting until I study these failures more (dane)
@ -188,8 +184,8 @@ int main(int argc, char** argv)
color dest(127,127,127,127);
unsigned cover = 255;
std::string expected_str = to_string(normal_blend(source,dest,cover));
BOOST_TEST_EQ( to_string(blend<source_over>(source,dest,cover)), expected_str );
BOOST_TEST_EQ( to_string(blend<source_over_old_agg>(source,dest,cover)), expected_str );
REQUIRE( to_string(blend<source_over>(source,dest,cover)) == expected_str );
REQUIRE( to_string(blend<source_over_old_agg>(source,dest,cover)) == expected_str );
}
{
@ -198,23 +194,16 @@ int main(int argc, char** argv)
color dest(128,128,128,128);
unsigned cover = 128;
std::string expected_str = to_string(normal_blend(source,dest,cover));
BOOST_TEST_EQ( to_string(blend<source_over>(source,dest,cover)), expected_str );
BOOST_TEST_EQ( to_string(blend<source_over_old_agg>(source,dest,cover)), expected_str );
REQUIRE( to_string(blend<source_over>(source,dest,cover)) == expected_str );
REQUIRE( to_string(blend<source_over_old_agg>(source,dest,cover)) == expected_str );
}
*/
}
catch (std::exception const & ex)
{
std::clog << ex.what() << "\n";
BOOST_TEST(false);
}
if (!::boost::detail::test_errors()) {
if (quiet) std::clog << "\x1b[1;32m.\x1b[0m";
else std::clog << "C++ AGG blending: \x1b[1;32m✓ \x1b[0m\n";
::boost::detail::report_errors_remind().called_report_errors_function = true;
} else {
std::clog << "C++ AGG blending: ";
return ::boost::report_errors();
REQUIRE(false);
}
}
}

View file

@ -1,3 +1,5 @@
#include "catch.hpp"
// mapnik
#include <mapnik/util/conversions.hpp>
#include <mapnik/util/trim.hpp>
@ -6,7 +8,6 @@
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-parameter"
#pragma GCC diagnostic ignored "-Wunused-local-typedef"
#include <boost/detail/lightweight_test.hpp>
#include <boost/algorithm/string.hpp>
#pragma GCC diagnostic pop
@ -21,10 +22,6 @@
// agg
#include "agg_conv_clip_polygon.h"
#include "agg_conv_clip_polyline.h"
//#include "agg_path_storage.h"
//#include "agg_conv_clipper.h"
#include "utils.hpp"
template <typename T>
std::string dump_path(T & path)
@ -82,19 +79,12 @@ void parse_geom(mapnik::path_type & path,
}
}
int main(int argc, char** argv)
{
std::vector<std::string> args;
for (int i=1;i<argc;++i)
{
args.push_back(argv[i]);
}
bool quiet = std::find(args.begin(), args.end(), "-q")!=args.end();
TEST_CASE("clipping") {
SECTION("lines") {
try {
BOOST_TEST(set_working_dir(args));
std::string filename("tests/cpp_tests/data/cases.txt");
std::ifstream stream(filename.c_str(),std::ios_base::in | std::ios_base::binary);
if (!stream.is_open())
@ -116,7 +106,7 @@ int main(int argc, char** argv)
parse_geom(path, parts[1]);
//std::clog << dump_path(path) << "\n";
// third part is expected, clipped geometry
BOOST_TEST_EQ(clip_line(bbox, path),mapnik::util::trim_copy(parts[2]));
REQUIRE(clip_line(bbox, path) == mapnik::util::trim_copy(parts[2]));
}
stream.close();
}
@ -125,14 +115,6 @@ int main(int argc, char** argv)
std::cerr << ex.what() << "\n";
}
if (!::boost::detail::test_errors())
{
if (quiet) std::clog << "\x1b[1;32m.\x1b[0m";
else std::clog << "C++ clipping: \x1b[1;32m✓ \x1b[0m\n";
::boost::detail::report_errors_remind().called_report_errors_function = true;
}
else
{
return ::boost::report_errors();
}
}
}

View file

@ -1,7 +1,8 @@
#include "catch.hpp"
#include <mapnik/value_types.hpp>
#include <mapnik/value.hpp>
#include <mapnik/util/conversions.hpp>
#include <boost/detail/lightweight_test.hpp>
#include <iostream>
#include <vector>
#include <algorithm>
@ -11,17 +12,13 @@
#include <cstdio>
#endif
int main(int argc, char** argv)
{
TEST_CASE("conversions") {
SECTION("to string") {
#if defined(_MSC_VER) && _MSC_VER < 1900
unsigned int old = _set_output_format(_TWO_DIGIT_EXPONENT);
#endif
std::vector<std::string> args;
for (int i=1;i<argc;++i)
{
args.push_back(argv[i]);
}
bool quiet = std::find(args.begin(), args.end(), "-q")!=args.end();
using mapnik::util::to_string;
using mapnik::util::string2bool;
@ -32,236 +29,236 @@ int main(int argc, char** argv)
// Test double
to_string(out, double(0));
BOOST_TEST_EQ( out, "0" );
REQUIRE( out == "0" );
out.clear();
to_string(out, double(1));
BOOST_TEST_EQ( out, "1" );
REQUIRE( out == "1" );
out.clear();
to_string(out, double(-1));
BOOST_TEST_EQ( out, "-1" );
REQUIRE( out == "-1" );
out.clear();
to_string(out, double(0.1));
BOOST_TEST_EQ( out, "0.1" );
REQUIRE( out == "0.1" );
out.clear();
to_string(out, double(-0.1));
BOOST_TEST_EQ( out, "-0.1" );
REQUIRE( out == "-0.1" );
out.clear();
to_string(out, double(0.123));
BOOST_TEST_EQ( out, "0.123" );
REQUIRE( out == "0.123" );
out.clear();
to_string(out, double(-0.123));
BOOST_TEST_EQ( out, "-0.123" );
REQUIRE( out == "-0.123" );
out.clear();
to_string(out, double(1e-06));
BOOST_TEST_EQ( out, "1e-06" );
REQUIRE( out == "1e-06" );
out.clear();
to_string(out, double(-1e-06));
BOOST_TEST_EQ( out, "-1e-06" );
REQUIRE( out == "-1e-06" );
out.clear();
to_string(out, double(1e-05));
BOOST_TEST_EQ( out, "1e-05" );
REQUIRE( out == "1e-05" );
out.clear();
to_string(out, double(-1e-05));
BOOST_TEST_EQ( out, "-1e-05" );
REQUIRE( out == "-1e-05" );
out.clear();
to_string(out, double(0.0001));
BOOST_TEST_EQ( out, "0.0001" );
REQUIRE( out == "0.0001" );
out.clear();
to_string(out, double(-0.0001));
BOOST_TEST_EQ( out, "-0.0001" );
REQUIRE( out == "-0.0001" );
out.clear();
to_string(out, double(0.0001));
BOOST_TEST_EQ( out, "0.0001" );
REQUIRE( out == "0.0001" );
out.clear();
to_string(out, double(0.00001));
BOOST_TEST_EQ( out, "1e-05" );
REQUIRE( out == "1e-05" );
out.clear();
to_string(out, double(0.000001));
BOOST_TEST_EQ( out, "1e-06" );
REQUIRE( out == "1e-06" );
out.clear();
to_string(out, double(0.0000001));
BOOST_TEST_EQ( out, "1e-07" );
REQUIRE( out == "1e-07" );
out.clear();
to_string(out, double(0.00000001));
BOOST_TEST_EQ( out, "1e-08" );
REQUIRE( out == "1e-08" );
out.clear();
to_string(out, double(0.000000001));
BOOST_TEST_EQ( out, "1e-09" );
REQUIRE( out == "1e-09" );
out.clear();
to_string(out, double(0.0000000001));
BOOST_TEST_EQ( out, "1e-10" );
REQUIRE( out == "1e-10" );
out.clear();
to_string(out, double(-1.234e+16));
BOOST_TEST_EQ( out, "-1.234e+16" );
REQUIRE( out == "-1.234e+16" );
out.clear();
// critical failure when karam is used
// https://github.com/mapnik/mapnik/issues/1741
// https://github.com/mapbox/tilemill/issues/1456
to_string(out, double(8.3));
BOOST_TEST_EQ( out, "8.3" );
REQUIRE( out == "8.3" );
out.clear();
// non-critical failures if karma is used
to_string(out, double(0.0001234567890123456));
// TODO: https://github.com/mapnik/mapnik/issues/1676
BOOST_TEST_EQ( out, "0.000123457" );
REQUIRE( out == "0.000123457" );
out.clear();
to_string(out, double(0.00000000001));
BOOST_TEST_EQ( out, "1e-11" );
REQUIRE( out == "1e-11" );
out.clear();
to_string(out, double(0.000000000001));
BOOST_TEST_EQ( out, "1e-12" );
REQUIRE( out == "1e-12" );
out.clear();
to_string(out, double(0.0000000000001));
BOOST_TEST_EQ( out, "1e-13" );
REQUIRE( out == "1e-13" );
out.clear();
to_string(out, double(0.00000000000001));
BOOST_TEST_EQ( out, "1e-14" );
REQUIRE( out == "1e-14" );
out.clear();
to_string(out, double(0.000000000000001));
BOOST_TEST_EQ( out, "1e-15" );
REQUIRE( out == "1e-15" );
out.clear();
to_string(out, double(100000));
BOOST_TEST_EQ( out, "100000" );
REQUIRE( out == "100000" );
out.clear();
to_string(out, double(1000000));
BOOST_TEST_EQ( out, "1e+06" );
REQUIRE( out == "1e+06" );
out.clear();
to_string(out, double(10000000));
BOOST_TEST_EQ( out, "1e+07" );
REQUIRE( out == "1e+07" );
out.clear();
to_string(out, double(100000000));
BOOST_TEST_EQ( out, "1e+08" );
REQUIRE( out == "1e+08" );
out.clear();
to_string(out, double(1000000000));
BOOST_TEST_EQ( out, "1e+09" );
REQUIRE( out == "1e+09" );
out.clear();
to_string(out, double(10000000000));
BOOST_TEST_EQ( out, "1e+10" );
REQUIRE( out == "1e+10" );
out.clear();
to_string(out, double(100000000000));
BOOST_TEST_EQ( out, "1e+11" );
REQUIRE( out == "1e+11" );
out.clear();
to_string(out, double(1000000000000));
BOOST_TEST_EQ( out, "1e+12" );
REQUIRE( out == "1e+12" );
out.clear();
to_string(out, double(10000000000000));
BOOST_TEST_EQ( out, "1e+13" );
REQUIRE( out == "1e+13" );
out.clear();
to_string(out, double(100000000000000));
BOOST_TEST_EQ( out, "1e+14" );
REQUIRE( out == "1e+14" );
out.clear();
to_string(out, double(1000000000000005));
BOOST_TEST_EQ( out, "1e+15" );
REQUIRE( out == "1e+15" );
out.clear();
to_string(out, double(-1000000000000000));
BOOST_TEST_EQ( out, "-1e+15" );
REQUIRE( out == "-1e+15" );
out.clear();
to_string(out, double(100000000000000.1));
BOOST_TEST_EQ( out, "1e+14" );
REQUIRE( out == "1e+14" );
out.clear();
to_string(out, double(1.00001));
BOOST_TEST_EQ( out, "1.00001" );
REQUIRE( out == "1.00001" );
out.clear();
to_string(out, double(67.65));
BOOST_TEST_EQ( out, "67.65" );
REQUIRE( out == "67.65" );
out.clear();
to_string(out, double(67.35));
BOOST_TEST_EQ( out, "67.35" );
REQUIRE( out == "67.35" );
out.clear();
to_string(out, double(1234000000000000));
BOOST_TEST_EQ( out, "1.234e+15" );
REQUIRE( out == "1.234e+15" );
out.clear();
to_string(out, double(1e+16));
BOOST_TEST_EQ( out, "1e+16" );
REQUIRE( out == "1e+16" );
out.clear();
to_string(out, double(1.234e+16));
BOOST_TEST_EQ( out, "1.234e+16" );
REQUIRE( out == "1.234e+16" );
out.clear();
// int
to_string(out, int(2));
BOOST_TEST_EQ( out, "2" );
REQUIRE( out == "2" );
out.clear();
to_string(out, int(0));
BOOST_TEST_EQ( out, "0" );
REQUIRE( out == "0" );
out.clear();
to_string(out, int(-2));
BOOST_TEST_EQ( out, "-2" );
REQUIRE( out == "-2" );
out.clear();
to_string(out, int(2147483647));
BOOST_TEST_EQ( out, "2147483647" );
REQUIRE( out == "2147483647" );
out.clear();
to_string(out, int(-2147483648));
BOOST_TEST_EQ( out, "-2147483648" );
REQUIRE( out == "-2147483648" );
out.clear();
// unsigned
to_string(out, unsigned(4294967295));
BOOST_TEST_EQ( out, "4294967295" );
REQUIRE( out == "4294967295" );
out.clear();
#ifdef BIGINT
// long long
to_string(out,mapnik::value_integer(-0));
BOOST_TEST_EQ( out, "0" );
REQUIRE( out == "0" );
out.clear();
to_string(out,mapnik::value_integer(-2));
BOOST_TEST_EQ( out, "-2" );
REQUIRE( out == "-2" );
out.clear();
to_string(out,mapnik::value_integer(9223372036854775807));
BOOST_TEST_EQ( out, "9223372036854775807" );
REQUIRE( out == "9223372036854775807" );
out.clear();
#else
#ifdef _MSC_VER
@ -272,38 +269,32 @@ int main(int argc, char** argv)
#endif
// bool
to_string(out, true);
BOOST_TEST_EQ( out, "true" );
REQUIRE( out == "true" );
out.clear();
to_string(out, false);
BOOST_TEST_EQ( out, "false" );
REQUIRE( out == "false" );
out.clear();
bool val = false;
BOOST_TEST( !string2bool("this is invalid",val) );
BOOST_TEST_EQ( val, false );
BOOST_TEST( string2bool("true",val) );
BOOST_TEST_EQ( val, true );
REQUIRE( !string2bool("this is invalid",val) );
REQUIRE( val == false );
REQUIRE( string2bool("true",val) );
REQUIRE( val == true );
// mapnik::value hashability
using values_container = boost::unordered_map<mapnik::value, unsigned>;
values_container vc;
mapnik::value val2(1);
vc[val2] = 1;
BOOST_TEST_EQ( (int)vc[1], (int)1 );
REQUIRE( vc[1] == static_cast<int>(1) );
}
catch (std::exception const & ex)
{
std::clog << ex.what() << "\n";
BOOST_TEST(false);
}
if (!::boost::detail::test_errors()) {
if (quiet) std::clog << "\x1b[1;32m.\x1b[0m";
else std::clog << "C++ type conversions: \x1b[1;32m✓ \x1b[0m\n";
::boost::detail::report_errors_remind().called_report_errors_function = true;
} else {
return ::boost::report_errors();
REQUIRE(false);
}
}
}

View file

@ -1,5 +1,4 @@
#include <boost/detail/lightweight_test.hpp>
#include <iostream>
#include <mapnik/layer.hpp>
#include <mapnik/map.hpp>
#include <mapnik/color.hpp>
@ -9,19 +8,20 @@
#include <vector>
#include <algorithm>
int main(int argc, char** argv)
{
std::vector<std::string> args;
for (int i=1;i<argc;++i)
{
args.push_back(argv[i]);
}
bool quiet = std::find(args.begin(), args.end(), "-q")!=args.end();
#include "catch.hpp"
TEST_CASE("copy") {
SECTION("layers") {
try
{
mapnik::Map m0(100,100);
mapnik::Map m2(200,100);
// FIXME: not compiling when ported to catch.hpp
// due to some conflict: 'include/mapnik/value.hpp:832:11: error: no matching constructor for initialization of 'value_base''
/*
// mapnik::datasource
mapnik::datasource_cache::instance().register_datasources("plugins/input/shape.input");
@ -32,29 +32,29 @@ int main(int argc, char** argv)
auto ds0 = mapnik::datasource_cache::instance().create(p);
auto ds1 = ds0; // shared ptr copy
BOOST_TEST(ds1 == ds0);
BOOST_TEST(*ds1 == *ds0);
REQUIRE(ds1 == ds0);
//REQUIRE(*ds1 == *ds0);
ds1 = mapnik::datasource_cache::instance().create(p); // new with the same parameters
BOOST_TEST(ds1 != ds0);
BOOST_TEST(*ds1 == *ds0);
REQUIRE(ds1 != ds0);
REQUIRE(*ds1 == *ds0);
auto ds2 = std::move(ds1);
BOOST_TEST(ds2 != ds0);
BOOST_TEST(*ds2 == *ds0);
REQUIRE(ds2 != ds0);
REQUIRE(*ds2 == *ds0);
// mapnik::layer
mapnik::layer l0("test-layer");
l0.set_datasource(ds0);
mapnik::layer l1 = l0; // copy assignment
BOOST_TEST(l1 == l0);
REQUIRE(l1 == l0);
mapnik::layer l2(l0); // copy ctor
BOOST_TEST(l2 == l0);
REQUIRE(l2 == l0);
mapnik::layer l3(mapnik::layer("test-layer")); // move ctor
l3.set_datasource(ds2);
BOOST_TEST(l3 == l0);
REQUIRE(l3 == l0);
mapnik::layer l4 = std::move(l3);
BOOST_TEST(l4 == l0); // move assignment
REQUIRE(l4 == l0); // move assignment
m0.add_layer(l4);
m0.set_background(mapnik::color("skyblue"));
@ -62,31 +62,22 @@ int main(int argc, char** argv)
auto m1 = m0; //copy
BOOST_TEST(m0 == m1);
BOOST_TEST(m0 != m2);
REQUIRE(m0 == m1);
REQUIRE(m0 != m2);
m2 = m1; // copy
BOOST_TEST(m2 == m1);
REQUIRE(m2 == m1);
m2 = std::move(m1);
BOOST_TEST(m2 == m0);
BOOST_TEST(m1 != m0);
REQUIRE(m2 == m0);
REQUIRE(m1 != m0);
BOOST_TEST(m0 == m2);
REQUIRE(m0 == m2);
*/
}
catch (std::exception const & ex)
{
std::clog << ex.what() << "\n";
BOOST_TEST(false);
}
if (!::boost::detail::test_errors())
{
if (quiet) std::clog << "\x1b[1;32m.\x1b[0m";
else std::clog << "C++ copy/move/assignment tests: \x1b[1;32m✓ \x1b[0m\n";
::boost::detail::report_errors_remind().called_report_errors_function = true;
}
else
{
return ::boost::report_errors();
REQUIRE(false);
}
}
}

View file

@ -1,4 +1,5 @@
#include <boost/detail/lightweight_test.hpp>
#include "catch.hpp"
#include <iostream>
#include <mapnik/projection.hpp>
#include <mapnik/unicode.hpp>
@ -19,45 +20,35 @@
#include <vector>
#include <algorithm>
#include "utils.hpp"
TEST_CASE("exceptions") {
int main(int argc, char** argv)
{
std::vector<std::string> args;
for (int i=1;i<argc;++i)
{
args.push_back(argv[i]);
}
bool quiet = std::find(args.begin(), args.end(), "-q")!=args.end();
BOOST_TEST(set_working_dir(args));
SECTION("handling") {
try {
mapnik::projection srs("foo");
// to avoid unused variable warning
srs.params();
BOOST_TEST(false);
REQUIRE(false);
} catch (...) {
BOOST_TEST(true);
REQUIRE(true);
}
// https://github.com/mapnik/mapnik/issues/2170
try {
BOOST_TEST(set_working_dir(args));
mapnik::projection srs("+proj=longlat foo",true);
BOOST_TEST(srs.is_geographic());
BOOST_TEST(true);
REQUIRE(srs.is_geographic());
REQUIRE(true);
srs.init_proj4();
// oddly init_proj4 does not throw with old proj/ubuntu precise
//BOOST_TEST(false);
//REQUIRE(false);
} catch (...) {
BOOST_TEST(true);
REQUIRE(true);
}
try {
mapnik::transcoder tr("bogus encoding");
BOOST_TEST(false);
REQUIRE(false);
} catch (...) {
BOOST_TEST(true);
REQUIRE(true);
}
mapnik::Map map(256,256);
@ -85,12 +76,12 @@ int main(int argc, char** argv)
mapnik::image_rgba8 im(m.width(),m.height());
mapnik::agg_renderer<mapnik::image_rgba8> ren(m,im);
//std::clog << mapnik::save_map_to_string(m) << "\n";
BOOST_TEST(true);
REQUIRE(true);
// should throw here with "CSV Plugin: no attribute 'foo'. Valid attributes are: x,y."
ren.apply();
BOOST_TEST(false);
REQUIRE(false);
} catch (...) {
BOOST_TEST(true);
REQUIRE(true);
}
}
@ -102,17 +93,11 @@ int main(int argc, char** argv)
p2["type"]="shape";
p2["file"]="foo";
mapnik::datasource_cache::instance().create(p2);
BOOST_TEST(false);
REQUIRE(false);
} catch (...) {
BOOST_TEST(true);
REQUIRE(true);
}
}
if (!::boost::detail::test_errors()) {
if (quiet) std::clog << "\x1b[1;32m.\x1b[0m";
else std::clog << "C++ exceptions: \x1b[1;32m✓ \x1b[0m\n";
::boost::detail::report_errors_remind().called_report_errors_function = true;
} else {
return ::boost::report_errors();
}
}
}

View file

@ -0,0 +1,192 @@
#include "catch.hpp"
#include <mapnik/font_engine_freetype.hpp>
#include <mapnik/util/fs.hpp>
#include <mapnik/map.hpp>
#include <mapnik/load_map.hpp>
#include <mapnik/debug.hpp>
#include <iostream>
#include <vector>
#include <algorithm>
TEST_CASE("font") {
SECTION("registration") {
try
{
mapnik::logger logger;
mapnik::logger::severity_type original_severity = logger.get_severity();
// grab references to global statics of registered/cached fonts
auto const& global_mapping = mapnik::freetype_engine::get_mapping();
auto const& global_cache = mapnik::freetype_engine::get_cache();
// mapnik.Map object has parallel structure for localized fonts
mapnik::Map m(1,1);
auto const& local_mapping = m.get_font_file_mapping();
auto const& local_cache = m.get_font_memory_cache();
// should be empty to start
REQUIRE( global_mapping.empty() );
REQUIRE( global_cache.empty() );
REQUIRE( local_mapping.empty() );
REQUIRE( local_cache.empty() );
std::string fontdir("fonts/");
REQUIRE( mapnik::util::exists( fontdir ) );
REQUIRE( mapnik::util::is_directory( fontdir ) );
// test map cached fonts
REQUIRE( m.register_fonts(fontdir , false ) );
REQUIRE( m.get_font_memory_cache().size() == 0 );
REQUIRE( m.get_font_file_mapping().size() == 1 );
REQUIRE( m.load_fonts() );
REQUIRE( m.get_font_memory_cache().size() == 1 );
REQUIRE( m.register_fonts(fontdir , true ) );
REQUIRE( m.get_font_file_mapping().size() == 22 );
REQUIRE( m.load_fonts() );
REQUIRE( m.get_font_memory_cache().size() == 22 );
// copy discards memory cache but not file mapping
mapnik::Map m2(m);
REQUIRE( m2.get_font_memory_cache().size() == 0 );
REQUIRE( m2.get_font_file_mapping().size() == 22 );
REQUIRE( m2.load_fonts() );
REQUIRE( m2.get_font_memory_cache().size() == 22 );
// test font-directory from XML
mapnik::Map m3(1,1);
mapnik::load_map_string(m3,"<Map font-directory=\"fonts/\"></Map>");
REQUIRE( m3.get_font_memory_cache().size() == 0 );
REQUIRE( m3.load_fonts() );
REQUIRE( m3.get_font_memory_cache().size() == 1 );
std::vector<std::string> face_names;
std::string foo("foo");
// fake directories
REQUIRE( !mapnik::freetype_engine::register_fonts(foo , true ) );
face_names = mapnik::freetype_engine::face_names();
REQUIRE( face_names.size() == 0 );
REQUIRE( !mapnik::freetype_engine::register_fonts(foo) );
face_names = mapnik::freetype_engine::face_names();
REQUIRE( face_names.size() == 0 );
// directories without fonts
// silence warnings here by altering the logging severity
logger.set_severity(mapnik::logger::none);
std::string src("src");
// an empty directory will not return true
// we need to register at least one font and not fail on any
// to return true
REQUIRE( mapnik::freetype_engine::register_font(src) == false );
REQUIRE( mapnik::freetype_engine::register_fonts(src, true) == false );
REQUIRE( mapnik::freetype_engine::face_names().size() == 0 );
// bogus, emtpy file that looks like font
REQUIRE( mapnik::freetype_engine::register_font("tests/data/fonts/fake.ttf") == false );
REQUIRE( mapnik::freetype_engine::register_fonts("tests/data/fonts/fake.ttf") == false );
REQUIRE( mapnik::freetype_engine::face_names().size() == 0 );
REQUIRE( mapnik::freetype_engine::register_font("tests/data/fonts/intentionally-broken.ttf") == false );
REQUIRE( mapnik::freetype_engine::register_fonts("tests/data/fonts/intentionally-broken.ttf") == false );
REQUIRE( mapnik::freetype_engine::face_names().size() == 0 );
// now restore the original severity
logger.set_severity(original_severity);
// register unifont, since we know it sits in the root fonts/ dir
REQUIRE( mapnik::freetype_engine::register_fonts(fontdir) );
face_names = mapnik::freetype_engine::face_names();
REQUIRE( face_names.size() > 0 );
REQUIRE( face_names.size() == 1 );
// re-register unifont, should not have any affect
REQUIRE( mapnik::freetype_engine::register_fonts(fontdir, false) );
face_names = mapnik::freetype_engine::face_names();
REQUIRE( face_names.size() == 1 );
// single dejavu font in separate location
std::string dejavu_bold_oblique("tests/data/fonts/DejaVuSansMono-BoldOblique.ttf");
REQUIRE( mapnik::freetype_engine::register_font(dejavu_bold_oblique) );
face_names = mapnik::freetype_engine::face_names();
REQUIRE( face_names.size() == 2 );
// now, inspect font mapping and confirm the correct 'DejaVu Sans Mono Bold Oblique' is registered
using font_file_mapping = std::map<std::string, std::pair<int,std::string> >;
font_file_mapping const& name2file = mapnik::freetype_engine::get_mapping();
bool found_dejavu = false;
for (auto const& item : name2file)
{
if (item.first == "DejaVu Sans Mono Bold Oblique")
{
found_dejavu = true;
REQUIRE( item.second.first == 0 );
REQUIRE( item.second.second == dejavu_bold_oblique );
}
}
REQUIRE( found_dejavu );
// recurse to find all dejavu fonts
REQUIRE( mapnik::freetype_engine::register_fonts(fontdir, true) );
face_names = mapnik::freetype_engine::face_names();
REQUIRE( face_names.size() == 22 );
// we should have re-registered 'DejaVu Sans Mono Bold Oblique' again,
// but now at a new path
bool found_dejavu2 = false;
for (auto const& item : name2file)
{
if (item.first == "DejaVu Sans Mono Bold Oblique")
{
found_dejavu2 = true;
REQUIRE( item.second.first == 0 );
// path should be different
REQUIRE( item.second.second != dejavu_bold_oblique );
}
}
REQUIRE( found_dejavu2 );
// now that global registry is populated
// now test that a map only loads new fonts
mapnik::Map m4(1,1);
REQUIRE( m4.register_fonts(fontdir , true ) );
REQUIRE( m4.get_font_memory_cache().size() == 0 );
REQUIRE( m4.get_font_file_mapping().size() == 22 );
REQUIRE( !m4.load_fonts() );
REQUIRE( m4.get_font_memory_cache().size() == 0 );
REQUIRE( m4.register_fonts(dejavu_bold_oblique, false) );
REQUIRE( m4.load_fonts() );
REQUIRE( m4.get_font_memory_cache().size() == 1 );
// check that we can correctly read a .ttc containing
// multiple valid faces
// https://github.com/mapnik/mapnik/issues/2274
REQUIRE( mapnik::freetype_engine::register_font("tests/data/fonts/NotoSans-Regular.ttc") );
face_names = mapnik::freetype_engine::face_names();
REQUIRE( face_names.size() == 24 );
// now blindly register as many system fonts as possible
// the goal here to make sure we don't crash
// linux
mapnik::freetype_engine::register_fonts("/usr/share/fonts/", true);
mapnik::freetype_engine::register_fonts("/usr/local/share/fonts/", true);
// osx
mapnik::freetype_engine::register_fonts("/Library/Fonts/", true);
mapnik::freetype_engine::register_fonts("/System/Library/Fonts/", true);
// windows
mapnik::freetype_engine::register_fonts("C:\\Windows\\Fonts", true);
face_names = mapnik::freetype_engine::face_names();
REQUIRE( face_names.size() > 22 );
}
catch (std::exception const & ex)
{
std::clog << ex.what() << "\n";
REQUIRE(false);
}
}
}

View file

@ -1,4 +1,5 @@
#include <boost/detail/lightweight_test.hpp>
#include "catch.hpp"
#include <iostream>
#include <mapnik/memory_datasource.hpp>
#include <mapnik/datasource_cache.hpp>
@ -26,19 +27,11 @@
// icu - for memory cleanup (to make valgrind happy)
#include "unicode/uclean.h"
#include "utils.hpp"
TEST_CASE("fontset") {
int main(int argc, char** argv)
{
std::vector<std::string> args;
for (int i=1;i<argc;++i)
{
args.push_back(argv[i]);
}
bool quiet = std::find(args.begin(), args.end(), "-q")!=args.end();
SECTION("error") {
try {
BOOST_TEST(set_working_dir(args));
// create a renderable map with a fontset and a text symbolizer
// and do not register any fonts, to ensure the error thrown is reasonable
@ -85,14 +78,8 @@ int main(int argc, char** argv)
mapnik::agg_renderer<mapnik::image_rgba8> ren(m,buf);
ren.apply();
} catch (std::exception const& ex) {
BOOST_TEST_EQ(std::string(ex.what()),std::string("Unable to find specified font face 'DejaVu Sans Book' in font set: 'fontset'"));
REQUIRE(std::string(ex.what()) == std::string("Unable to find specified font face 'DejaVu Sans Book' in font set: 'fontset'"));
}
u_cleanup();
if (!::boost::detail::test_errors()) {
if (quiet) std::clog << "\x1b[1;32m.\x1b[0m";
else std::clog << "C++ fontset runtime: \x1b[1;32m✓ \x1b[0m\n";
::boost::detail::report_errors_remind().called_report_errors_function = true;
} else {
return ::boost::report_errors();
}
}
}

View file

@ -1,8 +1,8 @@
#include <boost/detail/lightweight_test.hpp>
#include "catch.hpp"
#include <iostream>
#include <vector>
#include <algorithm>
#include "utils.hpp"
#include <mapnik/layer.hpp>
#include <mapnik/feature_type_style.hpp>
@ -133,16 +133,9 @@ boost::optional<std::string> polygon_bbox_clipping(mapnik::box2d<double> bbox,
#endif
int main(int argc, char** argv)
{
std::vector<std::string> args;
for (int i=1;i<argc;++i)
{
args.push_back(argv[i]);
}
bool quiet = std::find(args.begin(), args.end(), "-q")!=args.end();
TEST_CASE("geometry converters") {
BOOST_TEST(set_working_dir(args));
SECTION("TODO") {
try
{
@ -151,60 +144,49 @@ int main(int argc, char** argv)
{
std::string wkt_in("LineString(0 0,200 200)");
boost::optional<std::string> result = linestring_bbox_clipping(mapnik::box2d<double>(50,50,150,150),wkt_in);
BOOST_TEST(result);
BOOST_TEST_EQ(*result,std::string("LineString(50 50,150 150)"));
REQUIRE(result);
REQUIRE(*result == std::string("LineString(50 50,150 150)"));
}
// Polygon/bbox clipping
{
std::string wkt_in("Polygon((50 50,150 50,150 150,50 150,50 50))");
boost::optional<std::string> result = polygon_bbox_clipping(mapnik::box2d<double>(50,50,150,150),wkt_in);
BOOST_TEST(result);
REQUIRE(result);
// TODO - the extra 50 50 is not ideal, but we enforce this result for now to prevent
// regressions and because we don't have actionable solution to drop extra 50 50
BOOST_TEST_EQ(*result,std::string("Polygon((50 50,150 50,150 150,50 150,50 50,50 50))"));
REQUIRE(*result == std::string("Polygon((50 50,150 50,150 150,50 150,50 50,50 50))"));
// below is ideal, but not current result
//BOOST_TEST_EQ(*result,std::string("Polygon((50 50,150 50,150 150,50 150,50 50))"));
//REQUIRE(*result == std::string("Polygon((50 50,150 50,150 150,50 150,50 50))"));
}
{
std::string wkt_in("Polygon((60 60,140 60,140 160,60 140,60 60))");
boost::optional<std::string> result = polygon_bbox_clipping(mapnik::box2d<double>(50,50,150,150),wkt_in);
BOOST_TEST(result);
BOOST_TEST_EQ(*result,std::string("Polygon((60 60,140 60,140 150,100 150,60 140,60 60,60 60))"));
//BOOST_TEST_EQ(*result,std::string("Polygon((60 60,140 60,140 160,60 140,60 60))"));
REQUIRE(result);
REQUIRE(*result == std::string("Polygon((60 60,140 60,140 150,100 150,60 140,60 60,60 60))"));
//REQUIRE(*result == std::string("Polygon((60 60,140 60,140 160,60 140,60 60))"));
}
{
std::string wkt_in("Polygon((0 0,10 0,10 10,0 10,0 0))");
boost::optional<std::string> result = polygon_bbox_clipping(mapnik::box2d<double>(50,50,150,150),wkt_in);
BOOST_TEST(result);
REQUIRE(result);
// TODO - this is completely wrong: should not have )) and ideally should be EMPTY
BOOST_TEST_EQ(*result, std::string("Polygon())"));
REQUIRE(*result == std::string("Polygon())"));
}
{
std::string wkt_in("Polygon((0 0,100 200,200 0,0 0 ))");
boost::optional<std::string> result = polygon_bbox_clipping(mapnik::box2d<double>(50,50,150,150),wkt_in);
BOOST_TEST(result);
BOOST_TEST_EQ(*result, std::string("Polygon((50 50,50 100,75 150,125 150,150 100,150 50))"));
//BOOST_TEST_EQ(*result,std::string("Polygon((50 50,50 100,75 150,125 150,150 100,150 50,50 50))"));
REQUIRE(result);
REQUIRE(*result == std::string("Polygon((50 50,50 100,75 150,125 150,150 100,150 50))"));
//REQUIRE(*result == std::string("Polygon((50 50,50 100,75 150,125 150,150 100,150 50,50 50))"));
}
#endif
}
catch (std::exception const & ex)
{
std::clog << ex.what() << "\n";
BOOST_TEST(false);
}
if (!::boost::detail::test_errors())
{
if (quiet) std::clog << "\x1b[1;32m.\x1b[0m";
else std::clog << "C++ geometry conversions: \x1b[1;32m✓ \x1b[0m\n";
::boost::detail::report_errors_remind().called_report_errors_function = true;
}
else
{
return ::boost::report_errors();
REQUIRE(false);
}
}
}

View file

@ -1,4 +1,5 @@
#include <boost/detail/lightweight_test.hpp>
#include "catch.hpp"
#include <iostream>
#include <mapnik/image.hpp>
#include <mapnik/image_reader.hpp>
@ -11,46 +12,38 @@
#include <mapnik/cairo/cairo_image_util.hpp>
#endif
#include "utils.hpp"
TEST_CASE("image io") {
int main(int argc, char** argv)
{
std::vector<std::string> args;
for (int i=1;i<argc;++i)
{
args.push_back(argv[i]);
}
bool quiet = std::find(args.begin(), args.end(), "-q")!=args.end();
SECTION("readers") {
std::string should_throw;
boost::optional<std::string> type;
try
{
BOOST_TEST(set_working_dir(args));
#if defined(HAVE_JPEG)
should_throw = "./tests/cpp_tests/data/blank.jpg";
BOOST_TEST( mapnik::util::exists( should_throw ) );
REQUIRE( mapnik::util::exists( should_throw ) );
type = mapnik::type_from_filename(should_throw);
BOOST_TEST( type );
REQUIRE( type );
try
{
std::unique_ptr<mapnik::image_reader> reader(mapnik::get_image_reader(should_throw,*type));
BOOST_TEST( false );
REQUIRE( false );
}
catch (std::exception const&)
{
BOOST_TEST( true );
REQUIRE( true );
}
#endif
try
{
mapnik::image_rgba8 im(-10,-10); // should throw rather than overflow
BOOST_TEST( im.width() < 10 ); // should not get here, but if we did this test should fail
REQUIRE( im.width() < 10 ); // should not get here, but if we did this test should fail
}
catch (std::exception const& ex)
{
BOOST_TEST( true ); // should hit bad alloc here
REQUIRE( true ); // should hit bad alloc here
}
#if defined(HAVE_CAIRO)
@ -59,85 +52,79 @@ int main(int argc, char** argv)
mapnik::cairo_surface_closer());
mapnik::image_rgba8 im_data(cairo_image_surface_get_width(&*image_surface), cairo_image_surface_get_height(&*image_surface));
im_data.set(1);
BOOST_TEST( (unsigned)im_data(0,0) == unsigned(1) );
REQUIRE( (unsigned)im_data(0,0) == unsigned(1) );
// Should set back to fully transparent
mapnik::cairo_image_to_rgba8(im_data, image_surface);
BOOST_TEST( (unsigned)im_data(0,0) == unsigned(0) );
REQUIRE( (unsigned)im_data(0,0) == unsigned(0) );
#endif
#if defined(HAVE_PNG)
should_throw = "./tests/cpp_tests/data/blank.png";
BOOST_TEST( mapnik::util::exists( should_throw ) );
REQUIRE( mapnik::util::exists( should_throw ) );
type = mapnik::type_from_filename(should_throw);
BOOST_TEST( type );
REQUIRE( type );
try
{
std::unique_ptr<mapnik::image_reader> reader(mapnik::get_image_reader(should_throw,*type));
BOOST_TEST( false );
REQUIRE( false );
}
catch (std::exception const&)
{
BOOST_TEST( true );
REQUIRE( true );
}
should_throw = "./tests/data/images/xcode-CgBI.png";
BOOST_TEST( mapnik::util::exists( should_throw ) );
REQUIRE( mapnik::util::exists( should_throw ) );
type = mapnik::type_from_filename(should_throw);
BOOST_TEST( type );
REQUIRE( type );
try
{
std::unique_ptr<mapnik::image_reader> reader(mapnik::get_image_reader(should_throw,*type));
BOOST_TEST( false );
REQUIRE( false );
}
catch (std::exception const&)
{
BOOST_TEST( true );
REQUIRE( true );
}
#endif
#if defined(HAVE_TIFF)
should_throw = "./tests/cpp_tests/data/blank.tiff";
BOOST_TEST( mapnik::util::exists( should_throw ) );
REQUIRE( mapnik::util::exists( should_throw ) );
type = mapnik::type_from_filename(should_throw);
BOOST_TEST( type );
REQUIRE( type );
try
{
std::unique_ptr<mapnik::image_reader> reader(mapnik::get_image_reader(should_throw,*type));
BOOST_TEST( false );
REQUIRE( false );
}
catch (std::exception const&)
{
BOOST_TEST( true );
REQUIRE( true );
}
#endif
#if defined(HAVE_WEBP)
should_throw = "./tests/cpp_tests/data/blank.webp";
BOOST_TEST( mapnik::util::exists( should_throw ) );
REQUIRE( mapnik::util::exists( should_throw ) );
type = mapnik::type_from_filename(should_throw);
BOOST_TEST( type );
REQUIRE( type );
try
{
std::unique_ptr<mapnik::image_reader> reader(mapnik::get_image_reader(should_throw,*type));
BOOST_TEST( false );
REQUIRE( false );
}
catch (std::exception const&)
{
BOOST_TEST( true );
REQUIRE( true );
}
#endif
}
catch (std::exception const & ex)
{
std::clog << ex.what() << "\n";
BOOST_TEST(false);
REQUIRE(false);
}
if (!::boost::detail::test_errors()) {
if (quiet) std::clog << "\x1b[1;32m.\x1b[0m";
else std::clog << "C++ image i/o: \x1b[1;32m✓ \x1b[0m\n";
::boost::detail::report_errors_remind().called_report_errors_function = true;
} else {
return ::boost::report_errors();
}
}
}

View file

@ -1,7 +1,6 @@
#include "catch.hpp"
#include <iostream>
#include <boost/detail/lightweight_test.hpp>
#include <mapnik/map.hpp>
#include <mapnik/layer.hpp>
#include <mapnik/rule.hpp>
@ -10,14 +9,9 @@
#include <mapnik/agg_renderer.hpp>
#include <mapnik/expression.hpp>
int main(int argc, char** argv)
{
std::vector<std::string> args;
for (int i = 1; i < argc; ++i)
{
args.push_back(argv[i]);
}
bool quiet = std::find(args.begin(), args.end(), "-q") != args.end();
TEST_CASE("image") {
SECTION("painting") {
using namespace mapnik;
@ -63,22 +57,13 @@ int main(int argc, char** argv)
agg_renderer<image_rgba8> ren(m, image);
ren.apply();
BOOST_TEST_EQ(image.painted(), true);
REQUIRE(image.painted() == true);
}
catch (std::exception const & ex)
{
std::clog << ex.what() << std::endl;
BOOST_TEST(false);
REQUIRE(false);
}
if (::boost::detail::test_errors())
{
return ::boost::report_errors();
}
else
{
if (quiet) std::clog << "\x1b[1;32m.\x1b[0m";
else std::clog << "C++ image painted: \x1b[1;32m✓ \x1b[0m\n";
::boost::detail::report_errors_remind().called_report_errors_function = true;
}
}
}

View file

@ -1,4 +1,5 @@
#include <boost/detail/lightweight_test.hpp>
#include "catch.hpp"
#include <iostream>
#include <mapnik/geometry.hpp>
#include <mapnik/geometry_adapters.hpp>
@ -6,14 +7,9 @@
#include <vector>
#include <algorithm>
int main(int argc, char** argv)
{
std::vector<std::string> args;
for (int i=1;i<argc;++i)
{
args.push_back(argv[i]);
}
bool quiet = std::find(args.begin(), args.end(), "-q")!=args.end();
TEST_CASE("labeling") {
SECTION("algorithms") {
try
{
@ -22,9 +18,9 @@ int main(int argc, char** argv)
{
// single point
mapnik::geometry::point<double> pt(10,10);
BOOST_TEST( mapnik::geometry::centroid(pt, centroid));
BOOST_TEST( pt.x == centroid.x);
BOOST_TEST( pt.y == centroid.y);
REQUIRE( mapnik::geometry::centroid(pt, centroid));
REQUIRE( pt.x == centroid.x);
REQUIRE( pt.y == centroid.y);
}
// linestring with three consecutive verticies
@ -33,9 +29,9 @@ int main(int argc, char** argv)
line.add_coord(0, 0);
line.add_coord(25, 25);
line.add_coord(50, 50);
BOOST_TEST(mapnik::geometry::centroid(line, centroid));
BOOST_TEST( centroid.x == 25 );
BOOST_TEST( centroid.y == 25 );
REQUIRE(mapnik::geometry::centroid(line, centroid));
REQUIRE( centroid.x == 25 );
REQUIRE( centroid.y == 25 );
}
// TODO - centroid and interior should be equal but they appear not to be (check largest)
// MULTIPOLYGON(((-52 40,-60 32,-68 40,-60 48,-52 40)),((-60 50,-80 30,-100 49.9999999999999,-80.0000000000001 70,-60 50)),((-52 60,-60 52,-68 60,-60 68,-52 60)))
@ -45,32 +41,25 @@ int main(int argc, char** argv)
mapnik::geometry_type pt_hit(mapnik::geometry::geometry_types::Point);
pt_hit.move_to(10,10);
mapnik::vertex_adapter va(pt_hit);
BOOST_TEST( mapnik::label::hit_test(va, 10, 10, 0.1) );
BOOST_TEST( !mapnik::label::hit_test(va, 9, 9, 0) );
BOOST_TEST( mapnik::label::hit_test(va, 9, 9, 1.5) );
REQUIRE( mapnik::label::hit_test(va, 10, 10, 0.1) );
REQUIRE( !mapnik::label::hit_test(va, 9, 9, 0) );
REQUIRE( mapnik::label::hit_test(va, 9, 9, 1.5) );
}
{
mapnik::geometry_type line_hit(mapnik::geometry::geometry_types::LineString);
line_hit.move_to(0,0);
line_hit.line_to(50,50);
mapnik::vertex_adapter va(line_hit);
BOOST_TEST( mapnik::label::hit_test(va, 0, 0, 0.001) );
BOOST_TEST( !mapnik::label::hit_test(va, 1, 1, 0) );
BOOST_TEST( mapnik::label::hit_test(va, 1, 1, 1.001) );
REQUIRE( mapnik::label::hit_test(va, 0, 0, 0.001) );
REQUIRE( !mapnik::label::hit_test(va, 1, 1, 0) );
REQUIRE( mapnik::label::hit_test(va, 1, 1, 1.001) );
}
#endif
}
catch (std::exception const & ex)
{
std::clog << ex.what() << "\n";
BOOST_TEST(false);
}
if (!::boost::detail::test_errors()) {
if (quiet) std::clog << "\x1b[1;32m.\x1b[0m";
else std::clog << "C++ label algorithms: \x1b[1;32m✓ \x1b[0m\n";
::boost::detail::report_errors_remind().called_report_errors_function = true;
} else {
return ::boost::report_errors();
REQUIRE(false);
}
}
}

View file

@ -1,10 +1,9 @@
#include "catch.hpp"
// mapnik
#include <mapnik/coord.hpp>
#include <mapnik/vertex_cache.hpp>
// boost
#include <boost/detail/lightweight_test.hpp>
// stl
#include <stdexcept>
#include <iostream>
@ -13,9 +12,6 @@
#include <tuple>
#include <algorithm>
// test
#include "utils.hpp"
struct fake_path
{
using coord_type = std::tuple<double, double, unsigned>;
@ -68,27 +64,6 @@ double dist(mapnik::pixel_position const &a,
return std::sqrt(d.x*d.x + d.y*d.y);
}
namespace boost { namespace detail {
template<class T, class U>
inline void test_leq_impl(char const * expr1, char const * expr2,
char const * file, int line, char const * function,
T const & t, U const & u)
{
if( t > u )
{
BOOST_LIGHTWEIGHT_TEST_OSTREAM
<< file << "(" << line << "): test '" << expr1 << " == " << expr2
<< "' failed in function '" << function << "': "
<< "'" << t << "' > '" << u << "'" << std::endl;
++test_errors();
}
}
} }
#define BOOST_TEST_LEQ(expr1,expr2) ( ::boost::detail::test_leq_impl(#expr1, #expr2, __FILE__, __LINE__, BOOST_CURRENT_FUNCTION, expr1, expr2) )
void test_simple_segment(double const &offset)
{
const double dx = 0.01;
@ -101,7 +76,7 @@ void test_simple_segment(double const &offset)
while (vc.move(dx)) {
double pos = vc.linear_position();
double off_pos = off_vc.position_closest_to(vc.current_position());
BOOST_TEST_LEQ(std::abs(pos - off_pos), 1.0e-6);
REQUIRE(std::abs(pos - off_pos) < 1.0e-6);
}
}
@ -117,7 +92,7 @@ void test_straight_line(double const &offset) {
while (vc.move(dx)) {
double pos = vc.linear_position();
double off_pos = off_vc.position_closest_to(vc.current_position());
BOOST_TEST_LEQ(std::abs(pos - off_pos), 1.0e-6);
REQUIRE(std::abs(pos - off_pos) < 1.0e-6);
}
}
@ -145,9 +120,11 @@ void test_offset_curve(double const &offset) {
{
mapnik::vertex_cache::scoped_state s(off_vc);
off_vc.move(off_pos);
BOOST_TEST_LEQ(dist(vc.current_position(), off_vc.current_position()), (1.001 * offset));
auto eps = (1.001 * offset);
auto actual = dist(vc.current_position(), off_vc.current_position());
REQUIRE(actual < eps);
}
BOOST_TEST_LEQ(std::abs((pos / vc.length()) - (off_pos / off_vc.length())), 1.0e-3);
REQUIRE(std::abs((pos / vc.length()) - (off_pos / off_vc.length())) < 1.0e-3);
}
}
@ -180,24 +157,16 @@ void test_s_shaped_curve(double const &offset) {
{
mapnik::vertex_cache::scoped_state s(off_vc);
off_vc.move(off_pos);
BOOST_TEST_LEQ(dist(vc.current_position(), off_vc.current_position()), (1.002 * offset));
REQUIRE(dist(vc.current_position(), off_vc.current_position()) < (1.002 * offset));
}
}
}
int main(int argc, char** argv)
{
std::vector<std::string> args;
for (int i=1;i<argc;++i)
{
args.push_back(argv[i]);
}
bool quiet = std::find(args.begin(), args.end(), "-q")!=args.end();
TEST_CASE("offsets") {
SECTION("line") {
try {
BOOST_TEST(set_working_dir(args));
std::vector<double> offsets = { 0.01, 0.02, 0.1, 0.2 };
for (double offset : offsets) {
// test simple straight line segment - should be easy to
@ -220,17 +189,7 @@ int main(int argc, char** argv)
catch (std::exception const& ex)
{
std::cerr << ex.what() << "\n";
BOOST_TEST(false);
}
if (!::boost::detail::test_errors())
{
if (quiet) std::clog << "\x1b[1;32m.\x1b[0m";
else std::clog << "C++ line offset: \x1b[1;32m✓ \x1b[0m\n";
::boost::detail::report_errors_remind().called_report_errors_function = true;
}
else
{
return ::boost::report_errors();
REQUIRE(false);
}
}
}

View file

@ -1,4 +1,4 @@
#include <boost/detail/lightweight_test.hpp>
#include "catch.hpp"
#include <iostream>
#include <mapnik/map.hpp>
@ -19,7 +19,6 @@
#include <vector>
#include <algorithm>
#include "utils.hpp"
bool compare_images(std::string const& src_fn,std::string const& dest_fn)
{
@ -58,20 +57,14 @@ bool compare_images(std::string const& src_fn,std::string const& dest_fn)
return true;
}
int main(int argc, char** argv)
{
std::vector<std::string> args;
for (int i=1;i<argc;++i)
{
args.push_back(argv[i]);
}
bool quiet = std::find(args.begin(), args.end(), "-q")!=args.end();
TEST_CASE("mapnik::request") {
SECTION("rendering") {
std::string expected("./tests/cpp_tests/support/map-request-marker-text-line-expected.png");
std::string expected_cairo("./tests/cpp_tests/support/map-request-marker-text-line-expected-cairo.png");
try {
BOOST_TEST(set_working_dir(args));
mapnik::datasource_cache::instance().register_datasources("plugins/input/csv.input");
mapnik::freetype_engine::register_fonts("./fonts", true );
mapnik::Map m(256,256);
@ -88,7 +81,7 @@ int main(int argc, char** argv)
mapnik::save_to_file(im,actual1);
// TODO - re-enable if we can control the freetype/cairo versions used
// https://github.com/mapnik/mapnik/issues/1868
//BOOST_TEST(compare_images(actual1,expected));
//REQUIRE(compare_images(actual1,expected));
// reset image
mapnik::fill(im, 0);
@ -105,7 +98,7 @@ int main(int argc, char** argv)
mapnik::save_to_file(im,actual2);
// TODO - re-enable if we can control the freetype/cairo versions used
// https://github.com/mapnik/mapnik/issues/1868
//BOOST_TEST(compare_images(actual2,expected));
//REQUIRE(compare_images(actual2,expected));
// reset image
mapnik::fill(im, 0);
@ -139,7 +132,7 @@ int main(int argc, char** argv)
mapnik::save_to_file(im,actual3);
// TODO - re-enable if we can control the freetype/cairo versions used
// https://github.com/mapnik/mapnik/issues/1868
//BOOST_TEST(compare_images(actual3,expected));
//REQUIRE(compare_images(actual3,expected));
// also test cairo
#if defined(HAVE_CAIRO)
@ -154,18 +147,12 @@ int main(int argc, char** argv)
cairo_surface_write_to_png(&*image_surface, actual_cairo.c_str());
// TODO - re-enable if we can control the freetype/cairo versions used
// https://github.com/mapnik/mapnik/issues/1868
//BOOST_TEST(compare_images(actual_cairo,expected_cairo));
//REQUIRE(compare_images(actual_cairo,expected_cairo));
#endif
// TODO - test grid_renderer
} catch (std::exception const& ex) {
std::clog << ex.what() << "\n";
}
if (!::boost::detail::test_errors()) {
if (quiet) std::clog << "\x1b[1;32m.\x1b[0m";
else std::clog << "C++ Map Request rendering hook: \x1b[1;32m✓ \x1b[0m\n";
::boost::detail::report_errors_remind().called_report_errors_function = true;
} else {
return ::boost::report_errors();
}
}
}

115
tests/cxx/params_test.cpp Normal file
View file

@ -0,0 +1,115 @@
#include "catch.hpp"
#include <iostream>
#include <mapnik/value_types.hpp>
#include <mapnik/params.hpp>
#include <mapnik/boolean.hpp>
#include <vector>
#include <algorithm>
#include <ostream>
namespace detail {
class string_holder {
public:
string_holder() :
member_("member") {}
std::string const& get_string() const
{
return member_;
}
private:
std::string member_;
};
}
TEST_CASE("parameters") {
SECTION("get/set") {
try
{
mapnik::parameters params;
// true
params["bool"] = mapnik::value_integer(true);
REQUIRE( (params.get<mapnik::boolean_type>("bool") && *params.get<mapnik::boolean_type>("bool") == true));
params["bool"] = "true";
REQUIRE( (params.get<mapnik::boolean_type>("bool") && *params.get<mapnik::boolean_type>("bool") == true));
params["bool"] = mapnik::value_integer(1);
REQUIRE( (params.get<mapnik::boolean_type>("bool") && *params.get<mapnik::boolean_type>("bool") == true));
params["bool"] = "1";
REQUIRE( (params.get<mapnik::boolean_type>("bool") && *params.get<mapnik::boolean_type>("bool") == true));
params["bool"] = "True";
REQUIRE( (params.get<mapnik::boolean_type>("bool") && *params.get<mapnik::boolean_type>("bool") == true));
params["bool"] = "on";
REQUIRE( (params.get<mapnik::boolean_type>("bool") && *params.get<mapnik::boolean_type>("bool") == true));
params["bool"] = "yes";
REQUIRE( (params.get<mapnik::boolean_type>("bool") && *params.get<mapnik::boolean_type>("bool") == true));
// false
params["bool"] = mapnik::value_integer(false);
REQUIRE( (params.get<mapnik::boolean_type>("bool") && *params.get<mapnik::boolean_type>("bool") == false) );
params["bool"] = "false";
REQUIRE( (params.get<mapnik::boolean_type>("bool") && *params.get<mapnik::boolean_type>("bool") == false) );
params["bool"] = mapnik::value_integer(0);
REQUIRE( (params.get<mapnik::boolean_type>("bool") && *params.get<mapnik::boolean_type>("bool") == false));
params["bool"] = "0";
REQUIRE( (params.get<mapnik::boolean_type>("bool") && *params.get<mapnik::boolean_type>("bool") == false));
params["bool"] = "False";
REQUIRE( (params.get<mapnik::boolean_type>("bool") && *params.get<mapnik::boolean_type>("bool") == false));
params["bool"] = "off";
REQUIRE( (params.get<mapnik::boolean_type>("bool") && *params.get<mapnik::boolean_type>("bool") == false));
params["bool"] = "no";
REQUIRE( (params.get<mapnik::boolean_type>("bool") && *params.get<mapnik::boolean_type>("bool") == false));
// strings
params["string"] = "hello";
REQUIRE( (params.get<std::string>("string") && *params.get<std::string>("string") == "hello") );
// int
params["int"] = mapnik::value_integer(1);
REQUIRE( (params.get<mapnik::value_integer>("int") && *params.get<mapnik::value_integer>("int") == 1) );
// double
params["double"] = 1.5;
REQUIRE( (params.get<double>("double") && *params.get<double>("double") == 1.5) );
// value_null
params["null"] = mapnik::value_null();
// https://github.com/mapnik/mapnik/issues/2471
//REQUIRE( (params.get<mapnik::value_null>("null") && *params.get<mapnik::value_null>("null") == mapnik::value_null()) );
std::string value("value");
params["value"] = value;
REQUIRE( (params.get<std::string>("value") == std::string("value")) ) ;
REQUIRE(value == std::string("value"));
// ensure that const member is not moved incorrectly when added to params
detail::string_holder holder;
std::string const& holder_member = holder.get_string();
params["member"] = holder_member;
REQUIRE( (params.get<std::string>("member") == std::string("member")) );
REQUIRE( (holder_member == std::string("member")) );
}
catch (std::exception const& ex)
{
std::cerr << ex.what() << "\n";
REQUIRE(false);
}
}
}

View file

@ -1,9 +1,9 @@
#include <boost/detail/lightweight_test.hpp>
#include "catch.hpp"
#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
#include "utils.hpp"
#include <mapnik/layer.hpp>
#include <mapnik/wkt/wkt_factory.hpp>
@ -41,21 +41,14 @@ void simplify(std::string const& wkt_in, double tolerance, std::string const& me
mapnik::geometry_container multi_out;
multi_out.push_back(output);
std::string wkt_out;
BOOST_TEST(mapnik::to_wkt(multi_out, wkt_out));
BOOST_TEST_EQ(wkt_out, expected);
REQUIRE(mapnik::to_wkt(multi_out, wkt_out));
REQUIRE(wkt_out == expected);
#endif
}
int main(int argc, char** argv)
{
std::vector<std::string> args;
for (int i=1;i<argc;++i)
{
args.push_back(argv[i]);
}
bool quiet = std::find(args.begin(), args.end(), "-q")!=args.end();
TEST_CASE("converters") {
BOOST_TEST(set_working_dir(args));
SECTION("simplify") {
simplify( std::string("LineString(0 0,2 2,3 5,4 1,5 0,6 7,7 0)"),
4, "douglas-peucker",
@ -85,14 +78,5 @@ int main(int argc, char** argv)
3, "douglas-peucker",
std::string("LineString(0 0,0 -10,-5 7,4 6)"));
if (!::boost::detail::test_errors())
{
if (quiet) std::clog << "\x1b[1;32m.\x1b[0m";
else std::clog << "C++ simplify conversions: \x1b[1;32m✓ \x1b[0m\n";
::boost::detail::report_errors_remind().called_report_errors_function = true;
}
else
{
return ::boost::report_errors();
}
}
}

View file

@ -0,0 +1,30 @@
#include "catch.hpp"
#include <iostream>
#include <mapnik/symbolizer.hpp>
#include <vector>
#include <algorithm>
using namespace mapnik;
TEST_CASE("symbolizer") {
SECTION("enums") {
try {
marker_multi_policy_enum policy_in = MARKER_WHOLE_MULTI;
REQUIRE(policy_in == MARKER_WHOLE_MULTI);
markers_symbolizer sym;
put(sym, keys::markers_multipolicy, policy_in);
REQUIRE(sym.properties.count(keys::markers_multipolicy) == static_cast<unsigned long>(1));
marker_multi_policy_enum policy_out = get<mapnik::marker_multi_policy_enum>(sym, keys::markers_multipolicy);
REQUIRE(policy_out == MARKER_WHOLE_MULTI);
}
catch (std::exception const & ex)
{
std::clog << ex.what() << std::endl;
REQUIRE(false);
}
}
}

View file

@ -1,4 +1,5 @@
#include <boost/detail/lightweight_test.hpp>
#include "catch.hpp"
#include <iostream>
#include <mapnik/params.hpp>
#include <mapnik/wkb.hpp>
@ -11,23 +12,9 @@
#include <algorithm>
#include <boost/version.hpp>
namespace {
void test_simple_and_valid(const mapnik::geometry::geometry<double> &geom) {
// only Boost >= 1.56 has is_valid and is_simple
#if BOOST_VERSION >= 105600
BOOST_TEST(mapnik::geometry::is_valid(geom) && mapnik::geometry::is_simple(geom));
#endif
}
}
TEST_CASE("geometry formats") {
int main(int argc, char** argv)
{
std::vector<std::string> args;
for (int i=1;i<argc;++i)
{
args.push_back(argv[i]);
}
bool quiet = std::find(args.begin(), args.end(), "-q")!=args.end();
SECTION("wkb") {
unsigned char sp_valid_blob[] = {
0x0, 0x1, 0xBC, 0xB, 0x0, 0x0, 0x1F, 0x12, 0xDB, 0xCF, 0xC3, 0xA2, 0x41, 0x41, 0x9D, 0x74, 0xB0, 0x31, 0xE6, 0x34, 0x53, 0x41, 0xDB,
@ -83,47 +70,52 @@ int main(int argc, char** argv)
mapnik::wkbSpatiaLite);
// winding order is not correct per OGC so we'll fix it
mapnik::geometry::correct(geom);
test_simple_and_valid(geom);
#if BOOST_VERSION >= 105600
REQUIRE(mapnik::geometry::is_valid(geom));
REQUIRE(mapnik::geometry::is_simple(geom));
#endif
geom = mapnik::geometry_utils::from_wkb((const char*)sp_valid_blob,
sizeof(sp_valid_blob) / sizeof(sp_valid_blob[0]),
mapnik::wkbAuto);
mapnik::geometry::correct(geom);
test_simple_and_valid(geom);
#if BOOST_VERSION >= 105600
REQUIRE(mapnik::geometry::is_valid(geom));
REQUIRE(mapnik::geometry::is_simple(geom));
#endif
geom = mapnik::geometry_utils::from_wkb((const char*)sp_invalid_blob,
sizeof(sp_invalid_blob) / sizeof(sp_invalid_blob[0]),
mapnik::wkbAuto);
BOOST_TEST(geom.is<mapnik::geometry::geometry_empty>()); // returns geometry_empty
REQUIRE(geom.is<mapnik::geometry::geometry_empty>()); // returns geometry_empty
// sqlite generic wkb blob
geom = mapnik::geometry_utils::from_wkb((const char*)sq_valid_blob,
sizeof(sq_valid_blob) / sizeof(sq_valid_blob[0]),
mapnik::wkbGeneric);
test_simple_and_valid(geom);
#if BOOST_VERSION >= 105600
REQUIRE(mapnik::geometry::is_valid(geom));
REQUIRE(mapnik::geometry::is_simple(geom));
#endif
geom = mapnik::geometry_utils::from_wkb( (const char*)sq_valid_blob,
sizeof(sq_valid_blob) / sizeof(sq_valid_blob[0]),
mapnik::wkbAuto);
test_simple_and_valid(geom);
#if BOOST_VERSION >= 105600
REQUIRE(mapnik::geometry::is_valid(geom));
REQUIRE(mapnik::geometry::is_simple(geom));
#endif
geom = mapnik::geometry_utils::from_wkb((const char*)sq_invalid_blob,
sizeof(sq_invalid_blob) / sizeof(sq_invalid_blob[0]),
mapnik::wkbGeneric);
BOOST_TEST(geom.is<mapnik::geometry::geometry_empty>()); // returns geometry_empty
REQUIRE(geom.is<mapnik::geometry::geometry_empty>()); // returns geometry_empty
} catch (std::exception const& ex) {
BOOST_TEST(false);
REQUIRE(false);
std::clog << "threw: " << ex.what() << "\n";
}
if (!::boost::detail::test_errors()) {
if (quiet) std::clog << "\x1b[1;32m.\x1b[0m";
else std::clog << "C++ WKB formats test: \x1b[1;32m✓ \x1b[0m\n";
::boost::detail::report_errors_remind().called_report_errors_function = true;
} else {
return ::boost::report_errors();
}
}
}

View file

@ -1,71 +0,0 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from nose.tools import eq_
from utilities import run_all
import mapnik
import json
# geojson box of the world
geojson = { "type": "Feature", "properties": { }, "geometry": { "type": "Polygon", "coordinates": [ [ [ -17963313.143242701888084, -6300857.11560364998877 ], [ -17963313.143242701888084, 13071343.332991421222687 ], [ 7396658.353099936619401, 13071343.332991421222687 ], [ 7396658.353099936619401, -6300857.11560364998877 ], [ -17963313.143242701888084, -6300857.11560364998877 ] ] ] } }
def test_that_coordinates_do_not_overflow_and_polygon_is_rendered_memory():
expected_color = mapnik.Color('white')
projection = '+init=epsg:4326'
ds = mapnik.MemoryDatasource()
context = mapnik.Context()
feat = mapnik.Feature.from_geojson(json.dumps(geojson),context)
ds.add_feature(feat)
s = mapnik.Style()
r = mapnik.Rule()
sym = mapnik.PolygonSymbolizer()
sym.fill = expected_color
r.symbols.append(sym)
s.rules.append(r)
lyr = mapnik.Layer('Layer',projection)
lyr.datasource = ds
lyr.styles.append('style')
m = mapnik.Map(256,256,projection)
m.background_color = mapnik.Color('green')
m.append_style('style',s)
m.layers.append(lyr)
# 17/20864/45265.png
m.zoom_to_box(mapnik.Box2d(-13658379.710221574,6197514.253362091,-13657768.213995293,6198125.749588372))
# works 15/5216/11316.png
#m.zoom_to_box(mapnik.Box2d(-13658379.710221574,6195679.764683247,-13655933.72531645,6198125.749588372))
im = mapnik.Image(256,256)
mapnik.render(m,im)
eq_(im.get_pixel(128,128),expected_color.packed())
def test_that_coordinates_do_not_overflow_and_polygon_is_rendered_csv():
expected_color = mapnik.Color('white')
projection = '+init=epsg:4326'
ds = mapnik.MemoryDatasource()
context = mapnik.Context()
feat = mapnik.Feature.from_geojson(json.dumps(geojson),context)
ds.add_feature(feat)
geojson_string = "geojson\n'%s'" % json.dumps(geojson['geometry'])
ds = mapnik.Datasource(**{'type':'csv','inline':geojson_string})
s = mapnik.Style()
r = mapnik.Rule()
sym = mapnik.PolygonSymbolizer()
sym.fill = expected_color
r.symbols.append(sym)
s.rules.append(r)
lyr = mapnik.Layer('Layer',projection)
lyr.datasource = ds
lyr.styles.append('style')
m = mapnik.Map(256,256,projection)
m.background_color = mapnik.Color('green')
m.append_style('style',s)
m.layers.append(lyr)
# 17/20864/45265.png
m.zoom_to_box(mapnik.Box2d(-13658379.710221574,6197514.253362091,-13657768.213995293,6198125.749588372))
# works 15/5216/11316.png
#m.zoom_to_box(mapnik.Box2d(-13658379.710221574,6195679.764683247,-13655933.72531645,6198125.749588372))
im = mapnik.Image(256,256)
mapnik.render(m,im)
eq_(im.get_pixel(128,128),expected_color.packed())
if __name__ == "__main__":
exit(run_all(eval(x) for x in dir() if x.startswith("test_")))

View file

@ -1,176 +0,0 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from nose.tools import eq_,assert_true,assert_almost_equal,assert_false
from utilities import run_all
import mapnik
def test_coord_init():
c = mapnik.Coord(100, 100)
eq_(c.x, 100)
eq_(c.y, 100)
def test_coord_multiplication():
c = mapnik.Coord(100, 100)
c *= 2
eq_(c.x, 200)
eq_(c.y, 200)
def test_envelope_init():
e = mapnik.Box2d(100, 100, 200, 200)
assert_true(e.contains(100, 100))
assert_true(e.contains(100, 200))
assert_true(e.contains(200, 200))
assert_true(e.contains(200, 100))
assert_true(e.contains(e.center()))
assert_false(e.contains(99.9, 99.9))
assert_false(e.contains(99.9, 200.1))
assert_false(e.contains(200.1, 200.1))
assert_false(e.contains(200.1, 99.9))
eq_(e.width(), 100)
eq_(e.height(), 100)
eq_(e.minx, 100)
eq_(e.miny, 100)
eq_(e.maxx, 200)
eq_(e.maxy, 200)
eq_(e[0],100)
eq_(e[1],100)
eq_(e[2],200)
eq_(e[3],200)
eq_(e[0],e[-4])
eq_(e[1],e[-3])
eq_(e[2],e[-2])
eq_(e[3],e[-1])
c = e.center()
eq_(c.x, 150)
eq_(c.y, 150)
def test_envelope_static_init():
e = mapnik.Box2d.from_string('100 100 200 200')
e2 = mapnik.Box2d.from_string('100,100,200,200')
e3 = mapnik.Box2d.from_string('100 , 100 , 200 , 200')
eq_(e,e2)
eq_(e,e3)
assert_true(e.contains(100, 100))
assert_true(e.contains(100, 200))
assert_true(e.contains(200, 200))
assert_true(e.contains(200, 100))
assert_true(e.contains(e.center()))
assert_false(e.contains(99.9, 99.9))
assert_false(e.contains(99.9, 200.1))
assert_false(e.contains(200.1, 200.1))
assert_false(e.contains(200.1, 99.9))
eq_(e.width(), 100)
eq_(e.height(), 100)
eq_(e.minx, 100)
eq_(e.miny, 100)
eq_(e.maxx, 200)
eq_(e.maxy, 200)
eq_(e[0],100)
eq_(e[1],100)
eq_(e[2],200)
eq_(e[3],200)
eq_(e[0],e[-4])
eq_(e[1],e[-3])
eq_(e[2],e[-2])
eq_(e[3],e[-1])
c = e.center()
eq_(c.x, 150)
eq_(c.y, 150)
def test_envelope_multiplication():
# no width then no impact of multiplication
a = mapnik.Box2d(100, 100, 100, 100)
a *= 5
eq_(a.minx,100)
eq_(a.miny,100)
eq_(a.maxx,100)
eq_(a.maxy,100)
a = mapnik.Box2d(100.0, 100.0, 100.0, 100.0)
a *= 5
eq_(a.minx,100)
eq_(a.miny,100)
eq_(a.maxx,100)
eq_(a.maxy,100)
a = mapnik.Box2d(100.0, 100.0, 100.001, 100.001)
a *= 5
assert_almost_equal(a.minx, 99.9979, places=3)
assert_almost_equal(a.miny, 99.9979, places=3)
assert_almost_equal(a.maxx, 100.0030, places=3)
assert_almost_equal(a.maxy, 100.0030, places=3)
e = mapnik.Box2d(100, 100, 200, 200)
e *= 2
eq_(e.minx,50)
eq_(e.miny,50)
eq_(e.maxx,250)
eq_(e.maxy,250)
assert_true(e.contains(50, 50))
assert_true(e.contains(50, 250))
assert_true(e.contains(250, 250))
assert_true(e.contains(250, 50))
assert_false(e.contains(49.9, 49.9))
assert_false(e.contains(49.9, 250.1))
assert_false(e.contains(250.1, 250.1))
assert_false(e.contains(250.1, 49.9))
assert_true(e.contains(e.center()))
eq_(e.width(), 200)
eq_(e.height(), 200)
eq_(e.minx, 50)
eq_(e.miny, 50)
eq_(e.maxx, 250)
eq_(e.maxy, 250)
c = e.center()
eq_(c.x, 150)
eq_(c.y, 150)
def test_envelope_clipping():
e1 = mapnik.Box2d(-180,-90,180,90)
e2 = mapnik.Box2d(-120,40,-110,48)
e1.clip(e2)
eq_(e1,e2)
# madagascar in merc
e1 = mapnik.Box2d(4772116.5490, -2744395.0631, 5765186.4203, -1609458.0673)
e2 = mapnik.Box2d(5124338.3753, -2240522.1727, 5207501.8621, -2130452.8520)
e1.clip(e2)
eq_(e1,e2)
# nz in lon/lat
e1 = mapnik.Box2d(163.8062, -47.1897, 179.3628, -33.9069)
e2 = mapnik.Box2d(173.7378, -39.6395, 174.4849, -38.9252)
e1.clip(e2)
eq_(e1,e2)
if __name__ == "__main__":
exit(run_all(eval(x) for x in dir() if x.startswith("test_")))

View file

@ -1,61 +0,0 @@
import os, mapnik
from nose.tools import eq_
from utilities import execution_path, run_all
def setup():
# All of the paths used are relative, if we run the tests
# from another directory we need to chdir()
os.chdir(execution_path('.'))
def test_clearing_image_data():
im = mapnik.Image(256,256)
# make sure it equals itself
bytes = im.tostring()
eq_(im.tostring(),bytes)
# set background, then clear
im.fill(mapnik.Color('green'))
eq_(im.tostring()!=bytes,True)
# clear image, should now equal original
im.clear()
eq_(im.tostring(),bytes)
def make_map():
ds = mapnik.MemoryDatasource()
context = mapnik.Context()
context.push('Name')
pixel_key = 1
f = mapnik.Feature(context,pixel_key)
f['Name'] = str(pixel_key)
f.geometry=mapnik.Geometry.from_wkt('POLYGON ((0 0, 0 256, 256 256, 256 0, 0 0))')
ds.add_feature(f)
s = mapnik.Style()
r = mapnik.Rule()
symb = mapnik.PolygonSymbolizer()
r.symbols.append(symb)
s.rules.append(r)
lyr = mapnik.Layer('Places')
lyr.datasource = ds
lyr.styles.append('places_labels')
width,height = 256,256
m = mapnik.Map(width,height)
m.append_style('places_labels',s)
m.layers.append(lyr)
m.zoom_all()
return m
if mapnik.has_grid_renderer():
def test_clearing_grid_data():
g = mapnik.Grid(256,256)
utf = g.encode()
# make sure it equals itself
eq_(g.encode(),utf)
m = make_map()
mapnik.render_layer(m,g,layer=0,fields=['__id__','Name'])
eq_(g.encode()!=utf,True)
# clear grid, should now match original
g.clear()
eq_(g.encode(),utf)
if __name__ == "__main__":
setup()
exit(run_all(eval(x) for x in dir() if x.startswith("test_")))

View file

@ -1,196 +0,0 @@
#!/usr/bin/env python
import os
import shutil
import mapnik
from nose.tools import eq_
from utilities import execution_path, run_all
def setup():
# All of the paths used are relative, if we run the tests
# from another directory we need to chdir()
os.chdir(execution_path('.'))
def make_tmp_map():
m = mapnik.Map(512,512)
m.background_color = mapnik.Color('steelblue')
ds = mapnik.MemoryDatasource()
context = mapnik.Context()
context.push('Name')
f = mapnik.Feature(context,1)
f['Name'] = 'Hello'
f.geometry = mapnik.Geometry.from_wkt('POINT (0 0)')
ds.add_feature(f)
s = mapnik.Style()
r = mapnik.Rule()
sym = mapnik.MarkersSymbolizer()
sym.allow_overlap = True
r.symbols.append(sym)
s.rules.append(r)
lyr = mapnik.Layer('Layer')
lyr.datasource = ds
lyr.styles.append('style')
m.append_style('style',s)
m.layers.append(lyr)
return m
def draw_title(m,ctx,text,size=10,color=mapnik.Color('black')):
""" Draw a Map Title near the top of a page."""
middle = m.width/2.0
ctx.set_source_rgba(*cairo_color(color))
ctx.select_font_face("DejaVu Sans Book", cairo.FONT_SLANT_NORMAL, cairo.FONT_WEIGHT_NORMAL)
ctx.set_font_size(size)
x_bearing, y_bearing, width, height = ctx.text_extents(text)[:4]
ctx.move_to(middle - width / 2 - x_bearing, 20.0 - height / 2 - y_bearing)
ctx.show_text(text)
def draw_neatline(m,ctx):
w,h = m.width, m.height
ctx.set_source_rgba(*cairo_color(mapnik.Color('black')))
outline = [
[0,0],[w,0],[w,h],[0,h]
]
ctx.set_line_width(1)
for idx,pt in enumerate(outline):
if (idx == 0):
ctx.move_to(*pt)
else:
ctx.line_to(*pt)
ctx.close_path()
inset = 6
inline = [
[inset,inset],[w-inset,inset],[w-inset,h-inset],[inset,h-inset]
]
ctx.set_line_width(inset/2)
for idx,pt in enumerate(inline):
if (idx == 0):
ctx.move_to(*pt)
else:
ctx.line_to(*pt)
ctx.close_path()
ctx.stroke()
def cairo_color(c):
""" Return a Cairo color tuple from a Mapnik Color."""
ctx_c = (c.r/255.0,c.g/255.0,c.b/255.0,c.a/255.0)
return ctx_c
if mapnik.has_pycairo():
import cairo
def test_passing_pycairo_context_svg():
m = make_tmp_map()
m.zoom_to_box(mapnik.Box2d(-180,-90,180,90))
test_cairo_file = '/tmp/mapnik-cairo-context-test.svg'
surface = cairo.SVGSurface(test_cairo_file, m.width, m.height)
expected_cairo_file = './images/pycairo/cairo-cairo-expected.svg'
context = cairo.Context(surface)
mapnik.render(m,context)
draw_title(m,context,"Hello Map",size=20)
draw_neatline(m,context)
surface.finish()
if not os.path.exists(expected_cairo_file) or os.environ.get('UPDATE'):
print 'generated expected cairo surface file %s' % expected_cairo_file
shutil.copy(test_cairo_file,expected_cairo_file)
diff = abs(os.stat(expected_cairo_file).st_size-os.stat(test_cairo_file).st_size)
msg = 'diff in size (%s) between actual (%s) and expected(%s)' % (diff,test_cairo_file,'tests/python_tests/'+ expected_cairo_file)
eq_( diff < 1500, True, msg)
os.remove(test_cairo_file)
def test_passing_pycairo_context_pdf():
m = make_tmp_map()
m.zoom_to_box(mapnik.Box2d(-180,-90,180,90))
test_cairo_file = '/tmp/mapnik-cairo-context-test.pdf'
surface = cairo.PDFSurface(test_cairo_file, m.width, m.height)
expected_cairo_file = './images/pycairo/cairo-cairo-expected.pdf'
context = cairo.Context(surface)
mapnik.render(m,context)
draw_title(m,context,"Hello Map",size=20)
draw_neatline(m,context)
surface.finish()
if not os.path.exists(expected_cairo_file) or os.environ.get('UPDATE'):
print 'generated expected cairo surface file %s' % expected_cairo_file
shutil.copy(test_cairo_file,expected_cairo_file)
diff = abs(os.stat(expected_cairo_file).st_size-os.stat(test_cairo_file).st_size)
msg = 'diff in size (%s) between actual (%s) and expected(%s)' % (diff,test_cairo_file,'tests/python_tests/'+ expected_cairo_file)
eq_( diff < 1500, True, msg)
os.remove(test_cairo_file)
def test_passing_pycairo_context_png():
m = make_tmp_map()
m.zoom_to_box(mapnik.Box2d(-180,-90,180,90))
test_cairo_file = '/tmp/mapnik-cairo-context-test.png'
surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, m.width, m.height)
expected_cairo_file = './images/pycairo/cairo-cairo-expected.png'
expected_cairo_file2 = './images/pycairo/cairo-cairo-expected-reduced.png'
context = cairo.Context(surface)
mapnik.render(m,context)
draw_title(m,context,"Hello Map",size=20)
draw_neatline(m,context)
surface.write_to_png(test_cairo_file)
reduced_color_image = test_cairo_file.replace('png','-mapnik.png')
im = mapnik.Image.from_cairo(surface)
im.save(reduced_color_image,'png8')
surface.finish()
if not os.path.exists(expected_cairo_file) or os.environ.get('UPDATE'):
print 'generated expected cairo surface file %s' % expected_cairo_file
shutil.copy(test_cairo_file,expected_cairo_file)
diff = abs(os.stat(expected_cairo_file).st_size-os.stat(test_cairo_file).st_size)
msg = 'diff in size (%s) between actual (%s) and expected(%s)' % (diff,test_cairo_file,'tests/python_tests/'+ expected_cairo_file)
eq_( diff < 500, True, msg)
os.remove(test_cairo_file)
if not os.path.exists(expected_cairo_file2) or os.environ.get('UPDATE'):
print 'generated expected cairo surface file %s' % expected_cairo_file2
shutil.copy(reduced_color_image,expected_cairo_file2)
diff = abs(os.stat(expected_cairo_file2).st_size-os.stat(reduced_color_image).st_size)
msg = 'diff in size (%s) between actual (%s) and expected(%s)' % (diff,reduced_color_image,'tests/python_tests/'+ expected_cairo_file2)
eq_( diff < 500, True, msg)
os.remove(reduced_color_image)
if 'sqlite' in mapnik.DatasourceCache.plugin_names():
def _pycairo_surface(type,sym):
test_cairo_file = '/tmp/mapnik-cairo-surface-test.%s.%s' % (sym,type)
expected_cairo_file = './images/pycairo/cairo-surface-expected.%s.%s' % (sym,type)
m = mapnik.Map(256,256)
mapnik.load_map(m,'../data/good_maps/%s_symbolizer.xml' % sym)
m.zoom_all()
if hasattr(cairo,'%sSurface' % type.upper()):
surface = getattr(cairo,'%sSurface' % type.upper())(test_cairo_file, m.width,m.height)
mapnik.render(m, surface)
surface.finish()
if not os.path.exists(expected_cairo_file) or os.environ.get('UPDATE'):
print 'generated expected cairo surface file %s' % expected_cairo_file
shutil.copy(test_cairo_file,expected_cairo_file)
diff = abs(os.stat(expected_cairo_file).st_size-os.stat(test_cairo_file).st_size)
msg = 'diff in size (%s) between actual (%s) and expected(%s)' % (diff,test_cairo_file,'tests/python_tests/'+ expected_cairo_file)
if os.uname()[0] == 'Darwin':
eq_( diff < 2100, True, msg)
else:
eq_( diff < 23000, True, msg)
os.remove(test_cairo_file)
return True
else:
print 'skipping cairo.%s test since surface is not available' % type.upper()
return True
def test_pycairo_svg_surface1():
eq_(_pycairo_surface('svg','point'),True)
def test_pycairo_svg_surface2():
eq_(_pycairo_surface('svg','building'),True)
def test_pycairo_svg_surface3():
eq_(_pycairo_surface('svg','polygon'),True)
def test_pycairo_pdf_surface1():
eq_(_pycairo_surface('pdf','point'),True)
def test_pycairo_pdf_surface2():
eq_(_pycairo_surface('pdf','building'),True)
def test_pycairo_pdf_surface3():
eq_(_pycairo_surface('pdf','polygon'),True)
if __name__ == "__main__":
setup()
exit(run_all(eval(x) for x in dir() if x.startswith("test_")))

View file

@ -1,115 +0,0 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import sys
import os, mapnik
from timeit import Timer, time
from nose.tools import *
from utilities import execution_path, run_all, get_unique_colors
def setup():
# All of the paths used are relative, if we run the tests
# from another directory we need to chdir()
os.chdir(execution_path('.'))
def test_color_init():
c = mapnik.Color(12, 128, 255)
eq_(c.r, 12)
eq_(c.g, 128)
eq_(c.b, 255)
eq_(c.a, 255)
eq_(False, c.get_premultiplied())
c = mapnik.Color(16, 32, 64, 128)
eq_(c.r, 16)
eq_(c.g, 32)
eq_(c.b, 64)
eq_(c.a, 128)
eq_(False, c.get_premultiplied())
c = mapnik.Color(16, 32, 64, 128,True)
eq_(c.r, 16)
eq_(c.g, 32)
eq_(c.b, 64)
eq_(c.a, 128)
eq_(True, c.get_premultiplied())
c = mapnik.Color('rgba(16,32,64,0.5)')
eq_(c.r, 16)
eq_(c.g, 32)
eq_(c.b, 64)
eq_(c.a, 128)
eq_(False, c.get_premultiplied())
c = mapnik.Color('rgba(16,32,64,0.5)', True)
eq_(c.r, 16)
eq_(c.g, 32)
eq_(c.b, 64)
eq_(c.a, 128)
eq_(True, c.get_premultiplied())
hex_str = '#10204080'
c = mapnik.Color(hex_str)
eq_(c.r, 16)
eq_(c.g, 32)
eq_(c.b, 64)
eq_(c.a, 128)
eq_(hex_str, c.to_hex_string())
eq_(False, c.get_premultiplied())
c = mapnik.Color(hex_str, True)
eq_(c.r, 16)
eq_(c.g, 32)
eq_(c.b, 64)
eq_(c.a, 128)
eq_(hex_str, c.to_hex_string())
eq_(True, c.get_premultiplied())
rgba_int = 2151686160
c = mapnik.Color(rgba_int)
eq_(c.r, 16)
eq_(c.g, 32)
eq_(c.b, 64)
eq_(c.a, 128)
eq_(rgba_int, c.packed())
eq_(False, c.get_premultiplied())
c = mapnik.Color(rgba_int, True)
eq_(c.r, 16)
eq_(c.g, 32)
eq_(c.b, 64)
eq_(c.a, 128)
eq_(rgba_int, c.packed())
eq_(True, c.get_premultiplied())
def test_color_properties():
c = mapnik.Color(16, 32, 64, 128)
eq_(c.r, 16)
eq_(c.g, 32)
eq_(c.b, 64)
eq_(c.a, 128)
c.r = 17
eq_(c.r, 17)
c.g = 33
eq_(c.g, 33)
c.b = 65
eq_(c.b, 65)
c.a = 128
eq_(c.a, 128)
def test_color_premultiply():
c = mapnik.Color(16, 33, 255, 128)
eq_(c.premultiply(), True)
eq_(c.r, 8)
eq_(c.g, 17)
eq_(c.b, 128)
eq_(c.a, 128)
# Repeating it again should do nothing
eq_(c.premultiply(), False)
eq_(c.r, 8)
eq_(c.g, 17)
eq_(c.b, 128)
eq_(c.a, 128)
c.demultiply()
c.demultiply()
# This will not return the same values as before but we expect that
eq_(c.r,15)
eq_(c.g,33)
eq_(c.b,255)
eq_(c.a,128)
if __name__ == "__main__":
setup()
exit(run_all(eval(x) for x in dir() if x.startswith("test_")))

View file

@ -1,112 +0,0 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import os, mapnik
from nose.tools import *
from utilities import execution_path, run_all
def setup():
# All of the paths used are relative, if we run the tests
# from another directory we need to chdir()
os.chdir(execution_path('.'))
def test_another_compare():
im = mapnik.Image(5,5)
im2 = mapnik.Image(5,5)
im2.fill(mapnik.Color('rgba(255,255,255,0)'))
eq_(im.compare(im2,16), im.width() * im.height())
def test_compare_rgba8():
im = mapnik.Image(5,5,mapnik.ImageType.rgba8)
im.fill(mapnik.Color(0,0,0,0))
eq_(im.compare(im), 0)
im2 = mapnik.Image(5,5,mapnik.ImageType.rgba8)
im2.fill(mapnik.Color(0,0,0,0))
eq_(im.compare(im2), 0)
eq_(im2.compare(im), 0)
im2.fill(mapnik.Color(0,0,0,12))
eq_(im.compare(im2), 25)
eq_(im.compare(im2, 0, False), 0)
im3 = mapnik.Image(5,5,mapnik.ImageType.rgba8)
im3.set_pixel(0,0, mapnik.Color(0,0,0,0))
im3.set_pixel(0,1, mapnik.Color(1,1,1,1))
im3.set_pixel(1,0, mapnik.Color(2,2,2,2))
im3.set_pixel(1,1, mapnik.Color(3,3,3,3))
eq_(im.compare(im3), 3)
eq_(im.compare(im3,1),2)
eq_(im.compare(im3,2),1)
eq_(im.compare(im3,3),0)
def test_compare_2_image():
im = mapnik.Image(5,5)
im.set_pixel(0,0, mapnik.Color(254, 254, 254, 254))
im.set_pixel(4,4, mapnik.Color('white'))
im2 = mapnik.Image(5,5)
eq_(im2.compare(im,16), 2)
def test_compare_dimensions():
im = mapnik.Image(2,2)
im2 = mapnik.Image(3,3)
eq_(im.compare(im2), 4)
eq_(im2.compare(im), 9)
def test_compare_gray8():
im = mapnik.Image(2,2,mapnik.ImageType.gray8)
im.fill(0)
eq_(im.compare(im), 0)
im2 = mapnik.Image(2,2,mapnik.ImageType.gray8)
im2.fill(0)
eq_(im.compare(im2), 0)
eq_(im2.compare(im), 0)
eq_(im.compare(im2, 0, False), 0)
im3 = mapnik.Image(2,2,mapnik.ImageType.gray8)
im3.set_pixel(0,0,0)
im3.set_pixel(0,1,1)
im3.set_pixel(1,0,2)
im3.set_pixel(1,1,3)
eq_(im.compare(im3),3)
eq_(im.compare(im3,1),2)
eq_(im.compare(im3,2),1)
eq_(im.compare(im3,3),0)
def test_compare_gray16():
im = mapnik.Image(2,2,mapnik.ImageType.gray16)
im.fill(0)
eq_(im.compare(im), 0)
im2 = mapnik.Image(2,2,mapnik.ImageType.gray16)
im2.fill(0)
eq_(im.compare(im2), 0)
eq_(im2.compare(im), 0)
eq_(im.compare(im2, 0, False), 0)
im3 = mapnik.Image(2,2,mapnik.ImageType.gray16)
im3.set_pixel(0,0,0)
im3.set_pixel(0,1,1)
im3.set_pixel(1,0,2)
im3.set_pixel(1,1,3)
eq_(im.compare(im3),3)
eq_(im.compare(im3,1),2)
eq_(im.compare(im3,2),1)
eq_(im.compare(im3,3),0)
def test_compare_gray32f():
im = mapnik.Image(2,2,mapnik.ImageType.gray32f)
im.fill(0.5)
eq_(im.compare(im), 0)
im2 = mapnik.Image(2,2,mapnik.ImageType.gray32f)
im2.fill(0.5)
eq_(im.compare(im2), 0)
eq_(im2.compare(im), 0)
eq_(im.compare(im2, 0, False), 0)
im3 = mapnik.Image(2,2,mapnik.ImageType.gray32f)
im3.set_pixel(0,0,0.5)
im3.set_pixel(0,1,1.5)
im3.set_pixel(1,0,2.5)
im3.set_pixel(1,1,3.5)
eq_(im.compare(im3),3)
eq_(im.compare(im3,1.0),2)
eq_(im.compare(im3,2.0),1)
eq_(im.compare(im3,3.0),0)
if __name__ == "__main__":
setup()
exit(run_all(eval(x) for x in dir() if x.startswith("test_")))

View file

@ -1,258 +0,0 @@
#encoding: utf8
from nose.tools import eq_
import os
from utilities import execution_path, run_all
from utilities import get_unique_colors, pixel2channels, side_by_side_image
import mapnik
def setup():
# All of the paths used are relative, if we run the tests
# from another directory we need to chdir()
os.chdir(execution_path('.'))
def is_pre(color,alpha):
return (color*255.0/alpha) <= 255
def debug_image(image,step=2):
for x in range(0,image.width(),step):
for y in range(0,image.height(),step):
pixel = image.get_pixel(x,y)
red,green,blue,alpha = pixel2channels(pixel)
print "rgba(%s,%s,%s,%s) at %s,%s" % (red,green,blue,alpha,x,y)
def replace_style(m, name, style):
m.remove_style(name)
m.append_style(name, style)
# note: it is impossible to know for all pixel colors
# we can only detect likely cases of non premultiplied colors
def validate_pixels_are_not_premultiplied(image):
over_alpha = False
transparent = True
fully_opaque = True
for x in range(0,image.width(),2):
for y in range(0,image.height(),2):
pixel = image.get_pixel(x,y)
red,green,blue,alpha = pixel2channels(pixel)
if alpha > 0:
transparent = False
if alpha < 255:
fully_opaque = False
color_max = max(red,green,blue)
if color_max > alpha:
over_alpha = True
return over_alpha or transparent or fully_opaque
def validate_pixels_are_not_premultiplied2(image):
looks_not_multiplied = False
for x in range(0,image.width(),2):
for y in range(0,image.height(),2):
pixel = image.get_pixel(x,y)
red,green,blue,alpha = pixel2channels(pixel)
#each value of the color channels will never be bigger than that of the alpha channel.
if alpha > 0:
if red > 0 and red > alpha:
print 'red: %s, a: %s' % (red,alpha)
looks_not_multiplied = True
return looks_not_multiplied
def validate_pixels_are_premultiplied(image):
bad_pixels = []
for x in range(0,image.width(),2):
for y in range(0,image.height(),2):
pixel = image.get_pixel(x,y)
red,green,blue,alpha = pixel2channels(pixel)
if alpha > 0:
pixel = image.get_pixel(x,y)
is_valid = ((0 <= red <= alpha) and is_pre(red,alpha)) \
and ((0 <= green <= alpha) and is_pre(green,alpha)) \
and ((0 <= blue <= alpha) and is_pre(blue,alpha)) \
and (alpha >= 0 and alpha <= 255)
if not is_valid:
bad_pixels.append("rgba(%s,%s,%s,%s) at %s,%s" % (red,green,blue,alpha,x,y))
num_bad = len(bad_pixels)
return (num_bad == 0,bad_pixels)
def test_compare_images():
b = mapnik.Image.open('./images/support/b.png')
b.premultiply()
num_ops = len(mapnik.CompositeOp.names)
successes = []
fails = []
for name in mapnik.CompositeOp.names:
a = mapnik.Image.open('./images/support/a.png')
a.premultiply()
a.composite(b,getattr(mapnik.CompositeOp,name))
actual = '/tmp/mapnik-comp-op-test-' + name + '.png'
expected = 'images/composited/' + name + '.png'
valid = validate_pixels_are_premultiplied(a)
if not valid[0]:
fails.append('%s not validly premultiplied!:\n\t %s pixels (%s)' % (name,len(valid[1]),valid[1][0]))
a.demultiply()
if not validate_pixels_are_not_premultiplied(a):
fails.append('%s not validly demultiplied' % (name))
a.save(actual,'png32')
if not os.path.exists(expected) or os.environ.get('UPDATE'):
print 'generating expected test image: %s' % expected
a.save(expected,'png32')
expected_im = mapnik.Image.open(expected)
# compare them
if a.tostring('png32') == expected_im.tostring('png32'):
successes.append(name)
else:
fails.append('failed comparing actual (%s) and expected(%s)' % (actual,'tests/python_tests/'+ expected))
fail_im = side_by_side_image(expected_im, a)
fail_im.save('/tmp/mapnik-comp-op-test-' + name + '.fail.png','png32')
eq_(len(successes),num_ops,'\n'+'\n'.join(fails))
b.demultiply()
# b will be slightly modified by pre and then de multiplication rounding errors
# TODO - write test to ensure the image is 99% the same.
#expected_b = mapnik.Image.open('./images/support/b.png')
#b.save('/tmp/mapnik-comp-op-test-original-mask.png')
#eq_(b.tostring('png32'),expected_b.tostring('png32'), '/tmp/mapnik-comp-op-test-original-mask.png is no longer equivalent to original mask: ./images/support/b.png')
def test_pre_multiply_status():
b = mapnik.Image.open('./images/support/b.png')
# not premultiplied yet, should appear that way
result = validate_pixels_are_not_premultiplied(b)
eq_(result,True)
# not yet premultiplied therefore should return false
result = validate_pixels_are_premultiplied(b)
eq_(result[0],False)
# now actually premultiply the pixels
b.premultiply()
# now checking if premultiplied should succeed
result = validate_pixels_are_premultiplied(b)
eq_(result[0],True)
# should now not appear to look not premultiplied
result = validate_pixels_are_not_premultiplied(b)
eq_(result,False)
# now actually demultiply the pixels
b.demultiply()
# should now appear demultiplied
result = validate_pixels_are_not_premultiplied(b)
eq_(result,True)
def test_pre_multiply_status_of_map1():
m = mapnik.Map(256,256)
im = mapnik.Image(m.width,m.height)
eq_(validate_pixels_are_not_premultiplied(im),True)
mapnik.render(m,im)
eq_(validate_pixels_are_not_premultiplied(im),True)
def test_pre_multiply_status_of_map2():
m = mapnik.Map(256,256)
m.background = mapnik.Color(1,1,1,255)
im = mapnik.Image(m.width,m.height)
eq_(validate_pixels_are_not_premultiplied(im),True)
mapnik.render(m,im)
eq_(validate_pixels_are_not_premultiplied(im),True)
if 'shape' in mapnik.DatasourceCache.plugin_names():
def test_style_level_comp_op():
m = mapnik.Map(256, 256)
mapnik.load_map(m, '../data/good_maps/style_level_comp_op.xml')
m.zoom_all()
successes = []
fails = []
for name in mapnik.CompositeOp.names:
# find_style returns a copy of the style object
style_markers = m.find_style("markers")
style_markers.comp_op = getattr(mapnik.CompositeOp, name)
# replace the original style with the modified one
replace_style(m, "markers", style_markers)
im = mapnik.Image(m.width, m.height)
mapnik.render(m, im)
actual = '/tmp/mapnik-style-comp-op-' + name + '.png'
expected = 'images/style-comp-op/' + name + '.png'
im.save(actual,'png32')
if not os.path.exists(expected) or os.environ.get('UPDATE'):
print 'generating expected test image: %s' % expected
im.save(expected,'png32')
expected_im = mapnik.Image.open(expected)
# compare them
if im.tostring('png32') == expected_im.tostring('png32'):
successes.append(name)
else:
fails.append('failed comparing actual (%s) and expected(%s)' % (actual,'tests/python_tests/'+ expected))
fail_im = side_by_side_image(expected_im, im)
fail_im.save('/tmp/mapnik-style-comp-op-' + name + '.fail.png','png32')
eq_(len(fails), 0, '\n'+'\n'.join(fails))
def test_style_level_opacity():
m = mapnik.Map(512,512)
mapnik.load_map(m,'../data/good_maps/style_level_opacity_and_blur.xml')
m.zoom_all()
im = mapnik.Image(512,512)
mapnik.render(m,im)
actual = '/tmp/mapnik-style-level-opacity.png'
expected = 'images/support/mapnik-style-level-opacity.png'
im.save(actual,'png32')
expected_im = mapnik.Image.open(expected)
eq_(im.tostring('png32'),expected_im.tostring('png32'), 'failed comparing actual (%s) and expected (%s)' % (actual,'tests/python_tests/'+ expected))
def test_rounding_and_color_expectations():
m = mapnik.Map(1,1)
m.background = mapnik.Color('rgba(255,255,255,.4999999)')
im = mapnik.Image(m.width,m.height)
mapnik.render(m,im)
eq_(get_unique_colors(im),['rgba(255,255,255,127)'])
m = mapnik.Map(1,1)
m.background = mapnik.Color('rgba(255,255,255,.5)')
im = mapnik.Image(m.width,m.height)
mapnik.render(m,im)
eq_(get_unique_colors(im),['rgba(255,255,255,128)'])
im_file = mapnik.Image.open('../data/images/stripes_pattern.png')
eq_(get_unique_colors(im_file),['rgba(0,0,0,0)', 'rgba(74,74,74,255)'])
# should have no effect
im_file.premultiply()
eq_(get_unique_colors(im_file),['rgba(0,0,0,0)', 'rgba(74,74,74,255)'])
im_file.set_alpha(.5)
# should have effect now that image has transparency
im_file.premultiply()
eq_(get_unique_colors(im_file),['rgba(0,0,0,0)', 'rgba(37,37,37,127)'])
# should restore to original nonpremultiplied colors
im_file.demultiply()
eq_(get_unique_colors(im_file),['rgba(0,0,0,0)', 'rgba(74,74,74,127)'])
def test_background_image_and_background_color():
m = mapnik.Map(8,8)
m.background = mapnik.Color('rgba(255,255,255,.5)')
m.background_image = '../data/images/stripes_pattern.png'
im = mapnik.Image(m.width,m.height)
mapnik.render(m,im)
eq_(get_unique_colors(im),['rgba(255,255,255,128)', 'rgba(74,74,74,255)'])
def test_background_image_with_alpha_and_background_color():
m = mapnik.Map(10,10)
m.background = mapnik.Color('rgba(255,255,255,.5)')
m.background_image = '../data/images/yellow_half_trans.png'
im = mapnik.Image(m.width,m.height)
mapnik.render(m,im)
eq_(get_unique_colors(im),['rgba(255,255,85,191)'])
def test_background_image_with_alpha_and_background_color_against_composited_control():
m = mapnik.Map(10,10)
m.background = mapnik.Color('rgba(255,255,255,.5)')
m.background_image = '../data/images/yellow_half_trans.png'
im = mapnik.Image(m.width,m.height)
mapnik.render(m,im)
# create and composite the expected result
im1 = mapnik.Image(10,10)
im1.fill(mapnik.Color('rgba(255,255,255,.5)'))
im1.premultiply()
im2 = mapnik.Image(10,10)
im2.fill(mapnik.Color('rgba(255,255,0,.5)'))
im2.premultiply()
im1.composite(im2)
im1.demultiply()
# compare image rendered (compositing in `agg_renderer<T>::setup`)
# vs image composited via python bindings
#raise Todo("looks like we need to investigate PNG color rounding when saving")
#eq_(get_unique_colors(im),get_unique_colors(im1))
if __name__ == "__main__":
setup()
exit(run_all(eval(x) for x in dir() if x.startswith("test_")))

View file

@ -1,93 +0,0 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import os, mapnik
from nose.tools import *
from utilities import execution_path, run_all
def setup():
# All of the paths used are relative, if we run the tests
# from another directory we need to chdir()
os.chdir(execution_path('.'))
def test_image_16_8_simple():
im = mapnik.Image(2,2,mapnik.ImageType.gray16)
im.set_pixel(0,0, 256)
im.set_pixel(0,1, 999)
im.set_pixel(1,0, 5)
im.set_pixel(1,1, 2)
im2 = im.copy(mapnik.ImageType.gray8)
eq_(im2.get_pixel(0,0), 255)
eq_(im2.get_pixel(0,1), 255)
eq_(im2.get_pixel(1,0), 5)
eq_(im2.get_pixel(1,1), 2)
# Cast back!
im = im2.copy(mapnik.ImageType.gray16)
eq_(im.get_pixel(0,0), 255)
eq_(im.get_pixel(0,1), 255)
eq_(im.get_pixel(1,0), 5)
eq_(im.get_pixel(1,1), 2)
def test_image_32f_8_simple():
im = mapnik.Image(2,2,mapnik.ImageType.gray32f)
im.set_pixel(0,0, 120.1234)
im.set_pixel(0,1, -23.4)
im.set_pixel(1,0, 120.6)
im.set_pixel(1,1, 360.2)
im2 = im.copy(mapnik.ImageType.gray8)
eq_(im2.get_pixel(0,0), 120)
eq_(im2.get_pixel(0,1), 0)
eq_(im2.get_pixel(1,0), 120) # Notice this is truncated!
eq_(im2.get_pixel(1,1), 255)
def test_image_offset_and_scale():
im = mapnik.Image(2,2,mapnik.ImageType.gray16)
eq_(im.offset, 0.0)
eq_(im.scaling, 1.0)
im.offset = 1.0
im.scaling = 2.0
eq_(im.offset, 1.0)
eq_(im.scaling, 2.0)
def test_image_16_8_scale_and_offset():
im = mapnik.Image(2,2,mapnik.ImageType.gray16)
im.set_pixel(0,0, 256)
im.set_pixel(0,1, 258)
im.set_pixel(1,0, 99999)
im.set_pixel(1,1, 615)
offset = 255
scaling = 3
im2 = im.copy(mapnik.ImageType.gray8, offset, scaling)
eq_(im2.get_pixel(0,0), 0)
eq_(im2.get_pixel(0,1), 1)
eq_(im2.get_pixel(1,0), 255)
eq_(im2.get_pixel(1,1), 120)
# pixels will be a little off due to offsets in reverting!
im3 = im2.copy(mapnik.ImageType.gray16)
eq_(im3.get_pixel(0,0), 255) # Rounding error with ints
eq_(im3.get_pixel(0,1), 258) # same
eq_(im3.get_pixel(1,0), 1020) # The other one was way out of range for our scale/offset
eq_(im3.get_pixel(1,1), 615) # same
def test_image_16_32f_scale_and_offset():
im = mapnik.Image(2,2,mapnik.ImageType.gray16)
im.set_pixel(0,0, 256)
im.set_pixel(0,1, 258)
im.set_pixel(1,0, 0)
im.set_pixel(1,1, 615)
offset = 255
scaling = 3.2
im2 = im.copy(mapnik.ImageType.gray32f, offset, scaling)
eq_(im2.get_pixel(0,0), 0.3125)
eq_(im2.get_pixel(0,1), 0.9375)
eq_(im2.get_pixel(1,0), -79.6875)
eq_(im2.get_pixel(1,1), 112.5)
im3 = im2.copy(mapnik.ImageType.gray16)
eq_(im3.get_pixel(0,0), 256)
eq_(im3.get_pixel(0,1), 258)
eq_(im3.get_pixel(1,0), 0)
eq_(im3.get_pixel(1,1), 615)
if __name__ == "__main__":
setup()
exit(run_all(eval(x) for x in dir() if x.startswith("test_")))

View file

@ -1,605 +0,0 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import glob
from nose.tools import eq_,raises
from utilities import execution_path
import os, mapnik
default_logging_severity = mapnik.logger.get_severity()
def setup():
# make the tests silent since we intentially test error conditions that are noisy
mapnik.logger.set_severity(mapnik.severity_type.None)
# All of the paths used are relative, if we run the tests
# from another directory we need to chdir()
os.chdir(execution_path('.'))
def teardown():
mapnik.logger.set_severity(default_logging_severity)
if 'csv' in mapnik.DatasourceCache.plugin_names():
def get_csv_ds(filename):
return mapnik.Datasource(type='csv',file=os.path.join('../data/csv/',filename))
def test_broken_files(visual=False):
broken = glob.glob("../data/csv/fails/*.*")
broken.extend(glob.glob("../data/csv/warns/*.*"))
# Add a filename that doesn't exist
broken.append("../data/csv/fails/does_not_exist.csv")
for csv in broken:
if visual:
try:
mapnik.Datasource(type='csv',file=csv,strict=True)
print '\x1b[33mfailed: should have thrown\x1b[0m',csv
except Exception:
print '\x1b[1;32m✓ \x1b[0m', csv
def test_good_files(visual=False):
good_files = glob.glob("../data/csv/*.*")
good_files.extend(glob.glob("../data/csv/warns/*.*"))
ignorable = os.path.join('..','data','csv','long_lat.vrt')
good_files.remove(ignorable)
for csv in good_files:
if visual:
try:
mapnik.Datasource(type='csv',file=csv)
print '\x1b[1;32m✓ \x1b[0m', csv
except Exception, e:
print '\x1b[33mfailed: should not have thrown\x1b[0m',csv,str(e)
def test_lon_lat_detection(**kwargs):
ds = get_csv_ds('lon_lat.csv')
eq_(len(ds.fields()),2)
eq_(ds.fields(),['lon','lat'])
eq_(ds.field_types(),['int','int'])
query = mapnik.Query(ds.envelope())
for fld in ds.fields():
query.add_property_name(fld)
fs = ds.features(query)
desc = ds.describe()
eq_(desc['geometry_type'],mapnik.DataGeometryType.Point)
feat = fs.next()
attr = {'lon': 0, 'lat': 0}
eq_(feat.attributes,attr)
def test_lng_lat_detection(**kwargs):
ds = get_csv_ds('lng_lat.csv')
eq_(len(ds.fields()),2)
eq_(ds.fields(),['lng','lat'])
eq_(ds.field_types(),['int','int'])
query = mapnik.Query(ds.envelope())
for fld in ds.fields():
query.add_property_name(fld)
fs = ds.features(query)
desc = ds.describe()
eq_(desc['geometry_type'],mapnik.DataGeometryType.Point)
feat = fs.next()
attr = {'lng': 0, 'lat': 0}
eq_(feat.attributes,attr)
def test_type_detection(**kwargs):
ds = get_csv_ds('nypd.csv')
eq_(ds.fields(),['Precinct','Phone','Address','City','geo_longitude','geo_latitude','geo_accuracy'])
eq_(ds.field_types(),['str','str','str','str','float','float','str'])
feat = ds.featureset().next()
attr = {'City': u'New York, NY', 'geo_accuracy': u'house', 'Phone': u'(212) 334-0711', 'Address': u'19 Elizabeth Street', 'Precinct': u'5th Precinct', 'geo_longitude': -70, 'geo_latitude': 40}
eq_(feat.attributes,attr)
eq_(len(ds.all_features()),2)
desc = ds.describe()
eq_(desc['geometry_type'],mapnik.DataGeometryType.Point)
eq_(desc['name'],'csv')
eq_(desc['type'],mapnik.DataType.Vector)
eq_(desc['encoding'],'utf-8')
def test_skipping_blank_rows(**kwargs):
ds = get_csv_ds('blank_rows.csv')
eq_(ds.fields(),['x','y','name'])
eq_(ds.field_types(),['int','int','str'])
eq_(len(ds.all_features()),2)
desc = ds.describe()
eq_(desc['geometry_type'],mapnik.DataGeometryType.Point)
eq_(desc['name'],'csv')
eq_(desc['type'],mapnik.DataType.Vector)
eq_(desc['encoding'],'utf-8')
def test_empty_rows(**kwargs):
ds = get_csv_ds('empty_rows.csv')
eq_(len(ds.fields()),10)
eq_(len(ds.field_types()),10)
eq_(ds.fields(),['x', 'y', 'text', 'date', 'integer', 'boolean', 'float', 'time', 'datetime', 'empty_column'])
eq_(ds.field_types(),['int', 'int', 'str', 'str', 'int', 'bool', 'float', 'str', 'str', 'str'])
fs = ds.featureset()
attr = {'x': 0, 'empty_column': u'', 'text': u'a b', 'float': 1.0, 'datetime': u'1971-01-01T04:14:00', 'y': 0, 'boolean': True, 'time': u'04:14:00', 'date': u'1971-01-01', 'integer': 40}
first = True
for feat in fs:
if first:
first=False
eq_(feat.attributes,attr)
eq_(len(feat),10)
eq_(feat['empty_column'],u'')
desc = ds.describe()
eq_(desc['geometry_type'],mapnik.DataGeometryType.Point)
eq_(desc['name'],'csv')
eq_(desc['type'],mapnik.DataType.Vector)
eq_(desc['encoding'],'utf-8')
def test_slashes(**kwargs):
ds = get_csv_ds('has_attributes_with_slashes.csv')
eq_(len(ds.fields()),3)
fs = ds.all_features()
eq_(fs[0].attributes,{'x':0,'y':0,'name':u'a/a'})
eq_(fs[1].attributes,{'x':1,'y':4,'name':u'b/b'})
eq_(fs[2].attributes,{'x':10,'y':2.5,'name':u'c/c'})
desc = ds.describe()
eq_(desc['geometry_type'],mapnik.DataGeometryType.Point)
eq_(desc['name'],'csv')
eq_(desc['type'],mapnik.DataType.Vector)
eq_(desc['encoding'],'utf-8')
def test_wkt_field(**kwargs):
ds = get_csv_ds('wkt.csv')
eq_(len(ds.fields()),1)
eq_(ds.fields(),['type'])
eq_(ds.field_types(),['str'])
fs = ds.all_features()
#eq_(len(fs[0].geometries()),1)
eq_(fs[0].geometry.type(),mapnik.GeometryType.Point)
#eq_(len(fs[1].geometries()),1)
eq_(fs[1].geometry.type(),mapnik.GeometryType.LineString)
#eq_(len(fs[2].geometries()),1)
eq_(fs[2].geometry.type(),mapnik.GeometryType.Polygon)
#eq_(len(fs[3].geometries()),1) # one geometry, two parts
eq_(fs[3].geometry.type(),mapnik.GeometryType.Polygon)
#eq_(len(fs[4].geometries()),4)
eq_(fs[4].geometry.type(),mapnik.GeometryType.MultiPoint)
#eq_(len(fs[5].geometries()),2)
eq_(fs[5].geometry.type(),mapnik.GeometryType.MultiLineString)
#eq_(len(fs[6].geometries()),2)
eq_(fs[6].geometry.type(),mapnik.GeometryType.MultiPolygon)
#eq_(len(fs[7].geometries()),2)
eq_(fs[7].geometry.type(),mapnik.GeometryType.MultiPolygon)
desc = ds.describe()
eq_(desc['geometry_type'],mapnik.DataGeometryType.Collection)
eq_(desc['name'],'csv')
eq_(desc['type'],mapnik.DataType.Vector)
eq_(desc['encoding'],'utf-8')
def test_handling_of_missing_header(**kwargs):
ds = get_csv_ds('missing_header.csv')
eq_(len(ds.fields()),6)
eq_(ds.fields(),['one','two','x','y','_4','aftermissing'])
fs = ds.featureset()
feat = fs.next()
eq_(feat['_4'],'missing')
desc = ds.describe()
eq_(desc['geometry_type'],mapnik.DataGeometryType.Point)
eq_(desc['name'],'csv')
eq_(desc['type'],mapnik.DataType.Vector)
eq_(desc['encoding'],'utf-8')
def test_handling_of_headers_that_are_numbers(**kwargs):
ds = get_csv_ds('numbers_for_headers.csv')
eq_(len(ds.fields()),5)
eq_(ds.fields(),['x','y','1990','1991','1992'])
fs = ds.featureset()
feat = fs.next()
eq_(feat['x'],0)
eq_(feat['y'],0)
eq_(feat['1990'],1)
eq_(feat['1991'],2)
eq_(feat['1992'],3)
eq_(mapnik.Expression("[1991]=2").evaluate(feat),True)
def test_quoted_numbers(**kwargs):
ds = get_csv_ds('points.csv')
eq_(len(ds.fields()),3)
eq_(ds.fields(),['x','y','label'])
fs = ds.all_features()
eq_(fs[0]['label'],"0,0")
eq_(fs[1]['label'],"5,5")
eq_(fs[2]['label'],"0,5")
eq_(fs[3]['label'],"5,0")
eq_(fs[4]['label'],"2.5,2.5")
desc = ds.describe()
eq_(desc['geometry_type'],mapnik.DataGeometryType.Point)
eq_(desc['name'],'csv')
eq_(desc['type'],mapnik.DataType.Vector)
eq_(desc['encoding'],'utf-8')
def test_reading_windows_newlines(**kwargs):
ds = get_csv_ds('windows_newlines.csv')
eq_(len(ds.fields()),3)
feats = ds.all_features()
eq_(len(feats),1)
fs = ds.featureset()
feat = fs.next()
eq_(feat['x'],1)
eq_(feat['y'],10)
eq_(feat['z'],9999.9999)
desc = ds.describe()
eq_(desc['geometry_type'],mapnik.DataGeometryType.Point)
eq_(desc['name'],'csv')
eq_(desc['type'],mapnik.DataType.Vector)
eq_(desc['encoding'],'utf-8')
def test_reading_mac_newlines(**kwargs):
ds = get_csv_ds('mac_newlines.csv')
eq_(len(ds.fields()),3)
feats = ds.all_features()
eq_(len(feats),1)
fs = ds.featureset()
feat = fs.next()
eq_(feat['x'],1)
eq_(feat['y'],10)
eq_(feat['z'],9999.9999)
desc = ds.describe()
eq_(desc['geometry_type'],mapnik.DataGeometryType.Point)
eq_(desc['name'],'csv')
eq_(desc['type'],mapnik.DataType.Vector)
eq_(desc['encoding'],'utf-8')
def check_newlines(filename):
ds = get_csv_ds(filename)
eq_(len(ds.fields()),3)
feats = ds.all_features()
eq_(len(feats),1)
fs = ds.featureset()
feat = fs.next()
eq_(feat['x'],0)
eq_(feat['y'],0)
eq_(feat['line'],'many\n lines\n of text\n with unix newlines')
desc = ds.describe()
eq_(desc['geometry_type'],mapnik.DataGeometryType.Point)
eq_(desc['name'],'csv')
eq_(desc['type'],mapnik.DataType.Vector)
eq_(desc['encoding'],'utf-8')
def test_mixed_mac_unix_newlines(**kwargs):
check_newlines('mac_newlines_with_unix_inline.csv')
def test_mixed_mac_unix_newlines_escaped(**kwargs):
check_newlines('mac_newlines_with_unix_inline_escaped.csv')
# To hard to support this case
#def test_mixed_unix_windows_newlines(**kwargs):
# check_newlines('unix_newlines_with_windows_inline.csv')
# To hard to support this case
#def test_mixed_unix_windows_newlines_escaped(**kwargs):
# check_newlines('unix_newlines_with_windows_inline_escaped.csv')
def test_mixed_windows_unix_newlines(**kwargs):
check_newlines('windows_newlines_with_unix_inline.csv')
def test_mixed_windows_unix_newlines_escaped(**kwargs):
check_newlines('windows_newlines_with_unix_inline_escaped.csv')
def test_tabs(**kwargs):
ds = get_csv_ds('tabs_in_csv.csv')
eq_(len(ds.fields()),3)
eq_(ds.fields(),['x','y','z'])
fs = ds.featureset()
feat = fs.next()
eq_(feat['x'],-122)
eq_(feat['y'],48)
eq_(feat['z'],0)
desc = ds.describe()
eq_(desc['geometry_type'],mapnik.DataGeometryType.Point)
eq_(desc['name'],'csv')
eq_(desc['type'],mapnik.DataType.Vector)
eq_(desc['encoding'],'utf-8')
def test_separator_pipes(**kwargs):
ds = get_csv_ds('pipe_delimiters.csv')
eq_(len(ds.fields()),3)
eq_(ds.fields(),['x','y','z'])
fs = ds.featureset()
feat = fs.next()
eq_(feat['x'],0)
eq_(feat['y'],0)
eq_(feat['z'],'hello')
desc = ds.describe()
eq_(desc['geometry_type'],mapnik.DataGeometryType.Point)
eq_(desc['name'],'csv')
eq_(desc['type'],mapnik.DataType.Vector)
eq_(desc['encoding'],'utf-8')
def test_separator_semicolon(**kwargs):
ds = get_csv_ds('semicolon_delimiters.csv')
eq_(len(ds.fields()),3)
eq_(ds.fields(),['x','y','z'])
fs = ds.featureset()
feat = fs.next()
eq_(feat['x'],0)
eq_(feat['y'],0)
eq_(feat['z'],'hello')
desc = ds.describe()
eq_(desc['geometry_type'],mapnik.DataGeometryType.Point)
eq_(desc['name'],'csv')
eq_(desc['type'],mapnik.DataType.Vector)
eq_(desc['encoding'],'utf-8')
def test_that_null_and_bool_keywords_are_empty_strings(**kwargs):
ds = get_csv_ds('nulls_and_booleans_as_strings.csv')
eq_(len(ds.fields()),4)
eq_(ds.fields(),['x','y','null','boolean'])
eq_(ds.field_types(),['int', 'int', 'str', 'bool'])
fs = ds.featureset()
feat = fs.next()
eq_(feat['x'],0)
eq_(feat['y'],0)
eq_(feat['null'],'null')
eq_(feat['boolean'],True)
feat = fs.next()
eq_(feat['x'],0)
eq_(feat['y'],0)
eq_(feat['null'],'')
eq_(feat['boolean'],False)
desc = ds.describe()
eq_(desc['geometry_type'],mapnik.DataGeometryType.Point)
@raises(RuntimeError)
def test_that_nonexistant_query_field_throws(**kwargs):
ds = get_csv_ds('lon_lat.csv')
eq_(len(ds.fields()),2)
eq_(ds.fields(),['lon','lat'])
eq_(ds.field_types(),['int','int'])
query = mapnik.Query(ds.envelope())
for fld in ds.fields():
query.add_property_name(fld)
# also add an invalid one, triggering throw
query.add_property_name('bogus')
ds.features(query)
def test_that_leading_zeros_mean_strings(**kwargs):
ds = get_csv_ds('leading_zeros.csv')
eq_(len(ds.fields()),3)
eq_(ds.fields(),['x','y','fips'])
eq_(ds.field_types(),['int','int','str'])
fs = ds.featureset()
feat = fs.next()
eq_(feat['x'],0)
eq_(feat['y'],0)
eq_(feat['fips'],'001')
feat = fs.next()
eq_(feat['x'],0)
eq_(feat['y'],0)
eq_(feat['fips'],'003')
feat = fs.next()
eq_(feat['x'],0)
eq_(feat['y'],0)
eq_(feat['fips'],'005')
desc = ds.describe()
eq_(desc['geometry_type'],mapnik.DataGeometryType.Point)
def test_advanced_geometry_detection(**kwargs):
ds = get_csv_ds('point_wkt.csv')
eq_(ds.describe()['geometry_type'],mapnik.DataGeometryType.Point)
ds = get_csv_ds('poly_wkt.csv')
eq_(ds.describe()['geometry_type'],mapnik.DataGeometryType.Polygon)
ds = get_csv_ds('multi_poly_wkt.csv')
eq_(ds.describe()['geometry_type'],mapnik.DataGeometryType.Polygon)
ds = get_csv_ds('line_wkt.csv')
eq_(ds.describe()['geometry_type'],mapnik.DataGeometryType.LineString)
def test_creation_of_csv_from_in_memory_string(**kwargs):
csv_string = '''
wkt,Name
"POINT (120.15 48.47)","Winthrop, WA"
''' # csv plugin will test lines <= 10 chars for being fully blank
ds = mapnik.Datasource(**{"type":"csv","inline":csv_string})
eq_(ds.describe()['geometry_type'],mapnik.DataGeometryType.Point)
fs = ds.featureset()
feat = fs.next()
eq_(feat['Name'],u"Winthrop, WA")
def test_creation_of_csv_from_in_memory_string_with_uft8(**kwargs):
csv_string = '''
wkt,Name
"POINT (120.15 48.47)","Québec"
''' # csv plugin will test lines <= 10 chars for being fully blank
ds = mapnik.Datasource(**{"type":"csv","inline":csv_string})
eq_(ds.describe()['geometry_type'],mapnik.DataGeometryType.Point)
fs = ds.featureset()
feat = fs.next()
eq_(feat['Name'],u"Québec")
def validate_geojson_datasource(ds):
eq_(len(ds.fields()),1)
eq_(ds.fields(),['type'])
eq_(ds.field_types(),['str'])
fs = ds.all_features()
#eq_(len(fs[0].geometries()),1)
eq_(fs[0].geometry.type(),mapnik.GeometryType.Point)
#eq_(len(fs[1].geometries()),1)
eq_(fs[1].geometry.type(),mapnik.GeometryType.LineString)
#eq_(len(fs[2].geometries()),1)
eq_(fs[2].geometry.type(), mapnik.GeometryType.Polygon)
#eq_(len(fs[3].geometries()),1) # one geometry, two parts
eq_(fs[3].geometry.type(),mapnik.GeometryType.Polygon)
#eq_(len(fs[4].geometries()),4)
eq_(fs[4].geometry.type(),mapnik.GeometryType.MultiPoint)
#eq_(len(fs[5].geometries()),2)
eq_(fs[5].geometry.type(),mapnik.GeometryType.MultiLineString)
#eq_(len(fs[6].geometries()),2)
eq_(fs[6].geometry.type(),mapnik.GeometryType.MultiPolygon)
#eq_(len(fs[7].geometries()),2)
eq_(fs[7].geometry.type(),mapnik.GeometryType.MultiPolygon)
desc = ds.describe()
eq_(desc['geometry_type'],mapnik.DataGeometryType.Collection)
eq_(desc['name'],'csv')
eq_(desc['type'],mapnik.DataType.Vector)
eq_(desc['encoding'],'utf-8')
def test_json_field1(**kwargs):
ds = get_csv_ds('geojson_double_quote_escape.csv')
validate_geojson_datasource(ds)
def test_json_field2(**kwargs):
ds = get_csv_ds('geojson_single_quote.csv')
validate_geojson_datasource(ds)
def test_json_field3(**kwargs):
ds = get_csv_ds('geojson_2x_double_quote_filebakery_style.csv')
validate_geojson_datasource(ds)
def test_that_blank_undelimited_rows_are_still_parsed(**kwargs):
ds = get_csv_ds('more_headers_than_column_values.csv')
eq_(len(ds.fields()),5)
eq_(ds.fields(),['x','y','one', 'two','three'])
eq_(ds.field_types(),['int','int','str','str','str'])
fs = ds.featureset()
feat = fs.next()
eq_(feat['x'],0)
eq_(feat['y'],0)
eq_(feat['one'],'')
eq_(feat['two'],'')
eq_(feat['three'],'')
desc = ds.describe()
eq_(desc['geometry_type'],mapnik.DataGeometryType.Point)
@raises(RuntimeError)
def test_that_fewer_headers_than_rows_throws(**kwargs):
# this has invalid header # so throw
get_csv_ds('more_column_values_than_headers.csv')
def test_that_feature_id_only_incremented_for_valid_rows(**kwargs):
ds = mapnik.Datasource(type='csv',
file=os.path.join('../data/csv/warns','feature_id_counting.csv'))
eq_(len(ds.fields()),3)
eq_(ds.fields(),['x','y','id'])
eq_(ds.field_types(),['int','int','int'])
fs = ds.featureset()
# first
feat = fs.next()
eq_(feat['x'],0)
eq_(feat['y'],0)
eq_(feat['id'],1)
# second, should have skipped bogus one
feat = fs.next()
eq_(feat['x'],0)
eq_(feat['y'],0)
eq_(feat['id'],2)
desc = ds.describe()
eq_(desc['geometry_type'],mapnik.DataGeometryType.Point)
eq_(len(ds.all_features()),2)
def test_dynamically_defining_headers1(**kwargs):
ds = mapnik.Datasource(type='csv',
file=os.path.join('../data/csv/fails','needs_headers_two_lines.csv'),
headers='x,y,name')
eq_(len(ds.fields()),3)
eq_(ds.fields(),['x','y','name'])
eq_(ds.field_types(),['int','int','str'])
fs = ds.featureset()
feat = fs.next()
eq_(feat['x'],0)
eq_(feat['y'],0)
eq_(feat['name'],'data_name')
desc = ds.describe()
eq_(desc['geometry_type'],mapnik.DataGeometryType.Point)
eq_(len(ds.all_features()),2)
def test_dynamically_defining_headers2(**kwargs):
ds = mapnik.Datasource(type='csv',
file=os.path.join('../data/csv/fails','needs_headers_one_line.csv'),
headers='x,y,name')
eq_(len(ds.fields()),3)
eq_(ds.fields(),['x','y','name'])
eq_(ds.field_types(),['int','int','str'])
fs = ds.featureset()
feat = fs.next()
eq_(feat['x'],0)
eq_(feat['y'],0)
eq_(feat['name'],'data_name')
desc = ds.describe()
eq_(desc['geometry_type'],mapnik.DataGeometryType.Point)
eq_(len(ds.all_features()),1)
def test_dynamically_defining_headers3(**kwargs):
ds = mapnik.Datasource(type='csv',
file=os.path.join('../data/csv/fails','needs_headers_one_line_no_newline.csv'),
headers='x,y,name')
eq_(len(ds.fields()),3)
eq_(ds.fields(),['x','y','name'])
eq_(ds.field_types(),['int','int','str'])
fs = ds.featureset()
feat = fs.next()
eq_(feat['x'],0)
eq_(feat['y'],0)
eq_(feat['name'],'data_name')
desc = ds.describe()
eq_(desc['geometry_type'],mapnik.DataGeometryType.Point)
eq_(len(ds.all_features()),1)
def test_that_64bit_int_fields_work(**kwargs):
ds = get_csv_ds('64bit_int.csv')
eq_(len(ds.fields()),3)
eq_(ds.fields(),['x','y','bigint'])
eq_(ds.field_types(),['int','int','int'])
fs = ds.featureset()
feat = fs.next()
eq_(feat['bigint'],2147483648)
feat = fs.next()
eq_(feat['bigint'],9223372036854775807)
eq_(feat['bigint'],0x7FFFFFFFFFFFFFFF)
desc = ds.describe()
eq_(desc['geometry_type'],mapnik.DataGeometryType.Point)
eq_(len(ds.all_features()),2)
def test_various_number_types(**kwargs):
ds = get_csv_ds('number_types.csv')
eq_(len(ds.fields()),3)
eq_(ds.fields(),['x','y','floats'])
eq_(ds.field_types(),['int','int','float'])
fs = ds.featureset()
feat = fs.next()
eq_(feat['floats'],.0)
feat = fs.next()
eq_(feat['floats'],+.0)
feat = fs.next()
eq_(feat['floats'],1e-06)
feat = fs.next()
eq_(feat['floats'],-1e-06)
feat = fs.next()
eq_(feat['floats'],0.000001)
feat = fs.next()
eq_(feat['floats'],1.234e+16)
feat = fs.next()
eq_(feat['floats'],1.234e+16)
desc = ds.describe()
eq_(desc['geometry_type'],mapnik.DataGeometryType.Point)
eq_(len(ds.all_features()),8)
def test_manually_supplied_extent(**kwargs):
csv_string = '''
wkt,Name
'''
ds = mapnik.Datasource(**{"type":"csv","extent":"-180,-90,180,90","inline":csv_string})
b = ds.envelope()
eq_(b.minx,-180)
eq_(b.miny,-90)
eq_(b.maxx,180)
eq_(b.maxy,90)
def test_inline_geojson(**kwargs):
csv_string = "geojson\n'{\"coordinates\":[-92.22568,38.59553],\"type\":\"Point\"}'"
ds = mapnik.Datasource(**{"type":"csv","inline":csv_string})
eq_(len(ds.fields()),0)
eq_(ds.fields(),[])
# FIXME - re-enable after https://github.com/mapnik/mapnik/issues/2319 is fixed
#fs = ds.featureset()
#feat = fs.next()
#eq_(feat.num_geometries(),1)
if __name__ == "__main__":
setup()
[eval(run)(visual=True) for run in dir() if 'test_' in run]

View file

@ -1,168 +0,0 @@
#!/usr/bin/env python
from nose.tools import eq_, raises
from utilities import execution_path, run_all
import os, mapnik
from itertools import groupby
def setup():
# All of the paths used are relative, if we run the tests
# from another directory we need to chdir()
os.chdir(execution_path('.'))
def test_that_datasources_exist():
if len(mapnik.DatasourceCache.plugin_names()) == 0:
print '***NOTICE*** - no datasource plugins have been loaded'
# adapted from raster_symboliser_test#test_dataraster_query_point
@raises(RuntimeError)
def test_vrt_referring_to_missing_files():
srs = '+init=epsg:32630'
if 'gdal' in mapnik.DatasourceCache.plugin_names():
lyr = mapnik.Layer('dataraster')
lyr.datasource = mapnik.Gdal(
file = '../data/raster/missing_raster.vrt',
band = 1,
)
lyr.srs = srs
_map = mapnik.Map(256, 256, srs)
_map.layers.append(lyr)
# center of extent of raster
x, y = 556113.0,4381428.0 # center of extent of raster
_map.zoom_all()
# Fancy stuff to supress output of error
# open 2 fds
null_fds = [os.open(os.devnull, os.O_RDWR) for x in xrange(2)]
# save the current file descriptors to a tuple
save = os.dup(1), os.dup(2)
# put /dev/null fds on 1 and 2
os.dup2(null_fds[0], 1)
os.dup2(null_fds[1], 2)
# *** run the function ***
try:
# Should RuntimeError here
_map.query_point(0, x, y).features
finally:
# restore file descriptors so I can print the results
os.dup2(save[0], 1)
os.dup2(save[1], 2)
# close the temporary fds
os.close(null_fds[0])
os.close(null_fds[1])
def test_field_listing():
if 'shape' in mapnik.DatasourceCache.plugin_names():
ds = mapnik.Shapefile(file='../data/shp/poly.shp')
fields = ds.fields()
eq_(fields, ['AREA', 'EAS_ID', 'PRFEDEA'])
desc = ds.describe()
eq_(desc['geometry_type'],mapnik.DataGeometryType.Polygon)
eq_(desc['name'],'shape')
eq_(desc['type'],mapnik.DataType.Vector)
eq_(desc['encoding'],'utf-8')
def test_total_feature_count_shp():
if 'shape' in mapnik.DatasourceCache.plugin_names():
ds = mapnik.Shapefile(file='../data/shp/poly.shp')
features = ds.all_features()
num_feats = len(features)
eq_(num_feats, 10)
def test_total_feature_count_json():
if 'ogr' in mapnik.DatasourceCache.plugin_names():
ds = mapnik.Ogr(file='../data/json/points.geojson',layer_by_index=0)
desc = ds.describe()
eq_(desc['geometry_type'],mapnik.DataGeometryType.Point)
eq_(desc['name'],'ogr')
eq_(desc['type'],mapnik.DataType.Vector)
eq_(desc['encoding'],'utf-8')
features = ds.all_features()
num_feats = len(features)
eq_(num_feats, 5)
def test_sqlite_reading():
if 'sqlite' in mapnik.DatasourceCache.plugin_names():
ds = mapnik.SQLite(file='../data/sqlite/world.sqlite',table_by_index=0)
desc = ds.describe()
eq_(desc['geometry_type'],mapnik.DataGeometryType.Polygon)
eq_(desc['name'],'sqlite')
eq_(desc['type'],mapnik.DataType.Vector)
eq_(desc['encoding'],'utf-8')
features = ds.all_features()
num_feats = len(features)
eq_(num_feats, 245)
def test_reading_json_from_string():
json = open('../data/json/points.geojson','r').read()
if 'ogr' in mapnik.DatasourceCache.plugin_names():
ds = mapnik.Ogr(file=json,layer_by_index=0)
features = ds.all_features()
num_feats = len(features)
eq_(num_feats, 5)
def test_feature_envelope():
if 'shape' in mapnik.DatasourceCache.plugin_names():
ds = mapnik.Shapefile(file='../data/shp/poly.shp')
features = ds.all_features()
for feat in features:
env = feat.envelope()
contains = ds.envelope().contains(env)
eq_(contains, True)
intersects = ds.envelope().contains(env)
eq_(intersects, True)
def test_feature_attributes():
if 'shape' in mapnik.DatasourceCache.plugin_names():
ds = mapnik.Shapefile(file='../data/shp/poly.shp')
features = ds.all_features()
feat = features[0]
attrs = {'PRFEDEA': u'35043411', 'EAS_ID': 168, 'AREA': 215229.266}
eq_(feat.attributes, attrs)
eq_(ds.fields(),['AREA', 'EAS_ID', 'PRFEDEA'])
eq_(ds.field_types(),['float','int','str'])
def test_ogr_layer_by_sql():
if 'ogr' in mapnik.DatasourceCache.plugin_names():
ds = mapnik.Ogr(file='../data/shp/poly.shp', layer_by_sql='SELECT * FROM poly WHERE EAS_ID = 168')
features = ds.all_features()
num_feats = len(features)
eq_(num_feats, 1)
def test_hit_grid():
def rle_encode(l):
""" encode a list of strings with run-length compression """
return ["%d:%s" % (len(list(group)), name) for name, group in groupby(l)]
m = mapnik.Map(256,256);
try:
mapnik.load_map(m,'../data/good_maps/agg_poly_gamma_map.xml');
m.zoom_all()
join_field = 'NAME'
fg = [] # feature grid
for y in range(0, 256, 4):
for x in range(0, 256, 4):
featureset = m.query_map_point(0,x,y)
added = False
for feature in featureset.features:
fg.append(feature[join_field])
added = True
if not added:
fg.append('')
hit_list = '|'.join(rle_encode(fg))
eq_(hit_list[:16],'730:|2:Greenland')
eq_(hit_list[-12:],'1:Chile|812:')
except RuntimeError, e:
# only test datasources that we have installed
if not 'Could not create datasource' in str(e):
raise RuntimeError(str(e))
if __name__ == '__main__':
setup()
exit(run_all(eval(x) for x in dir() if x.startswith("test_")))

View file

@ -1,23 +0,0 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import os
from utilities import execution_path, run_all
import mapnik
def setup():
# All of the paths used are relative, if we run the tests
# from another directory we need to chdir()
os.chdir(execution_path('.'))
def test_datasource_template_is_working():
m = mapnik.Map(256,256)
try:
mapnik.load_map(m,'../data/good_maps/datasource.xml')
except RuntimeError, e:
if "Required parameter 'type'" in str(e):
raise RuntimeError(e)
if __name__ == "__main__":
setup()
exit(run_all(eval(x) for x in dir() if x.startswith("test_")))

View file

@ -1,54 +0,0 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from nose.tools import eq_
from utilities import execution_path, run_all
import os, mapnik
def setup():
# All of the paths used are relative, if we run the tests
# from another directory we need to chdir()
os.chdir(execution_path('.'))
def test_arbitrary_parameters_attached_to_map():
m = mapnik.Map(256,256)
mapnik.load_map(m,'../data/good_maps/extra_arbitary_map_parameters.xml')
eq_(len(m.parameters),5)
eq_(m.parameters['key'],'value2')
eq_(m.parameters['key3'],'value3')
eq_(m.parameters['unicode'],u'iván')
eq_(m.parameters['integer'],10)
eq_(m.parameters['decimal'],.999)
m2 = mapnik.Map(256,256)
for k,v in m.parameters:
m2.parameters.append(mapnik.Parameter(k,v))
eq_(len(m2.parameters),5)
eq_(m2.parameters['key'],'value2')
eq_(m2.parameters['key3'],'value3')
eq_(m2.parameters['unicode'],u'iván')
eq_(m2.parameters['integer'],10)
eq_(m2.parameters['decimal'],.999)
map_string = mapnik.save_map_to_string(m)
m3 = mapnik.Map(256,256)
mapnik.load_map_from_string(m3,map_string)
eq_(len(m3.parameters),5)
eq_(m3.parameters['key'],'value2')
eq_(m3.parameters['key3'],'value3')
eq_(m3.parameters['unicode'],u'iván')
eq_(m3.parameters['integer'],10)
eq_(m3.parameters['decimal'],.999)
def test_serializing_arbitrary_parameters():
m = mapnik.Map(256,256)
m.parameters.append(mapnik.Parameter('width',m.width))
m.parameters.append(mapnik.Parameter('height',m.height))
m2 = mapnik.Map(1,1)
mapnik.load_map_from_string(m2,mapnik.save_map_to_string(m))
eq_(m2.parameters['width'],m.width)
eq_(m2.parameters['height'],m.height)
if __name__ == "__main__":
setup()
exit(run_all(eval(x) for x in dir() if x.startswith("test_")))

View file

@ -1,66 +0,0 @@
#!/usr/bin/env python
from nose.tools import eq_
from utilities import execution_path, run_all
import os, mapnik
import itertools
def setup():
# All of the paths used are relative, if we run the tests
# from another directory we need to chdir()
os.chdir(execution_path('.'))
def compare_shape_between_mapnik_and_ogr(shapefile,query=None):
plugins = mapnik.DatasourceCache.plugin_names()
if 'shape' in plugins and 'ogr' in plugins:
ds1 = mapnik.Ogr(file=shapefile,layer_by_index=0)
ds2 = mapnik.Shapefile(file=shapefile)
if query:
fs1 = ds1.features(query)
fs2 = ds2.features(query)
else:
fs1 = ds1.featureset()
fs2 = ds2.featureset()
count = 0;
for feat1,feat2 in itertools.izip(fs1,fs2):
count += 1
eq_(feat1.id(),feat2.id(),
'%s : ogr feature id %s "%s" does not equal shapefile feature id %s "%s"'
% (count,feat1.id(),str(feat1.attributes), feat2.id(),str(feat2.attributes)))
return True
def test_shapefile_line_featureset_id():
compare_shape_between_mapnik_and_ogr('../data/shp/polylines.shp')
def test_shapefile_polygon_featureset_id():
compare_shape_between_mapnik_and_ogr('../data/shp/poly.shp')
def test_shapefile_polygon_feature_query_id():
bbox = (15523428.2632, 4110477.6323, -11218494.8310, 7495720.7404)
query = mapnik.Query(mapnik.Box2d(*bbox))
if 'ogr' in mapnik.DatasourceCache.plugin_names():
ds = mapnik.Ogr(file='../data/shp/world_merc.shp',layer_by_index=0)
for fld in ds.fields():
query.add_property_name(fld)
compare_shape_between_mapnik_and_ogr('../data/shp/world_merc.shp',query)
def test_feature_hit_count():
pass
#raise Todo("need to optimize multigeom bbox handling in shapeindex: https://github.com/mapnik/mapnik/issues/783")
# results in different results between shp and ogr!
#bbox = (-14284551.8434, 2074195.1992, -7474929.8687, 8140237.7628)
#bbox = (1113194.91,4512803.085,2226389.82,6739192.905)
#query = mapnik.Query(mapnik.Box2d(*bbox))
#if 'ogr' in mapnik.DatasourceCache.plugin_names():
# ds1 = mapnik.Ogr(file='../data/shp/world_merc.shp',layer_by_index=0)
# for fld in ds1.fields():
# query.add_property_name(fld)
# ds2 = mapnik.Shapefile(file='../data/shp/world_merc.shp')
# count1 = len(ds1.features(query).features)
# count2 = len(ds2.features(query).features)
# eq_(count1,count2,"Feature count differs between OGR driver (%s features) and Shapefile Driver (%s features) when querying the same bbox" % (count1,count2))
if __name__ == "__main__":
setup()
exit(run_all(eval(x) for x in dir() if x.startswith("test_")))

View file

@ -1,110 +0,0 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from nose.tools import eq_,raises
from utilities import run_all
import mapnik
from binascii import unhexlify
def test_default_constructor():
f = mapnik.Feature(mapnik.Context(),1)
eq_(f is not None,True)
def test_feature_geo_interface():
ctx = mapnik.Context()
feat = mapnik.Feature(ctx,1)
feat.geometry = mapnik.Geometry.from_wkt('Point (0 0)')
eq_(feat.__geo_interface__['geometry'],{u'type': u'Point', u'coordinates': [0, 0]})
def test_python_extended_constructor():
context = mapnik.Context()
context.push('foo')
context.push('foo')
f = mapnik.Feature(context,1)
wkt = 'POLYGON ((35 10, 10 20, 15 40, 45 45, 35 10),(20 30, 35 35, 30 20, 20 30))'
f.geometry = mapnik.Geometry.from_wkt(wkt)
f['foo'] = 'bar'
eq_(f['foo'], 'bar')
eq_(f.envelope(),mapnik.Box2d(10.0,10.0,45.0,45.0))
# reset
f['foo'] = u"avión"
eq_(f['foo'], u"avión")
f['foo'] = 1.4
eq_(f['foo'], 1.4)
f['foo'] = True
eq_(f['foo'], True)
def test_add_geom_wkb():
# POLYGON ((30 10, 10 20, 20 40, 40 40, 30 10))
wkb = '010300000001000000050000000000000000003e4000000000000024400000000000002440000000000000344000000000000034400000000000004440000000000000444000000000000044400000000000003e400000000000002440'
geometry = mapnik.Geometry.from_wkb(unhexlify(wkb))
eq_(geometry.is_valid(), False) # False because winding order is wrong according to OGC or because end point != first point
eq_(geometry.is_simple(), True)
eq_(geometry.envelope(), mapnik.Box2d(10.0,10.0,40.0,40.0))
geometry.correct()
# valid after calling correct
eq_(geometry.is_valid(), True)
def test_feature_expression_evaluation():
context = mapnik.Context()
context.push('name')
f = mapnik.Feature(context,1)
f['name'] = 'a'
eq_(f['name'],u'a')
expr = mapnik.Expression("[name]='a'")
evaluated = expr.evaluate(f)
eq_(evaluated,True)
num_attributes = len(f)
eq_(num_attributes,1)
eq_(f.id(),1)
# https://github.com/mapnik/mapnik/issues/933
def test_feature_expression_evaluation_missing_attr():
context = mapnik.Context()
context.push('name')
f = mapnik.Feature(context,1)
f['name'] = u'a'
eq_(f['name'],u'a')
expr = mapnik.Expression("[fielddoesnotexist]='a'")
eq_(f.has_key('fielddoesnotexist'),False)
try:
expr.evaluate(f)
except Exception, e:
eq_("Key does not exist" in str(e),True)
num_attributes = len(f)
eq_(num_attributes,1)
eq_(f.id(),1)
# https://github.com/mapnik/mapnik/issues/934
def test_feature_expression_evaluation_attr_with_spaces():
context = mapnik.Context()
context.push('name with space')
f = mapnik.Feature(context,1)
f['name with space'] = u'a'
eq_(f['name with space'],u'a')
expr = mapnik.Expression("[name with space]='a'")
eq_(str(expr),"([name with space]='a')")
eq_(expr.evaluate(f),True)
# https://github.com/mapnik/mapnik/issues/2390
@raises(RuntimeError)
def test_feature_from_geojson():
ctx = mapnik.Context()
inline_string = """
{
"geometry" : {
"coordinates" : [ 0,0 ]
"type" : "Point"
},
"type" : "Feature",
"properties" : {
"this":"that"
"known":"nope because missing comma"
}
}
"""
mapnik.Feature.from_geojson(inline_string,ctx)
if __name__ == "__main__":
exit(run_all(eval(x) for x in dir() if x.startswith("test_")))

View file

@ -1,451 +0,0 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from nose.tools import eq_,raises
from utilities import run_all
import mapnik
if hasattr(mapnik,'Expression'):
mapnik.Filter = mapnik.Expression
map_ = '''<Map>
<Style name="s">
<Rule>
<Filter><![CDATA[(([region]>=0) and ([region]<=50))]]></Filter>
</Rule>
<Rule>
<Filter><![CDATA[([region]>=0) and ([region]<=50)]]></Filter>
</Rule>
<Rule>
<Filter>
<![CDATA[
([region] >= 0)
and
([region] <= 50)
]]>
</Filter>
</Rule>
<Rule>
<Filter>([region]&gt;=0) and ([region]&lt;=50)</Filter>
</Rule>
<Rule>
<Filter>
([region] &gt;= 0)
and
([region] &lt;= 50)
</Filter>
</Rule>
</Style>
<Style name="s2" filter-mode="first">
<Rule>
</Rule>
<Rule>
</Rule>
</Style>
</Map>'''
def test_filter_init():
m = mapnik.Map(1,1)
mapnik.load_map_from_string(m,map_)
filters = []
filters.append(mapnik.Filter("([region]>=0) and ([region]<=50)"))
filters.append(mapnik.Filter("(([region]>=0) and ([region]<=50))"))
filters.append(mapnik.Filter("((([region]>=0) and ([region]<=50)))"))
filters.append(mapnik.Filter('((([region]>=0) and ([region]<=50)))'))
filters.append(mapnik.Filter('''((([region]>=0) and ([region]<=50)))'''))
filters.append(mapnik.Filter('''
((([region]>=0)
and
([region]<=50)))
'''))
filters.append(mapnik.Filter('''
([region]>=0)
and
([region]<=50)
'''))
filters.append(mapnik.Filter('''
([region]
>=
0)
and
([region]
<=
50)
'''))
s = m.find_style('s')
for r in s.rules:
filters.append(r.filter)
first = filters[0]
for f in filters:
eq_(str(first),str(f))
s = m.find_style('s2')
eq_(s.filter_mode,mapnik.filter_mode.FIRST)
def test_geometry_type_eval():
# clashing field called 'mapnik::geometry'
context2 = mapnik.Context()
context2.push('mapnik::geometry_type')
f = mapnik.Feature(context2,0)
f["mapnik::geometry_type"] = 'sneaky'
expr = mapnik.Expression("[mapnik::geometry_type]")
eq_(expr.evaluate(f),0)
expr = mapnik.Expression("[mapnik::geometry_type]")
context = mapnik.Context()
# no geometry
f = mapnik.Feature(context,0)
eq_(expr.evaluate(f),0)
eq_(mapnik.Expression("[mapnik::geometry_type]=0").evaluate(f),True)
# POINT = 1
f = mapnik.Feature(context,0)
f.geometry = mapnik.Geometry.from_wkt('POINT(10 40)')
eq_(expr.evaluate(f),1)
eq_(mapnik.Expression("[mapnik::geometry_type]=point").evaluate(f),True)
# LINESTRING = 2
f = mapnik.Feature(context,0)
f.geometry = mapnik.Geometry.from_wkt('LINESTRING (30 10, 10 30, 40 40)')
eq_(expr.evaluate(f),2)
eq_(mapnik.Expression("[mapnik::geometry_type] = linestring").evaluate(f),True)
# POLYGON = 3
f = mapnik.Feature(context,0)
f.geometry = mapnik.Geometry.from_wkt('POLYGON ((30 10, 10 20, 20 40, 40 40, 30 10))')
eq_(expr.evaluate(f),3)
eq_(mapnik.Expression("[mapnik::geometry_type] = polygon").evaluate(f),True)
# COLLECTION = 4
f = mapnik.Feature(context,0)
geom = mapnik.Geometry.from_wkt('GEOMETRYCOLLECTION(POLYGON((1 1,2 1,2 2,1 2,1 1)),POINT(2 3),LINESTRING(2 3,3 4))')
f.geometry = geom;
eq_(expr.evaluate(f),4)
eq_(mapnik.Expression("[mapnik::geometry_type] = collection").evaluate(f),True)
def test_regex_match():
context = mapnik.Context()
context.push('name')
f = mapnik.Feature(context,0)
f["name"] = 'test'
expr = mapnik.Expression("[name].match('test')")
eq_(expr.evaluate(f),True) # 1 == True
def test_unicode_regex_match():
context = mapnik.Context()
context.push('name')
f = mapnik.Feature(context,0)
f["name"] = 'Québec'
expr = mapnik.Expression("[name].match('Québec')")
eq_(expr.evaluate(f),True) # 1 == True
def test_regex_replace():
context = mapnik.Context()
context.push('name')
f = mapnik.Feature(context,0)
f["name"] = 'test'
expr = mapnik.Expression("[name].replace('(\B)|( )','$1 ')")
eq_(expr.evaluate(f),'t e s t')
def test_unicode_regex_replace_to_str():
expr = mapnik.Expression("[name].replace('(\B)|( )','$1 ')")
eq_(str(expr),"[name].replace('(\B)|( )','$1 ')")
def test_unicode_regex_replace():
context = mapnik.Context()
context.push('name')
f = mapnik.Feature(context,0)
f["name"] = 'Québec'
expr = mapnik.Expression("[name].replace('(\B)|( )','$1 ')")
# will fail if -DBOOST_REGEX_HAS_ICU is not defined
eq_(expr.evaluate(f), u'Q u é b e c')
def test_float_precision():
context = mapnik.Context()
context.push('num')
f = mapnik.Feature(context,0)
f["num1"] = 1.0000
f["num2"] = 1.0001
eq_(f["num1"],1.0000)
eq_(f["num2"],1.0001)
expr = mapnik.Expression("[num1] = 1.0000")
eq_(expr.evaluate(f),True)
expr = mapnik.Expression("[num1].match('1')")
eq_(expr.evaluate(f),True)
expr = mapnik.Expression("[num2] = 1.0001")
eq_(expr.evaluate(f),True)
expr = mapnik.Expression("[num2].match('1.0001')")
eq_(expr.evaluate(f),True)
def test_string_matching_on_precision():
context = mapnik.Context()
context.push('num')
f = mapnik.Feature(context,0)
f["num"] = "1.0000"
eq_(f["num"],"1.0000")
expr = mapnik.Expression("[num].match('.*(^0|00)$')")
eq_(expr.evaluate(f),True)
def test_creation_of_null_value():
context = mapnik.Context()
context.push('nv')
f = mapnik.Feature(context,0)
f["nv"] = None
eq_(f["nv"],None)
eq_(f["nv"] is None,True)
# test boolean
f["nv"] = 0
eq_(f["nv"],0)
eq_(f["nv"] is not None,True)
def test_creation_of_bool():
context = mapnik.Context()
context.push('bool')
f = mapnik.Feature(context,0)
f["bool"] = True
eq_(f["bool"],True)
# TODO - will become int of 1 do to built in boost python conversion
# https://github.com/mapnik/mapnik/issues/1873
eq_(isinstance(f["bool"],bool) or isinstance(f["bool"],long),True)
f["bool"] = False
eq_(f["bool"],False)
eq_(isinstance(f["bool"],bool) or isinstance(f["bool"],long),True)
# test NoneType
f["bool"] = None
eq_(f["bool"],None)
eq_(isinstance(f["bool"],bool) or isinstance(f["bool"],long),False)
# test integer
f["bool"] = 0
eq_(f["bool"],0)
# https://github.com/mapnik/mapnik/issues/1873
# ugh, boost_python's built into converter does not work right
#eq_(isinstance(f["bool"],bool),False)
null_equality = [
['hello',False,unicode],
[u'',False,unicode],
[0,False,long],
[123,False,long],
[0.0,False,float],
[123.123,False,float],
[.1,False,float],
[False,False,long], # TODO - should become bool: https://github.com/mapnik/mapnik/issues/1873
[True,False,long], # TODO - should become bool: https://github.com/mapnik/mapnik/issues/1873
[None,True,None],
[2147483648,False,long],
[922337203685477580,False,long]
]
def test_expressions_with_null_equality():
for eq in null_equality:
context = mapnik.Context()
f = mapnik.Feature(context,0)
f["prop"] = eq[0]
eq_(f["prop"],eq[0])
if eq[0] is None:
eq_(f["prop"] is None, True)
else:
eq_(isinstance(f['prop'],eq[2]),True,'%s is not an instance of %s' % (f['prop'],eq[2]))
expr = mapnik.Expression("[prop] = null")
eq_(expr.evaluate(f),eq[1])
expr = mapnik.Expression("[prop] is null")
eq_(expr.evaluate(f),eq[1])
def test_expressions_with_null_equality2():
for eq in null_equality:
context = mapnik.Context()
f = mapnik.Feature(context,0)
f["prop"] = eq[0]
eq_(f["prop"],eq[0])
if eq[0] is None:
eq_(f["prop"] is None, True)
else:
eq_(isinstance(f['prop'],eq[2]),True,'%s is not an instance of %s' % (f['prop'],eq[2]))
# TODO - support `is not` syntax:
# https://github.com/mapnik/mapnik/issues/796
expr = mapnik.Expression("not [prop] is null")
eq_(expr.evaluate(f),not eq[1])
# https://github.com/mapnik/mapnik/issues/1642
expr = mapnik.Expression("[prop] != null")
eq_(expr.evaluate(f),not eq[1])
truthyness = [
[u'hello',True,unicode],
[u'',False,unicode],
[0,False,long],
[123,True,long],
[0.0,False,float],
[123.123,True,float],
[.1,True,float],
[False,False,long], # TODO - should become bool: https://github.com/mapnik/mapnik/issues/1873
[True,True,long], # TODO - should become bool: https://github.com/mapnik/mapnik/issues/1873
[None,False,None],
[2147483648,True,long],
[922337203685477580,True,long]
]
def test_expressions_for_thruthyness():
context = mapnik.Context()
for eq in truthyness:
f = mapnik.Feature(context,0)
f["prop"] = eq[0]
eq_(f["prop"],eq[0])
if eq[0] is None:
eq_(f["prop"] is None, True)
else:
eq_(isinstance(f['prop'],eq[2]),True,'%s is not an instance of %s' % (f['prop'],eq[2]))
expr = mapnik.Expression("[prop]")
eq_(expr.to_bool(f),eq[1])
expr = mapnik.Expression("not [prop]")
eq_(expr.to_bool(f),not eq[1])
expr = mapnik.Expression("! [prop]")
eq_(expr.to_bool(f),not eq[1])
# also test if feature does not have property at all
f2 = mapnik.Feature(context,1)
# no property existing will return value_null since
# https://github.com/mapnik/mapnik/commit/562fada9d0f680f59b2d9f396c95320a0d753479#include/mapnik/feature.hpp
eq_(f2["prop"] is None,True)
expr = mapnik.Expression("[prop]")
eq_(expr.evaluate(f2),None)
eq_(expr.to_bool(f2),False)
# https://github.com/mapnik/mapnik/issues/1859
def test_if_null_and_empty_string_are_equal():
context = mapnik.Context()
f = mapnik.Feature(context,0)
f["empty"] = u""
f["null"] = None
# ensure base assumptions are good
eq_(mapnik.Expression("[empty] = ''").to_bool(f),True)
eq_(mapnik.Expression("[null] = null").to_bool(f),True)
eq_(mapnik.Expression("[empty] != ''").to_bool(f),False)
eq_(mapnik.Expression("[null] != null").to_bool(f),False)
# now test expected behavior
eq_(mapnik.Expression("[null] = ''").to_bool(f),False)
eq_(mapnik.Expression("[empty] = null").to_bool(f),False)
eq_(mapnik.Expression("[empty] != null").to_bool(f),True)
# this one is the back compatibility shim
eq_(mapnik.Expression("[null] != ''").to_bool(f),False)
def test_filtering_nulls_and_empty_strings():
context = mapnik.Context()
f = mapnik.Feature(context,0)
f["prop"] = u"hello"
eq_(f["prop"],u"hello")
eq_(mapnik.Expression("[prop]").to_bool(f),True)
eq_(mapnik.Expression("! [prop]").to_bool(f),False)
eq_(mapnik.Expression("[prop] != null").to_bool(f),True)
eq_(mapnik.Expression("[prop] != ''").to_bool(f),True)
eq_(mapnik.Expression("[prop] != null and [prop] != ''").to_bool(f),True)
eq_(mapnik.Expression("[prop] != null or [prop] != ''").to_bool(f),True)
f["prop2"] = u""
eq_(f["prop2"],u"")
eq_(mapnik.Expression("[prop2]").to_bool(f),False)
eq_(mapnik.Expression("! [prop2]").to_bool(f),True)
eq_(mapnik.Expression("[prop2] != null").to_bool(f),True)
eq_(mapnik.Expression("[prop2] != ''").to_bool(f),False)
eq_(mapnik.Expression("[prop2] = ''").to_bool(f),True)
eq_(mapnik.Expression("[prop2] != null or [prop2] != ''").to_bool(f),True)
eq_(mapnik.Expression("[prop2] != null and [prop2] != ''").to_bool(f),False)
f["prop3"] = None
eq_(f["prop3"],None)
eq_(mapnik.Expression("[prop3]").to_bool(f),False)
eq_(mapnik.Expression("! [prop3]").to_bool(f),True)
eq_(mapnik.Expression("[prop3] != null").to_bool(f),False)
eq_(mapnik.Expression("[prop3] = null").to_bool(f),True)
# https://github.com/mapnik/mapnik/issues/1859
#eq_(mapnik.Expression("[prop3] != ''").to_bool(f),True)
eq_(mapnik.Expression("[prop3] != ''").to_bool(f),False)
eq_(mapnik.Expression("[prop3] = ''").to_bool(f),False)
# https://github.com/mapnik/mapnik/issues/1859
#eq_(mapnik.Expression("[prop3] != null or [prop3] != ''").to_bool(f),True)
eq_(mapnik.Expression("[prop3] != null or [prop3] != ''").to_bool(f),False)
eq_(mapnik.Expression("[prop3] != null and [prop3] != ''").to_bool(f),False)
# attr not existing should behave the same as prop3
eq_(mapnik.Expression("[prop4]").to_bool(f),False)
eq_(mapnik.Expression("! [prop4]").to_bool(f),True)
eq_(mapnik.Expression("[prop4] != null").to_bool(f),False)
eq_(mapnik.Expression("[prop4] = null").to_bool(f),True)
# https://github.com/mapnik/mapnik/issues/1859
##eq_(mapnik.Expression("[prop4] != ''").to_bool(f),True)
eq_(mapnik.Expression("[prop4] != ''").to_bool(f),False)
eq_(mapnik.Expression("[prop4] = ''").to_bool(f),False)
# https://github.com/mapnik/mapnik/issues/1859
##eq_(mapnik.Expression("[prop4] != null or [prop4] != ''").to_bool(f),True)
eq_(mapnik.Expression("[prop4] != null or [prop4] != ''").to_bool(f),False)
eq_(mapnik.Expression("[prop4] != null and [prop4] != ''").to_bool(f),False)
f["prop5"] = False
eq_(f["prop5"],False)
eq_(mapnik.Expression("[prop5]").to_bool(f),False)
eq_(mapnik.Expression("! [prop5]").to_bool(f),True)
eq_(mapnik.Expression("[prop5] != null").to_bool(f),True)
eq_(mapnik.Expression("[prop5] = null").to_bool(f),False)
eq_(mapnik.Expression("[prop5] != ''").to_bool(f),True)
eq_(mapnik.Expression("[prop5] = ''").to_bool(f),False)
eq_(mapnik.Expression("[prop5] != null or [prop5] != ''").to_bool(f),True)
eq_(mapnik.Expression("[prop5] != null and [prop5] != ''").to_bool(f),True)
# note, we need to do [prop5] != 0 here instead of false due to this bug:
# https://github.com/mapnik/mapnik/issues/1873
eq_(mapnik.Expression("[prop5] != null and [prop5] != '' and [prop5] != 0").to_bool(f),False)
# https://github.com/mapnik/mapnik/issues/1872
def test_falseyness_comparision():
context = mapnik.Context()
f = mapnik.Feature(context,0)
f["prop"] = 0
eq_(mapnik.Expression("[prop]").to_bool(f),False)
eq_(mapnik.Expression("[prop] = false").to_bool(f),True)
eq_(mapnik.Expression("not [prop] != false").to_bool(f),True)
eq_(mapnik.Expression("not [prop] = true").to_bool(f),True)
eq_(mapnik.Expression("[prop] = true").to_bool(f),False)
eq_(mapnik.Expression("[prop] != true").to_bool(f),True)
# https://github.com/mapnik/mapnik/issues/1806, fixed by https://github.com/mapnik/mapnik/issues/1872
def test_truthyness_comparision():
context = mapnik.Context()
f = mapnik.Feature(context,0)
f["prop"] = 1
eq_(mapnik.Expression("[prop]").to_bool(f),True)
eq_(mapnik.Expression("[prop] = false").to_bool(f),False)
eq_(mapnik.Expression("not [prop] != false").to_bool(f),False)
eq_(mapnik.Expression("not [prop] = true").to_bool(f),False)
eq_(mapnik.Expression("[prop] = true").to_bool(f),True)
eq_(mapnik.Expression("[prop] != true").to_bool(f),False)
def test_division_by_zero():
expr = mapnik.Expression('[a]/[b]')
c = mapnik.Context()
c.push('a')
c.push('b')
f = mapnik.Feature(c,0);
f['a'] = 1
f['b'] = 0
eq_(expr.evaluate(f),None)
@raises(RuntimeError)
def test_invalid_syntax1():
mapnik.Expression('abs()')
if __name__ == "__main__":
exit(run_all(eval(x) for x in dir() if x.startswith("test_")))

View file

@ -1,41 +0,0 @@
#!/usr/bin/env python
from nose.tools import eq_
from utilities import execution_path, run_all
import os, mapnik
def setup():
# All of the paths used are relative, if we run the tests
# from another directory we need to chdir()
os.chdir(execution_path('.'))
def test_loading_fontset_from_map():
m = mapnik.Map(256,256)
mapnik.load_map(m,'../data/good_maps/fontset.xml',True)
fs = m.find_fontset('book-fonts')
eq_(len(fs.names),2)
eq_(list(fs.names),['DejaVu Sans Book','DejaVu Sans Oblique'])
# def test_loading_fontset_from_python():
# m = mapnik.Map(256,256)
# fset = mapnik.FontSet('foo')
# fset.add_face_name('Comic Sans')
# fset.add_face_name('Papyrus')
# eq_(fset.name,'foo')
# fset.name = 'my-set'
# eq_(fset.name,'my-set')
# m.append_fontset('my-set', fset)
# sty = mapnik.Style()
# rule = mapnik.Rule()
# tsym = mapnik.TextSymbolizer()
# eq_(tsym.fontset,None)
# tsym.fontset = fset
# rule.symbols.append(tsym)
# sty.rules.append(rule)
# m.append_style('Style',sty)
# serialized_map = mapnik.save_map_to_string(m)
# eq_('fontset-name="my-set"' in serialized_map,True)
if __name__ == "__main__":
setup()
exit(run_all(eval(x) for x in dir() if x.startswith("test_")))

View file

@ -1,151 +0,0 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from nose.tools import eq_,assert_almost_equal
from utilities import execution_path, run_all
import os, mapnik
try:
import json
except ImportError:
import simplejson as json
def setup():
# All of the paths used are relative, if we run the tests
# from another directory we need to chdir()
os.chdir(execution_path('.'))
if 'geojson' in mapnik.DatasourceCache.plugin_names():
def test_geojson_init():
ds = mapnik.Datasource(type='geojson',file='../data/json/escaped.geojson')
e = ds.envelope()
assert_almost_equal(e.minx, -81.705583, places=7)
assert_almost_equal(e.miny, 41.480573, places=6)
assert_almost_equal(e.maxx, -81.705583, places=5)
assert_almost_equal(e.maxy, 41.480573, places=3)
def test_geojson_properties():
ds = mapnik.Datasource(type='geojson',file='../data/json/escaped.geojson')
f = ds.features_at_point(ds.envelope().center()).features[0]
eq_(len(ds.fields()),9)
desc = ds.describe()
eq_(desc['geometry_type'],mapnik.DataGeometryType.Point)
eq_(f['name'], u'Test')
eq_(f['int'], 1)
eq_(f['description'], u'Test: \u005C')
eq_(f['spaces'], u'this has spaces')
eq_(f['double'], 1.1)
eq_(f['boolean'], True)
eq_(f['NOM_FR'], u'Qu\xe9bec')
eq_(f['NOM_FR'], u'Québec')
eq_(f['array'], u'[[[1],["deux"]],[["\\u0442\\u0440\\u0438","four","\\u4e94"]]]')
array = json.loads(f['array'])
eq_(array,[[[1], [u'deux']], [[u'\u0442\u0440\u0438', u'four', u'\u4e94']]])
eq_(f['object'], u'{"value":{"type":"\\u041c\\u0430pni\\u043a","array":[3,0,"x"]}}')
object = json.loads(f['object'])
eq_(object,{u'value': {u'array': [3, 0, u'x'], u'type': u'\u041c\u0430pni\u043a'}})
ds = mapnik.Datasource(type='geojson',file='../data/json/escaped.geojson')
f = ds.all_features()[0]
eq_(len(ds.fields()),9)
desc = ds.describe()
eq_(desc['geometry_type'],mapnik.DataGeometryType.Point)
eq_(f['name'], u'Test')
eq_(f['int'], 1)
eq_(f['description'], u'Test: \u005C')
eq_(f['spaces'], u'this has spaces')
eq_(f['double'], 1.1)
eq_(f['boolean'], True)
eq_(f['NOM_FR'], u'Qu\xe9bec')
eq_(f['NOM_FR'], u'Québec')
eq_(f['array'], u'[[[1],["deux"]],[["\\u0442\\u0440\\u0438","four","\\u4e94"]]]')
array = json.loads(f['array'])
eq_(array,[[[1], [u'deux']], [[u'\u0442\u0440\u0438', u'four', u'\u4e94']]])
eq_(f['object'], u'{"value":{"type":"\\u041c\\u0430pni\\u043a","array":[3,0,"x"]}}')
object = json.loads(f['object'])
eq_(object,{u'value': {u'array': [3, 0, u'x'], u'type': u'\u041c\u0430pni\u043a'}})
def test_large_geojson_properties():
ds = mapnik.Datasource(type='geojson',file='../data/json/escaped.geojson',cache_features = False)
f = ds.features_at_point(ds.envelope().center()).features[0]
eq_(len(ds.fields()),9)
desc = ds.describe()
eq_(desc['geometry_type'],mapnik.DataGeometryType.Point)
eq_(f['name'], u'Test')
eq_(f['int'], 1)
eq_(f['description'], u'Test: \u005C')
eq_(f['spaces'], u'this has spaces')
eq_(f['double'], 1.1)
eq_(f['boolean'], True)
eq_(f['NOM_FR'], u'Qu\xe9bec')
eq_(f['NOM_FR'], u'Québec')
eq_(f['array'], u'[[[1],["deux"]],[["\\u0442\\u0440\\u0438","four","\\u4e94"]]]')
array = json.loads(f['array'])
eq_(array,[[[1], [u'deux']], [[u'\u0442\u0440\u0438', u'four', u'\u4e94']]])
eq_(f['object'], u'{"value":{"type":"\\u041c\\u0430pni\\u043a","array":[3,0,"x"]}}')
object = json.loads(f['object'])
eq_(object,{u'value': {u'array': [3, 0, u'x'], u'type': u'\u041c\u0430pni\u043a'}})
ds = mapnik.Datasource(type='geojson',file='../data/json/escaped.geojson')
f = ds.all_features()[0]
eq_(len(ds.fields()),9)
desc = ds.describe()
eq_(desc['geometry_type'],mapnik.DataGeometryType.Point)
eq_(f['name'], u'Test')
eq_(f['int'], 1)
eq_(f['description'], u'Test: \u005C')
eq_(f['spaces'], u'this has spaces')
eq_(f['double'], 1.1)
eq_(f['boolean'], True)
eq_(f['NOM_FR'], u'Qu\xe9bec')
eq_(f['NOM_FR'], u'Québec')
eq_(f['array'], u'[[[1],["deux"]],[["\\u0442\\u0440\\u0438","four","\\u4e94"]]]')
array = json.loads(f['array'])
eq_(array,[[[1], [u'deux']], [[u'\u0442\u0440\u0438', u'four', u'\u4e94']]])
eq_(f['object'], u'{"value":{"type":"\\u041c\\u0430pni\\u043a","array":[3,0,"x"]}}')
object = json.loads(f['object'])
eq_(object,{u'value': {u'array': [3, 0, u'x'], u'type': u'\u041c\u0430pni\u043a'}})
def test_geojson_from_in_memory_string():
# will silently fail since it is a geometry and needs to be a featurecollection.
#ds = mapnik.Datasource(type='geojson',inline='{"type":"LineString","coordinates":[[0,0],[10,10]]}')
# works since it is a featurecollection
ds = mapnik.Datasource(type='geojson',inline='{ "type":"FeatureCollection", "features": [ { "type":"Feature", "properties":{"name":"test"}, "geometry": { "type":"LineString","coordinates":[[0,0],[10,10]] } } ]}')
eq_(len(ds.fields()),1)
f = ds.all_features()[0]
desc = ds.describe()
eq_(desc['geometry_type'],mapnik.DataGeometryType.LineString)
eq_(f['name'], u'test')
# @raises(RuntimeError)
def test_that_nonexistant_query_field_throws(**kwargs):
ds = mapnik.Datasource(type='geojson',file='../data/json/escaped.geojson')
eq_(len(ds.fields()),9)
# TODO - this sorting is messed up
#eq_(ds.fields(),['name', 'int', 'double', 'description', 'boolean', 'NOM_FR'])
#eq_(ds.field_types(),['str', 'int', 'float', 'str', 'bool', 'str'])
# TODO - should geojson plugin throw like others?
# query = mapnik.Query(ds.envelope())
# for fld in ds.fields():
# query.add_property_name(fld)
# # also add an invalid one, triggering throw
# query.add_property_name('bogus')
# fs = ds.features(query)
def test_parsing_feature_collection_with_top_level_properties():
ds = mapnik.Datasource(type='geojson',file='../data/json/feature_collection_level_properties.json')
f = ds.all_features()[0]
desc = ds.describe()
eq_(desc['geometry_type'],mapnik.DataGeometryType.Point)
eq_(f['feat_name'], u'feat_value')
if __name__ == "__main__":
setup()
exit(run_all(eval(x) for x in dir() if x.startswith("test_")))

File diff suppressed because one or more lines are too long

View file

@ -1,13 +0,0 @@
import mapnik
from nose.tools import eq_
from utilities import run_all
def test_grayscale_conversion():
im = mapnik.Image(2,2)
im.fill(mapnik.Color('white'))
im.set_grayscale_to_alpha()
pixel = im.get_pixel(0,0)
eq_((pixel >> 24) & 0xff,255);
if __name__ == "__main__":
exit(run_all(eval(x) for x in dir() if x.startswith("test_")))

View file

@ -1,124 +0,0 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import os, mapnik
from timeit import Timer, time
from utilities import execution_path, run_all
def setup():
# All of the paths used are relative, if we run the tests
# from another directory we need to chdir()
os.chdir(execution_path('.'))
combinations = ['png',
'png8',
'png8:m=o',
'png8:m=h',
'png8:m=o:t=0',
'png8:m=o:t=1',
'png8:m=o:t=2',
'png8:m=h:t=0',
'png8:m=h:t=1',
'png8:m=h:t=2',
'png:z=1',
'png:z=1:t=0', # forces rbg, no a
'png8:z=1',
'png8:z=1:m=o',
'png8:z=1:m=h',
'png8:z=1:c=1',
'png8:z=1:c=24',
'png8:z=1:c=64',
'png8:z=1:c=128',
'png8:z=1:c=200',
'png8:z=1:c=255',
'png8:z=9:c=64',
'png8:z=9:c=128',
'png8:z=9:c=200',
'png8:z=1:c=50:m=h',
'png8:z=1:c=1:m=o',
'png8:z=1:c=1:m=o:s=filtered',
'png:z=1:s=filtered',
'png:z=1:s=huff',
'png:z=1:s=rle',
'png8:m=h:g=2.0',
'png8:m=h:g=1.0',
'png:e=miniz',
'png8:e=miniz'
]
tiles = [
'blank',
'solid',
'many_colors',
'aerial_24'
]
iterations = 10
def do_encoding():
global image
results = {}
sortable = {}
def run(func, im, format, t):
global image
image = im
start = time.time()
set = t.repeat(iterations,1)
elapsed = (time.time() - start)
min_ = min(set)*1000
avg = (sum(set)/len(set))*1000
name = func.__name__ + ' ' + format
results[name] = [min_,avg,elapsed*1000,name,len(func())]
sortable[name] = [min_]
if 'blank' in tiles:
def blank():
return eval('image.tostring("%s")' % c)
blank_im = mapnik.Image(512,512)
for c in combinations:
t = Timer(blank)
run(blank,blank_im,c,t)
if 'solid' in tiles:
def solid():
return eval('image.tostring("%s")' % c)
solid_im = mapnik.Image(512,512)
solid_im.fill(mapnik.Color("#f2efe9"))
for c in combinations:
t = Timer(solid)
run(solid,solid_im,c,t)
if 'many_colors' in tiles:
def many_colors():
return eval('image.tostring("%s")' % c)
# lots of colors: http://tile.osm.org/13/4194/2747.png
many_colors_im = mapnik.Image.open('../data/images/13_4194_2747.png')
for c in combinations:
t = Timer(many_colors)
run(many_colors,many_colors_im,c,t)
if 'aerial_24' in tiles:
def aerial_24():
return eval('image.tostring("%s")' % c)
aerial_24_im = mapnik.Image.open('../data/images/12_654_1580.png')
for c in combinations:
t = Timer(aerial_24)
run(aerial_24,aerial_24_im,c,t)
for key, value in sorted(sortable.iteritems(), key=lambda (k,v): (v,k)):
s = results[key]
min_ = str(s[0])[:6]
avg = str(s[1])[:6]
elapsed = str(s[2])[:6]
name = s[3]
size = s[4]
print 'min: %sms | avg: %sms | total: %sms | len: %s <-- %s' % (min_,avg,elapsed,size,name)
if __name__ == "__main__":
setup()
do_encoding()
exit(run_all(eval(x) for x in dir() if x.startswith("test_")))

View file

@ -1,68 +0,0 @@
#!/usr/bin/env python
from nose.tools import eq_
from utilities import execution_path, run_all
from utilities import side_by_side_image
import os, mapnik
import re
def setup():
# All of the paths used are relative, if we run the tests
# from another directory we need to chdir()
os.chdir(execution_path('.'))
def replace_style(m, name, style):
m.remove_style(name)
m.append_style(name, style)
def test_append():
s = mapnik.Style()
eq_(s.image_filters,'')
s.image_filters = 'gray'
eq_(s.image_filters,'gray')
s.image_filters = 'sharpen'
eq_(s.image_filters,'sharpen')
if 'shape' in mapnik.DatasourceCache.plugin_names():
def test_style_level_image_filter():
m = mapnik.Map(256, 256)
mapnik.load_map(m, '../data/good_maps/style_level_image_filter.xml')
m.zoom_all()
successes = []
fails = []
for name in ("", "agg-stack-blur(2,2)", "blur",
"edge-detect", "emboss", "gray", "invert",
"sharpen", "sobel", "x-gradient", "y-gradient"):
if name == "":
filename = "none"
else:
filename = re.sub(r"[^-_a-z.0-9]", "", name)
# find_style returns a copy of the style object
style_markers = m.find_style("markers")
style_markers.image_filters = name
style_labels = m.find_style("labels")
style_labels.image_filters = name
# replace the original style with the modified one
replace_style(m, "markers", style_markers)
replace_style(m, "labels", style_labels)
im = mapnik.Image(m.width, m.height)
mapnik.render(m, im)
actual = '/tmp/mapnik-style-image-filter-' + filename + '.png'
expected = 'images/style-image-filter/' + filename + '.png'
im.save(actual,"png32")
if not os.path.exists(expected) or os.environ.get('UPDATE'):
print 'generating expected test image: %s' % expected
im.save(expected,'png32')
expected_im = mapnik.Image.open(expected)
# compare them
if im.tostring('png32') == expected_im.tostring('png32'):
successes.append(name)
else:
fails.append('failed comparing actual (%s) and expected(%s)' % (actual,'tests/python_tests/'+ expected))
fail_im = side_by_side_image(expected_im, im)
fail_im.save('/tmp/mapnik-style-image-filter-' + filename + '.fail.png','png32')
eq_(len(fails), 0, '\n'+'\n'.join(fails))
if __name__ == "__main__":
setup()
exit(run_all(eval(x) for x in dir() if x.startswith("test_")))

View file

@ -1,336 +0,0 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import os, mapnik
from nose.tools import eq_,raises, assert_almost_equal
from utilities import execution_path, run_all, get_unique_colors
def setup():
# All of the paths used are relative, if we run the tests
# from another directory we need to chdir()
os.chdir(execution_path('.'))
def test_type():
im = mapnik.Image(256, 256)
eq_(im.get_type(), mapnik.ImageType.rgba8)
im = mapnik.Image(256, 256, mapnik.ImageType.gray8)
eq_(im.get_type(), mapnik.ImageType.gray8)
def test_image_premultiply():
im = mapnik.Image(256,256)
eq_(im.premultiplied(),False)
# Premultiply should return true that it worked
eq_(im.premultiply(), True)
eq_(im.premultiplied(),True)
# Premultipling again should return false as nothing should happen
eq_(im.premultiply(), False)
eq_(im.premultiplied(),True)
# Demultiply should return true that it worked
eq_(im.demultiply(), True)
eq_(im.premultiplied(),False)
# Demultiply again should not work and return false as it did nothing
eq_(im.demultiply(), False)
eq_(im.premultiplied(),False)
def test_image_premultiply_values():
im = mapnik.Image(256,256)
im.fill(mapnik.Color(16, 33, 255, 128))
im.premultiply()
c = im.get_pixel(0,0, True)
eq_(c.r, 8)
eq_(c.g, 17)
eq_(c.b, 128)
eq_(c.a, 128)
im.demultiply()
# Do to the nature of this operation the result will not be exactly the same
c = im.get_pixel(0,0,True)
eq_(c.r,15)
eq_(c.g,33)
eq_(c.b,255)
eq_(c.a,128)
def test_background():
im = mapnik.Image(256,256)
eq_(im.premultiplied(), False)
im.fill(mapnik.Color(32,64,125,128))
eq_(im.premultiplied(), False)
c = im.get_pixel(0,0,True)
eq_(c.get_premultiplied(), False)
eq_(c.r,32)
eq_(c.g,64)
eq_(c.b,125)
eq_(c.a,128)
# Now again with a premultiplied alpha
im.fill(mapnik.Color(32,64,125,128,True))
eq_(im.premultiplied(), True)
c = im.get_pixel(0,0,True)
eq_(c.get_premultiplied(), True)
eq_(c.r,32)
eq_(c.g,64)
eq_(c.b,125)
eq_(c.a,128)
def test_set_and_get_pixel():
# Create an image that is not premultiplied
im = mapnik.Image(256,256)
c0 = mapnik.Color(16,33,255,128)
c0_pre = mapnik.Color(16,33,255,128, True)
im.set_pixel(0,0,c0)
im.set_pixel(1,1,c0_pre)
# No differences for non premultiplied pixels
c1_int = mapnik.Color(im.get_pixel(0,0))
eq_(c0.r, c1_int.r)
eq_(c0.g, c1_int.g)
eq_(c0.b, c1_int.b)
eq_(c0.a, c1_int.a)
c1 = im.get_pixel(0,0,True)
eq_(c0.r, c1.r)
eq_(c0.g, c1.g)
eq_(c0.b, c1.b)
eq_(c0.a, c1.a)
# The premultiplied Color should be demultiplied before being applied.
c0_pre.demultiply()
c1_int = mapnik.Color(im.get_pixel(1,1))
eq_(c0_pre.r, c1_int.r)
eq_(c0_pre.g, c1_int.g)
eq_(c0_pre.b, c1_int.b)
eq_(c0_pre.a, c1_int.a)
c1 = im.get_pixel(1,1,True)
eq_(c0_pre.r, c1.r)
eq_(c0_pre.g, c1.g)
eq_(c0_pre.b, c1.b)
eq_(c0_pre.a, c1.a)
# Now create a new image that is premultiplied
im = mapnik.Image(256,256, mapnik.ImageType.rgba8, True, True)
c0 = mapnik.Color(16,33,255,128)
c0_pre = mapnik.Color(16,33,255,128, True)
im.set_pixel(0,0,c0)
im.set_pixel(1,1,c0_pre)
# It should have put pixels that are the same as premultiplied so premultiply c0
c0.premultiply()
c1_int = mapnik.Color(im.get_pixel(0,0))
eq_(c0.r, c1_int.r)
eq_(c0.g, c1_int.g)
eq_(c0.b, c1_int.b)
eq_(c0.a, c1_int.a)
c1 = im.get_pixel(0,0,True)
eq_(c0.r, c1.r)
eq_(c0.g, c1.g)
eq_(c0.b, c1.b)
eq_(c0.a, c1.a)
# The premultiplied Color should be the same though
c1_int = mapnik.Color(im.get_pixel(1,1))
eq_(c0_pre.r, c1_int.r)
eq_(c0_pre.g, c1_int.g)
eq_(c0_pre.b, c1_int.b)
eq_(c0_pre.a, c1_int.a)
c1 = im.get_pixel(1,1,True)
eq_(c0_pre.r, c1.r)
eq_(c0_pre.g, c1.g)
eq_(c0_pre.b, c1.b)
eq_(c0_pre.a, c1.a)
def test_pixel_gray8():
im = mapnik.Image(4,4,mapnik.ImageType.gray8)
val_list = range(20)
for v in val_list:
im.set_pixel(0,0, v)
eq_(im.get_pixel(0,0), v)
im.set_pixel(0,0, -v)
eq_(im.get_pixel(0,0), 0)
def test_pixel_gray8s():
im = mapnik.Image(4,4,mapnik.ImageType.gray8s)
val_list = range(20)
for v in val_list:
im.set_pixel(0,0, v)
eq_(im.get_pixel(0,0), v)
im.set_pixel(0,0, -v)
eq_(im.get_pixel(0,0), -v)
def test_pixel_gray16():
im = mapnik.Image(4,4,mapnik.ImageType.gray16)
val_list = range(20)
for v in val_list:
im.set_pixel(0,0, v)
eq_(im.get_pixel(0,0), v)
im.set_pixel(0,0, -v)
eq_(im.get_pixel(0,0), 0)
def test_pixel_gray16s():
im = mapnik.Image(4,4,mapnik.ImageType.gray16s)
val_list = range(20)
for v in val_list:
im.set_pixel(0,0, v)
eq_(im.get_pixel(0,0), v)
im.set_pixel(0,0, -v)
eq_(im.get_pixel(0,0), -v)
def test_pixel_gray32():
im = mapnik.Image(4,4,mapnik.ImageType.gray32)
val_list = range(20)
for v in val_list:
im.set_pixel(0,0, v)
eq_(im.get_pixel(0,0), v)
im.set_pixel(0,0, -v)
eq_(im.get_pixel(0,0), 0)
def test_pixel_gray32s():
im = mapnik.Image(4,4,mapnik.ImageType.gray32s)
val_list = range(20)
for v in val_list:
im.set_pixel(0,0, v)
eq_(im.get_pixel(0,0), v)
im.set_pixel(0,0, -v)
eq_(im.get_pixel(0,0), -v)
def test_pixel_gray64():
im = mapnik.Image(4,4,mapnik.ImageType.gray64)
val_list = range(20)
for v in val_list:
im.set_pixel(0,0, v)
eq_(im.get_pixel(0,0), v)
im.set_pixel(0,0, -v)
eq_(im.get_pixel(0,0), 0)
def test_pixel_gray64s():
im = mapnik.Image(4,4,mapnik.ImageType.gray64s)
val_list = range(20)
for v in val_list:
im.set_pixel(0,0, v)
eq_(im.get_pixel(0,0), v)
im.set_pixel(0,0, -v)
eq_(im.get_pixel(0,0), -v)
def test_pixel_floats():
im = mapnik.Image(4,4,mapnik.ImageType.gray32f)
val_list = [0.9, 0.99, 0.999, 0.9999, 0.99999, 1, 1.0001, 1.001, 1.01, 1.1]
for v in val_list:
im.set_pixel(0,0, v)
assert_almost_equal(im.get_pixel(0,0), v)
im.set_pixel(0,0, -v)
assert_almost_equal(im.get_pixel(0,0), -v)
def test_pixel_doubles():
im = mapnik.Image(4,4,mapnik.ImageType.gray64f)
val_list = [0.9, 0.99, 0.999, 0.9999, 0.99999, 1, 1.0001, 1.001, 1.01, 1.1]
for v in val_list:
im.set_pixel(0,0, v)
assert_almost_equal(im.get_pixel(0,0), v)
im.set_pixel(0,0, -v)
assert_almost_equal(im.get_pixel(0,0), -v)
def test_pixel_overflow():
im = mapnik.Image(4,4,mapnik.ImageType.gray8)
im.set_pixel(0,0,256)
eq_(im.get_pixel(0,0),255)
def test_pixel_underflow():
im = mapnik.Image(4,4,mapnik.ImageType.gray8)
im.set_pixel(0,0,-1)
eq_(im.get_pixel(0,0),0)
im = mapnik.Image(4,4,mapnik.ImageType.gray16)
im.set_pixel(0,0,-1)
eq_(im.get_pixel(0,0),0)
@raises(IndexError)
def test_set_pixel_out_of_range_1():
im = mapnik.Image(4,4)
c = mapnik.Color('blue')
im.set_pixel(5,5,c)
@raises(OverflowError)
def test_set_pixel_out_of_range_2():
im = mapnik.Image(4,4)
c = mapnik.Color('blue')
im.set_pixel(-1,1,c)
@raises(IndexError)
def test_get_pixel_out_of_range_1():
im = mapnik.Image(4,4)
c = im.get_pixel(5,5)
@raises(OverflowError)
def test_get_pixel_out_of_range_2():
im = mapnik.Image(4,4)
c = im.get_pixel(-1,1)
@raises(IndexError)
def test_get_pixel_color_out_of_range_1():
im = mapnik.Image(4,4)
c = im.get_pixel(5,5,True)
@raises(OverflowError)
def test_get_pixel_color_out_of_range_2():
im = mapnik.Image(4,4)
c = im.get_pixel(-1,1,True)
def test_set_color_to_alpha():
im = mapnik.Image(256,256)
im.fill(mapnik.Color('rgba(12,12,12,255)'))
eq_(get_unique_colors(im), ['rgba(12,12,12,255)'])
im.set_color_to_alpha(mapnik.Color('rgba(12,12,12,0)'))
eq_(get_unique_colors(im), ['rgba(0,0,0,0)'])
@raises(RuntimeError)
def test_negative_image_dimensions():
# TODO - this may have regressed in https://github.com/mapnik/mapnik/commit/4f3521ac24b61fc8ae8fd344a16dc3a5fdf15af7
im = mapnik.Image(-40,40)
# should not get here
eq_(im.width(),0)
eq_(im.height(),0)
def test_jpeg_round_trip():
filepath = '/tmp/mapnik-jpeg-io.jpeg'
im = mapnik.Image(255,267)
im.fill(mapnik.Color('rgba(1,2,3,.5)'))
im.save(filepath,'jpeg')
im2 = mapnik.Image.open(filepath)
im3 = mapnik.Image.fromstring(open(filepath,'r').read())
eq_(im.width(),im2.width())
eq_(im.height(),im2.height())
eq_(im.width(),im3.width())
eq_(im.height(),im3.height())
eq_(len(im.tostring()),len(im2.tostring()))
eq_(len(im.tostring('jpeg')),len(im2.tostring('jpeg')))
eq_(len(im.tostring()),len(im3.tostring()))
eq_(len(im.tostring('jpeg')),len(im3.tostring('jpeg')))
def test_png_round_trip():
filepath = '/tmp/mapnik-png-io.png'
im = mapnik.Image(255,267)
im.fill(mapnik.Color('rgba(1,2,3,.5)'))
im.save(filepath,'png')
im2 = mapnik.Image.open(filepath)
im3 = mapnik.Image.fromstring(open(filepath,'r').read())
eq_(im.width(),im2.width())
eq_(im.height(),im2.height())
eq_(im.width(),im3.width())
eq_(im.height(),im3.height())
eq_(len(im.tostring()),len(im2.tostring()))
eq_(len(im.tostring('png')),len(im2.tostring('png')))
eq_(len(im.tostring('png8')),len(im2.tostring('png8')))
eq_(len(im.tostring()),len(im3.tostring()))
eq_(len(im.tostring('png')),len(im3.tostring('png')))
eq_(len(im.tostring('png8')),len(im3.tostring('png8')))
def test_image_open_from_string():
filepath = '../data/images/dummy.png'
im1 = mapnik.Image.open(filepath)
im2 = mapnik.Image.fromstring(open(filepath,'rb').read())
eq_(im1.width(),im2.width())
length = len(im1.tostring())
eq_(length,len(im2.tostring()))
eq_(len(mapnik.Image.fromstring(im1.tostring('png')).tostring()),length)
eq_(len(mapnik.Image.fromstring(im1.tostring('jpeg')).tostring()),length)
eq_(len(mapnik.Image.frombuffer(buffer(im1.tostring('png'))).tostring()),length)
eq_(len(mapnik.Image.frombuffer(buffer(im1.tostring('jpeg'))).tostring()),length)
# TODO - https://github.com/mapnik/mapnik/issues/1831
eq_(len(mapnik.Image.fromstring(im1.tostring('tiff')).tostring()),length)
eq_(len(mapnik.Image.frombuffer(buffer(im1.tostring('tiff'))).tostring()),length)
if __name__ == "__main__":
setup()
exit(run_all(eval(x) for x in dir() if x.startswith("test_")))

View file

@ -1,335 +0,0 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import os, mapnik
import hashlib
from nose.tools import eq_, assert_not_equal
from utilities import execution_path, run_all
def hashstr(var):
return hashlib.md5(var).hexdigest()
def setup():
# All of the paths used are relative, if we run the tests
# from another directory we need to chdir()
os.chdir(execution_path('.'))
def test_tiff_round_trip_scanline():
filepath = '/tmp/mapnik-tiff-io-scanline.tiff'
im = mapnik.Image(255,267)
im.fill(mapnik.Color('rgba(12,255,128,.5)'))
org_str = hashstr(im.tostring())
im.save(filepath,'tiff:method=scanline')
im2 = mapnik.Image.open(filepath)
im3 = mapnik.Image.fromstring(open(filepath,'r').read())
eq_(im.width(),im2.width())
eq_(im.height(),im2.height())
eq_(im.width(),im3.width())
eq_(im.height(),im3.height())
eq_(hashstr(im.tostring()), org_str)
# This won't be the same the first time around because the im is not premultiplied and im2 is
assert_not_equal(hashstr(im.tostring()),hashstr(im2.tostring()))
assert_not_equal(hashstr(im.tostring('tiff:method=scanline')),hashstr(im2.tostring('tiff:method=scanline')))
# Now premultiply
im.premultiply()
eq_(hashstr(im.tostring()),hashstr(im2.tostring()))
eq_(hashstr(im.tostring('tiff:method=scanline')),hashstr(im2.tostring('tiff:method=scanline')))
eq_(hashstr(im2.tostring()),hashstr(im3.tostring()))
eq_(hashstr(im2.tostring('tiff:method=scanline')),hashstr(im3.tostring('tiff:method=scanline')))
def test_tiff_round_trip_stripped():
filepath = '/tmp/mapnik-tiff-io-stripped.tiff'
im = mapnik.Image(255,267)
im.fill(mapnik.Color('rgba(12,255,128,.5)'))
org_str = hashstr(im.tostring())
im.save(filepath,'tiff:method=stripped')
im2 = mapnik.Image.open(filepath)
im2.save('/tmp/mapnik-tiff-io-stripped2.tiff','tiff:method=stripped')
im3 = mapnik.Image.fromstring(open(filepath,'r').read())
eq_(im.width(),im2.width())
eq_(im.height(),im2.height())
eq_(im.width(),im3.width())
eq_(im.height(),im3.height())
# Because one will end up with UNASSOC alpha tag which internally the TIFF reader will premultiply, the first to string will not be the same due to the
# difference in tags.
assert_not_equal(hashstr(im.tostring()),hashstr(im2.tostring()))
assert_not_equal(hashstr(im.tostring('tiff:method=stripped')),hashstr(im2.tostring('tiff:method=stripped')))
# Now if we premultiply they will be exactly the same
im.premultiply()
eq_(hashstr(im.tostring()),hashstr(im2.tostring()))
eq_(hashstr(im.tostring('tiff:method=stripped')),hashstr(im2.tostring('tiff:method=stripped')))
eq_(hashstr(im2.tostring()),hashstr(im3.tostring()))
# Both of these started out premultiplied, so this round trip should be exactly the same!
eq_(hashstr(im2.tostring('tiff:method=stripped')),hashstr(im3.tostring('tiff:method=stripped')))
def test_tiff_round_trip_rows_stripped():
filepath = '/tmp/mapnik-tiff-io-rows_stripped.tiff'
filepath2 = '/tmp/mapnik-tiff-io-rows_stripped2.tiff'
im = mapnik.Image(255,267)
im.fill(mapnik.Color('rgba(12,255,128,.5)'))
c = im.get_pixel(0,0,True)
eq_(c.r, 12)
eq_(c.g, 255)
eq_(c.b, 128)
eq_(c.a, 128)
eq_(c.get_premultiplied(), False)
im.save(filepath,'tiff:method=stripped:rows_per_strip=8')
im2 = mapnik.Image.open(filepath)
c2 = im2.get_pixel(0,0,True)
eq_(c2.r, 6)
eq_(c2.g, 128)
eq_(c2.b, 64)
eq_(c2.a, 128)
eq_(c2.get_premultiplied(), True)
im2.save(filepath2,'tiff:method=stripped:rows_per_strip=8')
im3 = mapnik.Image.fromstring(open(filepath,'r').read())
eq_(im.width(),im2.width())
eq_(im.height(),im2.height())
eq_(im.width(),im3.width())
eq_(im.height(),im3.height())
# Because one will end up with UNASSOC alpha tag which internally the TIFF reader will premultiply, the first to string will not be the same due to the
# difference in tags.
assert_not_equal(hashstr(im.tostring()),hashstr(im2.tostring()))
assert_not_equal(hashstr(im.tostring('tiff:method=stripped:rows_per_strip=8')),hashstr(im2.tostring('tiff:method=stripped:rows_per_strip=8')))
# Now premultiply the first image and they will be the same!
im.premultiply()
eq_(hashstr(im.tostring('tiff:method=stripped:rows_per_strip=8')),hashstr(im2.tostring('tiff:method=stripped:rows_per_strip=8')))
eq_(hashstr(im2.tostring()),hashstr(im3.tostring()))
# Both of these started out premultiplied, so this round trip should be exactly the same!
eq_(hashstr(im2.tostring('tiff:method=stripped:rows_per_strip=8')),hashstr(im3.tostring('tiff:method=stripped:rows_per_strip=8')))
def test_tiff_round_trip_buffered_tiled():
filepath = '/tmp/mapnik-tiff-io-buffered-tiled.tiff'
filepath2 = '/tmp/mapnik-tiff-io-buffered-tiled2.tiff'
filepath3 = '/tmp/mapnik-tiff-io-buffered-tiled3.tiff'
im = mapnik.Image(255,267)
im.fill(mapnik.Color('rgba(33,255,128,.5)'))
c = im.get_pixel(0,0,True)
eq_(c.r, 33)
eq_(c.g, 255)
eq_(c.b, 128)
eq_(c.a, 128)
eq_(c.get_premultiplied(), False)
im.save(filepath,'tiff:method=tiled:tile_width=32:tile_height=32')
im2 = mapnik.Image.open(filepath)
c2 = im2.get_pixel(0,0,True)
eq_(c2.r, 17)
eq_(c2.g, 128)
eq_(c2.b, 64)
eq_(c2.a, 128)
eq_(c2.get_premultiplied(), True)
im3 = mapnik.Image.fromstring(open(filepath,'r').read())
im2.save(filepath2, 'tiff:method=tiled:tile_width=32:tile_height=32')
im3.save(filepath3, 'tiff:method=tiled:tile_width=32:tile_height=32')
eq_(im.width(),im2.width())
eq_(im.height(),im2.height())
eq_(im.width(),im3.width())
eq_(im.height(),im3.height())
# Because one will end up with UNASSOC alpha tag which internally the TIFF reader will premultiply, the first to string will not be the same due to the
# difference in tags.
assert_not_equal(hashstr(im.tostring()),hashstr(im2.tostring()))
assert_not_equal(hashstr(im.tostring('tiff:method=tiled:tile_width=32:tile_height=32')),hashstr(im2.tostring('tiff:method=tiled:tile_width=32:tile_height=32')))
# Now premultiply the first image and they should be the same
im.premultiply()
eq_(hashstr(im.tostring()),hashstr(im2.tostring()))
eq_(hashstr(im.tostring('tiff:method=tiled:tile_width=32:tile_height=32')),hashstr(im2.tostring('tiff:method=tiled:tile_width=32:tile_height=32')))
eq_(hashstr(im2.tostring()),hashstr(im3.tostring()))
# Both of these started out premultiplied, so this round trip should be exactly the same!
eq_(hashstr(im2.tostring('tiff:method=tiled:tile_width=32:tile_height=32')),hashstr(im3.tostring('tiff:method=tiled:tile_width=32:tile_height=32')))
def test_tiff_round_trip_tiled():
filepath = '/tmp/mapnik-tiff-io-tiled.tiff'
im = mapnik.Image(256,256)
im.fill(mapnik.Color('rgba(1,255,128,.5)'))
im.save(filepath,'tiff:method=tiled')
im2 = mapnik.Image.open(filepath)
im3 = mapnik.Image.fromstring(open(filepath,'r').read())
eq_(im.width(),im2.width())
eq_(im.height(),im2.height())
eq_(im.width(),im3.width())
eq_(im.height(),im3.height())
# Because one will end up with UNASSOC alpha tag which internally the TIFF reader will premultiply, the first to string will not be the same due to the
# difference in tags.
assert_not_equal(hashstr(im.tostring()),hashstr(im2.tostring()))
assert_not_equal(hashstr(im.tostring('tiff:method=tiled')),hashstr(im2.tostring('tiff:method=tiled')))
# Now premultiply the first image and they will be exactly the same.
im.premultiply()
eq_(hashstr(im.tostring()),hashstr(im2.tostring()))
eq_(hashstr(im.tostring('tiff:method=tiled')),hashstr(im2.tostring('tiff:method=tiled')))
eq_(hashstr(im2.tostring()),hashstr(im3.tostring()))
# Both of these started out premultiplied, so this round trip should be exactly the same!
eq_(hashstr(im2.tostring('tiff:method=tiled')),hashstr(im3.tostring('tiff:method=tiled')))
def test_tiff_rgb8_compare():
filepath1 = '../data/tiff/ndvi_256x256_rgb8_striped.tif'
filepath2 = '/tmp/mapnik-tiff-rgb8.tiff'
im = mapnik.Image.open(filepath1)
im.save(filepath2,'tiff')
im2 = mapnik.Image.open(filepath2)
eq_(im.width(),im2.width())
eq_(im.height(),im2.height())
eq_(hashstr(im.tostring()),hashstr(im2.tostring()))
eq_(hashstr(im.tostring('tiff')),hashstr(im2.tostring('tiff')))
# should not be a blank image
eq_(hashstr(im.tostring("tiff")) != hashstr(mapnik.Image(im.width(),im.height(),mapnik.ImageType.rgba8).tostring("tiff")),True)
def test_tiff_rgba8_compare_scanline():
filepath1 = '../data/tiff/ndvi_256x256_rgba8_striped.tif'
filepath2 = '/tmp/mapnik-tiff-rgba8-scanline.tiff'
im = mapnik.Image.open(filepath1)
im.save(filepath2,'tiff:method=scanline')
im2 = mapnik.Image.open(filepath2)
eq_(im.width(),im2.width())
eq_(im.height(),im2.height())
eq_(hashstr(im.tostring()),hashstr(im2.tostring()))
eq_(hashstr(im.tostring('tiff:method=scanline')),hashstr(im2.tostring('tiff:method=scanline')))
# should not be a blank image
eq_(hashstr(im.tostring("tiff")) != hashstr(mapnik.Image(im.width(),im.height(),mapnik.ImageType.rgba8).tostring("tiff")),True)
def test_tiff_rgba8_compare_stripped():
filepath1 = '../data/tiff/ndvi_256x256_rgba8_striped.tif'
filepath2 = '/tmp/mapnik-tiff-rgba8-stripped.tiff'
im = mapnik.Image.open(filepath1)
im.save(filepath2,'tiff:method=stripped')
im2 = mapnik.Image.open(filepath2)
eq_(im.width(),im2.width())
eq_(im.height(),im2.height())
eq_(hashstr(im.tostring()),hashstr(im2.tostring()))
eq_(hashstr(im.tostring('tiff:method=stripped')),hashstr(im2.tostring('tiff:method=stripped')))
# should not be a blank image
eq_(hashstr(im.tostring("tiff")) != hashstr(mapnik.Image(im.width(),im.height(),mapnik.ImageType.rgba8).tostring("tiff")),True)
def test_tiff_rgba8_compare_tiled():
filepath1 = '../data/tiff/ndvi_256x256_rgba8_striped.tif'
filepath2 = '/tmp/mapnik-tiff-rgba8-stripped.tiff'
im = mapnik.Image.open(filepath1)
im.save(filepath2,'tiff:method=tiled')
im2 = mapnik.Image.open(filepath2)
eq_(im.width(),im2.width())
eq_(im.height(),im2.height())
eq_(hashstr(im.tostring()),hashstr(im2.tostring()))
eq_(hashstr(im.tostring('tiff:method=tiled')),hashstr(im2.tostring('tiff:method=tiled')))
# should not be a blank image
eq_(hashstr(im.tostring("tiff")) != hashstr(mapnik.Image(im.width(),im.height(),mapnik.ImageType.rgba8).tostring("tiff")),True)
def test_tiff_gray8_compare_scanline():
filepath1 = '../data/tiff/ndvi_256x256_gray8_striped.tif'
filepath2 = '/tmp/mapnik-tiff-gray8-scanline.tiff'
im = mapnik.Image.open(filepath1)
im.save(filepath2,'tiff:method=scanline')
im2 = mapnik.Image.open(filepath2)
eq_(im.width(),im2.width())
eq_(im.height(),im2.height())
eq_(hashstr(im.tostring()),hashstr(im2.tostring()))
eq_(hashstr(im.tostring('tiff:method=scanline')),hashstr(im2.tostring('tiff:method=scanline')))
# should not be a blank image
eq_(hashstr(im.tostring("tiff")) != hashstr(mapnik.Image(im.width(),im.height(),mapnik.ImageType.gray8).tostring("tiff")),True)
def test_tiff_gray8_compare_stripped():
filepath1 = '../data/tiff/ndvi_256x256_gray8_striped.tif'
filepath2 = '/tmp/mapnik-tiff-gray8-stripped.tiff'
im = mapnik.Image.open(filepath1)
im.save(filepath2,'tiff:method=stripped')
im2 = mapnik.Image.open(filepath2)
eq_(im.width(),im2.width())
eq_(im.height(),im2.height())
eq_(hashstr(im.tostring()),hashstr(im2.tostring()))
eq_(hashstr(im.tostring('tiff:method=stripped')),hashstr(im2.tostring('tiff:method=stripped')))
# should not be a blank image
eq_(hashstr(im.tostring("tiff")) != hashstr(mapnik.Image(im.width(),im.height(),mapnik.ImageType.gray8).tostring("tiff")),True)
def test_tiff_gray8_compare_tiled():
filepath1 = '../data/tiff/ndvi_256x256_gray8_striped.tif'
filepath2 = '/tmp/mapnik-tiff-gray8-tiled.tiff'
im = mapnik.Image.open(filepath1)
im.save(filepath2,'tiff:method=tiled')
im2 = mapnik.Image.open(filepath2)
eq_(im.width(),im2.width())
eq_(im.height(),im2.height())
eq_(hashstr(im.tostring()),hashstr(im2.tostring()))
eq_(hashstr(im.tostring('tiff:method=tiled')),hashstr(im2.tostring('tiff:method=tiled')))
# should not be a blank image
eq_(hashstr(im.tostring("tiff")) != hashstr(mapnik.Image(im.width(),im.height(),mapnik.ImageType.gray8).tostring("tiff")),True)
def test_tiff_gray16_compare_scanline():
filepath1 = '../data/tiff/ndvi_256x256_gray16_striped.tif'
filepath2 = '/tmp/mapnik-tiff-gray16-scanline.tiff'
im = mapnik.Image.open(filepath1)
im.save(filepath2,'tiff:method=scanline')
im2 = mapnik.Image.open(filepath2)
eq_(im.width(),im2.width())
eq_(im.height(),im2.height())
eq_(hashstr(im.tostring()),hashstr(im2.tostring()))
eq_(hashstr(im.tostring('tiff:method=scanline')),hashstr(im2.tostring('tiff:method=scanline')))
# should not be a blank image
eq_(hashstr(im.tostring("tiff")) != hashstr(mapnik.Image(im.width(),im.height(),mapnik.ImageType.gray16).tostring("tiff")),True)
def test_tiff_gray16_compare_stripped():
filepath1 = '../data/tiff/ndvi_256x256_gray16_striped.tif'
filepath2 = '/tmp/mapnik-tiff-gray16-stripped.tiff'
im = mapnik.Image.open(filepath1)
im.save(filepath2,'tiff:method=stripped')
im2 = mapnik.Image.open(filepath2)
eq_(im.width(),im2.width())
eq_(im.height(),im2.height())
eq_(hashstr(im.tostring()),hashstr(im2.tostring()))
eq_(hashstr(im.tostring('tiff:method=stripped')),hashstr(im2.tostring('tiff:method=stripped')))
# should not be a blank image
eq_(hashstr(im.tostring("tiff")) != hashstr(mapnik.Image(im.width(),im.height(),mapnik.ImageType.gray16).tostring("tiff")),True)
def test_tiff_gray16_compare_tiled():
filepath1 = '../data/tiff/ndvi_256x256_gray16_striped.tif'
filepath2 = '/tmp/mapnik-tiff-gray16-tiled.tiff'
im = mapnik.Image.open(filepath1)
im.save(filepath2,'tiff:method=tiled')
im2 = mapnik.Image.open(filepath2)
eq_(im.width(),im2.width())
eq_(im.height(),im2.height())
eq_(hashstr(im.tostring()),hashstr(im2.tostring()))
eq_(hashstr(im.tostring('tiff:method=tiled')),hashstr(im2.tostring('tiff:method=tiled')))
# should not be a blank image
eq_(hashstr(im.tostring("tiff")) != hashstr(mapnik.Image(im.width(),im.height(),mapnik.ImageType.gray16).tostring("tiff")),True)
def test_tiff_gray32f_compare_scanline():
filepath1 = '../data/tiff/ndvi_256x256_gray32f_striped.tif'
filepath2 = '/tmp/mapnik-tiff-gray32f-scanline.tiff'
im = mapnik.Image.open(filepath1)
im.save(filepath2,'tiff:method=scanline')
im2 = mapnik.Image.open(filepath2)
eq_(im.width(),im2.width())
eq_(im.height(),im2.height())
eq_(hashstr(im.tostring()),hashstr(im2.tostring()))
eq_(hashstr(im.tostring('tiff:method=scanline')),hashstr(im2.tostring('tiff:method=scanline')))
# should not be a blank image
eq_(hashstr(im.tostring("tiff")) != hashstr(mapnik.Image(im.width(),im.height(),mapnik.ImageType.gray32f).tostring("tiff")),True)
def test_tiff_gray32f_compare_stripped():
filepath1 = '../data/tiff/ndvi_256x256_gray32f_striped.tif'
filepath2 = '/tmp/mapnik-tiff-gray32f-stripped.tiff'
im = mapnik.Image.open(filepath1)
im.save(filepath2,'tiff:method=stripped')
im2 = mapnik.Image.open(filepath2)
eq_(im.width(),im2.width())
eq_(im.height(),im2.height())
eq_(hashstr(im.tostring()),hashstr(im2.tostring()))
eq_(hashstr(im.tostring('tiff:method=stripped')),hashstr(im2.tostring('tiff:method=stripped')))
# should not be a blank image
eq_(hashstr(im.tostring("tiff")) != hashstr(mapnik.Image(im.width(),im.height(),mapnik.ImageType.gray32f).tostring("tiff")),True)
def test_tiff_gray32f_compare_tiled():
filepath1 = '../data/tiff/ndvi_256x256_gray32f_striped.tif'
filepath2 = '/tmp/mapnik-tiff-gray32f-tiled.tiff'
im = mapnik.Image.open(filepath1)
im.save(filepath2,'tiff:method=tiled')
im2 = mapnik.Image.open(filepath2)
eq_(im.width(),im2.width())
eq_(im.height(),im2.height())
eq_(hashstr(im.tostring()),hashstr(im2.tostring()))
eq_(hashstr(im.tostring('tiff:method=tiled')),hashstr(im2.tostring('tiff:method=tiled')))
# should not be a blank image
eq_(hashstr(im.tostring("tiff")) != hashstr(mapnik.Image(im.width(),im.height(),mapnik.ImageType.gray32f).tostring("tiff")),True)
if __name__ == "__main__":
setup()
exit(run_all(eval(x) for x in dir() if x.startswith("test_")))

Binary file not shown.

Before

Width:  |  Height:  |  Size: 899 B

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