Merge branch 'master' of github.com:mapnik/mapnik

This commit is contained in:
kunitoki 2011-12-05 11:12:02 +01:00
commit d6cbdd3412
33 changed files with 1078 additions and 304 deletions

7
.gitignore vendored
View file

@ -35,3 +35,10 @@ tests/cpp_tests/svg_renderer_tests/path_element_test
tests/cpp_tests/svg_renderer_tests/path_element_test_case_1.svg
tests/cpp_tests/svg_renderer_tests/root_element_test
tests/data/sqlite/*index
demo/c++/cairo-demo.pdf
demo/c++/cairo-demo.png
demo/c++/cairo-demo256.png
demo/c++/demo.jpg
demo/c++/demo.png
demo/c++/demo256.png

View file

@ -34,7 +34,6 @@
#include <mapnik/datasource.hpp>
#include <mapnik/wkb.hpp>
#include <mapnik/wkt/wkt_factory.hpp>
#include "mapnik_value_converter.hpp"
mapnik::geometry_type & (mapnik::Feature::*get_geom1)(unsigned) = &mapnik::Feature::get_geometry;
@ -59,7 +58,7 @@ void feature_add_geometries_from_wkt(Feature &feature, std::string wkt)
namespace boost { namespace python {
// Forward declaration
// Forward declaration
template <class Container, bool NoProxy, class DerivedPolicies>
class map_indexing_suite2;
@ -95,9 +94,11 @@ namespace boost { namespace python {
template <class Class>
static void
extension_def(Class& /*cl*/)
extension_def(Class& cl)
{
cl
.def("get", &get)
;
}
static data_type&
@ -106,12 +107,25 @@ namespace boost { namespace python {
typename Container::iterator i = container.props().find(i_);
if (i == container.end())
{
PyErr_SetString(PyExc_KeyError, "Invalid key");
PyErr_SetString(PyExc_KeyError, i_.c_str());
throw_error_already_set();
}
// will be auto-converted to proper python type by `mapnik_value_to_python`
return i->second;
}
static data_type
get(Container& container, index_type i_)
{
typename Container::iterator i = container.props().find(i_);
if (i != container.end())
{
// will be auto-converted to proper python type by `mapnik_value_to_python`
return i->second;
}
return mapnik::value_null();
}
static void
set_item(Container& container, index_type i, data_type const& v)
{

View file

@ -31,6 +31,7 @@
#include <mapnik/geometry.hpp>
#include <mapnik/wkt/wkt_factory.hpp>
#include <mapnik/wkb.hpp>
#include <mapnik/util/geometry_to_wkb.hpp>
namespace {
@ -47,19 +48,47 @@ geometry_type const& getitem_impl(path_type & p, int key)
throw boost::python::error_already_set();
}
void from_wkt_impl(path_type& p, std::string const& wkt)
void add_wkt_impl(path_type& p, std::string const& wkt)
{
bool result = mapnik::from_wkt(wkt , p);
if (!result) throw std::runtime_error("Failed to parse WKT");
}
void from_wkb_impl(path_type& p, std::string const& wkb)
void add_wkb_impl(path_type& p, std::string const& wkb)
{
mapnik::geometry_utils::from_wkb(p, wkb.c_str(), wkb.size(), true);
}
boost::shared_ptr<path_type> from_wkt_impl(std::string const& wkt)
{
boost::shared_ptr<path_type> paths = boost::make_shared<path_type>();
bool result = mapnik::from_wkt(wkt, *paths);
if (!result) throw std::runtime_error("Failed to parse WKT");
return paths;
}
boost::shared_ptr<path_type> from_wkb_impl(std::string const& wkb)
{
boost::shared_ptr<path_type> paths = boost::make_shared<path_type>();
mapnik::geometry_utils::from_wkb(*paths, wkb.c_str(), wkb.size(), true);
return paths;
}
}
PyObject* to_wkb( geometry_type const& geom)
{
mapnik::util::wkb_buffer_ptr wkb = mapnik::util::to_wkb(geom,mapnik::util::wkbXDR);
return
#if PY_VERSION_HEX >= 0x03000000
::PyBytes_FromStringAndSize
#else
::PyString_FromStringAndSize
#endif
((const char*)wkb->buffer(),wkb->size());
}
void export_geometry()
{
using namespace boost::python;
@ -74,18 +103,23 @@ void export_geometry()
;
using mapnik::geometry_type;
class_<geometry_type, std::auto_ptr<geometry_type>,boost::noncopyable>("Geometry2d",no_init)
class_<geometry_type, std::auto_ptr<geometry_type>, boost::noncopyable>("Geometry2d",no_init)
.def("envelope",&geometry_type::envelope)
// .def("__str__",&geometry_type::to_string)
.def("type",&geometry_type::type)
.def("to_wkb",&to_wkb)
// TODO add other geometry_type methods
;
class_<path_type,boost::noncopyable>("Path")
class_<path_type, boost::shared_ptr<path_type>, boost::noncopyable>("Path")
.def("__getitem__", getitem_impl,return_value_policy<reference_existing_object>())
.def("__len__", &path_type::size)
.def("add_wkt",add_wkt_impl)
.def("add_wkb",add_wkb_impl)
.def("from_wkt",from_wkt_impl)
.def("from_wkb",from_wkb_impl)
.staticmethod("from_wkt")
.staticmethod("from_wkb")
;
}

View file

@ -119,6 +119,8 @@ struct map_pickle_suite : boost::python::pickle_suite
std::vector<layer>& (Map::*layers_nonconst)() = &Map::layers;
std::vector<layer> const& (Map::*layers_const)() const = &Map::layers;
mapnik::parameters& (Map::*attr_nonconst)() = &Map::get_extra_attributes;
mapnik::parameters& (Map::*params_nonconst)() = &Map::get_extra_parameters;
mapnik::feature_type_style find_style (mapnik::Map const& m, std::string const& name)
{
@ -173,6 +175,7 @@ mapnik::featureset_ptr query_map_point(mapnik::Map const& m, int index, double x
return m.query_map_point(idx, x, y);
}
void export_map()
{
using namespace boost::python;
@ -449,7 +452,8 @@ void export_map()
"about the hit areas rendered on the map.\n"
)
.def("extra_attributes",&Map::get_extra_attributes,return_value_policy<copy_const_reference>(),"TODO")
.add_property("extra_attributes",make_function(attr_nonconst,return_value_policy<reference_existing_object>()),"TODO")
.add_property("params",make_function(params_nonconst,return_value_policy<reference_existing_object>()),"TODO")
.add_property("aspect_fix_mode",
&Map::get_aspect_fix_mode,

View file

@ -48,6 +48,6 @@ void export_palette ()
( arg("palette"), arg("type")),
"Creates a new color palette from a file\n"
)*/
.def( "__init__", boost::python::make_constructor( &make_palette))
.def( "__init__", boost::python::make_constructor(make_palette))
;
}

View file

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

View file

@ -83,24 +83,13 @@ void export_label_collision_detector();
#include <mapnik/value_error.hpp>
#include <mapnik/save_map.hpp>
#include "python_grid_utils.hpp"
#include "mapnik_value_converter.hpp"
#if defined(HAVE_CAIRO) && defined(HAVE_PYCAIRO)
#include <pycairo.h>
static Pycairo_CAPI_t *Pycairo_CAPI;
#endif
namespace boost { namespace python {
struct mapnik_value_to_python
{
static PyObject* convert(mapnik::value const& v)
{
return boost::apply_visitor(value_converter(),v.base());
}
};
}}
void render(const mapnik::Map& map,
mapnik::image_32& image,
double scale_factor = 1.0,
@ -651,5 +640,6 @@ BOOST_PYTHON_MODULE(_mapnik)
register_ptr_to_python<mapnik::expression_ptr>();
register_ptr_to_python<mapnik::path_expression_ptr>();
to_python_converter<mapnik::value_holder,mapnik_param_to_python>();
to_python_converter<mapnik::value,mapnik_value_to_python>();
}

View file

@ -27,6 +27,7 @@
#include <boost/implicit_cast.hpp>
namespace boost { namespace python {
struct value_converter : public boost::static_visitor<PyObject*>
{
PyObject * operator() (int val) const
@ -48,6 +49,13 @@ namespace boost { namespace python {
return ::PyBool_FromLong(val);
}
PyObject * operator() (std::string const& s) const
{
PyObject *obj = Py_None;
obj = ::PyUnicode_DecodeUTF8(s.c_str(),implicit_cast<ssize_t>(s.length()),0);
return obj;
}
PyObject * operator() (UnicodeString const& s) const
{
std::string buffer;
@ -63,6 +71,25 @@ namespace boost { namespace python {
}
};
struct mapnik_value_to_python
{
static PyObject* convert(mapnik::value const& v)
{
return boost::apply_visitor(value_converter(),v.base());
}
};
struct mapnik_param_to_python
{
static PyObject* convert(mapnik::value_holder const& v)
{
return boost::apply_visitor(value_converter(),v);
}
};
}
}

View file

@ -253,12 +253,15 @@ int main ( int argc , char** argv)
save_to_file<image_data_32>(buf.data(),"demo.jpg","jpeg");
save_to_file<image_data_32>(buf.data(),"demo.png","png");
save_to_file<image_data_32>(buf.data(),"demo256.png","png256");
save_to_file<image_data_32>(buf.data(),"demo.tif","tiff");
std::cout << "Three maps have been rendered using AGG in the current directory:\n"
"- demo.jpg\n"
"- demo.png\n"
"- demo256.png\n"
"- demo.tif\n"
"Have a look!\n";
#if defined(HAVE_CAIRO)
Cairo::RefPtr<Cairo::ImageSurface> image_surface;

View file

@ -322,7 +322,7 @@ m.layers.append(popplaces_lyr)
# Set the initial extent of the map in 'master' spherical Mercator projection
m.zoom_to_box(mapnik.Box2d(-8024477.28459,5445190.38849,-7381388.20071,5662941.44855))
# Render two maps, two PNGs, one JPEG.
# Render map
im = mapnik.Image(m.width,m.height)
mapnik.render(m, im)
@ -347,6 +347,9 @@ images_.append('demo_high.jpg')
im.save('demo_low.jpg', 'jpeg50')
images_.append('demo_low.jpg')
im.save('demo.tif', 'tiff')
images_.append('demo.tif')
# Render cairo examples
if HAS_PYCAIRO_MODULE and mapnik.has_pycairo():

View file

@ -84,6 +84,7 @@ private:
boost::optional<box2d<double> > maximum_extent_;
std::string base_path_;
parameters extra_attr_;
parameters extra_params_;
public:
@ -444,14 +445,34 @@ public:
std::string get_metawriter_property(std::string name) const;
/*!
* @brief Get extra properties that can be carried on the Map
* @brief Get extra valid attributes of the Map that are not true members
*/
parameters const& get_extra_attributes() const;
/*!
* @brief Set extra properties that can be carried on the Map
* @brief Get non-const extra valid attributes of the Map that are not true members
*/
void set_extra_attributes(parameters& params);
parameters& get_extra_attributes();
/*!
* @brief Set extra attributes of the Map
*/
void set_extra_attributes(parameters& attr);
/*!
* @brief Get extra, arbitrary Parameters attached to the Map
*/
parameters const& get_extra_parameters() const;
/*!
* @brief Get non-const extra, arbitrary Parameters attached to the Map
*/
parameters& get_extra_parameters();
/*!
* @brief Set extra, arbitary Parameters of the Map
*/
void set_extra_parameters(parameters& params);
private:
void fixAspectRatio();

View file

@ -23,19 +23,22 @@
#ifndef MAPNIK_PARAMS_HPP
#define MAPNIK_PARAMS_HPP
// mapnik
// boost
#include <boost/variant.hpp>
#include <boost/optional.hpp>
#include <boost/none.hpp>
#include <boost/lexical_cast.hpp>
// mapnik
#include <mapnik/value.hpp>
// stl
#include <string>
#include <map>
namespace mapnik
{
typedef boost::variant<int,double,std::string> value_holder;
typedef boost::variant<value_null,int,double,std::string> value_holder;
typedef std::pair<const std::string, value_holder> parameter;
typedef std::map<const std::string, value_holder> param_map;

View file

@ -0,0 +1,235 @@
/*****************************************************************************
*
* 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_GEOMETRY_TO_WKB_HPP
#define MAPNIK_GEOMETRY_TO_WKB_HPP
// mapnik
#include <mapnik/global.hpp>
#include <mapnik/geometry.hpp>
// boost
#include <boost/shared_ptr.hpp>
#include <boost/make_shared.hpp>
#include <boost/interprocess/streams/bufferstream.hpp>
#include <boost/foreach.hpp>
// stl
#include <vector>
#include <cstdio>
namespace mapnik { namespace util {
std::string to_hex(const char* blob, unsigned size)
{
std::string buf;
buf.reserve(size*2);
std::ostringstream s(buf);
s.seekp(0);
char hex[3];
std::memset(hex,0,3);
for ( unsigned pos=0; pos < size; ++pos)
{
std::sprintf (hex, "%02x", int(blob[pos]) & 0xff);
s << hex;
}
return s.str();
}
enum wkbByteOrder {
wkbXDR=0,
wkbNDR=1
};
inline void reverse_bytes(char size, char *address)
{
char * first = address;
char * last = first + size - 1;
for(;first < last;++first, --last)
{
char x = *last;
*last = *first;
*first = x;
}
}
template <typename S, typename T>
inline void write (S & stream, T val, std::size_t size, wkbByteOrder byte_order)
{
#ifdef MAPNIK_BIG_ENDIAN
bool need_swap = byte_order ? wkbNDR : wkbXDR;
#else
bool need_swap = byte_order ? wkbXDR : wkbNDR;
#endif
char* buf = reinterpret_cast<char*>(&val);
if (need_swap)
{
reverse_bytes(size,buf);
}
stream.write(buf,size);
}
struct wkb_buffer
{
wkb_buffer(std::size_t size)
: 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()
{
return data_;
}
std::size_t size_;
char * data_;
};
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
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);
int type = static_cast<int>(g.type());
write(ss,type,4,byte_order);
double x,y;
g.get_vertex(0,&x,&y);
write(ss,x,8,byte_order);
write(ss,y,8,byte_order);
assert(ss.good());
return wkb;
}
wkb_buffer_ptr to_line_string_wkb( geometry_type const& g, wkbByteOrder byte_order)
{
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
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);
int type = static_cast<int>(g.type());
write(ss,type,4,byte_order);
write(ss,num_points,4,byte_order);
double x,y;
for (unsigned i=0; i< num_points; ++i)
{
g.get_vertex(i,&x,&y);
write(ss,x,8,byte_order);
write(ss,y,8,byte_order);
}
assert(ss.good());
return wkb;
}
wkb_buffer_ptr to_polygon_wkb( geometry_type const& g, wkbByteOrder byte_order)
{
unsigned num_points = g.num_points();
assert(num_points > 1);
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)
{
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
}
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);
int type = static_cast<int>(g.type());
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();
write(ss,num_points,4,byte_order);
BOOST_FOREACH ( point_type const& pt, ring)
{
double x = pt.first;
double y = pt.second;
write(ss,x,8,byte_order);
write(ss,y,8,byte_order);
}
}
assert(ss.good());
return wkb;
}
wkb_buffer_ptr to_wkb(geometry_type const& g, wkbByteOrder byte_order )
{
wkb_buffer_ptr wkb;
switch (g.type())
{
case mapnik::Point :
wkb = to_point_wkb(g, byte_order);
break;
case mapnik::LineString:
wkb = to_line_string_wkb(g, byte_order);
break;
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;
}
}}
#endif // MAPNIK_GEOMETRY_TO_WKB_HPP

View file

@ -351,19 +351,23 @@ includes = glob.glob('../include/mapnik/*.hpp')
svg_includes = glob.glob('../include/mapnik/svg/*.hpp')
wkt_includes = glob.glob('../include/mapnik/wkt/*.hpp')
grid_includes = glob.glob('../include/mapnik/grid/*.hpp')
util_includes = glob.glob('../include/mapnik/util/*.hpp')
inc_target = os.path.normpath(env['INSTALL_PREFIX']+'/include/mapnik')
svg_inc_target = os.path.normpath(env['INSTALL_PREFIX']+'/include/mapnik/svg')
wkt_inc_target = os.path.normpath(env['INSTALL_PREFIX']+'/include/mapnik/wkt')
grid_inc_target = os.path.normpath(env['INSTALL_PREFIX']+'/include/mapnik/grid')
util_inc_target = os.path.normpath(env['INSTALL_PREFIX']+'/include/mapnik/util')
if 'uninstall' not in COMMAND_LINE_TARGETS:
env.Alias(target='install', source=env.Install(inc_target, includes))
env.Alias(target='install', source=env.Install(svg_inc_target, svg_includes))
env.Alias(target='install', source=env.Install(wkt_inc_target, wkt_includes))
env.Alias(target='install', source=env.Install(grid_inc_target, grid_includes))
env.Alias(target='install', source=env.Install(util_inc_target, util_includes))
env['create_uninstall_target'](env, inc_target)
env['create_uninstall_target'](env, svg_inc_target)
env['create_uninstall_target'](env, wkt_inc_target)
env['create_uninstall_target'](env, grid_inc_target)
env['create_uninstall_target'](env, util_inc_target)

View file

@ -226,6 +226,10 @@ void datasource_cache::register_datasources(const std::string& str)
#endif
registered_=true;
}
else if (!ds_name)
{
std::clog << "Problem loading plugin library '" << itr->path().string() << "' (plugin is lacking compatible interface)" << std::endl;
}
}
else
{

View file

@ -255,10 +255,10 @@ void map_parser::parse_map( Map & map, ptree const & pt, std::string const& base
}
else
{
std::ostringstream s;
std::ostringstream s_err;
s << "failed to parse 'maximum-extent'";
if ( strict_ )
throw config_error(s.str());
throw config_error(s_err.str());
else
std::clog << "### WARNING: " << s.str() << std::endl;
}
@ -311,6 +311,7 @@ void map_parser::parse_map( Map & map, ptree const & pt, std::string const& base
}
}
map.set_extra_attributes(extra_attr);
}
catch (const config_error & ex)
@ -389,6 +390,32 @@ void map_parser::parse_map_include( Map & map, ptree const & include )
}
datasource_templates_[name] = params;
}
else if (v.first == "Parameters")
{
std::string name = get_attr(v.second, "name", std::string("Unnamed"));
parameters & params = map.get_extra_parameters();
ptree::const_iterator paramIter = v.second.begin();
ptree::const_iterator endParam = v.second.end();
for (; paramIter != endParam; ++paramIter)
{
ptree const& param = paramIter->second;
if (paramIter->first == "Parameter")
{
std::string name = get_attr<std::string>(param, "name");
std::string value = get_value<std::string>( param,
"parameter");
params[name] = value;
}
else if( paramIter->first != "<xmlattr>" &&
paramIter->first != "<xmlcomment>" )
{
throw config_error(std::string("Unknown child node in ") +
"'Parameters'. Expected 'Parameter' but got '" +
paramIter->first + "'");
}
}
}
else if (v.first != "<xmlcomment>" &&
v.first != "<xmlattr>")
{
@ -2185,43 +2212,42 @@ std::string map_parser::ensure_relative_to_xml( boost::optional<std::string> opt
void map_parser::ensure_attrs(ptree const& sym, std::string name, std::string attrs)
{
typedef ptree::key_type::value_type Ch;
//typedef boost::property_tree::xml_parser::xmlattr<Ch> x_att;
std::set<std::string> attr_set;
boost::split(attr_set, attrs, boost::is_any_of(","));
for (ptree::const_iterator itr = sym.begin(); itr != sym.end(); ++itr)
optional<const ptree &> attribs = sym.get_child_optional( boost::property_tree::xml_parser::xmlattr<Ch>() );
if (attribs)
{
//ptree::value_type const& v = *itr;
if (itr->first == boost::property_tree::xml_parser::xmlattr<Ch>())
{
optional<const ptree &> attribs = sym.get_child_optional( boost::property_tree::xml_parser::xmlattr<Ch>() );
if (attribs)
{
std::ostringstream s("");
s << "### " << name << " properties warning: ";
int missing = 0;
for (ptree::const_iterator it = attribs.get().begin(); it != attribs.get().end(); ++it)
{
std::string name = it->first;
bool found = (attr_set.find(name) != attr_set.end());
if (!found)
{
if (missing) s << ",";
s << "'" << name << "'";
++missing;
}
}
if (missing) {
if (missing > 1) s << " are";
else s << " is";
s << " invalid, acceptable values are:\n'" << attrs << "'\n";
std::clog << s.str();
}
}
}
}
std::set<std::string> attr_set;
boost::split(attr_set, attrs, boost::is_any_of(","));
std::ostringstream s("");
s << "### " << name << " properties warning: ";
int missing = 0;
for (ptree::const_iterator it = attribs.get().begin(); it != attribs.get().end(); ++it)
{
std::string name = it->first;
bool found = (attr_set.find(name) != attr_set.end());
if (!found)
{
if (missing)
{
s << ",";
}
s << "'" << name << "'";
++missing;
}
}
if (missing) {
if (missing > 1)
{
s << " are";
}
else
{
s << " is";
}
s << " invalid, acceptable values are:\n'" << attrs << "'\n";
std::clog << s.str();
}
}
}
} // end of namespace mapnik

View file

@ -92,7 +92,8 @@ Map::Map(const Map& rhs)
current_extent_(rhs.current_extent_),
maximum_extent_(rhs.maximum_extent_),
base_path_(rhs.base_path_),
extra_attr_(rhs.extra_attr_) {}
extra_attr_(rhs.extra_attr_),
extra_params_(rhs.extra_params_) {}
Map& Map::operator=(const Map& rhs)
{
@ -110,6 +111,7 @@ Map& Map::operator=(const Map& rhs)
maximum_extent_=rhs.maximum_extent_;
base_path_=rhs.base_path_;
extra_attr_=rhs.extra_attr_;
extra_params_=rhs.extra_params_;
return *this;
}
@ -677,9 +679,29 @@ parameters const& Map::get_extra_attributes() const
return extra_attr_;
}
void Map::set_extra_attributes(parameters& params)
parameters& Map::get_extra_attributes()
{
extra_attr_ = params;
return extra_attr_;
}
void Map::set_extra_attributes(parameters& attr)
{
extra_attr_ = attr;
}
parameters const& Map::get_extra_parameters() const
{
return extra_params_;
}
parameters& Map::get_extra_parameters()
{
return extra_params_;
}
void Map::set_extra_parameters(parameters& params)
{
extra_params_ = params;
}
}

View file

@ -120,11 +120,9 @@ void raster_colorizer::colorize(raster_ptr const& raster,const std::map<std::str
const std::map<std::string,value>::const_iterator fi = Props.find("NODATA");
if (fi != Props.end())
//if (Props.count("NODATA")>0)
{
hasNoData = true;
//noDataValue = Props.at("NODATA").to_double();
noDataValue = fi->second.to_double();
noDataValue = static_cast<float>(fi->second.to_double());
}
for (int i=0; i<len; ++i)
@ -138,9 +136,9 @@ void raster_colorizer::colorize(raster_ptr const& raster,const std::map<std::str
}
}
inline float interpolate(float start,float end, float fraction)
inline unsigned interpolate(unsigned start, unsigned end, float fraction)
{
return fraction * (end - start) + start;
return static_cast<unsigned>(fraction * (end - start) + start);
}
color raster_colorizer::get_color(float value) const {
@ -213,10 +211,10 @@ color raster_colorizer::get_color(float value) const {
else {
float fraction = (value - stopValue) / (nextStopValue - stopValue);
float r = interpolate(stopColor.red(), nextStopColor.red(),fraction);
float g = interpolate(stopColor.green(), nextStopColor.green(),fraction);
float b = interpolate(stopColor.blue(), nextStopColor.blue(),fraction);
float a = interpolate(stopColor.alpha(), nextStopColor.alpha(),fraction);
unsigned r = interpolate(stopColor.red(), nextStopColor.red(),fraction);
unsigned g = interpolate(stopColor.green(), nextStopColor.green(),fraction);
unsigned b = interpolate(stopColor.blue(), nextStopColor.blue(),fraction);
unsigned a = interpolate(stopColor.alpha(), nextStopColor.alpha(),fraction);
outputColor.set_red(r);
outputColor.set_green(g);

View file

@ -761,6 +761,24 @@ void serialize_datasource( ptree & layer_node, datasource_ptr datasource)
}
}
void serialize_parameters( ptree & map_node, mapnik::parameters const& params)
{
ptree & params_node = map_node.push_back(
ptree::value_type("Parameters", ptree()))->second;
parameters::const_iterator it = params.begin();
parameters::const_iterator end = params.end();
for (; it != end; ++it)
{
boost::property_tree::ptree & param_node = params_node.push_back(
boost::property_tree::ptree::value_type("Parameter",
boost::property_tree::ptree()))->second;
param_node.put("<xmlattr>.name", it->first );
param_node.put_value( it->second );
}
}
void serialize_layer( ptree & map_node, const layer & layer, bool explicit_defaults )
{
ptree & layer_node = map_node.push_back(
@ -900,6 +918,8 @@ void serialize_map(ptree & pt, Map const & map, bool explicit_defaults)
{
set_attr( map_node, p_it->first, p_it->second );
}
serialize_parameters( map_node, map.get_extra_parameters());
Map::const_style_iterator it = map.styles().begin();
Map::const_style_iterator end = map.styles().end();

View file

@ -0,0 +1,20 @@
<Map>
<!--
totally arbirary Parameters can also be attached to the map
which will be respected during serialization.
This makes it easier for calling applications that work with mapnik
xml, and leverage its serialization, to pass through directives that
the calling application needs which describe how to handle the map.
-->
<Parameters>
<Parameter name="key"><![CDATA[value]]></Parameter>
<!-- this one will override previous key with same name -->
<Parameter name="key"><![CDATA[value2]]></Parameter>
<Parameter name="key3"><![CDATA[value3]]></Parameter>
<Parameter name="unicode"><![CDATA[iván]]></Parameter>
</Parameters>
</Map>

View file

@ -0,0 +1,11 @@
<Map font-directory="." minimum-version="0.0.0">
<!--
font-directory and minimin-version are extra attributes known
to load_map which are and attached to the map object in order to be
carried through and respected by save map.
They are treated as 'extra' because they have no role during map rendering
-->
</Map>

View file

@ -0,0 +1,40 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from nose.tools import *
from utilities import execution_path
from Queue import Queue
import threading
import os, mapnik
import sqlite3
def setup():
# All of the paths used are relative, if we run the tests
# from another directory we need to chdir()
os.chdir(execution_path('.'))
def test_non_member_known_attributes():
m = mapnik.Map(256,256)
mapnik.load_map(m,'../data/good_maps/extra_known_map_attributes.xml')
attr = m.extra_attributes
eq_(len(attr),2)
eq_(attr['font-directory'],'.')
eq_(attr['minimum-version'],'0.0.0')
def test_arbitrary_parameters_attached_to_map():
m = mapnik.Map(256,256)
mapnik.load_map(m,'../data/good_maps/extra_arbitary_map_parameters.xml')
attr = m.extra_attributes
eq_(len(attr),0)
eq_(len(m.params),3)
eq_(m.params['key'],'value2')
eq_(m.params['key3'],'value3')
eq_(m.params['unicode'],u'iván')
if __name__ == "__main__":
setup()
[eval(run)() for run in dir() if 'test_' in run]

View file

@ -2,7 +2,7 @@
from nose.tools import *
import mapnik, pickle
import mapnik
# Tests that exercise fonts.

View file

@ -0,0 +1,45 @@
#encoding: utf8
from nose.tools import *
import os
from utilities import execution_path
import mapnik
wkts = [
[1,"POINT (30 10)"],
[1,"LINESTRING (30 10, 10 30, 40 40)"],
[1,"POLYGON ((30 10, 10 20, 20 40, 40 40, 30 10))"],
[1,"POLYGON ((35 10, 10 20, 15 40, 45 45, 35 10),(20 30, 35 35, 30 20, 20 30))"],
[4,"MULTIPOINT ((10 40), (40 30), (20 20), (30 10))"],
[2,"MULTILINESTRING ((10 10, 20 20, 10 40),(40 40, 30 30, 40 20, 30 10))"],
[2,"MULTIPOLYGON (((30 20, 10 40, 45 40, 30 20)),((15 5, 40 10, 10 20, 5 10, 15 5)))"],
[2,"MULTIPOLYGON (((40 40, 20 45, 45 30, 40 40)),((20 35, 45 20, 30 5, 10 10, 10 30, 20 35),(30 20, 20 25, 20 15, 30 20)))"]
]
def compare_wkb_from_wkt(wkt,num):
f = mapnik.Feature(1)
f.add_geometries_from_wkt(wkt)
eq_(len(f.geometries()),num)
paths = mapnik.Path.from_wkt(wkt)
eq_(len(paths),num)
eq_(f.geometries()[0].to_wkb(),paths[0].to_wkb())
paths2 = mapnik.Path()
for path in paths:
paths2.add_wkb(path.to_wkb())
eq_(len(paths2),num)
eq_(f.geometries()[0].to_wkb(),paths2[0].to_wkb())
def test_point():
for wkt in wkts:
try:
compare_wkb_from_wkt(wkt[1],wkt[0])
except RuntimeError, e:
raise RuntimeError('%s %s' % (e, wkt))
if __name__ == "__main__":
[eval(run)() for run in dir() if 'test_' in run]

View file

@ -5,8 +5,9 @@ import os
from nose.tools import *
from utilities import execution_path
from utilities import Todo
import tempfile
import mapnik, pickle
import mapnik
def setup():
# All of the paths used are relative, if we run the tests
@ -122,17 +123,6 @@ def test_pointsymbolizer_init():
#def test_pointsymbolizer_missing_image():
# p = mapnik.PointSymbolizer(mapnik.PathExpression("../data/images/broken.png"))
# PointSymbolizer pickling
def test_pointsymbolizer_pickle():
raise Todo("point_symbolizer pickling currently disabled")
p = mapnik.PointSymbolizer(mapnik.PathExpression("../data/images/dummy.png"))
p2 = pickle.loads(pickle.dumps(p,pickle.HIGHEST_PROTOCOL))
# image type, width, and height only used in contructor...
eq_(p.filename, p2.filename)
eq_(p.allow_overlap, p2.allow_overlap)
eq_(p.opacity, p2.opacity)
eq_(p.ignore_placement, p2.ignore_placement)
eq_(p.placement, p2.placement)
# PolygonSymbolizer initialization
def test_polygonsymbolizer_init():
@ -146,17 +136,6 @@ def test_polygonsymbolizer_init():
eq_(p.fill, mapnik.Color('blue'))
eq_(p.fill_opacity, 1)
# PolygonSymbolizer pickling
def test_polygonsymbolizer_pickle():
p = mapnik.PolygonSymbolizer(mapnik.Color('black'))
p.fill_opacity = .5
# does not work for some reason...
#eq_(pickle.loads(pickle.dumps(p)), p)
p2 = pickle.loads(pickle.dumps(p,pickle.HIGHEST_PROTOCOL))
eq_(p.fill, p2.fill)
eq_(p.fill_opacity, p2.fill_opacity)
# Stroke initialization
def test_stroke_init():
s = mapnik.Stroke()
@ -187,25 +166,6 @@ def test_stroke_dash_arrays():
eq_(s.get_dashes(), [(1,2),(3,4),(5,6)])
# Stroke pickling
def test_stroke_pickle():
s = mapnik.Stroke(mapnik.Color('black'),4.5)
eq_(s.width, 4.5)
eq_(s.color, mapnik.Color('black'))
s.add_dash(1,2)
s.add_dash(3,4)
s.add_dash(5,6)
s2 = pickle.loads(pickle.dumps(s,pickle.HIGHEST_PROTOCOL))
eq_(s.color, s2.color)
eq_(s.width, s2.width)
eq_(s.opacity, s2.opacity)
eq_(s.get_dashes(), s2.get_dashes())
eq_(s.line_cap, s2.line_cap)
eq_(s.line_join, s2.line_join)
# LineSymbolizer initialization
def test_linesymbolizer_init():
@ -234,19 +194,6 @@ def test_linesymbolizer_init():
eq_(l.stroke.line_cap, mapnik.line_cap.BUTT_CAP)
eq_(l.stroke.line_join, mapnik.line_join.MITER_JOIN)
# LineSymbolizer pickling
def test_linesymbolizer_pickle():
p = mapnik.LineSymbolizer()
p2 = pickle.loads(pickle.dumps(p,pickle.HIGHEST_PROTOCOL))
# line and stroke eq fails, so we compare attributes for now..
s,s2 = p.stroke, p2.stroke
eq_(s.color, s2.color)
eq_(s.opacity, s2.opacity)
eq_(s.width, s2.width)
eq_(s.get_dashes(), s2.get_dashes())
eq_(s.line_cap, s2.line_cap)
eq_(s.line_join, s2.line_join)
# TextSymbolizer initialization
def test_textsymbolizer_init():
@ -258,56 +205,6 @@ def test_textsymbolizer_init():
eq_(ts.fill, mapnik.Color('black'))
eq_(ts.label_placement, mapnik.label_placement.POINT_PLACEMENT)
# TextSymbolizer pickling
def test_textsymbolizer_pickle():
ts = mapnik.TextSymbolizer(mapnik.Expression('[Field_Name]'), 'Font Name', 8, mapnik.Color('black'))
eq_(str(ts.name), str(mapnik.Expression('[Field_Name]')))
eq_(ts.face_name, 'Font Name')
eq_(ts.text_size, 8)
eq_(ts.fill, mapnik.Color('black'))
raise Todo("text_symbolizer pickling currently disabled")
ts2 = pickle.loads(pickle.dumps(ts,pickle.HIGHEST_PROTOCOL))
eq_(ts.name, ts2.name)
eq_(ts.face_name, ts2.face_name)
eq_(ts.allow_overlap, ts2.allow_overlap)
eq_(ts.displacement, ts2.displacement)
eq_(ts.anchor, ts2.anchor)
eq_(ts.fill, ts2.fill)
eq_(ts.force_odd_labels, ts2.force_odd_labels)
eq_(ts.halo_fill, ts2.halo_fill)
eq_(ts.halo_radius, ts2.halo_radius)
eq_(ts.label_placement, ts2.label_placement)
eq_(ts.minimum_distance, ts2.minimum_distance)
eq_(ts.text_ratio, ts2.text_ratio)
eq_(ts.text_size, ts2.text_size)
eq_(ts.wrap_width, ts2.wrap_width)
eq_(ts.vertical_alignment, ts2.vertical_alignment)
eq_(ts.label_spacing, ts2.label_spacing)
eq_(ts.label_position_tolerance, ts2.label_position_tolerance)
# 22.5 * M_PI/180.0 initialized by default
assert_almost_equal(s.max_char_angle_delta, 0.39269908169872414)
eq_(ts.wrap_character, ts2.wrap_character)
eq_(ts.text_transform, ts2.text_transform)
eq_(ts.line_spacing, ts2.line_spacing)
eq_(ts.character_spacing, ts2.character_spacing)
# r1341
eq_(ts.wrap_before, ts2.wrap_before)
eq_(ts.horizontal_alignment, ts2.horizontal_alignment)
eq_(ts.justify_alignment, ts2.justify_alignment)
eq_(ts.opacity, ts2.opacity)
# r2300
eq_(s.minimum_padding, 0.0)
raise Todo("FontSet pickling support needed: http://trac.mapnik.org/ticket/348")
eq_(ts.fontset, ts2.fontset)
# Map initialization
def test_layer_init():
l = mapnik.Layer('test')
@ -365,11 +262,13 @@ def test_map_init_from_string():
eq_(m.base, './')
mapnik.load_map_from_string(m, map_string, False, "") # this "" will have no effect
eq_(m.base, './')
tmp_dir = tempfile.gettempdir()
try:
mapnik.load_map_from_string(m, map_string, False, "/tmp")
mapnik.load_map_from_string(m, map_string, False, tmp_dir)
except RuntimeError:
pass # runtime error expected because shapefile path should be wrong and datasource will throw
eq_(m.base, '/tmp') # /tmp will be set despite the exception because load_map mostly worked
eq_(m.base, tmp_dir) # tmp_dir will be set despite the exception because load_map mostly worked
m.base = 'foo'
mapnik.load_map_from_string(m, map_string, True, ".")
eq_(m.base, '.')
@ -379,19 +278,6 @@ def test_map_init_from_string():
if not 'Could not create datasource' in str(e):
raise RuntimeError(e)
# Map pickling
def test_map_pickle():
# Fails due to scale() not matching, possibly other things
raise(Todo("Map does not support pickling yet (Tickets #345)."))
m = mapnik.Map(256, 256)
eq_(pickle.loads(pickle.dumps(m)), m)
m = mapnik.Map(256, 256, '+proj=latlong')
eq_(pickle.loads(pickle.dumps(m)), m)
# Color initialization
@raises(Exception) # Boost.Python.ArgumentError
@ -503,21 +389,7 @@ def test_color_equality():
eq_(c1, mapnik.Color('red'))
eq_(c2, mapnik.Color('lime'))
eq_(c3, mapnik.Color(0,0,255,128))
# Color pickling
def test_color_pickle():
c = mapnik.Color('blue')
eq_(pickle.loads(pickle.dumps(c)), c)
c = mapnik.Color(0, 64, 128)
eq_(pickle.loads(pickle.dumps(c)), c)
c = mapnik.Color(0, 64, 128, 192)
eq_(pickle.loads(pickle.dumps(c)), c)
# Rule initialization
def test_rule_init():
@ -678,12 +550,6 @@ def test_envelope_static_init():
eq_(c.x, 150)
eq_(c.y, 150)
# Box2d pickling
def test_envelope_pickle():
e = mapnik.Box2d(100, 100, 200, 200)
eq_(pickle.loads(pickle.dumps(e)), e)
# Box2d multiplication
def test_envelope_multiplication():
e = mapnik.Box2d(100, 100, 200, 200)
@ -716,7 +582,7 @@ def test_envelope_multiplication():
eq_(c.y, 150)
# Box2d clipping
def test_envelope_pickle():
def test_envelope_clipping():
e1 = mapnik.Box2d(-180,-90,180,90)
e2 = mapnik.Box2d(-120,40,-110,48)
e1.clip(e2)

View file

@ -0,0 +1,53 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import os
from nose.tools import *
from utilities import execution_path
import mapnik
import pickle
def setup():
os.chdir(execution_path('.'))
def test_parameter():
p = mapnik.Parameter('key','value')
eq_(p[0],'key')
eq_(p[1],'value')
p = mapnik.Parameter('int',1)
eq_(p[0],'int')
eq_(p[1],1)
p = mapnik.Parameter('float',1.0777)
eq_(p[0],'float')
eq_(p[1],1.0777)
def test_parameters():
params = mapnik.Parameters()
p = mapnik.Parameter('float',1.0777)
eq_(p[0],'float')
eq_(p[1],1.0777)
params.append(p)
eq_(params[0][0],'float')
eq_(params[0][1],1.0777)
eq_(params.get('float'),1.0777)
def test_parameters_pickling():
params = mapnik.Parameters()
params.append(mapnik.Parameter('oh',str('yeah')))
params2 = pickle.loads(pickle.dumps(params,pickle.HIGHEST_PROTOCOL))
eq_(params[0][0],params2[0][0])
eq_(params[0][1],params2[0][1])
if __name__ == "__main__":
setup()
[eval(run)() for run in dir() if 'test_' in run]

View file

@ -0,0 +1,159 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import os
from nose.tools import *
from utilities import execution_path
from utilities import Todo
import tempfile
import mapnik, pickle
def setup():
# All of the paths used are relative, if we run the tests
# from another directory we need to chdir()
os.chdir(execution_path('.'))
# PointSymbolizer pickling
def test_pointsymbolizer_pickle():
raise Todo("point_symbolizer pickling currently disabled")
p = mapnik.PointSymbolizer(mapnik.PathExpression("../data/images/dummy.png"))
p2 = pickle.loads(pickle.dumps(p,pickle.HIGHEST_PROTOCOL))
# image type, width, and height only used in contructor...
eq_(p.filename, p2.filename)
eq_(p.allow_overlap, p2.allow_overlap)
eq_(p.opacity, p2.opacity)
eq_(p.ignore_placement, p2.ignore_placement)
eq_(p.placement, p2.placement)
# PolygonSymbolizer pickling
def test_polygonsymbolizer_pickle():
p = mapnik.PolygonSymbolizer(mapnik.Color('black'))
p.fill_opacity = .5
# does not work for some reason...
#eq_(pickle.loads(pickle.dumps(p)), p)
p2 = pickle.loads(pickle.dumps(p,pickle.HIGHEST_PROTOCOL))
eq_(p.fill, p2.fill)
eq_(p.fill_opacity, p2.fill_opacity)
# Stroke pickling
def test_stroke_pickle():
s = mapnik.Stroke(mapnik.Color('black'),4.5)
eq_(s.width, 4.5)
eq_(s.color, mapnik.Color('black'))
s.add_dash(1,2)
s.add_dash(3,4)
s.add_dash(5,6)
s2 = pickle.loads(pickle.dumps(s,pickle.HIGHEST_PROTOCOL))
eq_(s.color, s2.color)
eq_(s.width, s2.width)
eq_(s.opacity, s2.opacity)
eq_(s.get_dashes(), s2.get_dashes())
eq_(s.line_cap, s2.line_cap)
eq_(s.line_join, s2.line_join)
# LineSymbolizer pickling
def test_linesymbolizer_pickle():
p = mapnik.LineSymbolizer()
p2 = pickle.loads(pickle.dumps(p,pickle.HIGHEST_PROTOCOL))
# line and stroke eq fails, so we compare attributes for now..
s,s2 = p.stroke, p2.stroke
eq_(s.color, s2.color)
eq_(s.opacity, s2.opacity)
eq_(s.width, s2.width)
eq_(s.get_dashes(), s2.get_dashes())
eq_(s.line_cap, s2.line_cap)
eq_(s.line_join, s2.line_join)
# TextSymbolizer pickling
def test_textsymbolizer_pickle():
ts = mapnik.TextSymbolizer(mapnik.Expression('[Field_Name]'), 'Font Name', 8, mapnik.Color('black'))
eq_(str(ts.name), str(mapnik.Expression('[Field_Name]')))
eq_(ts.face_name, 'Font Name')
eq_(ts.text_size, 8)
eq_(ts.fill, mapnik.Color('black'))
raise Todo("text_symbolizer pickling currently disabled")
ts2 = pickle.loads(pickle.dumps(ts,pickle.HIGHEST_PROTOCOL))
eq_(ts.name, ts2.name)
eq_(ts.face_name, ts2.face_name)
eq_(ts.allow_overlap, ts2.allow_overlap)
eq_(ts.displacement, ts2.displacement)
eq_(ts.anchor, ts2.anchor)
eq_(ts.fill, ts2.fill)
eq_(ts.force_odd_labels, ts2.force_odd_labels)
eq_(ts.halo_fill, ts2.halo_fill)
eq_(ts.halo_radius, ts2.halo_radius)
eq_(ts.label_placement, ts2.label_placement)
eq_(ts.minimum_distance, ts2.minimum_distance)
eq_(ts.text_ratio, ts2.text_ratio)
eq_(ts.text_size, ts2.text_size)
eq_(ts.wrap_width, ts2.wrap_width)
eq_(ts.vertical_alignment, ts2.vertical_alignment)
eq_(ts.label_spacing, ts2.label_spacing)
eq_(ts.label_position_tolerance, ts2.label_position_tolerance)
# 22.5 * M_PI/180.0 initialized by default
assert_almost_equal(s.max_char_angle_delta, 0.39269908169872414)
eq_(ts.wrap_character, ts2.wrap_character)
eq_(ts.text_transform, ts2.text_transform)
eq_(ts.line_spacing, ts2.line_spacing)
eq_(ts.character_spacing, ts2.character_spacing)
# r1341
eq_(ts.wrap_before, ts2.wrap_before)
eq_(ts.horizontal_alignment, ts2.horizontal_alignment)
eq_(ts.justify_alignment, ts2.justify_alignment)
eq_(ts.opacity, ts2.opacity)
# r2300
eq_(s.minimum_padding, 0.0)
raise Todo("FontSet pickling support needed: http://trac.mapnik.org/ticket/348")
eq_(ts.fontset, ts2.fontset)
def test_map_pickle():
# Fails due to scale() not matching, possibly other things
raise(Todo("Map does not support pickling yet (Tickets #345)."))
m = mapnik.Map(256, 256)
eq_(pickle.loads(pickle.dumps(m)), m)
m = mapnik.Map(256, 256, '+proj=latlong')
eq_(pickle.loads(pickle.dumps(m)), m)
def test_color_pickle():
c = mapnik.Color('blue')
eq_(pickle.loads(pickle.dumps(c)), c)
c = mapnik.Color(0, 64, 128)
eq_(pickle.loads(pickle.dumps(c)), c)
c = mapnik.Color(0, 64, 128, 192)
eq_(pickle.loads(pickle.dumps(c)), c)
def test_envelope_pickle():
e = mapnik.Box2d(100, 100, 200, 200)
eq_(pickle.loads(pickle.dumps(e)), e)
if __name__ == "__main__":
setup()
[eval(run)() for run in dir() if 'test_' in run]

View file

@ -35,7 +35,7 @@ def psql_can_connect():
call('psql %s -c "select postgis_version()"' % POSTGIS_TEMPLATE_DBNAME)
return True
except RuntimeError, e:
print 'Notice: skipping postgis tests as basic auth is not correctly set up. Error was: %s' % e.message
print 'Notice: skipping postgis tests (connection)'
return False
def shp2pgsql_on_path():
@ -47,7 +47,7 @@ def shp2pgsql_on_path():
call('shp2pgsql')
return True
except RuntimeError, e:
print 'Notice: skipping postgis tests because shp2pgsql not found. Error was: %s' % e.message
print 'Notice: skipping postgis tests (shp2pgsql)'
return False
def createdb_and_dropdb_on_path():
@ -60,7 +60,7 @@ def createdb_and_dropdb_on_path():
call('dropdb --help')
return True
except RuntimeError, e:
print 'Notice: skipping postgis tests because createdb or dropdb not found. Error was: %s' % e.message
print 'Notice: skipping postgis tests (createdb/dropdb)'
return False
def postgis_setup():

View file

@ -2,7 +2,7 @@
from nose.tools import *
import mapnik, pickle
import mapnik
# Tests that exercise map projections.

View file

@ -2,10 +2,9 @@
# -*- coding: utf-8 -*-
from nose.tools import *
import tempfile
import os, mapnik
from nose.tools import *
from utilities import execution_path
from utilities import Todo
@ -216,7 +215,7 @@ def test_render_points():
p = mapnik.Projection(projs[projdescr])
m.zoom_to_box(p.forward(mapnik.Box2d(ul_lonlat,lr_lonlat)))
# Render to SVG so that it can be checked how many points are there with string comparison
svg_file = '/tmp/%s.svg'
svg_file = os.path.join(tempfile.gettempdir(),'%s.svg')
mapnik.render_to_file(m, svg_file)
num_points_present = len(places_ds.all_features())
svg = open(svg_file,'r').read()

View file

@ -42,9 +42,14 @@ if 'sqlite' in mapnik.DatasourceCache.instance().plugin_names():
eq_(os.path.exists(index),True)
conn = sqlite3.connect(index)
cur = conn.cursor()
cur.execute("Select count(*) from idx_%s_GEOMETRY" % TABLE.replace("'",""))
conn.commit()
eq_(cur.fetchone()[0],TOTAL)
try:
cur.execute("Select count(*) from idx_%s_GEOMETRY" % TABLE.replace("'",""))
conn.commit()
eq_(cur.fetchone()[0],TOTAL)
except sqlite3.OperationalError:
# don't worry about testing # of index records if
# python's sqlite module does not support rtree
pass
cur.close()
ds = mapnik.SQLite(file=DB,table=TABLE)

View file

@ -0,0 +1,19 @@
######################################################################
MAPNIK_INCLUDE_DIR = "/opt/mapnik/include" ;
MAPNIK_LIB_DIR = "/opt/mapnik/lib" ;
BOOST_INCLUDE_DIR = "/opt/boost_1_48_0/include" ;
lib mapnik : : <name>mapnik <search>$(MAPNIK_LIB_DIR) ;
lib icu : : <name>icuuc <search>/usr/local/lib ;
exe to_wkb :
main.cpp
.//mapnik
.//icu
:
<include>$(MAPNIK_INCLUDE_DIR)
<include>$(BOOST_INCLUDE_DIR)
;

View file

@ -0,0 +1,109 @@
/*****************************************************************************
*
* 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 <iostream>
#include <string>
#include <mapnik/geometry.hpp>
#include <mapnik/feature.hpp>
#include <mapnik/datasource_cache.hpp>
#include <mapnik/util/geometry_to_wkb.hpp>
#include <boost/foreach.hpp>
int main (int argc, char ** argv )
{
if ( argc !=2)
{
std::cerr << "Usage: " << argv[0] << " <path-to-shapefile>\n";
return EXIT_SUCCESS;
}
std::cerr << "Geometry to WKB converter\n";
mapnik::datasource_cache::instance()->register_datasources("/opt/mapnik/lib/mapnik/input/");
std::string filename(argv[1]);
std::cerr << filename << std::endl;
mapnik::parameters p;
p["type"] = "shape";
p["file"] = filename;
mapnik::datasource_ptr ds;
try
{
ds = mapnik::datasource_cache::instance()->create(p);
}
catch ( ... )
{
std::cerr << "Can't create datasource!\n";
return EXIT_FAILURE;
}
if (ds)
{
std::cerr << ds->envelope() << std::endl;
mapnik::query q(ds->envelope());
mapnik::layer_descriptor layer_desc = ds->get_descriptor();
BOOST_FOREACH ( mapnik::attribute_descriptor const& attr_desc, layer_desc.get_descriptors())
{
q.add_property_name(attr_desc.get_name());
}
mapnik::featureset_ptr fs = ds->features(q);
mapnik::feature_ptr f = fs->next();
while(f)
{
std::cerr << *f << std::endl;
boost::ptr_vector<mapnik::geometry_type> & paths = f->paths();
BOOST_FOREACH ( mapnik::geometry_type const& geom, paths)
{
// NDR
{
mapnik::util::wkb_buffer_ptr wkb = mapnik::util::to_wkb(geom,mapnik::util::wkbNDR);
std::cerr << mapnik::util::to_hex(wkb->buffer(),wkb->size()) << std::endl;
}
// XDR
{
mapnik::util::wkb_buffer_ptr wkb = mapnik::util::to_wkb(geom,mapnik::util::wkbXDR);
std::cerr << mapnik::util::to_hex(wkb->buffer(),wkb->size()) << std::endl;
}
}
f = fs->next();
}
}
return EXIT_SUCCESS;
}