Merge branch 'master' into unbuffered_extent

This commit is contained in:
Tom MacWright 2012-01-09 13:13:09 -05:00
commit 1640252b69
127 changed files with 2150 additions and 1718 deletions

View file

@ -14,6 +14,8 @@ For a complete change history, see the SVN log.
Mapnik 2.1.0
------------
- SQLite - Added support for !intersects! token in sql subselects (#809) allow custom positioning of rtree spatial filter.
- New CSV plugin - reads tabular files - autodetecting geo columns, newlines, and delimiters. Uses in-memory featureset for fast rendering and is not designed for large files (#902)
- Fixed bug in shield line placement when dx/dy are used to shift the label relative to the placement point (Matt Amos) (#908)

View file

@ -36,12 +36,17 @@ Build dependencies are:
Mapnik Core depends on:
* Boost >= 1.42.x (>= 1.45.x if using clang++) with these libraries:
- filesystem
- system
- thread (if mapnik threadsafe support is required, default on)
- regex (optionally built with icu regex support)
- program_options (optionally for mapnik command line programs)
* Boost
- >= 1.46 is recommended
- >= 1.45 is required if compiling with clang++
- >= 1.42 works on most systems and most compilers
- >= 1.47 is required to support wkt/wkb geometry output (optional)
- These libraries are required:
- filesystem
- system
- thread (if mapnik threadsafe support is required, default on)
- regex (optionally built with icu regex support)
- program_options (optionally for mapnik command line programs)
* libicuuc >= 4.0 (ideally >= 4.2) - International Components for Unicode
* libpng >= 1.2.x - PNG Graphics

View file

@ -12,6 +12,7 @@ clean:
reset:
if test -e ".sconf_temp/"; then rm -r ".sconf_temp/"; fi
if test -e ".sconsign.dblite"; then rm ".sconsign.dblite"; fi
if test -e "config.cache"; then rm "config.cache"; fi
uninstall:
python scons/scons.py uninstall

View file

@ -424,7 +424,8 @@ pickle_store = [# Scons internal variables
'CAIROMM_LINKFLAGS',
'CAIROMM_CPPPATHS',
'SVG_RENDERER',
'SQLITE_LINKFLAGS'
'SQLITE_LINKFLAGS',
'BOOST_LIB_VERSION_FROM_HEADER'
]
# Add all other user configurable options to pickle pickle_store
@ -1115,10 +1116,7 @@ if not preconfigured:
conf.FindBoost(BOOST_SEARCH_PREFIXES,thread_flag)
boost_lib_version_from_header = conf.GetBoostLibVersion()
if boost_lib_version_from_header:
boost_version_from_header = int(boost_lib_version_from_header.split('_')[1])
env['BOOST_LIB_VERSION_FROM_HEADER'] = conf.GetBoostLibVersion()
# The other required boost headers.
BOOST_LIBSHEADERS = [
@ -1148,7 +1146,7 @@ if not preconfigured:
if not env['BOOST_VERSION']:
env['MISSING_DEPS'].append('boost version >=%s' % BOOST_MIN_VERSION)
else:
color_print(4,'Found boost lib version... %s' % boost_lib_version_from_header )
color_print(4,'Found boost lib version... %s' % env.get('BOOST_LIB_VERSION_FROM_HEADER') )
for count, libinfo in enumerate(BOOST_LIBSHEADERS):
if not conf.CheckLibWithHeader('boost_%s%s' % (libinfo[0],env['BOOST_APPEND']), libinfo[1], 'C++'):
@ -1432,8 +1430,9 @@ if not preconfigured:
env.Append(CXXFLAGS = gcc_cxx_flags + '-O0 -fno-inline %s' % debug_flags)
else:
env.Append(CXXFLAGS = gcc_cxx_flags + '-O%s -finline-functions -Wno-inline -Wno-parentheses -Wno-char-subscripts %s' % (env['OPTIMIZATION'],ndebug_flags))
if env['DEBUG_UNDEFINED']:
env.Append(CXXFLAGS = '-fcatch-undefined-behavior') #-ftrapv -fwrapv
env.Append(CXXFLAGS = '-fcatch-undefined-behavior') #-ftrapv -fwrapv
if 'python' in env['BINDINGS']:
if not os.access(env['PYTHON'], os.X_OK):

View file

@ -41,11 +41,9 @@ def is_py3():
prefix = env['PREFIX']
target_path = os.path.normpath(env['PYTHON_INSTALL_LOCATION'] + os.path.sep + 'mapnik')
target_path_deprecated = os.path.normpath(env['PYTHON_INSTALL_LOCATION'] + os.path.sep + 'mapnik2')
libraries = ['mapnik','png']
if env['JPEG']:
libraries.append('jpeg')
libraries = ['mapnik']
if env['BOOST_PYTHON_LIB']:
libraries.append(env['BOOST_PYTHON_LIB'])
@ -55,11 +53,16 @@ else:
else:
libraries.append('boost_python%s' % env['BOOST_APPEND'])
# TODO - do solaris/fedora need direct linking too?
if env['PLATFORM'] == 'Darwin':
libraries.append(env['ICU_LIB_NAME'])
libraries.append('boost_regex%s' % env['BOOST_APPEND'])
if env['THREADING'] == 'multi':
libraries.append('boost_thread%s' % env['BOOST_APPEND'])
if not env['PYTHON_DYNAMIC_LOOKUP']:
libraries.append('png')
if env['JPEG']:
libraries.append('jpeg')
libraries.append(env['ICU_LIB_NAME'])
libraries.append('boost_regex%s' % env['BOOST_APPEND'])
if env['THREADING'] == 'multi':
libraries.append('boost_thread%s' % env['BOOST_APPEND'])
##### Python linking on OS X is tricky ###
# Confounding problems are:
@ -105,6 +108,7 @@ if env['PLATFORM'] == 'Darwin':
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
@ -121,22 +125,28 @@ else:
paths = '''
"""Configuration paths of Mapnik fonts and input plugins (auto-generated by SCons)."""
import os
from os.path import normpath,join,dirname
mapniklibpath = '%s'
mapniklibpath = normpath(join(dirname(__file__),mapniklibpath))
'''
paths += "inputpluginspath = os.path.normpath(mapniklibpath + '/input')\n"
paths += "inputpluginspath = join(mapniklibpath,'input')\n"
if env['SYSTEM_FONTS']:
paths += "fontscollectionpath = os.path.normpath('%s')" % env['SYSTEM_FONTS']
paths += "fontscollectionpath = normpath('%s')\n" % env['SYSTEM_FONTS']
else:
paths += "fontscollectionpath = os.path.normpath(mapniklibpath + '/fonts')"
paths += "fontscollectionpath = join(mapniklibpath,'fonts')\n"
paths += "__all__ = [mapniklibpath,inputpluginspath,fontscollectionpath]\n"
if not os.path.exists('mapnik'):
os.mkdir('mapnik')
file('mapnik/paths.py','w').write(paths % (env['MAPNIK_LIB_DIR']))
if hasattr(os.path,'relpath'): # python 2.6 and above
file('mapnik/paths.py','w').write(paths % (os.path.relpath(env['MAPNIK_LIB_DIR'],target_path)))
else:
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
@ -152,8 +162,7 @@ if 'install' in COMMAND_LINE_TARGETS:
init_module = env.Install(target_path, init_files)
env.Alias(target='install', source=init_module)
# install mapnik2 module which redirects to mapnik and issues DeprecatedWarning
path = os.path.normpath(env['PYTHON_INSTALL_LOCATION'] + os.path.sep + 'mapnik2')
init_mapnik2 = env.Install(path, 'mapnik2/__init__.py')
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'
@ -204,4 +213,5 @@ if 'uninstall' not in COMMAND_LINE_TARGETS:
env['create_uninstall_target'](env, target_path)
env['create_uninstall_target'](env, target_path_deprecated)

View file

@ -381,7 +381,6 @@ def PostGIS(**keywords):
srid -- specify srid to use (default: auto-detected from geometry_field)
row_limit -- integer limit of rows to return (default: 0)
cursor_size -- integer size of binary cursor to use (default: 0, no binary cursor is used)
multiple_geometries -- boolean, direct the Mapnik wkb reader to interpret as multigeometries (default False)
>>> from mapnik import PostGIS, Layer
>>> params = dict(dbname='mapnik',table='osm',user='postgres',password='gis')
@ -467,7 +466,6 @@ def Occi(**keywords):
encoding -- file encoding (default 'utf-8')
geometry_field -- specify geometry field (default 'GEOLOC')
use_spatial_index -- boolean, force the use of the spatial index (default True)
multiple_geometries -- boolean, direct the Mapnik wkb reader to interpret as multigeometries (default False)
>>> from mapnik import Occi, Layer
>>> params = dict(host='myoracle',user='scott',password='tiger',table='test')
@ -492,7 +490,6 @@ def Ogr(**keywords):
layer_by_sql -- choose layer by sql query number instead of by layer name or index.
base -- path prefix (default None)
encoding -- file encoding (default 'utf-8')
multiple_geometries -- boolean, direct the Mapnik wkb reader to interpret as multigeometries (default False)
>>> from mapnik import Ogr, Layer
>>> datasource = Ogr(base='/home/mapnik/data',file='rivers.geojson',layer='OGRGeoJSON')
@ -520,7 +517,6 @@ def SQLite(**keywords):
row_offset -- specify a custom integer row offset (default 0)
row_limit -- specify a custom integer row limit (default 0)
wkb_format -- specify a wkb type of 'spatialite' (default None)
multiple_geometries -- boolean, direct the Mapnik wkb reader to interpret as multigeometries (default False)
use_spatial_index -- boolean, instruct sqlite plugin to use Rtree spatial index (default True)
>>> from mapnik import SQLite, Layer
@ -601,7 +597,6 @@ def Geos(**keywords):
wkt -- inline WKT text of the geometry
Optional keyword arguments:
multiple_geometries -- boolean, direct the GEOS wkt reader to interpret as multigeometries (default False)
extent -- manually specified data extent (comma delimited string, default None)
>>> from mapnik import Geos, Layer
@ -655,6 +650,7 @@ __all__ = [
'Feature',
'Featureset',
'FontEngine',
'FontSet',
'Geometry2d',
'GlyphSymbolizer',
'Image',

View file

@ -1,3 +0,0 @@
mapniklibpath = '@PACKAGE_LIB_DIR@'
inputpluginspath = mapniklibpath + '/input'
fontscollectionpath = '@SYSTEM_FONTS_DIR@/truetype/ttf-dejavu'

View file

@ -593,7 +593,7 @@ class PDFPrinter:
for l in m.layers:
# extract the layer names for naming layers if we use OCG
self._layer_names.append(l.title or l.name)
self._layer_names.append(l.name)
layer_map = Map(m.width,m.height,m.srs)
layer_map.layers.append(l)
@ -884,7 +884,7 @@ class PDFPrinter:
for l in reversed(m.layers):
have_layer_header = False
added_styles={}
layer_title = l.title or l.name
layer_title = l.name
if layer_title in processed_layers:
continue
processed_layers.append(layer_title)
@ -906,8 +906,8 @@ class PDFPrinter:
if r.filter and str(r.filter) != "true":
if len(rule_text) > 0:
rule_text += " AND "
if r.title:
rule_text += r.title
if r.name:
rule_text += r.name
else:
rule_text += str(r.filter)
active_rules = tuple(active_rules)

View file

@ -87,6 +87,14 @@ void (box2d<double>::*re_center_p2)(coord<double,2> const& ) = &box2d<double>::r
// clip
void (box2d<double>::*clip)(box2d<double> const&) = &box2d<double>::clip;
// deepcopy
box2d<double> box2d_deepcopy(box2d<double> & obj, boost::python::dict memo)
{
// FIXME::ignore memo for now
box2d<double> result(obj);
return result;
}
void export_envelope()
{
using namespace boost::python;
@ -270,5 +278,7 @@ void export_envelope()
.def("__getitem__",&box2d<double>::operator[])
.def("valid",&box2d<double>::valid)
.def_pickle(envelope_pickle_suite())
.def("__deepcopy__", &box2d_deepcopy)
;
}

View file

@ -45,7 +45,7 @@ using mapnik::from_wkt;
void feature_add_geometries_from_wkb(Feature &feature, std::string wkb)
{
geometry_utils::from_wkb(feature.paths(), wkb.c_str(), wkb.size(), true);
geometry_utils::from_wkb(feature.paths(), wkb.c_str(), wkb.size());
}
void feature_add_geometries_from_wkt(Feature &feature, std::string wkt)

View file

@ -0,0 +1,61 @@
/*****************************************************************************
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2011 Artem Pavlenko
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*****************************************************************************/
// boost
#include <boost/python.hpp>
//mapnik
#include <mapnik/font_set.hpp>
using mapnik::font_set;
struct fontset_pickle_suite : boost::python::pickle_suite
{
static boost::python::tuple
getinitargs(const font_set& fs)
{
return boost::python::make_tuple(fs.get_name());
}
};
void export_fontset ()
{
using namespace boost::python;
class_<font_set>("FontSet", init<>("default fontset constructor")
)
.def_pickle(fontset_pickle_suite())
.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

@ -26,13 +26,18 @@
#include <boost/python/manage_new_object.hpp>
#include <boost/python/iterator.hpp>
#include <boost/ptr_container/ptr_vector.hpp>
#include <boost/make_shared.hpp>
// mapnik
#include <mapnik/geometry.hpp>
#include <mapnik/wkt/wkt_factory.hpp>
#include <mapnik/wkb.hpp>
#include <boost/version.hpp>
#if BOOST_VERSION >= 104700
#include <mapnik/util/geometry_to_wkb.hpp>
#include <mapnik/util/geometry_to_wkt.hpp>
#endif
namespace {
@ -57,7 +62,7 @@ void add_wkt_impl(path_type& p, std::string const& wkt)
void add_wkb_impl(path_type& p, std::string const& wkb)
{
mapnik::geometry_utils::from_wkb(p, wkb.c_str(), wkb.size(), true);
mapnik::geometry_utils::from_wkb(p, wkb.c_str(), wkb.size());
}
boost::shared_ptr<path_type> from_wkt_impl(std::string const& wkt)
@ -71,15 +76,23 @@ boost::shared_ptr<path_type> from_wkt_impl(std::string const& wkt)
boost::shared_ptr<path_type> from_wkb_impl(std::string const& wkb)
{
boost::shared_ptr<path_type> paths = boost::make_shared<path_type>();
mapnik::geometry_utils::from_wkb(*paths, wkb.c_str(), wkb.size(), true);
mapnik::geometry_utils::from_wkb(*paths, wkb.c_str(), wkb.size());
return paths;
}
}
PyObject* to_wkb( geometry_type const& geom)
inline std::string boost_version()
{
mapnik::util::wkb_buffer_ptr wkb = mapnik::util::to_wkb(geom,mapnik::util::wkbXDR);
std::ostringstream s;
s << BOOST_VERSION/100000 << "." << BOOST_VERSION/100 % 1000 << "." << BOOST_VERSION % 100;
return s.str();
}
#if BOOST_VERSION >= 104700
PyObject* to_wkb( geometry_type const& geom, mapnik::util::wkbByteOrder byte_order)
{
mapnik::util::wkb_buffer_ptr wkb = mapnik::util::to_wkb(geom,byte_order);
return
#if PY_VERSION_HEX >= 0x03000000
::PyBytes_FromStringAndSize
@ -88,9 +101,39 @@ PyObject* to_wkb( geometry_type const& geom)
#endif
((const char*)wkb->buffer(),wkb->size());
}
#else
PyObject* to_wkb( geometry_type const& geom)
{
throw std::runtime_error("mapnik::to_wkb() requires at least boost 1.47 while your build was compiled against boost "
+ boost_version());
}
#endif
#if BOOST_VERSION >= 104700
PyObject* to_wkb2( path_type const& p, mapnik::util::wkbByteOrder byte_order)
{
mapnik::util::wkb_buffer_ptr wkb = mapnik::util::to_wkb(p,byte_order);
return
#if PY_VERSION_HEX >= 0x03000000
::PyBytes_FromStringAndSize
#else
::PyString_FromStringAndSize
#endif
((const char*)wkb->buffer(),wkb->size());
}
#else
PyObject* to_wkb2( path_type const& p)
{
throw std::runtime_error("mapnik::to_wkb() requires at least boost 1.47 while your build was compiled against boost "
+ boost_version());
}
#endif
std::string to_wkt( geometry_type const& geom)
{
#if BOOST_VERSION >= 104700
std::string wkt; // Use Python String directly ?
bool result = mapnik::util::to_wkt(wkt,geom);
if (!result)
@ -98,8 +141,29 @@ std::string to_wkt( geometry_type const& geom)
throw std::runtime_error("Generate WKT failed");
}
return wkt;
#else
throw std::runtime_error("mapnik::to_wkt() requires at least boost 1.47 while your build was compiled against boost "
+ boost_version());
#endif
}
std::string to_wkt2( path_type const& geom)
{
#if BOOST_VERSION >= 104700
std::string wkt; // Use Python String directly ?
bool result = mapnik::util::to_wkt(wkt,geom);
if (!result)
{
throw std::runtime_error("Generate WKT failed");
}
return wkt;
#else
throw std::runtime_error("mapnik::to_wkt() requires at least boost 1.47 while your build was compiled against boost "
+ boost_version());
#endif
}
void export_geometry()
{
using namespace boost::python;
@ -108,11 +172,15 @@ void export_geometry()
.value("Point",mapnik::Point)
.value("LineString",mapnik::LineString)
.value("Polygon",mapnik::Polygon)
.value("MultiPoint",mapnik::MultiPoint)
.value("MultiLineString",mapnik::MultiLineString)
.value("MultiPolygon",mapnik::MultiPolygon)
;
#if BOOST_VERSION >= 104700
enum_<mapnik::util::wkbByteOrder>("wkbByteOrder")
.value("XDR",mapnik::util::wkbXDR)
.value("NDR",mapnik::util::wkbNDR)
;
#endif
using mapnik::geometry_type;
class_<geometry_type, std::auto_ptr<geometry_type>, boost::noncopyable>("Geometry2d",no_init)
.def("envelope",&geometry_type::envelope)
@ -128,6 +196,8 @@ void export_geometry()
.def("__len__", &path_type::size)
.def("add_wkt",add_wkt_impl)
.def("add_wkb",add_wkb_impl)
.def("to_wkt",&to_wkt2)
.def("to_wkb",&to_wkb2)
.def("from_wkt",from_wkt_impl)
.def("from_wkb",from_wkb_impl)
.staticmethod("from_wkt")

View file

@ -54,7 +54,7 @@ struct layer_pickle_suite : boost::python::pickle_suite
{
s.append(style_names[i]);
}
return boost::python::make_tuple(l.abstract(),l.title(),l.clear_label_cache(),l.getMinZoom(),l.getMaxZoom(),l.isQueryable(),l.datasource()->params(),l.cache_features(),s);
return boost::python::make_tuple(l.clear_label_cache(),l.getMinZoom(),l.getMaxZoom(),l.isQueryable(),l.datasource()->params(),l.cache_features(),s);
}
static void
@ -70,28 +70,24 @@ struct layer_pickle_suite : boost::python::pickle_suite
throw_error_already_set();
}
l.set_abstract(extract<std::string>(state[0]));
l.set_clear_label_cache(extract<bool>(state[0]));
l.set_title(extract<std::string>(state[1]));
l.setMinZoom(extract<double>(state[1]));
l.set_clear_label_cache(extract<bool>(state[2]));
l.setMaxZoom(extract<double>(state[2]));
l.setMinZoom(extract<double>(state[3]));
l.setQueryable(extract<bool>(state[3]));
l.setMaxZoom(extract<double>(state[4]));
l.setQueryable(extract<bool>(state[5]));
mapnik::parameters params = extract<parameters>(state[6]);
mapnik::parameters params = extract<parameters>(state[4]);
l.set_datasource(datasource_cache::instance()->create(params));
boost::python::list s = extract<boost::python::list>(state[7]);
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[8]));
l.set_cache_features(extract<bool>(state[6]));
}
};
@ -152,21 +148,6 @@ void export_layer()
"False\n"
)
.add_property("abstract",
make_function(&layer::abstract,return_value_policy<copy_const_reference>()),
&layer::set_abstract,
"Get/Set the abstract 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.abstract\n"
"'' # default is en empty string\n"
">>> lyr.abstract = 'My Shapefile rendered with Mapnik'\n"
">>> lyr.abstract\n"
"'My Shapefile rendered with Mapnik'\n"
)
.add_property("active",
&layer::isActive,
&layer::setActive,
@ -310,20 +291,5 @@ void export_layer()
"'My Style'\n"
)
.add_property("title",
make_function(&layer::title, return_value_policy<copy_const_reference>()),
&layer::set_title,
"Get/Set the title 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.title\n"
"''\n"
">>> lyr.title = 'My first layer'\n"
">>> lyr.title\n"
"'My first layer'\n"
)
;
}

View file

@ -31,7 +31,7 @@
#include <mapnik/map.hpp>
#include <mapnik/feature_type_style.hpp>
#include <mapnik/metawriter_inmem.hpp>
#include <mapnik/util/deepcopy.hpp>
#include "mapnik_enumeration.hpp"
#include "python_optional.hpp"
@ -122,7 +122,8 @@ std::vector<layer> const& (Map::*layers_const)() const = &Map::layers;
mapnik::parameters& (Map::*attr_nonconst)() = &Map::get_extra_attributes;
mapnik::parameters& (Map::*params_nonconst)() = &Map::get_extra_parameters;
mapnik::feature_type_style find_style (mapnik::Map const& m, std::string const& name)
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)
@ -133,6 +134,17 @@ mapnik::feature_type_style find_style (mapnik::Map const& m, std::string const&
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;
}
bool has_metawriter(mapnik::Map const& m)
{
if (m.metawriters().size() >=1)
@ -175,6 +187,15 @@ mapnik::featureset_ptr query_map_point(mapnik::Map const& m, int index, double x
return m.query_map_point(idx, x, y);
}
// deepcopy
mapnik::Map map_deepcopy(mapnik::Map & m, boost::python::dict memo)
{
// FIXME: ignore memo for now
mapnik::Map result;
mapnik::util::deepcopy(m, result);
return result;
}
void export_map()
{
@ -193,6 +214,7 @@ void export_map()
;
python_optional<mapnik::color> ();
python_optional<mapnik::box2d<double> > ();
class_<std::vector<layer> >("Layers")
.def(vector_indexing_suite<std::vector<layer> >())
;
@ -229,6 +251,11 @@ void export_map()
"False # you can only append styles with unique names\n"
)
.def("append_fontset",&Map::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"
@ -261,9 +288,14 @@ void export_map()
"...'maxy', 'minx', 'miny', 'width'\n"
)
.def("find_fontset",find_fontset,
(arg("name")),
"Find a fontset by name."
)
.def("find_style",
find_style,
(arg("style_name")),
(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"
@ -452,6 +484,7 @@ void export_map()
"about the hit areas rendered on the map.\n"
)
.def("__deepcopy__",&map_deepcopy)
.add_property("extra_attributes",make_function(attr_nonconst,return_value_policy<reference_existing_object>()),"TODO")
.add_property("parameters",make_function(params_nonconst,return_value_policy<reference_existing_object>()),"TODO")

View file

@ -144,7 +144,7 @@ mapnik::parameter get_params_by_index(mapnik::parameters const& p, int index)
parameters::const_iterator end = p.end();
unsigned idx = 0;
while (itr != p.end())
while (itr != end)
{
if (idx == index)
{

View file

@ -47,6 +47,7 @@ void export_style();
void export_stroke();
void export_feature();
void export_featureset();
void export_fontset();
void export_datasource();
void export_datasource_cache();
void export_symbolizer();
@ -397,6 +398,7 @@ BOOST_PYTHON_MODULE(_mapnik)
export_geometry();
export_feature();
export_featureset();
export_fontset();
export_datasource();
export_parameters();
export_color();

View file

@ -86,7 +86,7 @@ struct rule_pickle_suite : boost::python::pickle_suite
static boost::python::tuple
getinitargs(const rule& r)
{
return boost::python::make_tuple(r.get_name(),r.get_title(),r.get_min_scale(),r.get_max_scale());
return boost::python::make_tuple(r.get_name(),r.get_min_scale(),r.get_max_scale());
}
static boost::python::tuple
@ -102,7 +102,7 @@ struct rule_pickle_suite : boost::python::pickle_suite
// We serialize filter expressions AST as strings
std::string filter_expr = to_expression_string(*r.get_filter());
return boost::python::make_tuple(r.get_abstract(),filter_expr,r.has_else_filter(),r.has_also_filter(),syms);
return boost::python::make_tuple(filter_expr,r.has_else_filter(),r.has_also_filter(),syms);
}
static void
@ -119,11 +119,6 @@ struct rule_pickle_suite : boost::python::pickle_suite
}
if (state[0])
{
r.set_title(extract<std::string>(state[0]));
}
if (state[1])
{
rule dfl;
std::string filter = extract<std::string>(state[1]);
@ -134,12 +129,12 @@ struct rule_pickle_suite : boost::python::pickle_suite
}
}
if (state[2])
if (state[1])
{
r.set_else(true);
}
if (state[3])
if (state[2])
{
r.set_also(true);
}
@ -176,18 +171,12 @@ void export_rule()
class_<rule>("Rule",init<>("default constructor"))
.def(init<std::string const&,
boost::python::optional<std::string const&,double,double> >())
boost::python::optional<double,double> >())
.def_pickle(rule_pickle_suite())
.add_property("name",make_function
(&rule::get_name,
return_value_policy<copy_const_reference>()),
&rule::set_name)
.add_property("title",make_function
(&rule::get_title,return_value_policy<copy_const_reference>()),
&rule::set_title)
.add_property("abstract",make_function
(&rule::get_abstract,return_value_policy<copy_const_reference>()),
&rule::set_abstract)
.add_property("filter",make_function
(&rule::get_filter,return_value_policy<copy_const_reference>()),
&rule::set_filter)

View file

@ -213,6 +213,12 @@ struct symbolizer_attributes : public boost::static_visitor<>
void operator () (building_symbolizer const& sym)
{
expression_ptr const& height_expr = sym.height();
if (height_expr)
{
expression_attributes f_attr(names_);
boost::apply_visitor(f_attr,*height_expr);
}
collect_metawriter(sym);
}
// TODO - support remaining syms

View file

@ -23,8 +23,16 @@
#ifndef MAPNIK_FEATURE_STYLE_PROCESSOR_HPP
#define MAPNIK_FEATURE_STYLE_PROCESSOR_HPP
// mapnik
#include <mapnik/map.hpp>
#include <mapnik/projection.hpp>
#include <mapnik/memory_datasource.hpp>
// stl
#include <set>
#include <string>
#include <vector>
namespace mapnik
{
@ -62,11 +70,23 @@ private:
/*!
* @return render a layer given a projection and scale.
*/
void apply_to_layer(layer const& lay, Processor & p,
void apply_to_layer(layer const& lay,
Processor & p,
projection const& proj0,
double scale_denom,
std::set<std::string>& names);
/*!
* @return renders a featureset with the given styles.
*/
void render_style(layer const& lay,
Processor & p,
feature_type_style* style,
std::string const& style_name,
featureset_ptr features,
proj_transform const& prj_trans,
double scale_denom);
Map const& m_;
double scale_factor_;
};

View file

@ -1,5 +1,5 @@
/*****************************************************************************
*
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2011 Artem Pavlenko
@ -23,7 +23,7 @@
#ifndef MAPNIK_FEATURE_TYPE_STYLE_HPP
#define MAPNIK_FEATURE_TYPE_STYLE_HPP
// mapnik
// mapnik
#include <mapnik/rule.hpp>
#include <mapnik/feature.hpp>
#include <mapnik/enumeration.hpp>
@ -43,29 +43,43 @@ enum filter_mode_enum {
DEFINE_ENUM( filter_mode_e, filter_mode_enum );
typedef std::vector<rule> rules;
typedef std::vector<rule*> rule_ptrs;
class MAPNIK_DECL feature_type_style
{
private:
rules rules_;
filter_mode_e filter_mode_;
// The rule_ptrs vectors are only valid for the scale_denom_validity_.
double scale_denom_validity_;
rule_ptrs if_rules_;
rule_ptrs else_rules_;
rule_ptrs also_rules_;
public:
feature_type_style();
feature_type_style(feature_type_style const& rhs, bool deep_copy = false);
feature_type_style& operator=(feature_type_style const& rhs);
void add_rule(rule const& rule);
rules const& get_rules() const;
rule_ptrs const& get_if_rules(double scale_denom);
rule_ptrs const& get_else_rules(double scale_denom);
rule_ptrs const& get_also_rules(double scale_denom);
rules &get_rules_nonconst();
void set_filter_mode(filter_mode_e mode);
filter_mode_e get_filter_mode() const;
~feature_type_style() {}
private:
void update_rule_cache(double scale_denom);
};
}

View file

@ -246,7 +246,7 @@ public:
static bool register_font(std::string const& file_name);
static bool register_fonts(std::string const& dir, bool recurse = false);
static std::vector<std::string> face_names();
static std::map<std::string,std::string> const& get_mapping();
static std::map<std::string,std::pair<int,std::string> > const& get_mapping();
face_ptr create_face(std::string const& family_name);
stroker_ptr create_stroker();
virtual ~freetype_engine();
@ -256,7 +256,7 @@ private:
#ifdef MAPNIK_THREADSAFE
static boost::mutex mutex_;
#endif
static std::map<std::string,std::string> name2file_;
static std::map<std::string,std::pair<int,std::string> > name2file_;
};
template <typename T>

View file

@ -36,29 +36,24 @@ namespace mapnik {
enum eGeomType {
Point = 1,
LineString,
Polygon,
MultiPoint,
MultiLineString,
MultiPolygon
LineString = 2,
Polygon = 3
};
template <typename T, template <typename> class Container=vertex_vector>
class geometry
class geometry : private::boost::noncopyable
{
public:
typedef T coord_type;
typedef Container<coord_type> container_type;
typedef typename container_type::value_type value_type;
private:
container_type cont_;
eGeomType type_;
mutable unsigned itr_;
public:
geometry(eGeomType type)
explicit geometry(eGeomType type)
: type_(type),
itr_(0)
{}
@ -168,12 +163,12 @@ public:
*/
void label_position(double *x, double *y) const
{
if (type_ == LineString || type_ == MultiLineString)
if (type_ == LineString)
{
middle_point(x,y);
return;
}
unsigned size = cont_.size();
if (size < 3)
{
@ -232,7 +227,7 @@ public:
/* summarized distance centroid */
void label_position3(double *x, double *y) const
{
if (type_ == LineString || type_ == MultiLineString)
if (type_ == LineString)
{
middle_point(x,y);
return;
@ -392,7 +387,7 @@ public:
typedef geometry<double,vertex_vector> geometry_type;
typedef boost::shared_ptr<geometry_type> geometry_ptr;
typedef boost::ptr_vector<geometry_type> geometry_containter;
typedef boost::ptr_vector<geometry_type> geometry_container;
}

View file

@ -52,32 +52,13 @@ public:
* @brief Set the name of the layer.
*/
void set_name(std::string const& name);
/*!
* @return the name of the layer.
*/
const std::string& name() const;
/*!
* @brief Set the title of the layer.
*/
void set_title(std::string const& title);
/*!
* @return the title of the layer.
*/
const std::string& title() const;
/*!
* @brief Set the abstract of the layer.
*/
void set_abstract(std::string const& abstract);
/*!
* @return the abstract of the layer.
*/
const std::string& abstract() const;
/*!
* @brief Set the SRS of the layer.
*/
@ -180,6 +161,16 @@ public:
*/
bool cache_features() const;
/*!
* @param group_by Set the field rendering of this layer is grouped by.
*/
void set_group_by(std::string column);
/*!
* @return The field rendering of this layer is grouped by.
*/
std::string group_by() const;
/*!
* @brief Attach a datasource for this layer.
*
@ -202,16 +193,15 @@ private:
void swap(const layer& other);
std::string name_;
std::string title_;
std::string abstract_;
std::string srs_;
double minZoom_;
double maxZoom_;
bool active_;
bool queryable_;
bool clear_label_cache_;
bool cache_features_;
std::string group_by_;
std::vector<std::string> styles_;
datasource_ptr ds_;
};

View file

@ -218,7 +218,7 @@ public:
* @param name The name of the fontset.
* @return The fontset if found. If not found return the default map fontset.
*/
font_set const& find_fontset(std::string const& name) const;
boost::optional<font_set const&> find_fontset(std::string const& name) const;
/*! \brief Get all fontsets
* @return Const reference to fontsets

View file

@ -45,6 +45,7 @@ public:
box2d<double> envelope() const;
layer_descriptor get_descriptor() const;
size_t size() const;
void clear();
private:
std::vector<feature_ptr> features_;
mapnik::layer_descriptor desc_;

View file

@ -26,6 +26,7 @@
// mapnik
#include <mapnik/color.hpp>
#include <mapnik/symbolizer.hpp>
#include <mapnik/filter_factory.hpp>
namespace mapnik
{
@ -79,11 +80,10 @@ struct MAPNIK_DECL building_symbolizer : public symbolizer_base
explicit building_symbolizer()
: symbolizer_base(),
fill_(color(128,128,128)),
height_(0.0),
opacity_(1.0)
{}
building_symbolizer(color const& fill,double height)
building_symbolizer(color const& fill, expression_ptr height)
: symbolizer_base(),
fill_(fill),
height_(height),
@ -97,11 +97,11 @@ struct MAPNIK_DECL building_symbolizer : public symbolizer_base
{
fill_ = fill;
}
double height() const
expression_ptr height() const
{
return height_;
}
void set_height(double height)
void set_height(expression_ptr height)
{
height_=height;
}
@ -115,7 +115,7 @@ struct MAPNIK_DECL building_symbolizer : public symbolizer_base
}
private:
color fill_;
double height_;
expression_ptr height_;
double opacity_;
};
}

View file

@ -39,6 +39,7 @@
#include <mapnik/expression_string.hpp>
// boost
#include <boost/concept_check.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/make_shared.hpp>
#include <boost/variant.hpp>
@ -125,6 +126,8 @@ typedef boost::variant<point_symbolizer,
glyph_symbolizer> symbolizer;
class rule
{
public:
@ -132,19 +135,113 @@ public:
private:
std::string name_;
std::string title_;
std::string abstract_;
double min_scale_;
double max_scale_;
symbolizers syms_;
expression_ptr filter_;
bool else_filter_;
bool also_filter_;
struct deepcopy_symbolizer : public boost::static_visitor<>
{
void operator () (markers_symbolizer & sym) const
{
copy_path_ptr(sym);
}
void operator () (point_symbolizer & sym) const
{
copy_path_ptr(sym);
}
void operator () (polygon_pattern_symbolizer & sym) const
{
copy_path_ptr(sym);
}
void operator () (line_pattern_symbolizer & sym) const
{
copy_path_ptr(sym);
}
void operator () (raster_symbolizer & sym) const
{
raster_colorizer_ptr old_colorizer = sym.get_colorizer();
raster_colorizer_ptr new_colorizer = raster_colorizer_ptr();
new_colorizer->set_stops(old_colorizer->get_stops());
new_colorizer->set_default_mode(old_colorizer->get_default_mode());
new_colorizer->set_default_color(old_colorizer->get_default_color());
new_colorizer->set_epsilon(old_colorizer->get_epsilon());
sym.set_colorizer(new_colorizer);
}
void operator () (text_symbolizer & sym) const
{
copy_text_ptr(sym);
}
void operator () (shield_symbolizer & sym) const
{
copy_path_ptr(sym);
copy_text_ptr(sym);
}
void operator () (building_symbolizer & sym) const
{
copy_height_ptr(sym);
}
template <typename T> void operator () (T &sym) const
{
boost::ignore_unused_variable_warning(sym);
}
private:
template <class T>
void copy_path_ptr(T & sym) const
{
std::string path = path_processor_type::to_string(*sym.get_filename());
sym.set_filename( parse_path(path) );
}
template <class T>
void copy_text_ptr(T & sym) const
{
std::string name = to_expression_string(*sym.get_name());
sym.set_name( parse_expression(name) );
// FIXME - orientation doesn't appear to be initialized in constructor?
//std::string orientation = to_expression_string(*sym->get_orientation());
//sym->set_orientation( parse_expression(orientation) );
float text_size = sym.get_text_size();
position displace = sym.get_displacement();
vertical_alignment_e valign = sym.get_vertical_alignment();
horizontal_alignment_e halign = sym.get_horizontal_alignment();
justify_alignment_e jalign = sym.get_justify_alignment();
text_placements_ptr placements = text_placements_ptr(boost::make_shared<text_placements_dummy>());
sym.set_placement_options( placements );
sym.set_text_size(text_size);
sym.set_displacement(displace);
sym.set_vertical_alignment(valign);
sym.set_horizontal_alignment(halign);
sym.set_justify_alignment(jalign);
}
template <class T>
void copy_height_ptr(T & sym) const
{
std::string height_expr = to_expression_string(sym.height());
sym.set_height(parse_expression(height_expr,"utf8"));
}
};
public:
rule()
: name_(),
title_(),
abstract_(),
min_scale_(0),
max_scale_(std::numeric_limits<double>::infinity()),
syms_(),
@ -153,11 +250,9 @@ public:
also_filter_(false) {}
rule(const std::string& name,
const std::string& title="",
double min_scale_denominator=0,
double max_scale_denominator=std::numeric_limits<double>::infinity())
: name_(name),
title_(title),
min_scale_(min_scale_denominator),
max_scale_(max_scale_denominator),
syms_(),
@ -167,8 +262,6 @@ public:
rule(const rule& rhs, bool deep_copy = false)
: name_(rhs.name_),
title_(rhs.title_),
abstract_(rhs.abstract_),
min_scale_(rhs.min_scale_),
max_scale_(rhs.max_scale_),
syms_(rhs.syms_),
@ -177,48 +270,17 @@ public:
also_filter_(rhs.also_filter_)
{
if (deep_copy) {
//std::string expr = to_expression_string(rhs.filter_);
//filter_ = parse_expression(expr,"utf8");
symbolizers::iterator it = syms_.begin(),
end = syms_.end();
std::string expr = to_expression_string(*filter_);
filter_ = parse_expression(expr,"utf8");
symbolizers::const_iterator it = syms_.begin();
symbolizers::const_iterator end = syms_.end();
// FIXME - metawriter_ptr?
for(; it != end; ++it) {
/*if (polygon_symbolizer *sym = boost::get<polygon_symbolizer>(&(*it))) {
// no shared pointers
} else if (line_symbolizer *sym = boost::get<line_symbolizer>(&(*it))) {
// no shared pointers
} else if (building_symbolizer *sym = boost::get<building_symbolizer>(&(*it))) {
// no shared pointers
}*/
if (markers_symbolizer *sym = boost::get<markers_symbolizer>(&(*it))) {
copy_path_ptr(sym);
} else if (point_symbolizer *sym = boost::get<point_symbolizer>(&(*it))) {
copy_path_ptr(sym);
} else if (polygon_pattern_symbolizer *sym = boost::get<polygon_pattern_symbolizer>(&(*it))) {
copy_path_ptr(sym);
} else if (line_pattern_symbolizer *sym = boost::get<line_pattern_symbolizer>(&(*it))) {
copy_path_ptr(sym);
} else if (raster_symbolizer *sym = boost::get<raster_symbolizer>(&(*it))) {
raster_colorizer_ptr old_colorizer = sym->get_colorizer(),
new_colorizer = raster_colorizer_ptr();
new_colorizer->set_stops( old_colorizer->get_stops());
new_colorizer->set_default_mode( old_colorizer->get_default_mode() );
new_colorizer->set_default_color( old_colorizer->get_default_color() );
new_colorizer->set_epsilon( old_colorizer->get_epsilon() );
sym->set_colorizer(new_colorizer);
} else if (shield_symbolizer *sym = boost::get<shield_symbolizer>(&(*it))) {
copy_path_ptr(sym);
copy_text_ptr(sym);
} else if (text_symbolizer *sym = boost::get<text_symbolizer>(&(*it))) {
copy_text_ptr(sym);
}
for(; it != end; ++it)
{
boost::apply_visitor(deepcopy_symbolizer(),*it);
}
}
}
@ -263,27 +325,7 @@ public:
{
return name_;
}
std::string const& get_title() const
{
return title_;
}
void set_title(std::string const& title)
{
title_=title;
}
void set_abstract(std::string const& abstract)
{
abstract_=abstract;
}
std::string const& get_abstract() const
{
return abstract_;
}
void append(const symbolizer& sym)
{
syms_.push_back(sym);
@ -362,48 +404,13 @@ private:
void swap(rule& rhs) throw()
{
name_=rhs.name_;
title_=rhs.title_;
abstract_=rhs.abstract_;
min_scale_=rhs.min_scale_;
max_scale_=rhs.max_scale_;
syms_=rhs.syms_;
filter_=rhs.filter_;
else_filter_=rhs.else_filter_;
also_filter_=rhs.also_filter_;
}
template <class T>
void copy_path_ptr(T* sym)
{
std::string path = path_processor_type::to_string(*sym->get_filename());
sym->set_filename( parse_path(path) );
}
template <class T>
void copy_text_ptr(T* sym)
{
std::string name = to_expression_string(*sym->get_name());
sym->set_name( parse_expression(name) );
// FIXME - orientation doesn't appear to be initialized in constructor?
//std::string orientation = to_expression_string(*sym->get_orientation());
//sym->set_orientation( parse_expression(orientation) );
float text_size = sym->get_text_size();
position displace = sym->get_displacement();
vertical_alignment_e valign = sym->get_vertical_alignment();
horizontal_alignment_e halign = sym->get_horizontal_alignment();
justify_alignment_e jalign = sym->get_justify_alignment();
text_placements_ptr placements = text_placements_ptr(boost::make_shared<text_placements_dummy>());
sym->set_placement_options( placements );
sym->set_text_size(text_size);
sym->set_displacement(displace);
sym->set_vertical_alignment(valign);
sym->set_horizontal_alignment(halign);
sym->set_justify_alignment(jalign);
}
}
};
}

View file

@ -0,0 +1,37 @@
/*****************************************************************************
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2011 Artem Pavlenko
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*****************************************************************************/
//$Id$
#ifndef MAPNIK_DEEPCOPY_HPP
#define MAPNIK_DEEPCOPY_HPP
#include <mapnik/map.hpp>
namespace mapnik { namespace util {
// poor man deepcopy implementation
void deepcopy(Map const& map_in, Map & map_out);
}}
#endif // MAPNIK_DEEPSOPY_HPP

View file

@ -30,7 +30,6 @@
#include <mapnik/geometry.hpp>
#include <mapnik/util/vertex_iterator.hpp>
#include <mapnik/util/container_adapter.hpp>
// boost
#include <boost/tuple/tuple.hpp>
#include <boost/spirit/include/karma.hpp>
@ -38,6 +37,8 @@
#include <boost/spirit/include/phoenix_operator.hpp>
#include <boost/spirit/include/phoenix_fusion.hpp>
#include <boost/spirit/include/phoenix_function.hpp>
#include <boost/spirit/home/phoenix/statement/if.hpp>
#include <boost/fusion/include/boost_tuple.hpp>
//#define BOOST_SPIRIT_USE_PHOENIX_V3 1
@ -46,20 +47,100 @@ namespace mapnik { namespace util {
namespace karma = boost::spirit::karma;
namespace phoenix = boost::phoenix;
template <typename OutputIterator>
bool generate_svg (OutputIterator sink, mapnik::geometry_type const& geom)
namespace detail {
struct get_type
{
using boost::spirit::karma::double_;
using boost::spirit::karma::uint_;
using boost::spirit::karma::generate;
return generate (sink,
// begin grammar
((&uint_(mapnik::SEG_MOVETO) << 'M' | 'L')
<< " " << double_ << " " << double_) % ' '
// end grammar
, geom);
template <typename T>
struct result { typedef int type; };
int operator() (geometry_type const& geom) const
{
return (int)geom.type();
}
};
struct get_first
{
template <typename T>
struct result { typedef geometry_type::value_type const type; };
geometry_type::value_type const operator() (geometry_type const& geom) const
{
geometry_type::value_type coord;
boost::get<0>(coord) = geom.get_vertex(0,&boost::get<1>(coord),&boost::get<2>(coord));
return coord;
}
};
template <typename T>
struct coordinate_policy : karma::real_policies<T>
{
typedef boost::spirit::karma::real_policies<T> base_type;
static int floatfield(T n) { return base_type::fmtflags::fixed; }
static unsigned precision(T n) { return 6u ;}
};
}
template <typename OutputIterator>
struct svg_generator :
karma::grammar<OutputIterator, geometry_type const& ()>
{
svg_generator()
: svg_generator::base_type(svg)
{
using boost::spirit::karma::uint_;
using boost::spirit::karma::_val;
using boost::spirit::karma::_1;
using boost::spirit::karma::lit;
using boost::spirit::karma::_a;
svg = point | linestring | polygon
;
point = &uint_(mapnik::Point)[_1 = _type(_val)]
<< svg_point [_1 = _first(_val)]
;
svg_point = &uint_
<< lit("cx=\"") << coord_type
<< lit("\" cy=\"") << coord_type
<< lit('\"')
;
linestring = &uint_(mapnik::LineString)[_1 = _type(_val)]
<< svg_path
;
polygon = &uint_(mapnik::Polygon)[_1 = _type(_val)]
<< svg_path
;
svg_path %= ((&uint_(mapnik::SEG_MOVETO) << lit('M')
| &uint_(mapnik::SEG_LINETO) [_a +=1] << karma::string [if_(_a == 1) [_1 = "L" ] ])
<< lit(' ') << coord_type << lit(' ') << coord_type) % lit(' ')
;
}
// rules
karma::rule<OutputIterator, geometry_type const& ()> svg;
karma::rule<OutputIterator, geometry_type const& ()> point;
karma::rule<OutputIterator, geometry_type const& ()> linestring;
karma::rule<OutputIterator, geometry_type const& ()> polygon;
karma::rule<OutputIterator, geometry_type::value_type ()> svg_point;
karma::rule<OutputIterator, karma::locals<unsigned>, geometry_type const& ()> svg_path;
// phoenix functions
phoenix::function<detail::get_type > _type;
phoenix::function<detail::get_first> _first;
//
karma::real_generator<double, detail::coordinate_policy<double> > coord_type;
};
}}
#endif // MAPNIK_GEOMETRY_SVG_GENERATOR_HPP

View file

@ -1,5 +1,5 @@
/*****************************************************************************
*
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2011 Artem Pavlenko
@ -61,11 +61,11 @@ enum wkbByteOrder {
};
inline void reverse_bytes(char size, char *address)
inline void reverse_bytes(char size, char *address)
{
char * first = address;
char * last = first + size - 1;
for(;first < last;++first, --last)
for(;first < last;++first, --last)
{
char x = *last;
*last = *first;
@ -80,7 +80,7 @@ inline void write (S & stream, T val, std::size_t size, wkbByteOrder byte_order)
bool need_swap = byte_order ? wkbNDR : wkbXDR;
#else
bool need_swap = byte_order ? wkbXDR : wkbNDR;
#endif
#endif
char* buf = reinterpret_cast<char*>(&val);
if (need_swap)
{
@ -95,22 +95,22 @@ struct wkb_buffer
: size_(size),
data_( (size_!=0) ? static_cast<char*>(::operator new (size_)):0)
{}
~wkb_buffer()
{
::operator delete(data_);
}
inline std::size_t size() const
{
return size_;
}
inline char* buffer()
inline char* buffer()
{
return data_;
}
std::size_t size_;
char * data_;
};
@ -120,10 +120,10 @@ typedef boost::shared_ptr<wkb_buffer> wkb_buffer_ptr;
wkb_buffer_ptr to_point_wkb( geometry_type const& g, wkbByteOrder byte_order)
{
assert(g.num_points() == 1);
std::size_t size = 1 + 4 + 8*2 ; // byteOrder + wkbType + Point
std::size_t size = 1 + 4 + 8*2 ; // byteOrder + wkbType + Point
wkb_buffer_ptr wkb = boost::make_shared<wkb_buffer>(size);
boost::interprocess::bufferstream ss(wkb->buffer(), wkb->size(), std::ios::out | std::ios::binary);
ss.write(reinterpret_cast<char*>(&byte_order),1);
ss.write(reinterpret_cast<char*>(&byte_order),1);
int type = static_cast<int>(mapnik::Point);
write(ss,type,4,byte_order);
double x,y;
@ -138,10 +138,10 @@ wkb_buffer_ptr to_line_string_wkb( geometry_type const& g, wkbByteOrder byte_ord
{
unsigned num_points = g.num_points();
assert(num_points > 1);
std::size_t size = 1 + 4 + 4 + 8*2*num_points ; // byteOrder + wkbType + numPoints + Point*numPoints
std::size_t size = 1 + 4 + 4 + 8*2*num_points ; // byteOrder + wkbType + numPoints + Point*numPoints
wkb_buffer_ptr wkb = boost::make_shared<wkb_buffer>(size);
boost::interprocess::bufferstream ss(wkb->buffer(), wkb->size(), std::ios::out | std::ios::binary);
ss.write(reinterpret_cast<char*>(&byte_order),1);
ss.write(reinterpret_cast<char*>(&byte_order),1);
int type = static_cast<int>(mapnik::LineString);
write(ss,type,4,byte_order);
write(ss,num_points,4,byte_order);
@ -164,29 +164,29 @@ wkb_buffer_ptr to_polygon_wkb( geometry_type const& g, wkbByteOrder byte_order)
typedef std::pair<double,double> point_type;
typedef std::vector<point_type> linear_ring;
boost::ptr_vector<linear_ring> rings;
double x,y;
std::size_t size = 1 + 4 + 4 ; // byteOrder + wkbType + numRings
for (unsigned i=0; i< num_points; ++i)
{
unsigned command = g.get_vertex(i,&x,&y);
if (command == SEG_MOVETO)
{
if (command == SEG_MOVETO)
{
rings.push_back(new linear_ring); // start new loop
size += 4; // num_points
}
rings.back().push_back(std::make_pair(x,y));
size += 2 * 8; // point
size += 2 * 8; // point
}
unsigned num_rings = rings.size();
wkb_buffer_ptr wkb = boost::make_shared<wkb_buffer>(size);
boost::interprocess::bufferstream ss(wkb->buffer(), wkb->size(), std::ios::out | std::ios::binary);
ss.write(reinterpret_cast<char*>(&byte_order),1);
ss.write(reinterpret_cast<char*>(&byte_order),1);
int type = static_cast<int>(mapnik::Polygon);
write(ss,type,4,byte_order);
write(ss,num_rings,4,byte_order);
BOOST_FOREACH ( linear_ring const& ring, rings)
{
unsigned num_points = ring.size();
@ -199,7 +199,7 @@ wkb_buffer_ptr to_polygon_wkb( geometry_type const& g, wkbByteOrder byte_order)
write(ss,y,8,byte_order);
}
}
assert(ss.good());
return wkb;
}
@ -207,7 +207,7 @@ wkb_buffer_ptr to_polygon_wkb( geometry_type const& g, wkbByteOrder byte_order)
wkb_buffer_ptr to_wkb(geometry_type const& g, wkbByteOrder byte_order )
{
wkb_buffer_ptr wkb;
switch (g.type())
{
case mapnik::Point :
@ -219,16 +219,57 @@ wkb_buffer_ptr to_wkb(geometry_type const& g, wkbByteOrder byte_order )
case mapnik::Polygon:
wkb = to_polygon_wkb(g, byte_order);
break;
case mapnik::MultiPoint:
case mapnik::MultiLineString:
case mapnik::MultiPolygon:
break;
default:
break;
}
return wkb;
}
wkb_buffer_ptr to_wkb(geometry_container const& paths, wkbByteOrder byte_order )
{
if (paths.size() == 1)
{
// single geometry
return to_wkb(paths.front(), byte_order);
}
if (paths.size() > 1)
{
// multi geometry or geometry collection
std::vector<wkb_buffer_ptr> wkb_cont;
bool collection = false;
int multi_type = 0;
size_t multi_size = 1 + 4 + 4;
geometry_container::const_iterator itr = paths.begin();
geometry_container::const_iterator end = paths.end();
for ( ; itr!=end; ++itr)
{
wkb_buffer_ptr wkb = to_wkb(*itr,byte_order);
multi_size += wkb->size();
int type = static_cast<int>(itr->type());
if (multi_type > 0 && multi_type != itr->type())
collection = true;
multi_type = type;
wkb_cont.push_back(wkb);
}
wkb_buffer_ptr multi_wkb = boost::make_shared<wkb_buffer>(multi_size);
boost::interprocess::bufferstream ss(multi_wkb->buffer(), multi_wkb->size(), std::ios::out | std::ios::binary);
ss.write(reinterpret_cast<char*>(&byte_order),1);
multi_type = collection ? 7 : multi_type + 3;
write(ss,multi_type, 4, byte_order);
write(ss,paths.size(),4,byte_order);
BOOST_FOREACH ( wkb_buffer_ptr const& wkb, wkb_cont)
{
ss.write(wkb->buffer(),wkb->size());
}
return multi_wkb;
}
return wkb_buffer_ptr();
}
}}

View file

@ -42,7 +42,16 @@ bool to_wkt(std::string & wkt, mapnik::geometry_type const& geom)
{
typedef std::back_insert_iterator<std::string> sink_type;
sink_type sink(wkt);
wkt_generator<sink_type> generator;
wkt_generator<sink_type> generator(true);
bool result = karma::generate(sink, generator, geom);
return result;
}
bool to_wkt(std::string & wkt, mapnik::geometry_container const& geom)
{
typedef std::back_insert_iterator<std::string> sink_type;
sink_type sink(wkt);
wkt_multi_generator<sink_type> generator;
bool result = karma::generate(sink, generator, geom);
return result;
}

View file

@ -30,7 +30,6 @@
#include <mapnik/geometry.hpp>
#include <mapnik/util/vertex_iterator.hpp>
#include <mapnik/util/container_adapter.hpp>
// boost
#include <boost/tuple/tuple.hpp>
#include <boost/spirit/include/karma.hpp>
@ -44,11 +43,24 @@
//#define BOOST_SPIRIT_USE_PHOENIX_V3 1
namespace boost { namespace spirit { namespace traits {
// make gcc and darwin toolsets happy.
template <>
struct is_container<mapnik::geometry_container>
: mpl::false_
{};
}}}
namespace mapnik { namespace util {
namespace karma = boost::spirit::karma;
namespace phoenix = boost::phoenix;
namespace {
struct get_type
{
template <typename T>
@ -56,7 +68,7 @@ struct get_type
int operator() (geometry_type const& geom) const
{
return (int)geom.type();
return static_cast<int>(geom.type());
}
};
@ -73,20 +85,61 @@ struct get_first
}
};
struct multi_geometry_
{
template <typename T>
struct result { typedef bool type; };
bool operator() (geometry_container const& geom) const
{
return geom.size() > 1 ? true : false;
}
};
struct multi_geometry_type
{
template <typename T>
struct result { typedef boost::tuple<unsigned,bool> type; };
boost::tuple<unsigned,bool> operator() (geometry_container const& geom) const
{
unsigned type = 0u;
bool collection = false;
geometry_container::const_iterator itr = geom.begin();
geometry_container::const_iterator end = geom.end();
for ( ; itr != end; ++itr)
{
if (type != 0 && itr->type() != type)
{
collection = true;
break;
}
type = itr->type();
}
return boost::tuple<unsigned,bool>(type, collection);
}
};
template <typename T>
struct coordinate_policy : karma::real_policies<T>
struct wkt_coordinate_policy : karma::real_policies<T>
{
typedef boost::spirit::karma::real_policies<T> base_type;
static int floatfield(T n) { return base_type::fmtflags::fixed; }
static unsigned precision(T n) { return 6 ;}
};
}
template <typename OutputIterator>
struct wkt_generator :
karma::grammar<OutputIterator, geometry_type const& ()>
{
wkt_generator()
wkt_generator(bool single = false)
: wkt_generator::base_type(wkt)
{
using boost::spirit::karma::uint_;
@ -96,22 +149,27 @@ struct wkt_generator :
using boost::spirit::karma::_a;
using boost::spirit::karma::_r1;
using boost::spirit::karma::eps;
using boost::spirit::karma::string;
wkt = point | linestring | polygon
;
point = &uint_(mapnik::Point)[_1 = _type(_val)]
<< lit("Point(") << point_coord [_1 = _first(_val)] << lit(')')
<< string[ phoenix::if_ (single) [_1 = "Point("]
.else_[_1 = "("]]
<< point_coord [_1 = _first(_val)] << lit(')')
;
linestring = &uint_(mapnik::LineString)[_1 = _type(_val)]
<< lit("LineString(")
<< string[ phoenix::if_ (single) [_1 = "LineString("]
.else_[_1 = "("]]
<< coords
<< lit(')')
;
polygon = &uint_(mapnik::Polygon)[_1 = _type(_val)]
<< lit("Polygon(")
<< string[ phoenix::if_ (single) [_1 = "Polygon("]
.else_[_1 = "("]]
<< coords2
<< lit("))")
;
@ -120,8 +178,8 @@ struct wkt_generator :
;
polygon_coord %= ( &uint_(mapnik::SEG_MOVETO) << eps[_r1 += 1]
<< karma::string[ if_ (_r1 > 1) [_1 = "),("]
.else_[_1 = "("] ] | &uint_ << ",")
<< string[ if_ (_r1 > 1) [_1 = "),("]
.else_[_1 = "("] ] | &uint_ << ",")
<< coord_type
<< lit(' ')
<< coord_type
@ -143,16 +201,69 @@ struct wkt_generator :
karma::rule<OutputIterator, geometry_type const& ()> coords;
karma::rule<OutputIterator, karma::locals<unsigned>, geometry_type const& ()> coords2;
karma::rule<OutputIterator, geometry_type::value_type ()> point_coord;
karma::rule<OutputIterator, geometry_type::value_type const& (unsigned& )> polygon_coord;
karma::rule<OutputIterator, geometry_type::value_type (unsigned& )> polygon_coord;
// phoenix functions
phoenix::function<get_type > _type;
phoenix::function<get_first> _first;
//
karma::real_generator<double, coordinate_policy<double> > coord_type;
karma::real_generator<double, wkt_coordinate_policy<double> > coord_type;
};
template <typename OutputIterator>
struct wkt_multi_generator :
karma::grammar<OutputIterator, karma::locals< boost::tuple<unsigned,bool> >, geometry_container const& ()>
{
wkt_multi_generator()
: wkt_multi_generator::base_type(wkt)
{
using boost::spirit::karma::lit;
using boost::spirit::karma::eps;
using boost::spirit::karma::_val;
using boost::spirit::karma::_1;
using boost::spirit::karma::_a;
geometry_types.add
(mapnik::Point,"Point")
(mapnik::LineString,"LineString")
(mapnik::Polygon,"Polygon")
;
wkt = eps(phoenix::at_c<1>(_a))[_a = _multi_type(_val)]
<< lit("GeometryCollection(") << geometry << lit(")")
| eps(is_multi(_val)) << lit("Multi") << geometry_types[_1 = phoenix::at_c<0>(_a)]
<< "(" << multi_geometry << ")"
| geometry
;
geometry = -(single_geometry % lit(','))
;
single_geometry = geometry_types[_1 = _type(_val)] << path
;
multi_geometry = -(path % lit(','))
;
}
// rules
karma::rule<OutputIterator, karma::locals<boost::tuple<unsigned,bool> >, geometry_container const& ()> wkt;
karma::rule<OutputIterator, geometry_container const& ()> geometry;
karma::rule<OutputIterator, geometry_type const& ()> single_geometry;
karma::rule<OutputIterator, geometry_container const& ()> multi_geometry;
wkt_generator<OutputIterator> path;
// phoenix
phoenix::function<multi_geometry_> is_multi;
phoenix::function<multi_geometry_type> _multi_type;
phoenix::function<get_type > _type;
//
karma::symbols<unsigned, char const*> geometry_types;
};
}}

View file

@ -27,6 +27,8 @@
#include <mapnik/geometry.hpp>
#include <mapnik/ctrans.hpp>
#include <mapnik/feature.hpp>
// boost
#include <boost/utility.hpp>
namespace mapnik
{
@ -49,19 +51,14 @@ enum wkbFormat
wkbSpatiaLite=3
};
class MAPNIK_DECL geometry_utils
class MAPNIK_DECL geometry_utils : private boost::noncopyable
{
public:
static void from_wkb (boost::ptr_vector<geometry_type>& paths,
const char* wkb,
unsigned size,
bool multiple_geometries = false,
wkbFormat format = wkbGeneric);
private:
geometry_utils();
geometry_utils(geometry_utils const&);
geometry_utils& operator=(const geometry_utils&);
};
}

View file

@ -489,10 +489,12 @@ void csv_datasource::parse_csv(T& stream,
std::string::const_iterator str_beg = value.begin();
std::string::const_iterator str_end = value.end();
bool r = qi::phrase_parse(str_beg,str_end,
(
qi::lit("POINT") >> '(' >> double_[ref(x) = _1] >> double_[ref(y) = _1] >> ')'
),
ascii::space);
(
qi::lit("POINT") >> '('
>> double_[ref(x) = _1]
>> double_[ref(y) = _1] >> ')'
),
ascii::space);
if (r && (str_beg == str_end))
{
@ -615,28 +617,27 @@ void csv_datasource::parse_csv(T& stream,
}
}
// add all values as attributes
// here we detect numbers and treat everything else as pure strings
// this is intentional since boolean and null types are not common in csv editors
if (value.empty())
{
UnicodeString ustr = tr.transcode(value.c_str());
boost::put(*feature,fld_name,ustr);
if (feature_count == 1)
{
desc_.add_descriptor(mapnik::attribute_descriptor(fld_name,mapnik::String));
}
}
// only true strings are this long
else if (value_length > 20)
{
UnicodeString ustr = tr.transcode(value.c_str());
boost::put(*feature,fld_name,ustr);
if (feature_count == 1)
{
desc_.add_descriptor(mapnik::attribute_descriptor(fld_name,mapnik::String));
}
// now, add all values as attributes
/* First we detect likely strings, then try parsing likely numbers,
finally falling back to string type
* We intentionally do not try to detect boolean or null types
since they are not common in csv
* Likely strings are either empty values, very long values
or value with leading zeros like 001 (which are not safe
to assume are numbers)
*/
bool has_dot = value.find(".") != std::string::npos;
if (value.empty() ||
(value_length > 20) ||
(value_length > 1 && !has_dot && value[0] == '0'))
{
UnicodeString ustr = tr.transcode(value.c_str());
boost::put(*feature,fld_name,ustr);
if (feature_count == 1)
{
desc_.add_descriptor(mapnik::attribute_descriptor(fld_name,mapnik::String));
}
}
else if ((value[0] >= '0' && value[0] <= '9') || value[0] == '-')
{
@ -646,12 +647,14 @@ void csv_datasource::parse_csv(T& stream,
bool r = qi::phrase_parse(str_beg,str_end,qi::double_,ascii::space,float_val);
if (r && (str_beg == str_end))
{
if (value.find(".") != std::string::npos)
if (has_dot)
{
boost::put(*feature,fld_name,float_val);
if (feature_count == 1)
{
desc_.add_descriptor(mapnik::attribute_descriptor(fld_name,mapnik::Double));
desc_.add_descriptor(
mapnik::attribute_descriptor(
fld_name,mapnik::Double));
}
}
else
@ -660,7 +663,9 @@ void csv_datasource::parse_csv(T& stream,
boost::put(*feature,fld_name,val);
if (feature_count == 1)
{
desc_.add_descriptor(mapnik::attribute_descriptor(fld_name,mapnik::Integer));
desc_.add_descriptor(
mapnik::attribute_descriptor(
fld_name,mapnik::Integer));
}
}
}
@ -671,7 +676,9 @@ void csv_datasource::parse_csv(T& stream,
boost::put(*feature,fld_name,ustr);
if (feature_count == 1)
{
desc_.add_descriptor(mapnik::attribute_descriptor(fld_name,mapnik::String));
desc_.add_descriptor(
mapnik::attribute_descriptor(
fld_name,mapnik::String));
}
}
}
@ -682,7 +689,9 @@ void csv_datasource::parse_csv(T& stream,
boost::put(*feature,fld_name,ustr);
if (feature_count == 1)
{
desc_.add_descriptor(mapnik::attribute_descriptor(fld_name,mapnik::String));
desc_.add_descriptor(
mapnik::attribute_descriptor(
fld_name,mapnik::String));
}
}
}

View file

@ -152,10 +152,15 @@ void gdal_datasource::bind() const
<< tr[4] << "," << tr[5] << std::endl;
#endif
// TODO - We should throw for true non-north up images, but the check
// below is clearly too restrictive.
// https://github.com/mapnik/mapnik/issues/970
/*
if (tr[2] != 0 || tr[4] != 0)
{
throw datasource_exception("GDAL Plugin: only 'north up' images are supported");
}
*/
dx_ = tr[1];
dy_ = tr[5];

View file

@ -97,9 +97,7 @@ geos_datasource::geos_datasource(parameters const& params, bool bind)
boost::optional<std::string> geometry = params.get<std::string>("wkt");
if (! geometry) throw datasource_exception("missing <wkt> parameter");
geometry_string_ = *geometry;
multiple_geometries_ = *params_.get<mapnik::boolean>("multiple_geometries",false);
boost::optional<std::string> ext = params_.get<std::string>("extent");
if (ext) extent_initialized_ = extent_.from_string(*ext);
@ -270,8 +268,7 @@ featureset_ptr geos_datasource::features(query const& q) const
geometry_id_,
geometry_data_,
geometry_data_name_,
desc_.get_encoding(),
multiple_geometries_);
desc_.get_encoding());
}
featureset_ptr geos_datasource::features_at_point(coord2d const& pt) const
@ -290,6 +287,5 @@ featureset_ptr geos_datasource::features_at_point(coord2d const& pt) const
geometry_id_,
geometry_data_,
geometry_data_name_,
desc_.get_encoding(),
multiple_geometries_);
desc_.get_encoding());
}

View file

@ -56,7 +56,6 @@ private:
mutable std::string geometry_data_name_;
mutable int geometry_id_;
std::string geometry_string_;
bool multiple_geometries_;
};
#endif // GEOS_DATASOURCE_HPP

View file

@ -53,15 +53,13 @@ geos_featureset::geos_featureset(GEOSGeometry* geometry,
int identifier,
const std::string& field,
const std::string& field_name,
const std::string& encoding,
bool multiple_geometries)
const std::string& encoding)
: geometry_(geometry),
tr_(new transcoder(encoding)),
extent_(extent),
identifier_(identifier),
field_(field),
field_name_(field_name),
multiple_geometries_(multiple_geometries),
already_rendered_(false)
{
}
@ -120,14 +118,12 @@ feature_ptr geos_featureset::next()
geometry_utils::from_wkb(feature->paths(),
wkb.data(),
wkb.size(),
multiple_geometries_);
wkb.size());
if (field_ != "")
{
boost::put(*feature, field_name_, tr_->transcode(field_.c_str()));
}
return feature;
}
}

View file

@ -44,8 +44,7 @@ public:
int identifier,
const std::string& field,
const std::string& field_name,
const std::string& encoding,
bool multiple_geometries);
const std::string& encoding);
virtual ~geos_featureset();
mapnik::feature_ptr next();
@ -56,7 +55,6 @@ private:
int identifier_;
std::string field_;
std::string field_name_;
bool multiple_geometries_;
bool already_rendered_;
geos_featureset(const geos_featureset&);

View file

@ -50,7 +50,6 @@ private:
const std::list<kismet_network_data>& knd_list_;
boost::scoped_ptr<mapnik::transcoder> tr_;
mapnik::wkbFormat format_;
bool multiple_geometries_;
int feature_id_;
std::list<kismet_network_data>::const_iterator knd_list_it;
mapnik::projection source_;

View file

@ -94,7 +94,6 @@ occi_datasource::occi_datasource(parameters const& params, bool bind)
table_ = *table;
}
multiple_geometries_ = *params_.get<mapnik::boolean>("multiple_geometries",false);
use_spatial_index_ = *params_.get<mapnik::boolean>("use_spatial_index",true);
use_connection_pool_ = *params_.get<mapnik::boolean>("use_connection_pool",true);
@ -559,8 +558,7 @@ featureset_ptr occi_datasource::features(query const& q) const
return boost::make_shared<occi_featureset>(pool_,
conn_,
s.str(),
desc_.get_encoding(),
multiple_geometries_,
desc_.get_encoding(),
use_connection_pool_,
row_prefetch_,
props.size());
@ -642,7 +640,6 @@ featureset_ptr occi_datasource::features_at_point(coord2d const& pt) const
conn_,
s.str(),
desc_.get_encoding(),
multiple_geometries_,
use_connection_pool_,
row_prefetch_,
size);

View file

@ -64,7 +64,6 @@ private:
mutable oracle::occi::StatelessConnectionPool* pool_;
mutable oracle::occi::Connection* conn_;
bool use_connection_pool_;
bool multiple_geometries_;
bool use_spatial_index_;
static const std::string METADATA_TABLE;
};

View file

@ -59,12 +59,10 @@ occi_featureset::occi_featureset(StatelessConnectionPool* pool,
Connection* conn,
std::string const& sqlstring,
std::string const& encoding,
bool multiple_geometries,
bool use_connection_pool,
unsigned prefetch_rows,
unsigned num_attrs)
: tr_(new transcoder(encoding)),
multiple_geometries_(multiple_geometries),
num_attrs_(num_attrs),
feature_id_(1)
{
@ -101,7 +99,7 @@ feature_ptr occi_featureset::next()
boost::scoped_ptr<SDOGeometry> geom(dynamic_cast<SDOGeometry*>(rs_->getObject(1)));
if (geom.get())
{
convert_geometry(geom.get(), feature, multiple_geometries_);
convert_geometry(geom.get(), feature);
}
std::vector<MetaData> listOfColumns = rs_->getColumnListMetaData();
@ -204,7 +202,7 @@ feature_ptr occi_featureset::next()
}
void occi_featureset::convert_geometry(SDOGeometry* geom, feature_ptr feature, bool multiple_geometries)
void occi_featureset::convert_geometry(SDOGeometry* geom, feature_ptr feature)
{
int gtype = (int)geom->getSdo_gtype();
int dimensions = gtype / 1000;
@ -248,16 +246,13 @@ void occi_featureset::convert_geometry(SDOGeometry* geom, feature_ptr feature, b
{
const bool is_single_geom = true;
const bool is_point_type = false;
const bool multiple_geoms = false;
convert_ordinates(feature,
mapnik::LineString,
elem_info,
ordinates,
dimensions,
is_single_geom,
is_point_type,
multiple_geoms);
is_point_type);
}
}
break;
@ -267,16 +262,13 @@ void occi_featureset::convert_geometry(SDOGeometry* geom, feature_ptr feature, b
{
const bool is_single_geom = true;
const bool is_point_type = false;
const bool multiple_geoms = false;
convert_ordinates(feature,
mapnik::Polygon,
elem_info,
ordinates,
dimensions,
is_single_geom,
is_point_type,
multiple_geoms);
is_point_type);
}
}
break;
@ -286,19 +278,15 @@ void occi_featureset::convert_geometry(SDOGeometry* geom, feature_ptr feature, b
{
const bool is_single_geom = false;
const bool is_point_type = true;
const bool multiple_geoms = true;
// Todo - force using true as multiple_geometries until we have proper multipoint handling
// http://trac.mapnik.org/ticket/458
// FIXME :http://trac.mapnik.org/ticket/458
convert_ordinates(feature,
mapnik::Point,
elem_info,
ordinates,
dimensions,
is_single_geom,
is_point_type,
multiple_geoms);
is_point_type);
}
}
break;
@ -315,8 +303,7 @@ void occi_featureset::convert_geometry(SDOGeometry* geom, feature_ptr feature, b
ordinates,
dimensions,
is_single_geom,
is_point_type,
multiple_geometries);
is_point_type);
}
}
break;
@ -333,8 +320,7 @@ void occi_featureset::convert_geometry(SDOGeometry* geom, feature_ptr feature, b
ordinates,
dimensions,
is_single_geom,
is_point_type,
multiple_geometries);
is_point_type);
}
}
@ -352,8 +338,7 @@ void occi_featureset::convert_geometry(SDOGeometry* geom, feature_ptr feature, b
ordinates,
dimensions,
is_single_geom,
is_point_type,
multiple_geometries);
is_point_type);
}
}
break;
@ -374,8 +359,7 @@ void occi_featureset::convert_ordinates(mapnik::feature_ptr feature,
const std::vector<Number>& ordinates,
const int dimensions,
const bool is_single_geom,
const bool is_point_geom,
const bool multiple_geometries)
const bool is_point_geom)
{
const int elem_size = elem_info.size();
const int ord_size = ordinates.size();
@ -388,7 +372,7 @@ void occi_featureset::convert_ordinates(mapnik::feature_ptr feature,
if (! is_single_geom && elem_size > SDO_ELEM_INFO_SIZE)
{
geometry_type* geom = multiple_geometries ? 0 : new geometry_type(geom_type);
geometry_type* geom = new geometry_type(geom_type);
if (geom) geom->set_capacity(ord_size);
for (int i = SDO_ELEM_INFO_SIZE; i < elem_size; i+=3)
@ -444,16 +428,13 @@ void occi_featureset::convert_ordinates(mapnik::feature_ptr feature,
if (is_linear_element)
{
if (multiple_geometries)
if (geom)
{
if (geom)
{
feature->add_geometry(geom);
}
geom = new geometry_type(gtype);
geom->set_capacity((next_offset - 1) - (offset - 1 - dimensions));
feature->add_geometry(geom);
}
geom = new geometry_type(gtype);
geom->set_capacity((next_offset - 1) - (offset - 1 - dimensions));
fill_geometry_type(geom,
offset - 1,

View file

@ -42,7 +42,6 @@ public:
oracle::occi::Connection* conn,
std::string const& sqlstring,
std::string const& encoding,
bool multiple_geometries,
bool use_connection_pool,
unsigned prefetch_rows,
unsigned num_attrs);
@ -50,15 +49,14 @@ public:
mapnik::feature_ptr next();
private:
void convert_geometry (SDOGeometry* geom, mapnik::feature_ptr feature, bool multiple_geometries);
void convert_geometry (SDOGeometry* geom, mapnik::feature_ptr feature);
void convert_ordinates (mapnik::feature_ptr feature,
const mapnik::eGeomType& geom_type,
const std::vector<oracle::occi::Number>& elem_info,
const std::vector<oracle::occi::Number>& ordinates,
const int dimensions,
const bool is_single_geom,
const bool is_point_geom,
const bool multiple_geometries);
const bool is_point_geom);
void fill_geometry_type (mapnik::geometry_type* geom,
const int real_offset,
const int next_offset,
@ -70,7 +68,6 @@ private:
oracle::occi::ResultSet* rs_;
boost::scoped_ptr<mapnik::transcoder> tr_;
const char* fidcolumn_;
bool multiple_geometries_;
unsigned num_attrs_;
mutable int feature_id_;
};

View file

@ -36,57 +36,34 @@ using mapnik::feature_ptr;
using mapnik::geometry_utils;
using mapnik::geometry_type;
void ogr_converter::convert_geometry(OGRGeometry* geom, feature_ptr feature, bool multiple_geometries)
void ogr_converter::convert_geometry(OGRGeometry* geom, feature_ptr feature)
{
// NOTE: wkbFlatten macro in ogr flattens 2.5d types into base 2d type
switch (wkbFlatten(geom->getGeometryType()))
{
case wkbPoint:
convert_point(static_cast<OGRPoint*>(geom), feature);
break;
case wkbMultiPoint:
convert_multipoint(static_cast<OGRMultiPoint*>(geom), feature);
break;
case wkbLinearRing:
convert_linestring(static_cast<OGRLinearRing*>(geom), feature);
break;
case wkbLineString:
convert_linestring(static_cast<OGRLineString*>(geom), feature);
break;
case wkbMultiLineString:
convert_multilinestring(static_cast<OGRMultiLineString*>(geom), feature);
break;
case wkbPolygon:
convert_polygon(static_cast<OGRPolygon*>(geom), feature);
break;
case wkbMultiPoint:
if (multiple_geometries)
{
convert_multipoint_2(static_cast<OGRMultiPoint*>(geom), feature);
}
else
{
// Todo - using convert_multipoint_2 until we have proper multipoint handling in convert_multipoint
// http://trac.mapnik.org/ticket/458
//convert_multipoint(static_cast<OGRMultiPoint*>(geom), feature);
convert_multipoint_2(static_cast<OGRMultiPoint*>(geom), feature);
}
break;
case wkbMultiLineString:
if (multiple_geometries)
{
convert_multilinestring_2(static_cast<OGRMultiLineString*>(geom), feature);
}
else
{
convert_multilinestring(static_cast<OGRMultiLineString*>(geom), feature);
}
break;
case wkbMultiPolygon:
if (multiple_geometries)
{
convert_multipolygon_2(static_cast<OGRMultiPolygon*>(geom), feature);
}
else
{
convert_multipolygon(static_cast<OGRMultiPolygon*>(geom), feature);
}
convert_multipolygon(static_cast<OGRMultiPolygon*>(geom), feature);
break;
case wkbGeometryCollection:
convert_collection(static_cast<OGRGeometryCollection*>(geom), feature, multiple_geometries);
break;
case wkbLinearRing:
convert_linestring(static_cast<OGRLinearRing*>(geom), feature);
convert_collection(static_cast<OGRGeometryCollection*>(geom), feature);
break;
case wkbNone:
case wkbUnknown:
@ -151,22 +128,6 @@ void ogr_converter::convert_polygon(OGRPolygon* geom, feature_ptr feature)
}
void ogr_converter::convert_multipoint(OGRMultiPoint* geom, feature_ptr feature)
{
int num_geometries = geom->getNumGeometries();
geometry_type* point = new geometry_type(mapnik::Point);
for (int i = 0; i < num_geometries; i++)
{
OGRPoint* ogrpoint = static_cast<OGRPoint*>(geom->getGeometryRef(i));
point->move_to(ogrpoint->getX(), ogrpoint->getY());
//Todo - need to accept multiple points per mapnik::Point
}
// Todo - this only gets last point
feature->add_geometry(point);
}
void ogr_converter::convert_multipoint_2(OGRMultiPoint* geom, feature_ptr feature)
{
int num_geometries = geom->getNumGeometries();
for (int i = 0; i < num_geometries; i++)
@ -176,34 +137,6 @@ void ogr_converter::convert_multipoint_2(OGRMultiPoint* geom, feature_ptr featur
}
void ogr_converter::convert_multilinestring(OGRMultiLineString* geom, feature_ptr feature)
{
int num_geometries = geom->getNumGeometries();
int num_points = 0;
for (int i = 0; i < num_geometries; i++)
{
OGRLineString* ls = static_cast<OGRLineString*>(geom->getGeometryRef(i));
num_points += ls->getNumPoints();
}
geometry_type* line = new geometry_type(mapnik::LineString);
line->set_capacity(num_points);
for (int i = 0; i < num_geometries; i++)
{
OGRLineString* ls = static_cast<OGRLineString*>(geom->getGeometryRef(i));
num_points = ls->getNumPoints();
line->move_to(ls->getX(0), ls->getY(0));
for (int i = 1; i < num_points; ++i)
{
line->line_to(ls->getX(i), ls->getY(i));
}
}
feature->add_geometry(line);
}
void ogr_converter::convert_multilinestring_2(OGRMultiLineString* geom, feature_ptr feature)
{
int num_geometries = geom->getNumGeometries();
for (int i = 0; i < num_geometries; i++)
@ -213,52 +146,6 @@ void ogr_converter::convert_multilinestring_2(OGRMultiLineString* geom, feature_
}
void ogr_converter::convert_multipolygon(OGRMultiPolygon* geom, feature_ptr feature)
{
int num_geometries = geom->getNumGeometries();
int capacity = 0;
for (int i = 0; i < num_geometries; i++)
{
OGRPolygon* p = static_cast<OGRPolygon*>(geom->getGeometryRef(i));
OGRLinearRing* exterior = p->getExteriorRing();
capacity += exterior->getNumPoints();
for (int r = 0; r < p->getNumInteriorRings(); r++)
{
OGRLinearRing* interior = p->getInteriorRing(r);
capacity += interior->getNumPoints();
}
}
geometry_type* poly = new geometry_type(mapnik::Polygon);
poly->set_capacity(capacity);
for (int i = 0; i < num_geometries; i++)
{
OGRPolygon* p = static_cast<OGRPolygon*>(geom->getGeometryRef(i));
OGRLinearRing* exterior = p->getExteriorRing();
int num_points = exterior->getNumPoints();
int num_interior = p->getNumInteriorRings();
poly->move_to(exterior->getX(0), exterior->getY(0));
for (int i = 1; i < num_points; ++i)
{
poly->line_to(exterior->getX(i), exterior->getY(i));
}
for (int r = 0; r < num_interior; r++)
{
OGRLinearRing* interior = p->getInteriorRing(r);
num_points = interior->getNumPoints();
poly->move_to(interior->getX(0), interior->getY(0));
for (int i = 1; i < num_points; ++i)
{
poly->line_to(interior->getX(i), interior->getY(i));
}
}
}
feature->add_geometry(poly);
}
void ogr_converter::convert_multipolygon_2(OGRMultiPolygon* geom, feature_ptr feature)
{
int num_geometries = geom->getNumGeometries();
for (int i = 0; i < num_geometries; i++)
@ -267,7 +154,7 @@ void ogr_converter::convert_multipolygon_2(OGRMultiPolygon* geom, feature_ptr fe
}
}
void ogr_converter::convert_collection(OGRGeometryCollection* geom, feature_ptr feature, bool multiple_geometries)
void ogr_converter::convert_collection(OGRGeometryCollection* geom, feature_ptr feature)
{
int num_geometries = geom->getNumGeometries();
for (int i = 0; i < num_geometries; i++)
@ -275,7 +162,7 @@ void ogr_converter::convert_collection(OGRGeometryCollection* geom, feature_ptr
OGRGeometry* g = geom->getGeometryRef(i);
if (g != NULL)
{
convert_geometry(g, feature, multiple_geometries);
convert_geometry(g, feature);
}
}
}

View file

@ -33,17 +33,14 @@ class ogr_converter
{
public:
static void convert_geometry (OGRGeometry* geom, mapnik::feature_ptr feature, bool multiple_geometries);
static void convert_collection (OGRGeometryCollection* geom, mapnik::feature_ptr feature, bool multiple_geometries);
static void convert_geometry (OGRGeometry* geom, mapnik::feature_ptr feature);
static void convert_collection (OGRGeometryCollection* geom, mapnik::feature_ptr feature);
static void convert_point (OGRPoint* geom, mapnik::feature_ptr feature);
static void convert_linestring (OGRLineString* geom, mapnik::feature_ptr feature);
static void convert_polygon (OGRPolygon* geom, mapnik::feature_ptr feature);
static void convert_multipoint (OGRMultiPoint* geom, mapnik::feature_ptr feature);
static void convert_multipoint_2 (OGRMultiPoint* geom, mapnik::feature_ptr feature);
static void convert_multilinestring (OGRMultiLineString* geom, mapnik::feature_ptr feature);
static void convert_multilinestring_2 (OGRMultiLineString* geom, mapnik::feature_ptr feature);
static void convert_multipolygon (OGRMultiPolygon* geom, mapnik::feature_ptr feature);
static void convert_multipolygon_2 (OGRMultiPolygon* geom, mapnik::feature_ptr feature);
};
#endif // OGR_CONVERTER_HPP

View file

@ -66,8 +66,6 @@ ogr_datasource::ogr_datasource(parameters const& params, bool bind)
throw datasource_exception("missing <file> or <string> parameter");
}
multiple_geometries_ = *params.get<mapnik::boolean>("multiple_geometries", false);
if (string)
{
dataset_name_ = *string;
@ -403,16 +401,16 @@ featureset_ptr ogr_datasource::features(query const& q) const
*layer,
filter,
index_name_,
desc_.get_encoding(),
multiple_geometries_));
desc_.get_encoding()
));
}
else
{
return featureset_ptr(new ogr_featureset (*dataset_,
*layer,
q.get_bbox(),
desc_.get_encoding(),
multiple_geometries_));
desc_.get_encoding()
));
}
}
@ -435,8 +433,8 @@ featureset_ptr ogr_datasource::features_at_point(coord2d const& pt) const
*layer,
filter,
index_name_,
desc_.get_encoding(),
multiple_geometries_));
desc_.get_encoding()
));
}
else
{
@ -447,8 +445,8 @@ featureset_ptr ogr_datasource::features_at_point(coord2d const& pt) const
return featureset_ptr(new ogr_featureset (*dataset_,
*layer,
point,
desc_.get_encoding(),
multiple_geometries_));
desc_.get_encoding()
));
}
}

View file

@ -58,7 +58,6 @@ private:
mutable ogr_layer_ptr layer_;
mutable std::string layer_name_;
mutable mapnik::layer_descriptor desc_;
bool multiple_geometries_;
mutable bool indexed_;
};

View file

@ -49,14 +49,12 @@ using mapnik::feature_factory;
ogr_featureset::ogr_featureset(OGRDataSource & dataset,
OGRLayer & layer,
OGRGeometry & extent,
const std::string& encoding,
const bool multiple_geometries)
const std::string& encoding)
: dataset_(dataset),
layer_(layer),
layerdef_(layer.GetLayerDefn()),
tr_(new transcoder(encoding)),
fidcolumn_(layer_.GetFIDColumn ()),
multiple_geometries_(multiple_geometries),
count_(0)
{
layer_.SetSpatialFilter (&extent);
@ -65,14 +63,12 @@ ogr_featureset::ogr_featureset(OGRDataSource & dataset,
ogr_featureset::ogr_featureset(OGRDataSource & dataset,
OGRLayer & layer,
const mapnik::box2d<double> & extent,
const std::string& encoding,
const bool multiple_geometries)
const std::string& encoding)
: dataset_(dataset),
layer_(layer),
layerdef_(layer.GetLayerDefn()),
tr_(new transcoder(encoding)),
fidcolumn_(layer_.GetFIDColumn()),
multiple_geometries_(multiple_geometries),
count_(0)
{
layer_.SetSpatialFilterRect (extent.minx(),
@ -99,7 +95,7 @@ feature_ptr ogr_featureset::next()
OGRGeometry* geom = (*feat)->GetGeometryRef();
if (geom && ! geom->IsEmpty())
{
ogr_converter::convert_geometry(geom, feature, multiple_geometries_);
ogr_converter::convert_geometry(geom, feature);
}
#ifdef MAPNIK_DEBUG
else

View file

@ -40,14 +40,12 @@ public:
ogr_featureset(OGRDataSource & dataset,
OGRLayer & layer,
OGRGeometry & extent,
const std::string& encoding,
const bool multiple_geometries);
const std::string& encoding);
ogr_featureset(OGRDataSource & dataset,
OGRLayer & layer,
const mapnik::box2d<double> & extent,
const std::string& encoding,
const bool multiple_geometries);
const std::string& encoding);
virtual ~ogr_featureset();
mapnik::feature_ptr next();
@ -60,7 +58,6 @@ private:
OGRFeatureDefn* layerdef_;
boost::scoped_ptr<mapnik::transcoder> tr_;
const char* fidcolumn_;
bool multiple_geometries_;
mutable int count_;
};

View file

@ -56,15 +56,13 @@ ogr_index_featureset<filterT>::ogr_index_featureset(OGRDataSource & dataset,
OGRLayer & layer,
const filterT& filter,
const std::string& index_file,
const std::string& encoding,
const bool multiple_geometries)
const std::string& encoding)
: dataset_(dataset),
layer_(layer),
layerdef_(layer.GetLayerDefn()),
filter_(filter),
tr_(new transcoder(encoding)),
fidcolumn_(layer_.GetFIDColumn()),
multiple_geometries_(multiple_geometries)
fidcolumn_(layer_.GetFIDColumn())
{
boost::optional<mapnik::mapped_region_ptr> memory = mapnik::mapped_memory_cache::find(index_file.c_str(),true);
@ -108,7 +106,7 @@ feature_ptr ogr_index_featureset<filterT>::next()
OGRGeometry* geom=(*feat)->GetGeometryRef();
if (geom && !geom->IsEmpty())
{
ogr_converter::convert_geometry (geom, feature, multiple_geometries_);
ogr_converter::convert_geometry (geom, feature);
}
#ifdef MAPNIK_DEBUG
else

View file

@ -36,8 +36,7 @@ public:
OGRLayer& layer,
const filterT& filter,
const std::string& index_file,
const std::string& encoding,
const bool multiple_geometries);
const std::string& encoding);
virtual ~ogr_index_featureset();
mapnik::feature_ptr next();
@ -53,7 +52,6 @@ private:
std::vector<int>::iterator itr_;
boost::scoped_ptr<mapnik::transcoder> tr_;
const char* fidcolumn_;
bool multiple_geometries_;
};
#endif // OGR_INDEX_FEATURESET_HPP

View file

@ -33,15 +33,23 @@ postgis_src = Split(
"""
)
libraries = ['pq']
# clear out and rebuild libs
plugin_env['LIBS'] = ['pq']
# Link Library to Dependencies
libraries.append('mapnik')
libraries.append(env['ICU_LIB_NAME'])
plugin_env['LIBS'].append('mapnik')
plugin_env['LIBS'].append(env['ICU_LIB_NAME'])
if env['THREADING'] == 'multi':
libraries.append('boost_thread%s' % env['BOOST_APPEND'])
plugin_env['LIBS'].append('boost_thread%s' % env['BOOST_APPEND'])
input_plugin = plugin_env.SharedLibrary('../postgis', source=postgis_src, SHLIBPREFIX='', SHLIBSUFFIX='.input', LIBS=libraries, LINKFLAGS=env['CUSTOM_LDFLAGS'])
if env['RUNTIME_LINK'] == 'static':
#cmd = 'pg_config --libs'
#plugin_env.ParseConfig(cmd)
# pg_config does not seem to report correct deps of libpq
# so resort to hardcoding for now
plugin_env['LIBS'].extend(['ldap','pam','ssl','crypto','krb5'])
input_plugin = plugin_env.SharedLibrary('../postgis', source=postgis_src, SHLIBPREFIX='', SHLIBSUFFIX='.input', LINKFLAGS=env['CUSTOM_LDFLAGS'])
# if the plugin links to libmapnik ensure it is built first
Depends(input_plugin, env.subst('../../../src/%s' % env['MAPNIK_LIB_NAME']))

View file

@ -87,8 +87,6 @@ postgis_datasource::postgis_datasource(parameters const& params, bool bind)
{
if (table_.empty()) throw mapnik::datasource_exception("Postgis Plugin: missing <table> parameter");
multiple_geometries_ = *params_.get<mapnik::boolean>("multiple_geometries",false);
boost::optional<std::string> ext = params_.get<std::string>("extent");
if (ext) extent_initialized_ = extent_.from_string(*ext);
@ -517,7 +515,7 @@ featureset_ptr postgis_datasource::features(const query& q) const
unsigned num_attr = props.size();
if (!key_field_.empty())
++num_attr;
return boost::make_shared<postgis_featureset>(rs,desc_.get_encoding(),multiple_geometries_,!key_field_.empty(),num_attr);
return boost::make_shared<postgis_featureset>(rs,desc_.get_encoding(), !key_field_.empty(),num_attr);
}
else
{
@ -585,7 +583,7 @@ featureset_ptr postgis_datasource::features_at_point(coord2d const& pt) const
}
boost::shared_ptr<IResultSet> rs = get_resultset(conn, s.str());
return boost::make_shared<postgis_featureset>(rs,desc_.get_encoding(),multiple_geometries_,!key_field_.empty(),size);
return boost::make_shared<postgis_featureset>(rs,desc_.get_encoding(), !key_field_.empty(),size);
}
}
return featureset_ptr();

View file

@ -69,7 +69,6 @@ class postgis_datasource : public datasource
mutable mapnik::box2d<double> extent_;
mutable layer_descriptor desc_;
ConnectionCreator<Connection> creator_;
bool multiple_geometries_;
const std::string bbox_token_;
const std::string scale_denom_token_;
bool persist_connection_;

View file

@ -49,11 +49,9 @@ using mapnik::feature_factory;
postgis_featureset::postgis_featureset(boost::shared_ptr<IResultSet> const& rs,
std::string const& encoding,
bool multiple_geometries,
bool key_field=false,
unsigned num_attrs=0)
: rs_(rs),
multiple_geometries_(multiple_geometries),
num_attrs_(num_attrs),
tr_(new transcoder(encoding)),
totalGeomSize_(0),
@ -103,7 +101,7 @@ feature_ptr postgis_featureset::next()
// parse geometry
int size = rs_->getFieldLength(0);
const char *data = rs_->getValue(0);
geometry_utils::from_wkb(feature->paths(),data,size,multiple_geometries_);
geometry_utils::from_wkb(feature->paths(), data, size);
totalGeomSize_+=size;
for ( ;pos<num_attrs_+1;++pos)

View file

@ -44,7 +44,6 @@ class postgis_featureset : public mapnik::Featureset
{
private:
boost::shared_ptr<IResultSet> rs_;
bool multiple_geometries_;
unsigned num_attrs_;
boost::scoped_ptr<mapnik::transcoder> tr_;
int totalGeomSize_;
@ -53,7 +52,6 @@ private:
public:
postgis_featureset(boost::shared_ptr<IResultSet> const& rs,
std::string const& encoding,
bool multiple_geometries,
bool key_field,
unsigned num_attrs);
mapnik::feature_ptr next();

View file

@ -248,55 +248,25 @@ feature_ptr shape_featureset<filterT>::next()
}
case shape_io::shape_polyline:
{
geometry_type* line = shape_.read_polyline();
feature->add_geometry(line);
++count_;
break;
}
case shape_io::shape_polylinem:
{
geometry_type* line = shape_.read_polylinem();
feature->add_geometry(line);
++count_;
break;
}
case shape_io::shape_polylinez:
{
geometry_type* line = shape_.read_polylinez();
feature->add_geometry(line);
shape_.read_polyline(feature->paths());
++count_;
break;
}
case shape_io::shape_polygon:
{
geometry_type* poly = shape_.read_polygon();
feature->add_geometry(poly);
++count_;
break;
}
case shape_io::shape_polygonm:
{
geometry_type* poly = shape_.read_polygonm();
feature->add_geometry(poly);
++count_;
break;
}
case shape_io::shape_polygonz:
{
geometry_type* poly = shape_.read_polygonz();
feature->add_geometry(poly);
shape_.read_polygon(feature->paths());
++count_;
break;
}
}
}
feature->set_id(shape_.id_);
if (attr_ids_.size())
{

View file

@ -193,49 +193,18 @@ feature_ptr shape_index_featureset<filterT>::next()
}
case shape_io::shape_polyline:
{
geometry_type* line = shape_.read_polyline();
feature->add_geometry(line);
++count_;
break;
}
case shape_io::shape_polylinem:
{
geometry_type* line = shape_.read_polylinem();
feature->add_geometry(line);
++count_;
break;
}
case shape_io::shape_polylinez:
{
geometry_type* line = shape_.read_polylinez();
feature->add_geometry(line);
shape_.read_polyline(feature->paths());
++count_;
break;
}
case shape_io::shape_polygon:
{
geometry_type* poly = shape_.read_polygon();
feature->add_geometry(poly);
++count_;
break;
}
case shape_io::shape_polygonm:
{
geometry_type* poly = shape_.read_polygonm();
feature->add_geometry(poly);
++count_;
break;
}
case shape_io::shape_polygonz:
{
geometry_type* poly = shape_.read_polygonz();
feature->add_geometry(poly);
shape_.read_polygon(feature->paths());
++count_;
break;
}

View file

@ -106,18 +106,16 @@ dbf_file& shape_io::dbf()
return dbf_;
}
geometry_type* shape_io::read_polyline()
void shape_io::read_polyline(mapnik::geometry_container & geom)
{
shape_file::record_type record(reclength_ * 2 - 36);
shp_.read_record(record);
int num_parts = record.read_ndr_integer();
int num_points = record.read_ndr_integer();
geometry_type* line = new geometry_type(mapnik::LineString);
line->set_capacity(num_points + num_parts);
if (num_parts == 1)
{
line->set_capacity(num_points + 1);
geometry_type* line = new geometry_type(mapnik::LineString);
record.skip(4);
double x = record.read_double();
double y = record.read_double();
@ -128,6 +126,7 @@ geometry_type* shape_io::read_polyline()
y = record.read_double();
line->line_to(x, y);
}
geom.push_back(line);
}
else
{
@ -140,6 +139,7 @@ geometry_type* shape_io::read_polyline()
int start, end;
for (int k = 0; k < num_parts; ++k)
{
geometry_type* line = new geometry_type(mapnik::LineString);
start = parts[k];
if (k == num_parts - 1)
{
@ -160,135 +160,9 @@ geometry_type* shape_io::read_polyline()
y = record.read_double();
line->line_to(x, y);
}
geom.push_back(line);
}
}
return line;
}
geometry_type* shape_io::read_polylinem()
{
shape_file::record_type record(reclength_ * 2 - 36);
shp_.read_record(record);
int num_parts = record.read_ndr_integer();
int num_points = record.read_ndr_integer();
geometry_type* line = new geometry_type(mapnik::LineString);
line->set_capacity(num_points + num_parts);
if (num_parts == 1)
{
record.skip(4);
double x = record.read_double();
double y = record.read_double();
line->move_to(x, y);
for (int i = 1; i < num_points; ++i)
{
x = record.read_double();
y = record.read_double();
line->line_to(x, y);
}
}
else
{
std::vector<int> parts(num_parts);
for (int i = 0; i < num_parts; ++i)
{
parts[i] = record.read_ndr_integer();
}
int start, end;
for (int k = 0; k < num_parts; ++k)
{
start = parts[k];
if (k == num_parts - 1)
{
end = num_points;
}
else
{
end = parts[k + 1];
}
double x = record.read_double();
double y = record.read_double();
line->move_to(x, y);
for (int j = start + 1; j < end; ++j)
{
x = record.read_double();
y = record.read_double();
line->line_to(x, y);
}
}
}
// m-range
//double m0=record.read_double();
//double m1=record.read_double();
//for (int i=0;i<num_points;++i)
//{
// double m=record.read_double();
//}
return line;
}
geometry_type* shape_io::read_polylinez()
{
shape_file::record_type record(reclength_ * 2 - 36);
shp_.read_record(record);
int num_parts = record.read_ndr_integer();
int num_points = record.read_ndr_integer();
geometry_type* line = new geometry_type(mapnik::LineString);
line->set_capacity(num_points + num_parts);
if (num_parts == 1)
{
record.skip(4);
double x = record.read_double();
double y = record.read_double();
line->move_to(x, y);
for (int i = 1; i < num_points; ++i)
{
x = record.read_double();
y = record.read_double();
line->line_to(x, y);
}
}
else
{
std::vector<int> parts(num_parts);
for (int i = 0; i < num_parts; ++i)
{
parts[i] = record.read_ndr_integer();
}
int start, end;
for (int k = 0; k < num_parts; ++k)
{
start = parts[k];
if (k == num_parts - 1)
{
end = num_points;
}
else
{
end = parts[k + 1];
}
double x = record.read_double();
double y = record.read_double();
line->move_to(x, y);
for (int j = start + 1; j < end; ++j)
{
x = record.read_double();
y = record.read_double();
line->line_to(x, y);
}
}
}
// z-range
//double z0=record.read_double();
//double z1=record.read_double();
@ -306,10 +180,9 @@ geometry_type* shape_io::read_polylinez()
// double m=record.read_double();
//}
return line;
}
geometry_type* shape_io::read_polygon()
void shape_io::read_polygon(mapnik::geometry_container & geom)
{
shape_file::record_type record(reclength_ * 2 - 36);
shp_.read_record(record);
@ -317,15 +190,17 @@ geometry_type* shape_io::read_polygon()
int num_parts = record.read_ndr_integer();
int num_points = record.read_ndr_integer();
std::vector<int> parts(num_parts);
geometry_type* poly = new geometry_type(mapnik::Polygon);
poly->set_capacity(num_points + num_parts);
for (int i = 0; i < num_parts; ++i)
{
parts[i] = record.read_ndr_integer();
}
geometry_type* poly = new geometry_type(mapnik::Polygon);
for (int k = 0; k < num_parts; k++)
{
int start = parts[k];
int end;
if (k == num_parts - 1)
@ -339,6 +214,13 @@ geometry_type* shape_io::read_polygon()
double x = record.read_double();
double y = record.read_double();
if (k > 0 && !poly->hit_test(x,y,0))
{
geom.push_back(poly);
poly = new geometry_type(mapnik::Polygon);
}
poly->move_to(x, y);
for (int j=start+1;j<end;j++)
@ -348,100 +230,8 @@ geometry_type* shape_io::read_polygon()
poly->line_to(x, y);
}
}
return poly;
}
geometry_type* shape_io::read_polygonm()
{
shape_file::record_type record(reclength_ * 2 - 36);
shp_.read_record(record);
int num_parts = record.read_ndr_integer();
int num_points = record.read_ndr_integer();
std::vector<int> parts(num_parts);
geometry_type* poly = new geometry_type(mapnik::Polygon);
poly->set_capacity(num_points + num_parts);
for (int i = 0; i < num_parts; ++i)
{
parts[i] = record.read_ndr_integer();
}
for (int k = 0; k < num_parts; k++)
{
int start = parts[k];
int end;
if (k == num_parts - 1)
{
end = num_points;
}
else
{
end = parts[k + 1];
}
double x = record.read_double();
double y = record.read_double();
poly->move_to(x, y);
for (int j = start + 1; j < end; j++)
{
x = record.read_double();
y = record.read_double();
poly->line_to(x, y);
}
}
// m-range
//double m0=record.read_double();
//double m1=record.read_double();
//for (int i=0;i<num_points;++i)
//{
// double m=record.read_double();
//}
return poly;
}
geometry_type* shape_io::read_polygonz()
{
shape_file::record_type record(reclength_ * 2 - 36);
shp_.read_record(record);
int num_parts = record.read_ndr_integer();
int num_points = record.read_ndr_integer();
std::vector<int> parts(num_parts);
geometry_type* poly = new geometry_type(mapnik::Polygon);
poly->set_capacity(num_points + num_parts);
for (int i = 0; i < num_parts; ++i)
{
parts[i] = record.read_ndr_integer();
}
for (int k = 0; k < num_parts; k++)
{
int start = parts[k];
int end;
if (k == num_parts - 1)
{
end = num_points;
}
else
{
end = parts[k + 1];
}
double x = record.read_double();
double y = record.read_double();
poly->move_to(x, y);
for (int j = start + 1; j < end; j++)
{
x = record.read_double();
y = record.read_double();
poly->line_to(x, y);
}
}
geom.push_back(poly);
// z-range
//double z0=record.read_double();
//double z1=record.read_double();
@ -458,6 +248,6 @@ geometry_type* shape_io::read_polygonz()
//{
// double m=record.read_double();
//}
return poly;
}

View file

@ -23,6 +23,8 @@
#ifndef SHAPE_IO_HPP
#define SHAPE_IO_HPP
// mapnik
#include <mapnik/geometry.hpp>
// boost
#include <boost/utility.hpp>
#include <boost/shared_ptr.hpp>
@ -56,9 +58,8 @@ public:
~shape_io();
shape_file& shp();
//shape_file& shx();
dbf_file& dbf();
inline boost::shared_ptr<shape_file>& index()
{
return index_;
@ -72,16 +73,10 @@ public:
void move_to(int id);
int type() const;
const box2d<double>& current_extent() const;
mapnik::geometry_type* read_polyline();
mapnik::geometry_type* read_polylinem();
mapnik::geometry_type* read_polylinez();
mapnik::geometry_type* read_polygon();
mapnik::geometry_type* read_polygonm();
mapnik::geometry_type* read_polygonz();
void read_polyline(mapnik::geometry_container & geom);
void read_polygon(mapnik::geometry_container & geom);
unsigned type_;
shape_file shp_;
//shape_file shx_;
dbf_file dbf_;
boost::shared_ptr<shape_file> index_;
unsigned reclength_;
@ -89,7 +84,6 @@ public:
box2d<double> cur_extent_;
static const std::string SHP;
//static const std::string SHX;
static const std::string DBF;
static const std::string INDEX;
};

View file

@ -62,6 +62,7 @@ sqlite_datasource::sqlite_datasource(parameters const& params, bool bind)
key_field_(*params_.get<std::string>("key_field", "")),
row_offset_(*params_.get<int>("row_offset", 0)),
row_limit_(*params_.get<int>("row_limit", 0)),
intersects_token_("!intersects!"),
desc_(*params_.get<std::string>("type"), *params_.get<std::string>("encoding", "utf-8")),
format_(mapnik::wkbAuto)
{
@ -102,7 +103,6 @@ void sqlite_datasource::bind() const
throw datasource_exception("Sqlite Plugin: " + dataset_name_ + " does not exist");
}
multiple_geometries_ = *params_.get<mapnik::boolean>("multiple_geometries", false);
use_spatial_index_ = *params_.get<mapnik::boolean>("use_spatial_index", true);
// TODO - remove this option once all datasources have an indexing api
@ -186,7 +186,8 @@ void sqlite_datasource::bind() const
if (using_subquery_)
{
std::ostringstream s;
s << "SELECT " << fields_ << " FROM (" << table_ << ") LIMIT 1";
std::string query = populate_tokens(table_);
s << "SELECT " << fields_ << " FROM (" << query << ") LIMIT 1";
found_types_via_subquery = sqlite_utils::detect_types_from_subquery(s.str(),geometry_field_,desc_,dataset_);
}
@ -225,7 +226,12 @@ void sqlite_datasource::bind() const
if (geometry_field_.empty())
{
throw datasource_exception("Sqlite Plugin: cannot detect geometry_field, please supply the name of the geometry_field to use.");
std::ostringstream s;
s << "Sqlite Plugin: unable to detect the column "
<< "containing a valid geometry on table '" << geometry_table_ << "'. "
<< "Please provide a column name by passing the 'geometry_field' option "
<< "or indicate a different spatial table to use by passing the 'geometry_table' option";
throw datasource_exception(s.str());
}
if (index_table_.empty())
@ -302,6 +308,7 @@ void sqlite_datasource::bind() const
{
// TODO - clean this up - reducing arguments
std::string query = populate_tokens(table_);
if (!sqlite_utils::detect_extent(dataset_,
has_spatial_index_,
extent_,
@ -310,7 +317,7 @@ void sqlite_datasource::bind() const
geometry_field_,
geometry_table_,
key_field_,
table_))
query))
{
std::ostringstream s;
s << "Sqlite Plugin: extent could not be determined for table '"
@ -324,6 +331,17 @@ void sqlite_datasource::bind() const
is_bound_ = true;
}
std::string sqlite_datasource::populate_tokens(const std::string& sql) const
{
std::string populated_sql = sql;
if (boost::algorithm::ifind_first(populated_sql, intersects_token_))
{
// replace with dummy comparison that is true
boost::algorithm::ireplace_first(populated_sql, intersects_token_, "1=1");
}
return populated_sql;
}
sqlite_datasource::~sqlite_datasource()
{
}
@ -461,23 +479,21 @@ featureset_ptr sqlite_datasource::features(query const& q) const
s << " FROM ";
std::string query (table_);
std::string query(table_);
if (! key_field_.empty() && has_spatial_index_)
{
std::ostringstream spatial_sql;
spatial_sql << std::setprecision(16);
spatial_sql << " WHERE " << key_field_ << " IN (SELECT pkid FROM " << index_table_;
spatial_sql << " WHERE xmax>=" << e.minx() << " AND xmin<=" << e.maxx() ;
spatial_sql << " AND ymax>=" << e.miny() << " AND ymin<=" << e.maxy() << ")";
if (boost::algorithm::ifind_first(query, "WHERE"))
{
boost::algorithm::ireplace_first(query, "WHERE", spatial_sql.str() + " AND ");
}
else if (boost::algorithm::ifind_first(query, geometry_table_))
{
boost::algorithm::ireplace_first(query, table_, table_ + " " + spatial_sql.str());
}
// TODO - debug warn if fails
sqlite_utils::apply_spatial_filter(query,
e,
table_,
key_field_,
index_table_,
geometry_table_,
intersects_token_); }
else
{
query = populate_tokens(table_);
}
s << query ;
@ -502,7 +518,6 @@ featureset_ptr sqlite_datasource::features(query const& q) const
return boost::make_shared<sqlite_featureset>(rs,
desc_.get_encoding(),
format_,
multiple_geometries_,
using_subquery_);
}
@ -541,19 +556,18 @@ featureset_ptr sqlite_datasource::features_at_point(coord2d const& pt) const
if (! key_field_.empty() && has_spatial_index_)
{
std::ostringstream spatial_sql;
spatial_sql << std::setprecision(16);
spatial_sql << " WHERE " << key_field_ << " IN (SELECT pkid FROM " << index_table_;
spatial_sql << " WHERE xmax>=" << e.minx() << " AND xmin<=" << e.maxx() ;
spatial_sql << " AND ymax>=" << e.miny() << " AND ymin<=" << e.maxy() << ")";
if (boost::algorithm::ifind_first(query, "WHERE"))
{
boost::algorithm::ireplace_first(query, "WHERE", spatial_sql.str() + " AND ");
}
else if (boost::algorithm::ifind_first(query, geometry_table_))
{
boost::algorithm::ireplace_first(query, table_, table_ + " " + spatial_sql.str());
}
// TODO - debug warn if fails
sqlite_utils::apply_spatial_filter(query,
e,
table_,
key_field_,
index_table_,
geometry_table_,
intersects_token_);
}
else
{
query = populate_tokens(table_);
}
s << query ;
@ -577,9 +591,8 @@ featureset_ptr sqlite_datasource::features_at_point(coord2d const& pt) const
return boost::make_shared<sqlite_featureset>(rs,
desc_.get_encoding(),
format_,
multiple_geometries_,
using_subquery_);
}
return featureset_ptr();
}

View file

@ -51,6 +51,11 @@ public:
void bind() const;
private:
// FIXME: remove mutable qualifier from data members
// by factoring out bind() logic out from
// datasource impl !!!
mutable mapnik::box2d<double> extent_;
mutable bool extent_initialized_;
int type_;
@ -65,9 +70,10 @@ private:
mutable std::string key_field_;
mutable int row_offset_;
mutable int row_limit_;
// TODO - also add to postgis.input
const std::string intersects_token_;
mutable mapnik::layer_descriptor desc_;
mutable mapnik::wkbFormat format_;
mutable bool multiple_geometries_;
mutable bool use_spatial_index_;
mutable bool has_spatial_index_;
mutable bool using_subquery_;
@ -76,6 +82,7 @@ private:
// Fill init_statements with any statements
// needed to attach auxillary databases
void parse_attachdb(std::string const& attachdb) const;
std::string populate_tokens(const std::string& sql) const;
};
#endif // MAPNIK_SQLITE_DATASOURCE_HPP

View file

@ -47,12 +47,10 @@ using mapnik::feature_factory;
sqlite_featureset::sqlite_featureset(boost::shared_ptr<sqlite_resultset> rs,
std::string const& encoding,
mapnik::wkbFormat format,
bool multiple_geometries,
bool using_subquery)
: rs_(rs),
tr_(new transcoder(encoding)),
format_(format),
multiple_geometries_(multiple_geometries),
using_subquery_(using_subquery)
{
}
@ -75,8 +73,8 @@ feature_ptr sqlite_featureset::next()
int feature_id = rs_->column_integer(1);
feature_ptr feature(feature_factory::create(feature_id));
geometry_utils::from_wkb(feature->paths(), data, size, multiple_geometries_, format_);
geometry_utils::from_wkb(feature->paths(), data, size, format_);
for (int i = 2; i < rs_->column_count(); ++i)
{
const int type_oid = rs_->column_type(i);

View file

@ -42,7 +42,6 @@ public:
sqlite_featureset(boost::shared_ptr<sqlite_resultset> rs,
std::string const& encoding,
mapnik::wkbFormat format,
bool multiple_geometries,
bool using_subquery);
virtual ~sqlite_featureset();
mapnik::feature_ptr next();
@ -51,7 +50,6 @@ private:
boost::shared_ptr<sqlite_resultset> rs_;
boost::scoped_ptr<mapnik::transcoder> tr_;
mapnik::wkbFormat format_;
bool multiple_geometries_;
bool using_subquery_;
};

View file

@ -108,6 +108,42 @@ public:
//}
}
static bool apply_spatial_filter(std::string & query,
mapnik::box2d<double> const& e,
std::string const& table,
std::string const& key_field,
std::string const& index_table,
std::string const& geometry_table,
std::string const& intersects_token)
{
std::ostringstream spatial_sql;
spatial_sql << std::setprecision(16);
spatial_sql << key_field << " IN (SELECT pkid FROM " << index_table;
spatial_sql << " WHERE xmax>=" << e.minx() << " AND xmin<=" << e.maxx() ;
spatial_sql << " AND ymax>=" << e.miny() << " AND ymin<=" << e.maxy() << ")";
if (boost::algorithm::ifind_first(query, intersects_token))
{
boost::algorithm::ireplace_all(query, intersects_token, spatial_sql.str());
return true;
}
// substitute first WHERE found if not using JOIN
// (because we can't know the WHERE is on the right table)
else if (boost::algorithm::ifind_first(query, "WHERE")
&& !boost::algorithm::ifind_first(query, "JOIN"))
{
std::string replace(" WHERE " + spatial_sql.str() + " AND ");
boost::algorithm::ireplace_first(query, "WHERE", replace);
return true;
}
// fallback to appending spatial filter at end of query
else if (boost::algorithm::ifind_first(query, geometry_table))
{
query = table + " WHERE " + spatial_sql.str();
return true;
}
return false;
}
static void get_tables(boost::shared_ptr<sqlite_connection> ds,
std::vector<std::string> & tables)
{
@ -151,11 +187,11 @@ public:
while (rs->is_valid() && rs->step_next())
{
int size;
const char* data = (const char*) rs->column_blob(0, size);
const char* data = static_cast<const char*>(rs->column_blob(0, size));
if (data)
{
boost::ptr_vector<mapnik::geometry_type> paths;
mapnik::geometry_utils::from_wkb(paths, data, size, false, mapnik::wkbAuto);
mapnik::geometry_utils::from_wkb(paths, data, size, mapnik::wkbAuto);
for (unsigned i=0; i<paths.size(); ++i)
{
mapnik::box2d<double> const& bbox = paths[i].envelope();
@ -241,41 +277,47 @@ public:
if (data)
{
boost::ptr_vector<mapnik::geometry_type> paths;
// TODO - contraint fails if multiple_geometries = true
bool multiple_geometries = false;
mapnik::geometry_utils::from_wkb(paths, data, size, multiple_geometries, mapnik::wkbAuto);
mapnik::geometry_utils::from_wkb(paths, data, size, mapnik::wkbAuto);
mapnik::box2d<double> bbox;
for (unsigned i=0; i<paths.size(); ++i)
{
mapnik::box2d<double> const& bbox = paths[i].envelope();
if (bbox.valid())
if (i==0)
{
ps.bind(bbox);
const int type_oid = rs->column_type(1);
if (type_oid != SQLITE_INTEGER)
{
std::ostringstream error_msg;
error_msg << "Sqlite Plugin: invalid type for key field '"
<< rs->column_name(1) << "' when creating index '" << index_table
<< "' type was: " << type_oid << "";
throw mapnik::datasource_exception(error_msg.str());
}
const sqlite_int64 pkid = rs->column_integer64(1);
ps.bind(pkid);
bbox = paths[i].envelope();
}
else
{
bbox.expand_to_include(paths[i].envelope());
}
}
if (bbox.valid())
{
ps.bind(bbox);
const int type_oid = rs->column_type(1);
if (type_oid != SQLITE_INTEGER)
{
std::ostringstream error_msg;
error_msg << "SQLite Plugin: encountered invalid bbox at '"
<< rs->column_name(1) << "' == " << rs->column_integer64(1);
error_msg << "Sqlite Plugin: invalid type for key field '"
<< rs->column_name(1) << "' when creating index '" << index_table
<< "' type was: " << type_oid << "";
throw mapnik::datasource_exception(error_msg.str());
}
ps.step_next();
one_success = true;
const sqlite_int64 pkid = rs->column_integer64(1);
ps.bind(pkid);
}
else
{
std::ostringstream error_msg;
error_msg << "SQLite Plugin: encountered invalid bbox at '"
<< rs->column_name(1) << "' == " << rs->column_integer64(1);
throw mapnik::datasource_exception(error_msg.str());
}
ps.step_next();
one_success = true;
}
}
}
@ -320,13 +362,11 @@ public:
while (rs->is_valid() && rs->step_next())
{
int size;
const char* data = (const char*) rs->column_blob(0, size);
const char* data = static_cast<const char*>(rs->column_blob(0, size));
if (data)
{
boost::ptr_vector<mapnik::geometry_type> paths;
// TODO - contraint fails if multiple_geometries = true
bool multiple_geometries = false;
mapnik::geometry_utils::from_wkb(paths, data, size, multiple_geometries, mapnik::wkbAuto);
mapnik::geometry_utils::from_wkb(paths, data, size, mapnik::wkbAuto);
for (unsigned i=0; i<paths.size(); ++i)
{
mapnik::box2d<double> const& bbox = paths[i].envelope();
@ -568,6 +608,7 @@ public:
// PRAGMA table_info is used so here we assume the column is a string
// which is a lesser evil than altogether dropping the column
desc.add_descriptor(mapnik::attribute_descriptor(fld_name, mapnik::String));
break;
case SQLITE_BLOB:
if (geometry_field.empty()

View file

@ -25,6 +25,7 @@
#include <mapnik/agg_renderer.hpp>
#include <mapnik/agg_rasterizer.hpp>
#include <mapnik/segment.hpp>
#include <mapnik/expression_evaluator.hpp>
// boost
#include <boost/scoped_ptr.hpp>
@ -66,7 +67,13 @@ void agg_renderer<T>::process(building_symbolizer const& sym,
ras_ptr->reset();
ras_ptr->gamma(agg::gamma_linear());
double height = sym.height() * scale_factor_;
double height = 0.0;
expression_ptr height_expr = sym.height();
if (height_expr)
{
value_type result = boost::apply_visitor(evaluate<Feature,value_type>(feature), *height_expr);
height = result.to_double() * scale_factor_;
}
for (unsigned i=0;i<feature.num_geometries();++i)
{
@ -78,6 +85,8 @@ void agg_renderer<T>::process(building_symbolizer const& sym,
std::deque<segment_t> face_segments;
double x0(0);
double y0(0);
geom.rewind(0);
unsigned cm = geom.vertex(&x0,&y0);
for (unsigned j=1;j<geom.num_points();++j)
{
@ -133,6 +142,7 @@ void agg_renderer<T>::process(building_symbolizer const& sym,
roof->line_to(x,y+height);
}
}
path_type path(t_,*frame,prj_trans);
agg::conv_stroke<path_type> stroke(path);
ras_ptr->add_path(stroke);

View file

@ -62,7 +62,7 @@ void agg_renderer<T>::process(polygon_symbolizer const& sym,
renderer ren(renb);
ras_ptr->reset();
ras_ptr->gamma(agg::gamma_linear(0.0, sym.get_gamma()));
ras_ptr->gamma(agg::gamma_power(sym.get_gamma()));
metawriter_with_properties writer = sym.get_metawriter();
for (unsigned i=0;i<feature.num_geometries();++i)
{

View file

@ -44,7 +44,7 @@ void agg_renderer<T>::process(text_symbolizer const& sym,
if (geom.num_points() == 0) continue; // don't bother with empty geometries
if ((geom.type() == Polygon || geom.type() == MultiPolygon) && sym.get_minimum_path_length() > 0)
if ((geom.type() == Polygon) && sym.get_minimum_path_length() > 0)
{
// TODO - find less costly method than fetching full envelope
box2d<double> gbox = t_.forward(geom.envelope(),prj_trans);

View file

@ -106,6 +106,7 @@ source = Split(
color.cpp
box2d.cpp
datasource_cache.cpp
deepcopy.cpp
expression_string.cpp
filter_factory.cpp
feature_type_style.cpp
@ -193,6 +194,20 @@ if env['RENDERING_STATS']:
else:
source.insert(0,processor_cpp);
if env.get('BOOST_LIB_VERSION_FROM_HEADER'):
boost_version_from_header = int(env['BOOST_LIB_VERSION_FROM_HEADER'].split('_')[1])
if boost_version_from_header < 46:
# avoid ubuntu issue with boost interprocess:
# https://github.com/mapnik/mapnik/issues/1001
env4 = lib_env.Clone()
env4.Append(CXXFLAGS = '-fpermissive')
cpp ='mapped_memory_cache.cpp'
source.remove(cpp)
if env['LINKING'] == 'static':
source.insert(0,env4.StaticObject(cpp))
else:
source.insert(0,env4.SharedObject(cpp))
if env['JPEG']:
source += Split(
"""

View file

@ -779,7 +779,13 @@ void cairo_renderer_base::process(building_symbolizer const& sym,
cairo_context context(context_);
color const& fill = sym.get_fill();
double height = 0.7071 * sym.height(); // height in meters
double height = 0.0;
expression_ptr height_expr = sym.height();
if (height_expr)
{
value_type result = boost::apply_visitor(evaluate<Feature,value_type>(feature), *height_expr);
height = 0.7071 * result.to_double();
}
for (unsigned i = 0; i < feature.num_geometries(); ++i)
{
@ -792,6 +798,8 @@ void cairo_renderer_base::process(building_symbolizer const& sym,
std::deque<segment_t> face_segments;
double x0(0);
double y0(0);
geom.rewind(0);
unsigned cm = geom.vertex(&x0, &y0);
for (unsigned j = 1; j < geom.num_points(); ++j)
@ -842,7 +850,6 @@ void cairo_renderer_base::process(building_symbolizer const& sym,
}
geom.rewind(0);
for (unsigned j = 0; j < geom.num_points(); ++j)
{
double x, y;

127
src/deepcopy.cpp Normal file
View file

@ -0,0 +1,127 @@
/*****************************************************************************
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2011 Artem Pavlenko
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*****************************************************************************/
//$Id$
#include <mapnik/map.hpp>
#include <mapnik/feature.hpp>
#include <mapnik/layer.hpp>
#include <mapnik/rule.hpp>
#include <mapnik/symbolizer.hpp>
#include <mapnik/params.hpp>
#include <mapnik/filter_factory.hpp>
#include <mapnik/datasource_cache.hpp>
#include <mapnik/util/deepcopy.hpp>
// boost
#include <boost/optional.hpp>
#include <boost/foreach.hpp>
namespace mapnik { namespace util {
// poor man's deepcopy implementation
void deepcopy(Map const& map_in, Map & map_out)
{
// * width_(rhs.width_),
// * height_(rhs.height_),
// * srs_(rhs.srs_),
// * buffer_size_(rhs.buffer_size_),
// * background_(rhs.background_),
// * background_image_(rhs.background_image_),
// * styles_(rhs.styles_),
// metawriters_(rhs.metawriters_),
// fontsets_(rhs.fontsets_),
// * layers_(rhs.layers_),
// aspectFixMode_(rhs.aspectFixMode_),
// current_extent_(rhs.current_extent_),
// * maximum_extent_(rhs.maximum_extent_),
// * base_path_(rhs.base_path_),
// extra_attr_(rhs.extra_attr_),
// extra_params_(rhs.extra_params_)
// width, height
map_out.resize(map_in.width(), map_in.height());
// srs
map_out.set_srs(map_in.srs());
// buffer_size
map_out.set_buffer_size(map_in.buffer_size());
// background
boost::optional<color> background = map_in.background();
if (background)
{
map_out.set_background(*background);
}
// background_image
boost::optional<std::string> background_image = map_in.background_image();
if (background_image)
{
map_out.set_background_image(*background_image);
}
// maximum extent
boost::optional<box2d<double> > max_extent = map_in.maximum_extent();
if (max_extent)
{
map_out.set_maximum_extent(*max_extent);
}
// base_path
map_out.set_base_path(map_in.base_path());
// fontsets
typedef std::map<std::string,font_set> fontsets;
BOOST_FOREACH ( fontsets::value_type const& kv,map_in.fontsets())
{
map_out.insert_fontset(kv.first,kv.second);
}
BOOST_FOREACH ( layer const& lyr_in, map_in.layers())
{
layer lyr_out(lyr_in);
datasource_ptr ds_in = lyr_in.datasource();
if (ds_in)
{
parameters p(ds_in->params());
// TODO : re-use datasource extent if already set.
datasource_ptr ds_out = datasource_cache::create(p);
if (ds_out)
{
lyr_out.set_datasource(ds_out);
}
}
map_out.addLayer(lyr_out);
}
typedef std::map<std::string, feature_type_style> style_cont;
typedef style_cont::value_type value_type;
style_cont const& styles = map_in.styles();
BOOST_FOREACH ( value_type const& kv, styles )
{
feature_type_style const& style_in = kv.second;
feature_type_style style_out(style_in,true); // deep copy
map_out.insert_style(kv.first, style_out);
}
}
}}

View file

@ -25,13 +25,10 @@
#include <mapnik/box2d.hpp>
#include <mapnik/datasource.hpp>
#include <mapnik/layer.hpp>
#include <mapnik/map.hpp>
#include <mapnik/attribute_collector.hpp>
#include <mapnik/expression_evaluator.hpp>
#include <mapnik/utils.hpp>
#include <mapnik/projection.hpp>
#include <mapnik/scale_denominator.hpp>
#include <mapnik/memory_datasource.hpp>
#include <mapnik/agg_renderer.hpp>
#include <mapnik/grid/grid_renderer.hpp>
@ -309,65 +306,23 @@ void feature_style_processor<Processor>::apply_to_layer(layer const& lay, Proces
}
}
// push all property names
BOOST_FOREACH(std::string const& name, names)
// Don't even try to do more work if there are no active styles.
if (active_styles.size() > 0)
{
q.add_property_name(name);
}
memory_datasource cache;
bool cache_features = lay.cache_features() && num_styles>1?true:false;
bool first = true;
#if defined(RENDERING_STATS)
int style_index = 0;
if (!active_styles.size() > 0) {
layer_timer.discard();
}
#endif
BOOST_FOREACH (feature_type_style * style, active_styles)
{
#if defined(RENDERING_STATS)
std::string s_name = style_names[style_index];
std::ostringstream s1;
s1 << "rendering style #" << style_index+1
<< " for layer: '" << lay.name() << "' and style '" << s_name << "'";
mapnik::progress_timer style_timer(std::clog, s1.str());
if (!num_styles>1)
style_timer.discard();
style_index++;
#endif
std::vector<rule*> if_rules;
std::vector<rule*> else_rules;
std::vector<rule*> also_rules;
std::vector<rule> const& rules=style->get_rules();
#if defined(RENDERING_STATS)
int feature_count = 0;
int feature_processed_count = 0;
#endif
BOOST_FOREACH(rule const& r, rules)
// push all property names
BOOST_FOREACH(std::string const& name, names)
{
if (r.active(scale_denom))
{
if (r.has_else_filter())
{
else_rules.push_back(const_cast<rule*>(&r));
}
else if (r.has_also_filter())
{
also_rules.push_back(const_cast<rule*>(&r));
}
else
{
if_rules.push_back(const_cast<rule*>(&r));
}
q.add_property_name(name);
}
if ( (ds->type() == datasource::Raster) &&
(ds->params().get<double>("filter_factor",0.0) == 0.0) )
// Update filter_factor for all enabled raster layers.
BOOST_FOREACH (feature_type_style * style, active_styles)
{
BOOST_FOREACH(rule const& r, style->get_rules())
{
if (r.active(scale_denom) &&
ds->type() == datasource::Raster &&
ds->params().get<double>("filter_factor",0.0) == 0.0)
{
rule::symbolizers const& symbols = r.get_symbolizers();
rule::symbolizers::const_iterator symIter = symbols.begin();
@ -383,163 +338,235 @@ void feature_style_processor<Processor>::apply_to_layer(layer const& lay, Proces
}
}
// process features
featureset_ptr fs;
if (first)
// Also query the group by attribute
std::string group_by = lay.group_by();
if (group_by != "")
{
if (cache_features)
first = false;
fs = ds->features(q);
}
else
{
fs = cache.features(q);
q.add_property_name(group_by);
}
if (fs)
bool cache_features = lay.cache_features() && active_styles.size() > 1;
// Render incrementally when the column that we group by
// changes value.
if (group_by != "")
{
feature_ptr feature;
while ((feature = fs->next()))
{
featureset_ptr features = ds->features(q);
if (features) {
// Cache all features into the memory_datasource before rendering.
memory_datasource cache;
feature_ptr feature, prev;
#if defined(RENDERING_STATS)
feature_count++;
bool feat_processed = false;
#endif
while ((feature = features->next()))
{
if (prev && prev->props()[group_by] != feature->props()[group_by])
{
// We're at a value boundary, so render what we have
// up to this point.
int i = 0;
BOOST_FOREACH (feature_type_style * style, active_styles)
{
render_style(lay, p, style, style_names[i++],
cache.features(q), prj_trans, scale_denom);
}
cache.clear();
}
cache.push(feature);
prev = feature;
}
bool do_else=true;
bool do_also=false;
if (cache_features)
int i = 0;
BOOST_FOREACH (feature_type_style * style, active_styles)
{
render_style(lay, p, style, style_names[i++],
cache.features(q), prj_trans, scale_denom);
}
}
}
else if (cache_features)
{
featureset_ptr features = ds->features(q);
if (features) {
// Cache all features into the memory_datasource before rendering.
memory_datasource cache;
feature_ptr feature;
while ((feature = features->next()))
{
cache.push(feature);
}
BOOST_FOREACH(rule * r, if_rules )
int i = 0;
BOOST_FOREACH (feature_type_style * style, active_styles)
{
expression_ptr const& expr=r->get_filter();
value_type result = boost::apply_visitor(evaluate<Feature,value_type>(*feature),*expr);
if (result.to_bool())
{
#if defined(RENDERING_STATS)
feat_processed = true;
#endif
p.painted(true);
do_else=false;
do_also=true;
rule::symbolizers const& symbols = r->get_symbolizers();
// if the underlying renderer is not able to process the complete set of symbolizers,
// process one by one.
#if defined(SVG_RENDERER)
if(!p.process(symbols,*feature,prj_trans))
#endif
{
BOOST_FOREACH (symbolizer const& sym, symbols)
{
boost::apply_visitor(symbol_dispatch(p,*feature,prj_trans),sym);
}
}
if (style->get_filter_mode() == FILTER_FIRST)
{
// Stop iterating over rules and proceed with next feature.
break;
}
}
render_style(lay, p, style, style_names[i++],
cache.features(q), prj_trans, scale_denom);
}
if (do_else)
{
BOOST_FOREACH( rule * r, else_rules )
{
#if defined(RENDERING_STATS)
feat_processed = true;
#endif
p.painted(true);
rule::symbolizers const& symbols = r->get_symbolizers();
// if the underlying renderer is not able to process the complete set of symbolizers,
// process one by one.
#if defined(SVG_RENDERER)
if(!p.process(symbols,*feature,prj_trans))
#endif
{
BOOST_FOREACH (symbolizer const& sym, symbols)
{
boost::apply_visitor(symbol_dispatch(p,*feature,prj_trans),sym);
}
}
}
}
if (do_also)
{
BOOST_FOREACH( rule * r, also_rules )
{
#if defined(RENDERING_STATS)
feat_processed = true;
#endif
p.painted(true);
rule::symbolizers const& symbols = r->get_symbolizers();
// if the underlying renderer is not able to process the complete set of symbolizers,
// process one by one.
#if defined(SVG_RENDERER)
if(!p.process(symbols,*feature,prj_trans))
#endif
{
BOOST_FOREACH (symbolizer const& sym, symbols)
{
boost::apply_visitor(symbol_dispatch(p,*feature,prj_trans),sym);
}
}
}
}
#if defined(RENDERING_STATS)
if (feat_processed)
feature_processed_count++;
#endif
}
#if defined(RENDERING_STATS)
style_timer.stop();
// done with style
std::ostringstream s;
if (feature_count > 0) {
double perc_processed = ((double)feature_processed_count/(double)feature_count)*100.0;
s << "percent rendered: " << perc_processed << "% - " << feature_processed_count
<< " rendered for " << feature_count << " queried for ";
s << std::setw(15 - (int)s.tellp()) << " layer '" << lay.name() << "' and style '" << s_name << "'\n";
} else {
s << "" << std::setw(15) << "- no features returned from query for layer '" << lay.name() << "' and style '" << s_name << "'\n";
}
// We only have a single style and no grouping.
else
{
int i = 0;
BOOST_FOREACH (feature_type_style * style, active_styles)
{
featureset_ptr features = ds->features(q);
if (features) {
render_style(lay, p, style, style_names[i++],
features, prj_trans, scale_denom);
}
}
std::clog << s.str();
#endif
}
#if defined(RENDERING_STATS)
else {
style_timer.discard();
layer_timer.discard();
}
#endif
cache_features = false;
}
#if defined(RENDERING_STATS)
layer_timer.stop();
#endif
p.end_layer_processing(lay);
}
template <typename Processor>
void feature_style_processor<Processor>::render_style(
layer const& lay,
Processor & p,
feature_type_style* style,
std::string const& style_name,
featureset_ptr features,
proj_transform const& prj_trans,
double scale_denom)
{
#if defined(RENDERING_STATS)
std::ostringstream s1;
s1 << "rendering style for layer: '" << lay.name()
<< "' and style '" << style_name << "'";
mapnik::progress_timer style_timer(std::clog, s1.str());
int feature_processed_count = 0;
int feature_count = 0;
#endif
feature_ptr feature;
while ((feature = features->next()))
{
#if defined(RENDERING_STATS)
feature_count++;
bool feat_processed = false;
#endif
bool do_else = true;
bool do_also = false;
BOOST_FOREACH(rule * r, style->get_if_rules(scale_denom) )
{
expression_ptr const& expr=r->get_filter();
value_type result = boost::apply_visitor(evaluate<Feature,value_type>(*feature),*expr);
if (result.to_bool())
{
#if defined(RENDERING_STATS)
feat_processed = true;
#endif
p.painted(true);
do_else=false;
do_also=true;
rule::symbolizers const& symbols = r->get_symbolizers();
// if the underlying renderer is not able to process the complete set of symbolizers,
// process one by one.
#if defined(SVG_RENDERER)
if(!p.process(symbols,*feature,prj_trans))
#endif
{
BOOST_FOREACH (symbolizer const& sym, symbols)
{
boost::apply_visitor(symbol_dispatch(p,*feature,prj_trans),sym);
}
}
if (style->get_filter_mode() == FILTER_FIRST)
{
// Stop iterating over rules and proceed with next feature.
break;
}
}
}
if (do_else)
{
BOOST_FOREACH( rule * r, style->get_else_rules(scale_denom) )
{
#if defined(RENDERING_STATS)
feat_processed = true;
#endif
p.painted(true);
rule::symbolizers const& symbols = r->get_symbolizers();
// if the underlying renderer is not able to process the complete set of symbolizers,
// process one by one.
#if defined(SVG_RENDERER)
if(!p.process(symbols,*feature,prj_trans))
#endif
{
BOOST_FOREACH (symbolizer const& sym, symbols)
{
boost::apply_visitor(symbol_dispatch(p,*feature,prj_trans),sym);
}
}
}
}
if (do_also)
{
BOOST_FOREACH( rule * r, style->get_also_rules(scale_denom) )
{
#if defined(RENDERING_STATS)
feat_processed = true;
#endif
p.painted(true);
rule::symbolizers const& symbols = r->get_symbolizers();
// if the underlying renderer is not able to process the complete set of symbolizers,
// process one by one.
#if defined(SVG_RENDERER)
if(!p.process(symbols,*feature,prj_trans))
#endif
{
BOOST_FOREACH (symbolizer const& sym, symbols)
{
boost::apply_visitor(symbol_dispatch(p,*feature,prj_trans),sym);
}
}
}
}
#if defined(RENDERING_STATS)
if (feat_processed)
feature_processed_count++;
#endif
}
#if defined(RENDERING_STATS)
style_timer.stop();
// done with style
std::ostringstream s;
if (feature_count > 0) {
double perc_processed = ((double)feature_processed_count/(double)feature_count)*100.0;
s << "percent rendered: " << perc_processed << "% - " << feature_processed_count
<< " rendered for " << feature_count << " queried for ";
s << std::setw(15 - (int)s.tellp()) << " layer '" << lay.name() << "' and style '" << s_name << "'\n";
} else {
s << "" << std::setw(15) << "- no features returned from query for layer '" << lay.name() << "' and style '" << s_name << "'\n";
}
std::clog << s.str();
style_timer.discard();
#endif
}
#if defined(HAVE_CAIRO)
template class feature_style_processor<cairo_renderer<Cairo::Context> >;
template class feature_style_processor<cairo_renderer<Cairo::Surface> >;

View file

@ -35,10 +35,12 @@ IMPLEMENT_ENUM( filter_mode_e, filter_mode_strings )
feature_type_style::feature_type_style()
: filter_mode_(FILTER_ALL) {}
: filter_mode_(FILTER_ALL),
scale_denom_validity_(-1) {}
feature_type_style::feature_type_style(feature_type_style const& rhs, bool deep_copy)
: filter_mode_(rhs.filter_mode_)
: filter_mode_(rhs.filter_mode_),
scale_denom_validity_(-1)
{
if (!deep_copy) {
rules_ = rhs.rules_;
@ -55,12 +57,14 @@ feature_type_style& feature_type_style::operator=(feature_type_style const& rhs)
{
if (this == &rhs) return *this;
rules_=rhs.rules_;
scale_denom_validity_ = -1;
return *this;
}
void feature_type_style::add_rule(rule const& rule)
{
rules_.push_back(rule);
scale_denom_validity_ = -1;
}
rules const& feature_type_style::get_rules() const
@ -83,4 +87,60 @@ filter_mode_e feature_type_style::get_filter_mode() const
return filter_mode_;
}
void feature_type_style::update_rule_cache(double scale_denom)
{
if_rules_.clear();
else_rules_.clear();
also_rules_.clear();
BOOST_FOREACH(rule const& r, rules_)
{
if (r.active(scale_denom))
{
if (r.has_else_filter())
{
else_rules_.push_back(const_cast<rule*>(&r));
}
else if (r.has_also_filter())
{
also_rules_.push_back(const_cast<rule*>(&r));
}
else
{
if_rules_.push_back(const_cast<rule*>(&r));
}
}
}
scale_denom_validity_ = scale_denom;
}
rule_ptrs const& feature_type_style::get_if_rules(double scale_denom)
{
if (scale_denom_validity_ != scale_denom)
{
update_rule_cache(scale_denom);
}
return if_rules_;
}
rule_ptrs const& feature_type_style::get_else_rules(double scale_denom)
{
if (scale_denom_validity_ != scale_denom)
{
update_rule_cache(scale_denom);
}
return else_rules_;
}
rule_ptrs const& feature_type_style::get_also_rules(double scale_denom)
{
if (scale_denom_validity_ != scale_denom)
{
update_rule_cache(scale_denom);
}
return also_rules_;
}
}

View file

@ -78,29 +78,36 @@ bool freetype_engine::register_font(std::string const& file_name)
throw std::runtime_error("Failed to initialize FreeType2 library");
}
FT_Face face;
error = FT_New_Face (library,file_name.c_str(),0,&face);
if (error)
{
FT_Done_FreeType(library);
return false;
}
// some fonts can lack names, skip them
// http://www.freetype.org/freetype2/docs/reference/ft2-base_interface.html#FT_FaceRec
if (face->family_name && face->style_name) {
std::string name = std::string(face->family_name) + " " + std::string(face->style_name);
name2file_.insert(std::make_pair(name,file_name));
FT_Done_Face(face);
FT_Done_FreeType(library);
return true;
} else {
FT_Done_Face(face);
FT_Done_FreeType(library);
std::ostringstream s;
s << "Error: unable to load invalid font file which lacks identifiable family and style name: '"
<< file_name << "'";
throw std::runtime_error(s.str());
FT_Face face = 0;
// some font files have multiple fonts in a file
// the count is in the 'root' face library[0]
// see the FT_FaceRec in freetype.h
for ( int i = 0; face == 0 || i < face->num_faces; i++ ) {
// if face is null then this is the first face
error = FT_New_Face (library,file_name.c_str(),i,&face);
if (error)
{
FT_Done_FreeType(library);
return false;
}
// some fonts can lack names, skip them
// http://www.freetype.org/freetype2/docs/reference/ft2-base_interface.html#FT_FaceRec
if (face->family_name && face->style_name) {
std::string name = std::string(face->family_name) + " " + std::string(face->style_name);
name2file_.insert(std::make_pair(name, std::make_pair(i,file_name)));
FT_Done_Face(face);
//FT_Done_FreeType(library);
//return true;
} else {
FT_Done_Face(face);
FT_Done_FreeType(library);
std::ostringstream s;
s << "Error: unable to load invalid font file which lacks identifiable family and style name: '"
<< file_name << "'";
throw std::runtime_error(s.str());
}
}
FT_Done_FreeType(library);
return true;
}
@ -141,7 +148,7 @@ bool freetype_engine::register_fonts(std::string const& dir, bool recurse)
std::vector<std::string> freetype_engine::face_names ()
{
std::vector<std::string> names;
std::map<std::string,std::string>::const_iterator itr;
std::map<std::string,std::pair<int,std::string> >::const_iterator itr;
for (itr = name2file_.begin();itr!=name2file_.end();++itr)
{
names.push_back(itr->first);
@ -149,7 +156,7 @@ std::vector<std::string> freetype_engine::face_names ()
return names;
}
std::map<std::string,std::string> const& freetype_engine::get_mapping()
std::map<std::string,std::pair<int,std::string> > const& freetype_engine::get_mapping()
{
return name2file_;
}
@ -157,15 +164,17 @@ std::map<std::string,std::string> const& freetype_engine::get_mapping()
face_ptr freetype_engine::create_face(std::string const& family_name)
{
std::map<std::string,std::string>::iterator itr;
std::map<std::string, std::pair<int,std::string> >::iterator itr;
itr = name2file_.find(family_name);
if (itr != name2file_.end())
{
FT_Face face;
FT_Error error = FT_New_Face (library_,itr->second.c_str(),0,&face);
FT_Error error = FT_New_Face (library_,
itr->second.second.c_str(),
itr->second.first,
&face);
if (!error)
{
{
return face_ptr (new font_face(face));
}
}
@ -283,5 +292,5 @@ void font_face_set::get_string_info(string_info & info)
#ifdef MAPNIK_THREADSAFE
boost::mutex freetype_engine::mutex_;
#endif
std::map<std::string,std::string> freetype_engine::name2file_;
std::map<std::string,std::pair<int,std::string> > freetype_engine::name2file_;
}

View file

@ -28,6 +28,7 @@
#include <mapnik/grid/grid_pixel.hpp>
#include <mapnik/grid/grid.hpp>
#include <mapnik/segment.hpp>
#include <mapnik/expression_evaluator.hpp>
// boost
#include <boost/scoped_ptr.hpp>
@ -59,7 +60,13 @@ void grid_renderer<T>::process(building_symbolizer const& sym,
ras_ptr->reset();
double height = sym.height() * scale_factor_;
double height = 0.0;
expression_ptr height_expr = sym.height();
if (height_expr)
{
value_type result = boost::apply_visitor(evaluate<Feature,value_type>(feature), *height_expr);
height = result.to_double() * scale_factor_;
}
for (unsigned i=0;i<feature.num_geometries();++i)
{

View file

@ -37,8 +37,6 @@ namespace mapnik
{
layer::layer(std::string const& name, std::string const& srs)
: name_(name),
title_(""),
abstract_(""),
srs_(srs),
minZoom_(0),
maxZoom_(std::numeric_limits<double>::max()),
@ -46,12 +44,11 @@ layer::layer(std::string const& name, std::string const& srs)
queryable_(false),
clear_label_cache_(false),
cache_features_(false),
group_by_(""),
ds_() {}
layer::layer(const layer& rhs)
: name_(rhs.name_),
title_(rhs.title_),
abstract_(rhs.abstract_),
srs_(rhs.srs_),
minZoom_(rhs.minZoom_),
maxZoom_(rhs.maxZoom_),
@ -59,6 +56,7 @@ layer::layer(const layer& rhs)
queryable_(rhs.queryable_),
clear_label_cache_(rhs.clear_label_cache_),
cache_features_(rhs.cache_features_),
group_by_(rhs.group_by_),
styles_(rhs.styles_),
ds_(rhs.ds_) {}
@ -77,8 +75,6 @@ bool layer::operator==(layer const& other) const
void layer::swap(const layer& rhs)
{
name_=rhs.name_;
title_=rhs.title_;
abstract_=rhs.abstract_;
srs_ = rhs.srs_;
minZoom_=rhs.minZoom_;
maxZoom_=rhs.maxZoom_;
@ -86,6 +82,7 @@ void layer::swap(const layer& rhs)
queryable_=rhs.queryable_;
clear_label_cache_ = rhs.clear_label_cache_;
cache_features_ = rhs.cache_features_;
group_by_ = rhs.group_by_;
styles_=rhs.styles_;
ds_=rhs.ds_;
}
@ -102,26 +99,6 @@ std::string const& layer::name() const
return name_;
}
void layer::set_title( std::string const& title)
{
title_ = title;
}
std::string const& layer::title() const
{
return title_;
}
void layer::set_abstract( std::string const& abstract)
{
abstract_ = abstract;
}
std::string const& layer::abstract() const
{
return abstract_;
}
void layer::set_srs(std::string const& srs)
{
srs_ = srs;
@ -228,4 +205,14 @@ bool layer::cache_features() const
return cache_features_;
}
void layer::set_group_by(std::string column)
{
group_by_ = column;
}
std::string layer::group_by() const
{
return group_by_;
}
}

View file

@ -560,14 +560,19 @@ void map_parser::parse_font(font_set & fset, ptree const & f)
{
ensure_attrs(f, "Font", "face-name");
std::string face_name = get_attr(f, "face-name", std::string());
if ( strict_ )
optional<std::string> face_name = get_opt_attr<std::string>(f, "face-name");
if (face_name)
{
ensure_font_face( face_name );
if ( strict_ )
{
ensure_font_face(*face_name);
}
fset.add_face_name(*face_name);
}
else
{
throw config_error(std::string("Must have 'face-name' set"));
}
fset.add_face_name(face_name);
}
void map_parser::parse_layer( Map & map, ptree const & lay )
@ -577,13 +582,12 @@ void map_parser::parse_layer( Map & map, ptree const & lay )
s << "name,"
<< "srs,"
<< "status,"
<< "title,"
<< "abstract,"
<< "minzoom,"
<< "maxzoom,"
<< "queryable,"
<< "clear-label-cache,"
<< "cache-features";
<< "cache-features,"
<< "group-by";
ensure_attrs(lay, "Layer", s.str());
try
{
@ -599,19 +603,7 @@ void map_parser::parse_layer( Map & map, ptree const & lay )
{
lyr.setActive( * status );
}
optional<std::string> title = get_opt_attr<std::string>(lay, "title");
if (title)
{
lyr.set_title( * title );
}
optional<std::string> abstract = get_opt_attr<std::string>(lay, "abstract");
if (abstract)
{
lyr.set_abstract( * abstract );
}
optional<double> minZoom = get_opt_attr<double>(lay, "minzoom");
if (minZoom)
{
@ -644,6 +636,12 @@ void map_parser::parse_layer( Map & map, ptree const & lay )
lyr.set_cache_features( * cache_features );
}
optional<std::string> group_by =
get_opt_attr<std::string>(lay, "group-by");
if (group_by)
{
lyr.set_group_by( * group_by );
}
ptree::const_iterator itr2 = lay.begin();
ptree::const_iterator end2 = lay.end();
@ -758,14 +756,12 @@ void map_parser::parse_layer( Map & map, ptree const & lay )
void map_parser::parse_rule( feature_type_style & style, ptree const & r )
{
ensure_attrs(r, "Rule", "name,title");
ensure_attrs(r, "Rule", "name");
std::string name;
try
{
name = get_attr( r, "name", std::string());
std::string title = get_attr( r, "title", std::string());
rule rule(name,title);
rule rule(name);
optional<std::string> filter_expr =
get_opt_child<std::string>( r, "Filter");
@ -1915,9 +1911,8 @@ void map_parser::parse_building_symbolizer( rule & rule, ptree const & sym )
optional<double> opacity = get_opt_attr<double>(sym, "fill-opacity");
if (opacity) building_sym.set_opacity(*opacity);
// height
// TODO - expression
optional<double> height = get_opt_attr<double>(sym, "height");
if (height) building_sym.set_height(*height);
optional<std::string> height = get_opt_attr<std::string>(sym, "height");
if (height) building_sym.set_height(parse_expression(*height, "utf8"));
parse_metawriter_in_symbolizer(building_sym, sym);
rule.append(building_sym);

View file

@ -87,6 +87,7 @@ Map::Map(const Map& rhs)
background_image_(rhs.background_image_),
styles_(rhs.styles_),
metawriters_(rhs.metawriters_),
fontsets_(rhs.fontsets_),
layers_(rhs.layers_),
aspectFixMode_(rhs.aspectFixMode_),
current_extent_(rhs.current_extent_),
@ -106,6 +107,7 @@ Map& Map::operator=(const Map& rhs)
background_image_=rhs.background_image_;
styles_=rhs.styles_;
metawriters_ = rhs.metawriters_;
fontsets_ = rhs.fontsets_;
layers_=rhs.layers_;
aspectFixMode_=rhs.aspectFixMode_;
maximum_extent_=rhs.maximum_extent_;
@ -202,14 +204,14 @@ bool Map::insert_fontset(std::string const& name, font_set const& fontset)
{
return fontsets_.insert(make_pair(name, fontset)).second;
}
font_set const& Map::find_fontset(std::string const& name) const
boost::optional<font_set const&> Map::find_fontset(std::string const& name) const
{
std::map<std::string,font_set>::const_iterator itr = fontsets_.find(name);
if (itr!=fontsets_.end())
return itr->second;
static font_set default_fontset;
return default_fontset;
if (itr != fontsets_.end())
return boost::optional<font_set const&>(itr->second);
else
return boost::optional<font_set const&>() ;
}
std::map<std::string,font_set> const& Map::fontsets() const

View file

@ -107,6 +107,11 @@ size_t memory_datasource::size() const
return features_.size();
}
void memory_datasource::clear()
{
features_.clear();
}
// point_datasource
void point_datasource::add_point(double x, double y, const char* key, const char* value)

View file

@ -293,7 +293,7 @@ void placement_finder<DetectorT>::find_point_placement(placement & p,
// wrap text at first wrap_char after (default) the wrap width or immediately before the current word
if ((c == '\n') ||
(line_width > 0 && (((line_width - character_spacing) > wrap_at && !p.wrap_before) ||
((line_width + word_width - character_spacing) > wrap_at && p.wrap_before)) ))
((line_width + word_width - character_spacing) > wrap_at && p.wrap_before)) ))
{
// Remove width of breaking space character since it is not rendered and the character_spacing for the last character on the line
line_width -= (last_wrap_char_width + character_spacing);
@ -381,12 +381,12 @@ void placement_finder<DetectorT>::find_point_placement(placement & p,
x = -(line_width / 2.0);
if (p.info.get_rtl()==false)
{
y = (0.5 * (string_height + (line_spacing * (total_lines-1)))) - max_character_height;
}
else
{
y = -(0.5 * (string_height + (line_spacing * (total_lines-1)))) + max_character_height;
}
y = (0.5 * (string_height + (line_spacing * (total_lines-1)))) - max_character_height;
}
else
{
y = -(0.5 * (string_height + (line_spacing * (total_lines-1)))) + max_character_height;
}
// if needed, adjust for desired justification (J_MIDDLE is the default)
if( po->jalign == J_LEFT )
@ -411,14 +411,14 @@ void placement_finder<DetectorT>::find_point_placement(placement & p,
index_to_wrap_at = line_breaks[++line_number];
line_width = line_widths[line_number];
if (p.info.get_rtl()==false)
{
y -= (max_character_height + line_spacing); // move position down to line start
}
else
{
y += (max_character_height + line_spacing); // move position up to line start
}
if (p.info.get_rtl()==false)
{
y -= (max_character_height + line_spacing); // move position down to line start
}
else
{
y += (max_character_height + line_spacing); // move position up to line start
}
// reset to begining of line position
x = ((po->jalign == J_LEFT)? -(string_width / 2.0): ((po->jalign == J_RIGHT)? ((string_width /2.0) - line_width): -(line_width / 2.0)));
@ -467,9 +467,9 @@ void placement_finder<DetectorT>::find_point_placement(placement & p,
if (p.minimum_padding > 0)
{
box2d<double> epad(e.minx()-p.minimum_padding,
e.miny()-p.minimum_padding,
e.maxx()+p.minimum_padding,
e.maxy()+p.minimum_padding);
e.miny()-p.minimum_padding,
e.maxx()+p.minimum_padding,
e.maxy()+p.minimum_padding);
if (!dimensions_.contains(epad))
{
return;
@ -485,18 +485,18 @@ void placement_finder<DetectorT>::find_point_placement(placement & p,
// check the placement of any additional envelopes
if (!p.allow_overlap && !p.additional_boxes.empty())
{
BOOST_FOREACH(box2d<double> box, p.additional_boxes)
{
box2d<double> pt(box.minx() + current_placement->starting_x,
box.miny() + current_placement->starting_y,
box.maxx() + current_placement->starting_x,
box.maxy() + current_placement->starting_y);
BOOST_FOREACH(box2d<double> box, p.additional_boxes)
{
box2d<double> pt(box.minx() + current_placement->starting_x,
box.miny() + current_placement->starting_y,
box.maxx() + current_placement->starting_x,
box.maxy() + current_placement->starting_y);
// abort the whole placement if the additional envelopes can't be placed.
if (!detector_.has_point_placement(pt, p.minimum_distance)) return;
// abort the whole placement if the additional envelopes can't be placed.
if (!detector_.has_point_placement(pt, p.minimum_distance)) return;
c_envelopes.push(pt);
}
c_envelopes.push(pt);
}
}
// since there was no early exit, add the character envelopes to the placements' envelopes

View file

@ -138,7 +138,7 @@ void raster_colorizer::colorize(raster_ptr const& raster,const std::map<std::str
inline unsigned interpolate(unsigned start, unsigned end, float fraction)
{
return static_cast<unsigned>(fraction * (end - start) + start);
return static_cast<unsigned>(fraction * ((float)end - (float)start) + start);
}
color raster_colorizer::get_color(float value) const {

View file

@ -241,10 +241,9 @@ public:
{
set_attr( sym_node, "fill-opacity", sym.get_opacity() );
}
if ( sym.height() != dfl.height() || explicit_defaults_ )
{
set_attr( sym_node, "height", sym.height() );
}
set_attr( sym_node, "height", to_expression_string(*sym.height()) );
add_metawriter_attributes(sym_node, sym);
}
@ -647,11 +646,7 @@ void serialize_rule( ptree & style_node, const rule & r, bool explicit_defaults)
{
set_attr(rule_node, "name", r.get_name());
}
if ( r.get_title() != dfl.get_title() )
{
set_attr(rule_node, "title", r.get_title());
}
if ( r.has_else_filter() )
{
rule_node.push_back( ptree::value_type(
@ -815,21 +810,12 @@ void serialize_layer( ptree & map_node, const layer & layer, bool explicit_defau
{
ptree & layer_node = map_node.push_back(
ptree::value_type("Layer", ptree()))->second;
if ( layer.name() != "" )
{
set_attr( layer_node, "name", layer.name() );
}
if ( layer.abstract() != "" )
{
set_attr( layer_node, "abstract", layer.abstract() );
}
if ( layer.title() != "" )
{
set_attr( layer_node, "title", layer.title() );
}
if ( layer.srs() != "" )
{
set_attr( layer_node, "srs", layer.srs() );
@ -865,6 +851,11 @@ void serialize_layer( ptree & map_node, const layer & layer, bool explicit_defau
set_attr/*<bool>*/( layer_node, "cache-features", layer.cache_features() );
}
if ( layer.group_by() != "" || explicit_defaults )
{
set_attr( layer_node, "group-by", layer.group_by() );
}
std::vector<std::string> const& style_names = layer.styles();
for (unsigned i = 0; i < style_names.size(); ++i)
{

View file

@ -114,16 +114,13 @@ public:
needSwap_ = byteOrder_ ? wkbNDR : wkbXDR;
#endif
}
~wkb_reader() {}
void read_multi(boost::ptr_vector<geometry_type> & paths)
void read(boost::ptr_vector<geometry_type> & paths)
{
int type = read_integer();
#ifdef MAPNIK_DEBUG_WKB
std::clog << "wkb_reader: read_multi "
<< wkb_geometry_type_string(type) << " " << type << std::endl;
std::clog << "wkb_reader: read " << wkb_geometry_type_string(type) << " " << type << std::endl;
#endif
switch (type)
@ -174,63 +171,6 @@ public:
break;
}
}
void read(boost::ptr_vector<geometry_type> & paths)
{
int type = read_integer();
#ifdef MAPNIK_DEBUG_WKB
std::clog << "wkb_reader: read " << wkb_geometry_type_string(type) << " " << type << std::endl;
#endif
switch (type)
{
case wkbPoint:
read_point(paths);
break;
case wkbLineString:
read_linestring(paths);
break;
case wkbPolygon:
read_polygon(paths);
break;
case wkbMultiPoint:
read_multipoint_2(paths);
break;
case wkbMultiLineString:
read_multilinestring_2(paths);
break;
case wkbMultiPolygon:
read_multipolygon_2(paths);
break;
case wkbGeometryCollection:
read_collection_2(paths);
break;
case wkbPointZ:
read_point_xyz(paths);
break;
case wkbLineStringZ:
read_linestring_xyz(paths);
break;
case wkbPolygonZ:
read_polygon_xyz(paths);
break;
case wkbMultiPointZ:
read_multipoint_xyz_2(paths);
break;
case wkbMultiLineStringZ:
read_multilinestring_xyz_2(paths);
break;
case wkbMultiPolygonZ:
read_multipolygon_xyz_2(paths);
break;
case wkbGeometryCollectionZ:
read_collection_2(paths);
break;
default:
break;
}
}
private:
@ -329,21 +269,7 @@ private:
read_point(paths);
}
}
void read_multipoint_2(boost::ptr_vector<geometry_type> & paths)
{
geometry_type* pt = new geometry_type(MultiPoint);
int num_points = read_integer();
for (int i = 0; i < num_points; ++i)
{
pos_ += 5;
double x = read_double();
double y = read_double();
pt->move_to(x, y);
}
paths.push_back(pt);
}
void read_point_xyz(boost::ptr_vector<geometry_type> & paths)
{
geometry_type* pt = new geometry_type(Point);
@ -364,22 +290,6 @@ private:
}
}
void read_multipoint_xyz_2(boost::ptr_vector<geometry_type> & paths)
{
geometry_type* pt = new geometry_type(MultiPoint);
int num_points = read_integer();
for (int i = 0; i < num_points; ++i)
{
pos_ += 5;
double x = read_double();
double y = read_double();
pos_ += 8; // double z = read_double();
pt->move_to(x, y);
}
paths.push_back(pt);
}
void read_linestring(boost::ptr_vector<geometry_type> & paths)
{
geometry_type* line = new geometry_type(LineString);
@ -404,29 +314,7 @@ private:
read_linestring(paths);
}
}
void read_multilinestring_2(boost::ptr_vector<geometry_type> & paths)
{
geometry_type* line = new geometry_type(MultiLineString);
int num_lines = read_integer();
unsigned capacity = 0;
for (int i = 0; i < num_lines; ++i)
{
pos_ += 5;
int num_points = read_integer();
capacity += num_points;
CoordinateArray ar(num_points);
read_coords(ar);
line->set_capacity(capacity);
line->move_to(ar[0].x, ar[0].y);
for (int j = 1; j < num_points; ++j)
{
line->line_to(ar[j].x, ar[j].y);
}
}
paths.push_back(line);
}
void read_linestring_xyz(boost::ptr_vector<geometry_type> & paths)
{
geometry_type* line = new geometry_type(LineString);
@ -452,29 +340,7 @@ private:
}
}
void read_multilinestring_xyz_2(boost::ptr_vector<geometry_type> & paths)
{
geometry_type* line = new geometry_type(MultiLineString);
int num_lines = read_integer();
unsigned capacity = 0;
for (int i = 0; i < num_lines; ++i)
{
pos_ += 5;
int num_points = read_integer();
capacity += num_points;
CoordinateArray ar(num_points);
read_coords_xyz(ar);
line->set_capacity(capacity);
line->move_to(ar[0].x, ar[0].y);
for (int j = 1; j < num_points; ++j)
{
line->line_to(ar[j].x, ar[j].y);
}
}
paths.push_back(line);
}
void read_polygon(boost::ptr_vector<geometry_type> & paths)
{
geometry_type* poly = new geometry_type(Polygon);
@ -506,33 +372,6 @@ private:
}
}
void read_multipolygon_2(boost::ptr_vector<geometry_type> & paths)
{
geometry_type* poly = new geometry_type(MultiPolygon);
int num_polys = read_integer();
unsigned capacity = 0;
for (int i = 0; i < num_polys; ++i)
{
pos_ += 5;
int num_rings = read_integer();
for (int r = 0; r < num_rings; ++r)
{
int num_points = read_integer();
capacity += num_points;
CoordinateArray ar(num_points);
read_coords(ar);
poly->set_capacity(capacity);
poly->move_to(ar[0].x, ar[0].y);
for (int j = 1; j < num_points; ++j)
{
poly->line_to(ar[j].x, ar[j].y);
}
poly->line_to(ar[0].x, ar[0].y);
}
}
paths.push_back(poly);
}
void read_polygon_xyz(boost::ptr_vector<geometry_type> & paths)
{
geometry_type* poly = new geometry_type(Polygon);
@ -564,34 +403,6 @@ private:
}
}
void read_multipolygon_xyz_2(boost::ptr_vector<geometry_type> & paths)
{
geometry_type* poly = new geometry_type(MultiPolygon);
int num_polys = read_integer();
unsigned capacity = 0;
for (int i = 0; i < num_polys; ++i)
{
pos_ += 5;
int num_rings = read_integer();
for (int r = 0; r < num_rings; ++r)
{
int num_points = read_integer();
capacity += num_points;
CoordinateArray ar(num_points);
read_coords_xyz(ar);
poly->set_capacity(capacity);
poly->move_to(ar[0].x, ar[0].y);
for (int j = 1; j < num_points; ++j)
{
poly->line_to(ar[j].x, ar[j].y);
}
poly->line_to(ar[0].x, ar[0].y);
}
}
paths.push_back(poly);
}
void read_collection(boost::ptr_vector<geometry_type> & paths)
{
int num_geometries = read_integer();
@ -602,16 +413,6 @@ private:
}
}
void read_collection_2(boost::ptr_vector<geometry_type> & paths)
{
int num_geometries = read_integer();
for (int i = 0; i < num_geometries; ++i)
{
pos_ += 1; // skip byte order
read_multi(paths);
}
}
#ifdef MAPNIK_DEBUG_WKB
std::string wkb_geometry_type_string(int type)
{
@ -645,17 +446,10 @@ private:
void geometry_utils::from_wkb (boost::ptr_vector<geometry_type>& paths,
const char* wkb,
unsigned size,
bool multiple_geometries,
wkbFormat format)
{
wkb_reader reader(wkb, size, format);
if (multiple_geometries)
{
return reader.read_multi(paths);
}
else
{
return reader.read(paths);
}
return reader.read(paths);
}
}

View file

@ -0,0 +1,7 @@
<Map>
<FontSet name="book-fonts">
<Font face-name="does not exist" />
</FontSet>
</Map>

View file

@ -0,0 +1,4 @@
x,y,fips
0,0,001
0,0,003
0,0,005
1 x y fips
2 0 0 001
3 0 0 003
4 0 0 005

View file

@ -0,0 +1,8 @@
<Map>
<FontSet name="book-fonts">
<Font face-name="DejaVu Sans Book" />
<Font face-name="DejaVu Sans Oblique" />
</FontSet>
</Map>

View file

@ -3,7 +3,6 @@
<Datasource name="sqlite">
<Parameter name="type">sqlite</Parameter>
<Parameter name="file">../sqlite/qgis_spatiallite.sqlite</Parameter>
<Parameter name="multiple_geometries">true</Parameter>
</Datasource>
<Style name="polygon_style">

View file

@ -1,7 +1,7 @@
<!DOCTYPE Map>
<Map background-color="white" srs="+init=epsg:4326" minimum-version="0.7.2">
<Style name="1">
<Rule title="foo">
<Rule>
<MarkersSymbolizer stroke="green" stroke-width="1.3" fill="yellow"/>
<LineSymbolizer stroke-width=".2" stroke="grey"/>
</Rule>

View file

@ -2,31 +2,31 @@
<Map background-color="white" srs="+init=epsg:4326" minimum-version="0.7.2">
<Style name="1">
<Rule title="foo">
<Rule>
<Filter>([name]='CHILE')</Filter>
<MarkersSymbolizer fill="darkgreen" opacity=".7" width="15" height="10" stroke="green" stroke-width="7" stroke-opacity=".2" placement="point" marker-type="ellipse"/>
</Rule>
<Rule title="foo">
<Rule>
<Filter>([name]='Australia')</Filter>
<MarkersSymbolizer fill="darkblue" opacity=".7" width="10" height="20" stroke="blue" stroke-width="7" stroke-opacity=".2" placement="point" marker-type="ellipse"/>
</Rule>
<Rule title="foo1">
<Rule>
<Filter>([name]='Brazil')</Filter>
<MarkersSymbolizer fill="darkorange" opacity=".7" width="20" height="10" stroke="orange" stroke-width="7" stroke-opacity=".2" placement="point" marker-type="ellipse"/>
</Rule>
<Rule title="foo">
<Rule>
<Filter>([name]='Mongolia')</Filter>
<MarkersSymbolizer fill="darkgoldenrod" opacity=".7" width="25" height="10" stroke="yellow" stroke-width="7" stroke-opacity=".2" placement="point" marker-type="ellipse"/>
</Rule>
<Rule title="foo">
<Rule>
<Filter>([name]='Sudan')</Filter>
<MarkersSymbolizer fill="darkcyan" opacity=".7" width="15" height="10" stroke="cadetblue" stroke-width="7" stroke-opacity=".2" placement="point" marker-type="ellipse"/>
</Rule>
<Rule title="foo">
<Rule>
<Filter>([name]='United States')</Filter>
<MarkersSymbolizer fill="#cc3344" opacity=".7" width="15" height="10" stroke="#cc3344" stroke-width="7" stroke-opacity=".2" placement="point" marker-type="ellipse"/>
</Rule>
<Rule title="foo">
<Rule>
<ElseFilter/>
<PointSymbolizer file="../svg/ellipses.svg"/>
</Rule>

View file

@ -1,17 +1,17 @@
<!DOCTYPE Map>
<Map background-color="#b5d0d0" srs="+init=epsg:4326" minimum-version="0.7.2">
<Style name="1">
<Rule title="foo">
<Rule>
<Filter>([x]=0)</Filter>
<TextSymbolizer size="10" dy="-10" face-name="DejaVu Sans Book" halo-radius="1" allow-overlap="true">[label]</TextSymbolizer>
<PointSymbolizer/>
</Rule>
<Rule title="foo">
<Rule>
<Filter>([y]=0)</Filter>
<TextSymbolizer size="10" dy="5" face-name="DejaVu Sans Book" halo-radius="1">[label]</TextSymbolizer>
<PointSymbolizer/>
</Rule>
<Rule title="foo">
<Rule>
<ElseFilter/>
<TextSymbolizer size="10" dy="-5" face-name="DejaVu Sans Book" halo-radius="1">[label]</TextSymbolizer>
<PointSymbolizer/>

View file

@ -1,17 +1,17 @@
<!DOCTYPE Map>
<Map background-color="#b5d0d0" srs="+init=epsg:4326" minimum-version="0.7.2">
<Style name="1">
<Rule title="foo">
<Rule>
<Filter>([x]=0)</Filter>
<TextSymbolizer size="10" dy="-10" face-name="DejaVu Sans Book" halo-radius="1" allow-overlap="true">[label]</TextSymbolizer>
<PointSymbolizer/>
</Rule>
<Rule title="foo">
<Rule>
<Filter>([y]=0)</Filter>
<TextSymbolizer size="10" dy="5" face-name="DejaVu Sans Book" halo-radius="1">[label]</TextSymbolizer>
<PointSymbolizer/>
</Rule>
<Rule title="foo">
<Rule>
<ElseFilter/>
<TextSymbolizer size="10" dy="-5" face-name="DejaVu Sans Book" halo-radius="1">[label]</TextSymbolizer>
<PointSymbolizer/>

View file

@ -1,17 +1,17 @@
<!DOCTYPE Map>
<Map background-color="#b5d0d0" srs="+init=epsg:4326" minimum-version="0.7.2">
<Style name="1">
<Rule title="foo">
<Rule>
<Filter>([x]=0)</Filter>
<TextSymbolizer size="10" dy="-10" face-name="DejaVu Sans Book" halo-radius="1" allow-overlap="true">[label]</TextSymbolizer>
<PointSymbolizer/>
</Rule>
<Rule title="foo">
<Rule>
<Filter>([y]=0)</Filter>
<TextSymbolizer size="10" dy="5" face-name="DejaVu Sans Book" halo-radius="1">[label]</TextSymbolizer>
<PointSymbolizer/>
</Rule>
<Rule title="foo">
<Rule>
<ElseFilter/>
<TextSymbolizer size="10" dy="-5" face-name="DejaVu Sans Book" halo-radius="1">[label]</TextSymbolizer>
<PointSymbolizer/>

View file

@ -1,38 +1,38 @@
<!DOCTYPE Map>
<Map background-color="#b5d0d0" srs="+init=epsg:4326" minimum-version="0.7.2">
<Style name="1">
<Rule title="foo">
<Rule>
<Filter>([name]='CHILE')</Filter>
<TextSymbolizer size="10" dy="5" face-name="DejaVu Sans Book" text-transform="lowercase" wrap-width="10" wrap-character=" " halo-radius="1">[name] + ' (default OGC pixel)'</TextSymbolizer>
<PointSymbolizer/>
</Rule>
<Rule title="foo">
<Rule>
<Filter>([name]='Australia')</Filter>
<TextSymbolizer size="10" dy="20" face-name="DejaVu Sans Book" halo-radius="1">[name] + ' (png)'</TextSymbolizer>
<PointSymbolizer file="../images/dummy.png" allow-overlap="true"/>
</Rule>
<Rule title="foo1">
<Rule>
<Filter>([name]='Brazil')</Filter>
<TextSymbolizer size="10" dy="20" face-name="DejaVu Sans Book" halo-radius="1">[name] + ' (svg &amp; tif)'</TextSymbolizer>
<PointSymbolizer file="../images/dummy.tif" allow-overlap="true"/>
<PointSymbolizer file="../svg/ellipses.svg" allow-overlap="true"/>
</Rule>
<Rule title="foo">
<Rule>
<Filter>([name]='Mongolia')</Filter>
<TextSymbolizer size="10" dy="20" face-name="DejaVu Sans Book" halo-radius="1">[name] + ' (tiff)'</TextSymbolizer>
<PointSymbolizer file="../images/dummy.tiff" allow-overlap="true"/>
</Rule>
<Rule title="foo">
<Rule>
<Filter>([name]='Sudan')</Filter>
<TextSymbolizer size="10" dy="20" face-name="DejaVu Sans Book" halo-radius="1">[name] + ' (jpeg)'</TextSymbolizer>
<PointSymbolizer file="../images/dummy.jpeg"/>
</Rule>
<Rule title="foo">
<Rule>
<Filter>([name]='United States')</Filter>
<TextSymbolizer size="10" dy="20" face-name="DejaVu Sans Book" halo-radius="1">[name] + ' (jpg)'</TextSymbolizer>
<PointSymbolizer file="../images/dummy.jpg"/>
</Rule>
<Rule title="foo">
<Rule>
<ElseFilter/>
<TextSymbolizer size="10" dy="20" face-name="DejaVu Sans Book" halo-radius="1">[name]</TextSymbolizer>
<PointSymbolizer file="../images/bogus_will_fail.png"/>

View file

@ -1,11 +1,11 @@
<!DOCTYPE Map>
<Map background-color="#b5d0d0" srs="+init=epsg:4326" minimum-version="0.7.2">
<Style name="1">
<Rule title="foo1">
<Rule>
<Filter>([name]='Brazil' or [name]='Mongolia' or [name]='Sudan')</Filter>
<PointSymbolizer file="../svg/point_sm.svg" allow-overlap="true"/>
</Rule>
<Rule title="foo">
<Rule>
<ElseFilter/>
<PointSymbolizer file="../svg/point_sm.svg" ignore-placement="true"/>
<PointSymbolizer/>

View file

@ -1,26 +1,26 @@
<!DOCTYPE Map>
<Map background-color="#b5d0d0" minimum-version="0.7.2">
<Style name="test">
<Rule title="asia">
<Rule name="asia">
<Filter>([REGION]=142)</Filter>
<PointSymbolizer file="../images/dummy.png" allow-overlap="true"/>
</Rule>
<Rule title="europe">
<Rule name="europe">
<Filter>([REGION]=150)</Filter>
<!-- requires at least Mapnik 0.7.1 to work due to http://trac.mapnik.org/ticket/508 -->
<PolygonPatternSymbolizer file="../images/dummy.png"/>
</Rule>
<Rule title="americas">
<Rule name="americas">
<Filter>([REGION]=19)</Filter>
<!-- requires at least Mapnik 0.7.1 to work due to http://trac.mapnik.org/ticket/508 -->
<LinePatternSymbolizer file="../images/dummy.png"/>
</Rule>
<Rule title="Africa">
<Rule name="Africa">
<Filter>([REGION]=2)</Filter>
<ShieldSymbolizer placement="vertex" size="10" fill="#000000" file="../images/dummy.png" face-name="DejaVu Sans Bold">[NAME]</ShieldSymbolizer>
</Rule>
<Rule title="rest">
<Rule name="rest">
<ElseFilter/>
<LineSymbolizer stroke-width="1"/>
</Rule>

View file

@ -7,25 +7,15 @@
</Rule>
</Style>
<!-- layer created by ogr like: ogr2ogr -t_srs EPSG:4326 -f SQLite ../sqlite/world.sqlite world_merc.shp -->
<!-- here we read with the ogr plugin -->
<Layer name="world_borders1" srs="+init=epsg:4326">
<StyleName>world_borders_style1</StyleName>
<Datasource>
<Parameter name="type">ogr</Parameter>
<Parameter name="file">../sqlite/world.sqlite</Parameter>
<Parameter name="layer">world_merc</Parameter>
</Datasource>
</Layer>
<Style name="world_borders_style2">
<Rule>
<PolygonSymbolizer fill="yellow" gamma="0.5"/>
</Rule>
</Style>
<!-- here we read with native sqlite plugin -->
<!-- layer created by ogr like: ogr2ogr -t_srs EPSG:4326 -f SQLite ../sqlite/world.sqlite world_merc.shp -->
<Layer name="world_borders2" srs="+init=epsg:4326">
<StyleName>world_borders_style1</StyleName>
<StyleName>world_borders_style2</StyleName>
<Datasource>
<Parameter name="type">sqlite</Parameter>

View file

@ -1,31 +1,31 @@
<Map srs="+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0 +k=1.0 +units=m +nadgrids=@null +wktext +no_defs +over" background-color="steelblue" minimum-version="0.7.2">
<Style name="labels">
<Rule title="foo">
<Rule>
<Filter>([name]='CHILE')</Filter>
<TextSymbolizer size="15" orientation="45" face-name="DejaVu Sans Book" halo-radius="1">'45˚ angle'</TextSymbolizer>
</Rule>
<Rule title="foo">
<Rule>
<Filter>([name]='Australia')</Filter>
<TextSymbolizer size="15" orientation="-45" face-name="DejaVu Sans Book" halo-radius="1">'- 45˚ angle'</TextSymbolizer>
</Rule>
<Rule title="foo1">
<Rule>
<Filter>([name]='Brazil')</Filter>
<TextSymbolizer size="15" orientation="90" face-name="DejaVu Sans Book" halo-radius="1">'90˚ angle'</TextSymbolizer>
</Rule>
<Rule title="foo">
<Rule>
<Filter>([name]='Mongolia')</Filter>
<TextSymbolizer size="15" orientation="-90" face-name="DejaVu Sans Book" halo-radius="1">'- 90˚ angle'</TextSymbolizer>
</Rule>
<Rule title="foo">
<Rule>
<Filter>([name]='South Sudan')</Filter>
<TextSymbolizer size="15" orientation="180" face-name="DejaVu Sans Book" halo-radius="1">'180&#730; angle'</TextSymbolizer>
</Rule>
<Rule title="foo">
<Rule>
<Filter>([name]='United States')</Filter>
<TextSymbolizer size="15" face-name="DejaVu Sans Book" halo-radius="1">'no rotation of text'</TextSymbolizer>
</Rule>
<Rule title="foo">
<Rule>
<ElseFilter/>
<TextSymbolizer size="15" face-name="DejaVu Sans Book" halo-radius="1">[name]</TextSymbolizer>
</Rule>

BIN
tests/data/shp/wkt_poly.dbf Normal file

Binary file not shown.

BIN
tests/data/shp/wkt_poly.shp Normal file

Binary file not shown.

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