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

This commit is contained in:
kunitoki 2011-10-22 02:24:39 +02:00
commit 8877c681c4
94 changed files with 1432 additions and 428 deletions

1
.gitignore vendored
View file

@ -1,3 +1,4 @@
*~
*.o
*.pyc
*.os

View file

@ -110,6 +110,50 @@ Mapnik 2.0.0
- Implement MarkersSymbolizer in Cairo render and improve the markers placement finder. (#553)
Mapnik 0.7.2 Release
--------------------
- Added forward compatibility for Mapnik 2.0 XML syntax (https://trac.mapnik.org/wiki/Mapnik2/Changes)
- Build fixes to ensure boost_threads are not used unless THREADING=multi build option is used
- Fixes for the clang compiler
- Support for latest libpng (>= 1.5.x) (r2999)
- Fixes to the postgres pool
- Fix for correct transparency levels in png256/png8 output (#540)
- Various build system fixes, especially for gcc compiler on open solaris.
- When plugins are not found, report the searched directories (#568)
- Improved font loading support (#559)
- Fix to shapeindex for allowing indexing of directory of shapefiles like `shapeindex dir/*shp`
- Fixed handling of null and multipatch shapes in shapefile driver - avoiding inf loop (#573)
- Fixed raster alpha blending (#589,#674)
- Enhanced support for faster reprojection if proj >= 4.8 is used (#575)
- Allow for late-binding of datasources (#622)
- Fix to OSM plugin to avoid over-caching of data (#542)
- Various fixes to sqlite, ogr, and occi driver backported from trunk.
- Ensured that '\n' triggers linebreaks in text rendering (#584)
- Support for boost filesystem v3
- Fixes to cairo renderer to avoid missing images (r2526)
- Fixed reading of label_position_tolerance on text_symbolizer and height for building_symbolizer
Mapnik 0.7.0 Release
--------------------

View file

@ -102,9 +102,8 @@ PLUGINS = { # plugins with external dependencies
# plugins without external dependencies requiring CheckLibWithHeader...
'shape': {'default':True,'path':None,'inc':None,'lib':None,'lang':'C++'},
'csv': {'default':False,'path':None,'inc':None,'lib':None,'lang':'C++'},
'csv': {'default':True,'path':None,'inc':None,'lib':None,'lang':'C++'},
'raster': {'default':True,'path':None,'inc':None,'lib':None,'lang':'C++'},
'csv': {'default':False,'path':None,'inc':None,'lib':None,'lang':'C++'},
'kismet': {'default':False,'path':None,'inc':None,'lib':None,'lang':'C++'},
}
@ -526,19 +525,13 @@ if sys.platform == "win32":
color_print(4,'\nWelcome to Mapnik...\n')
color_print(1,'*'*45)
color_print(1,'You are compiling Mapnik trunk (aka Mapnik2)')
color_print(1,'See important details at:\nhttp://trac.mapnik.org/wiki/Mapnik2')
color_print(1,('*'*45)+'\n')
#### Custom Configure Checks ###
def prioritize_paths(context,silent=True):
env = context.env
prefs = env['LINK_PRIORITY'].split(',')
if not silent:
context.Message( 'Sorting lib and inc compiler paths by priority... %s' % ','.join(prefs) )
context.Message( 'Sorting lib and inc compiler paths...')
env['LIBPATH'] = sort_paths(env['LIBPATH'],prefs)
env['CPPPATH'] = sort_paths(env['CPPPATH'],prefs)
if silent:
@ -839,10 +832,10 @@ int main()
major, minor = map(int,result.split('.'))
if major >= 4 and minor >= 0:
color_print(4,'\nFound icu version... %s\n' % result)
color_print(4,'found: icu %s' % result)
return True
color_print(1,'\nFound insufficient icu version... %s\n' % result)
color_print(1,'\nFound insufficient icu version... %s' % result)
return False
def boost_regex_has_icu(context):
@ -937,7 +930,7 @@ if not preconfigured:
opts.files.append(conf)
color_print(4,"SCons CONFIG found: '%s', variables will be inherited..." % conf)
optfile = file(conf)
print optfile.read().replace("\n", " ").replace("'","").replace(" = ","=")
#print optfile.read().replace("\n", " ").replace("'","").replace(" = ","=")
optfile.close()
elif not conf == SCONS_LOCAL_CONFIG:
@ -1305,10 +1298,12 @@ if not preconfigured:
env['HAS_CAIRO'] = False
env['SKIPPED_DEPS'].append('cairomm-version')
else:
print 'Checking for cairo/cairomm lib and include paths... ',
cmd = 'pkg-config --libs --cflags cairomm-1.0'
if env['RUNTIME_LINK'] == 'static':
cmd += ' --static'
cairo_env = env.Clone()
try:
cairo_env.ParseConfig(cmd)
for lib in cairo_env['LIBS']:
if not lib in env['LIBS']:
@ -1320,6 +1315,12 @@ if not preconfigured:
if not inc in env['CPPPATH']:
env["CAIROMM_CPPPATHS"].append(inc)
env['HAS_CAIRO'] = True
print 'yes'
except OSError,e:
color_print(1,'no')
env['SKIPPED_DEPS'].append('cairo')
env['SKIPPED_DEPS'].append('cairomm')
color_print(1,'pkg-config reported: %s' % e)
else:
color_print(4,'Not building with cairo support, pass CAIRO=True to enable')
@ -1433,7 +1434,7 @@ if not preconfigured:
if env['DEBUG']:
env.Append(CXXFLAGS = gcc_cxx_flags + '-O0 -fno-inline %s' % debug_flags)
else:
env.Append(CXXFLAGS = gcc_cxx_flags + '-O%s -finline-functions -Wno-inline %s' % (env['OPTIMIZATION'],ndebug_flags))
env.Append(CXXFLAGS = gcc_cxx_flags + '-O%s -finline-functions -Wno-inline -Wno-parentheses -Wno-char-subscripts %s' % (env['OPTIMIZATION'],ndebug_flags))
if 'python' in env['BINDINGS']:
if not os.access(env['PYTHON'], os.X_OK):
@ -1548,7 +1549,7 @@ if not preconfigured:
except: pass
if 'configure' in command_line_args:
color_print(4,'\n*Configure complete*\nNow run "python scons/scons.py" to build or "python scons/scons.py install" to install')
color_print(4,'\nConfigure completed: run `make` to build or `make install`')
if not HELP_REQUESTED:
Exit(0)

View file

@ -410,6 +410,13 @@ def Raster(**keywords):
Optional keyword arguments:
base -- path prefix (default None)
multi -- whether the image is in tiles on disk (default False)
Multi-tiled keyword arguments:
x_width -- virtual image number of tiles in X direction (required)
y_width -- virtual image number of tiles in Y direction (required)
tile_size -- if an image is in tiles, how large are the tiles (default 256)
tile_stride -- if an image is in tiles, what's the increment between rows/cols (default 1)
>>> from mapnik import Raster, Layer
>>> raster = Raster(base='/home/mapnik/data',file='elevation.tif',lox=-122.8,loy=48.5,hix=-122.7,hiy=48.6)

View file

@ -264,7 +264,6 @@ void export_envelope()
.def(self == self) // __eq__
.def(self != self) // __neq__
.def(self + self) // __add__
//.def(self - self) // __sub__
.def(self * float()) // __mult__
.def(float() * self)
.def(self / float()) // __div__

View file

@ -78,7 +78,6 @@ void export_geometry()
.def("envelope",&geometry_type::envelope)
// .def("__str__",&geometry_type::to_string)
.def("type",&geometry_type::type)
.def("area",&geometry_type::area)
// TODO add other geometry_type methods
;

View file

@ -46,7 +46,7 @@ void export_grid()
"Grid",
"This class represents a feature hitgrid.",
init<int,int,std::string,unsigned>(
( arg("width"),arg("height"),arg("key")="__id__",arg("resolution")=1 ),
( boost::python::arg("width"), boost::python::arg("height"),boost::python::arg("key")="__id__", boost::python::arg("resolution")=1 ),
"Create a mapnik.Grid object\n"
))
.def("painted",&painted)
@ -54,7 +54,7 @@ void export_grid()
.def("height",&mapnik::grid::height)
.def("view",&mapnik::grid::get_view)
.def("encode",encode,
( arg("encoding")="utf",arg("features")=true,arg("resolution")=4 ),
( boost::python::arg("encoding")="utf", boost::python::arg("features")=true,boost::python::arg("resolution")=4 ),
"Encode the grid as as optimized json\n"
)
.add_property("key",

View file

@ -45,7 +45,7 @@ void export_grid_view()
.def("width",&mapnik::grid_view::width)
.def("height",&mapnik::grid_view::height)
.def("encode",encode,
( arg("encoding")="utf",arg("add_features")=true,arg("resolution")=4 ),
( boost::python::arg("encoding")="utf",boost::python::arg("add_features")=true,boost::python::arg("resolution")=4 ),
"Encode the grid as as optimized json\n"
)
;

View file

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

View file

@ -66,6 +66,7 @@ void export_view_transform();
void export_raster_colorizer();
void export_glyph_symbolizer();
void export_inmem_metawriter();
void export_label_collision_detector();
#include <mapnik/version.hpp>
#include <mapnik/value_error.hpp>
@ -120,6 +121,28 @@ void render(const mapnik::Map& map,
Py_END_ALLOW_THREADS
}
void render_with_detector(
const mapnik::Map &map,
mapnik::image_32 &image,
boost::shared_ptr<mapnik::label_collision_detector4> detector,
double scale_factor = 1.0,
unsigned offset_x = 0u,
unsigned offset_y = 0u)
{
Py_BEGIN_ALLOW_THREADS
try
{
mapnik::agg_renderer<mapnik::image_32> ren(map,image,detector);
ren.apply();
}
catch (...)
{
Py_BLOCK_THREADS
throw;
}
Py_END_ALLOW_THREADS
}
void render_layer2(const mapnik::Map& map,
mapnik::image_32& image,
unsigned layer_idx)
@ -374,6 +397,7 @@ BOOST_PYTHON_FUNCTION_OVERLOADS(load_map_string_overloads, load_map_string, 2, 4
BOOST_PYTHON_FUNCTION_OVERLOADS(save_map_overloads, save_map, 2, 3)
BOOST_PYTHON_FUNCTION_OVERLOADS(save_map_to_string_overloads, save_map_to_string, 1, 2)
BOOST_PYTHON_FUNCTION_OVERLOADS(render_overloads, render, 2, 5)
BOOST_PYTHON_FUNCTION_OVERLOADS(render_with_detector_overloads, render_with_detector, 3, 6)
BOOST_PYTHON_MODULE(_mapnik2)
{
@ -427,6 +451,7 @@ BOOST_PYTHON_MODULE(_mapnik2)
export_raster_colorizer();
export_glyph_symbolizer();
export_inmem_metawriter();
export_label_collision_detector();
def("render_grid",&render_grid,
( arg("map"),
@ -503,6 +528,19 @@ BOOST_PYTHON_MODULE(_mapnik2)
"\n"
));
def("render_with_detector", &render_with_detector, render_with_detector_overloads(
"\n"
"Render Map to an AGG image_32 using a pre-constructed detector.\n"
"\n"
"Usage:\n"
">>> from mapnik import Map, Image, LabelCollisionDetector, render_with_detector, load_map\n"
">>> m = Map(256,256)\n"
">>> load_map(m,'mapfile.xml')\n"
">>> im = Image(m.width,m.height)\n"
">>> detector = LabelCollisionDetector(m)\n"
">>> render_with_detector(m, im, detector)\n"
));
def("render_layer", &render_layer2,
(arg("map"),arg("image"),args("layer"))
);

View file

@ -148,8 +148,8 @@ struct rule_pickle_suite : boost::python::pickle_suite
extract_symbolizer serializer( r );
for (int i=0;i<len(syms);++i)
{
symbolizer symbol = extract<symbolizer>(syms[i]);
boost::apply_visitor( serializer, symbol );
//symbolizer symbol = extract<symbolizer>(syms[i]);
//boost::apply_visitor( serializer, symbol );
}
}

View file

@ -43,7 +43,7 @@ template <class T>
void set_svg_transform(T& symbolizer, std::string const& transform_wkt)
{
agg::trans_affine tr;
if (!mapnik::svg::parse_transform(transform_wkt, tr))
if (!mapnik::svg::parse_transform(transform_wkt.c_str(), tr))
{
std::stringstream ss;
ss << "Could not parse transform from '" << transform_wkt << "', expected string like: 'matrix(1, 0, 0, 1, 0, 0)'";

View file

@ -50,12 +50,12 @@ static void grid2utf(T const& grid_type,
typename T::key_type::const_iterator key_pos;
typename T::feature_key_type::const_iterator feature_pos;
// start counting at utf8 codepoint 32, aka space character
uint16_t codepoint = 32;
boost::uint16_t codepoint = 32;
unsigned array_size = data.width();
for (unsigned y = 0; y < data.height(); ++y)
{
uint16_t idx = 0;
boost::uint16_t idx = 0;
boost::scoped_array<Py_UNICODE> line(new Py_UNICODE[array_size]);
typename T::value_type const* row = data.getRow(y);
for (unsigned x = 0; x < data.width(); ++x)
@ -103,13 +103,13 @@ static void grid2utf(T const& grid_type,
typename T::key_type::const_iterator key_pos;
typename T::feature_key_type::const_iterator feature_pos;
// start counting at utf8 codepoint 32, aka space character
uint16_t codepoint = 32;
boost::uint16_t codepoint = 32;
// TODO - use double?
unsigned array_size = static_cast<unsigned int>(grid_type.width()/resolution);
for (unsigned y = 0; y < grid_type.height(); y=y+resolution)
{
uint16_t idx = 0;
boost::uint16_t idx = 0;
boost::scoped_array<Py_UNICODE> line(new Py_UNICODE[array_size]);
mapnik::grid::value_type const* row = grid_type.getRow(y);
for (unsigned x = 0; x < grid_type.width(); x=x+resolution)

View file

@ -40,6 +40,7 @@
// boost
#include <boost/utility.hpp>
#include <boost/scoped_ptr.hpp>
#include <boost/shared_ptr.hpp>
// FIXME
// forward declare so that
@ -61,7 +62,11 @@ class MAPNIK_DECL agg_renderer : public feature_style_processor<agg_renderer<T>
{
public:
// create with default, empty placement detector
agg_renderer(Map const& m, T & pixmap, double scale_factor=1.0, unsigned offset_x=0, unsigned offset_y=0);
// create with external placement detector, possibly non-empty
agg_renderer(Map const &m, T & pixmap, boost::shared_ptr<label_collision_detector4> detector,
double scale_factor=1.0, unsigned offset_x=0, unsigned offset_y=0);
~agg_renderer();
void start_map_processing(Map const& map);
void end_map_processing(Map const& map);
@ -122,8 +127,10 @@ private:
CoordTransform t_;
freetype_engine font_engine_;
face_manager<freetype_engine> font_manager_;
label_collision_detector4 detector_;
boost::shared_ptr<label_collision_detector4> detector_;
boost::scoped_ptr<rasterizer> ras_ptr;
void setup(Map const &m);
};
}

View file

@ -41,9 +41,8 @@ namespace mapnik {
template <typename T> class MAPNIK_DECL box2d
: boost::equality_comparable<box2d<T> ,
boost::addable<box2d<T>,
boost::subtractable<box2d<T>,
boost::dividable2<box2d<T>, T,
boost::multipliable2<box2d<T>, T > > > > >
boost::multipliable2<box2d<T>, T > > > >
{
public:
typedef box2d<T> box2d_type;
@ -86,7 +85,6 @@ public:
// define some operators
box2d_type& operator+=(box2d_type const& other);
box2d_type& operator-=(box2d_type const& other);
box2d_type& operator*=(T);
box2d_type& operator/=(T);
T operator[](int index) const;

View file

@ -19,8 +19,7 @@
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*****************************************************************************/
//$Id: ctrans.hpp 39 2005-04-10 20:39:53Z pavlenko $
//$Id$
#ifndef CTRANS_HPP
#define CTRANS_HPP
@ -32,9 +31,12 @@
#include <mapnik/coord_array.hpp>
#include <mapnik/proj_transform.hpp>
namespace mapnik {
namespace mapnik
{
typedef coord_array<coord2d> CoordinateArray;
template <typename Transform, typename Geometry>
struct MAPNIK_DECL coord_transform
{
@ -58,6 +60,7 @@ private:
Geometry& geom_;
};
template <typename Transform, typename Geometry>
struct MAPNIK_DECL coord_transform2
{
@ -73,18 +76,17 @@ struct MAPNIK_DECL coord_transform2
unsigned vertex(double *x, double *y) const
{
unsigned command(SEG_MOVETO);
unsigned command = SEG_MOVETO;
bool ok = false;
bool skipped_points = false;
while (!ok)
double z = 0;
while (!ok && command != SEG_END)
{
command = geom_.vertex(x, y);
double z=0;
ok = prj_trans_.backward(*x, *y, z);
if (!ok) {
skipped_points = true;
}
ok = ok || (command == SEG_END);
}
if (skipped_points && (command == SEG_LINETO))
{
@ -94,15 +96,6 @@ struct MAPNIK_DECL coord_transform2
return command;
}
/*unsigned vertex(double * x , double * y) const
{
unsigned command = geom_.vertex(x,y);
double z=0;
prj_trans_.backward(*x,*y,z);
t_.forward(x,y);
return command;
}*/
void rewind(unsigned pos)
{
geom_.rewind(pos);
@ -156,6 +149,7 @@ private:
int dy_;
};
class CoordTransform
{
private:
@ -166,13 +160,15 @@ private:
box2d<double> extent_;
double offset_x_;
double offset_y_;
public:
CoordTransform(int width, int height, const box2d<double>& extent,
double offset_x = 0, double offset_y = 0)
:width_(width),height_(height),extent_(extent),offset_x_(offset_x),offset_y_(offset_y)
: width_(width), height_(height), extent_(extent),
offset_x_(offset_x), offset_y_(offset_y)
{
sx_ = (double(width_))/extent_.width();
sy_ = (double(height_))/extent_.height();
sx_ = static_cast<double>(width_) / extent_.width();
sy_ = static_cast<double>(height_) / extent_.height();
}
inline int width() const
@ -219,7 +215,8 @@ public:
return c;
}
inline box2d<double> forward(const box2d<double>& e,proj_transform const& prj_trans) const
inline box2d<double> forward(const box2d<double>& e,
proj_transform const& prj_trans) const
{
double x0 = e.minx();
double y0 = e.miny();
@ -244,7 +241,8 @@ public:
return box2d<double>(x0, y0, x1, y1);
}
inline box2d<double> backward(const box2d<double>& e,proj_transform const& prj_trans) const
inline box2d<double> backward(const box2d<double>& e,
proj_transform const& prj_trans) const
{
double x0 = e.minx();
double y0 = e.miny();
@ -286,6 +284,7 @@ public:
}
return coords;
}
inline box2d<double> const& extent() const
{
return extent_;

View file

@ -50,6 +50,7 @@
namespace mapnik
{
using namespace boost;
namespace qi = boost::spirit::qi;
namespace standard_wide = boost::spirit::standard_wide;
using standard_wide::space_type;
@ -217,7 +218,7 @@ struct expression_grammar : qi::grammar<Iterator, expr_node(), space_type>
| lit("false") [_val = false]
| lit("null") [_val = value_null() ]
| ustring [_val = unicode_(_1) ]
| attr [_val = construct<attribute>( _1 ) ]
| attr [_val = construct<mapnik::attribute>( _1 ) ]
| '(' >> expr [_val = _1 ] >> ')'
;

View file

@ -43,7 +43,7 @@ enum filter_mode_enum {
DEFINE_ENUM( filter_mode_e, filter_mode_enum );
typedef std::vector<rule> rules;
class feature_type_style
class MAPNIK_DECL feature_type_style
{
private:
rules rules_;

View file

@ -200,7 +200,7 @@ public:
void init(double radius)
{
FT_Stroker_Set(s_,radius * (1<<6),
FT_Stroker_Set(s_, (FT_Fixed) radius * (1<<6),
FT_STROKER_LINECAP_ROUND,
FT_STROKER_LINEJOIN_ROUND,
0);

View file

@ -69,26 +69,6 @@ public:
return type_;
}
double area() const
{
double sum = 0.0;
double x(0);
double y(0);
rewind(0);
double xs = x;
double ys = y;
for (unsigned i=0;i<num_points();++i)
{
double x0(0);
double y0(0);
vertex(&x0,&y0);
sum += x * y0 - y * x0;
x = x0;
y = y0;
}
return (sum + x * ys - y * xs) * 0.5;
}
box2d<double> envelope() const
{
box2d<double> result;

View file

@ -166,8 +166,21 @@ inline int rint( double val)
{
return int(floor(val + 0.5));
}
inline double round (double val)
{
return floor(val);
}
#define _USE_MATH_DEFINES
#ifndef M_PI
#define M_PI 3.14159265358979323846
#endif
#endif
}
#endif //GLOBAL_HPP

View file

@ -24,6 +24,7 @@
#define MAPNIK_GRID_HPP
// mapnik
#include <mapnik/config.hpp>
#include <mapnik/image_data.hpp>
#include <mapnik/box2d.hpp>
#include <mapnik/grid/grid_view.hpp>
@ -31,6 +32,9 @@
#include <mapnik/value.hpp>
#include <mapnik/feature.hpp>
// boost
#include <boost/cstdint.hpp>
// stl
#include <map>
#include <set>
@ -95,17 +99,17 @@ public:
~hit_grid() {}
void painted(bool painted)
inline void painted(bool painted)
{
painted_ = painted;
}
bool painted() const
inline bool painted() const
{
return painted_;
}
void add_feature(mapnik::Feature const& feature)
inline void add_feature(mapnik::Feature const& feature)
{
// copies feature props
@ -152,12 +156,12 @@ public:
}
}
void add_property_name(std::string const& name)
inline void add_property_name(std::string const& name)
{
names_.insert(name);
}
std::set<std::string> property_names() const
inline std::set<std::string> const& property_names() const
{
return names_;
}
@ -275,7 +279,7 @@ public:
inline void blendPixel(value_type feature_id,int x,int y,unsigned int rgba1,int t)
{
blendPixel2(x,y,rgba1,t,1.0); // do not change opacity
blendPixel2(feature_id ,x,y,rgba1,t,1.0); // do not change opacity
}
inline void blendPixel2(value_type feature_id,int x,int y,unsigned int rgba1,int t,double opacity)
@ -331,7 +335,7 @@ public:
};
typedef hit_grid<uint16_t> grid;
typedef MAPNIK_DECL hit_grid<boost::uint16_t> grid;
}
#endif //MAPNIK_GRID_HPP

View file

@ -30,6 +30,8 @@
#include <mapnik/global.hpp>
#include <mapnik/value.hpp>
// boost
#include <boost/cstdint.hpp>
// stl
#include <map>
#include <set>
@ -188,7 +190,7 @@ private:
feature_type const& features_;
};
typedef hit_grid_view<mapnik::ImageData<uint16_t> > grid_view;
typedef hit_grid_view<mapnik::ImageData<boost::uint16_t> > grid_view;
}

View file

@ -434,7 +434,7 @@ private:
}
tries=0;
// ignore leaves and also nodes with small mean error and not excessive number of pixels
if ((cur_node->reduce_cost / cur_node->pixel_count + 1) * std::log(long(cur_node->pixel_count)) > 15
if ((cur_node->reduce_cost / cur_node->pixel_count + 1) * std::log(double(cur_node->pixel_count)) > 15
&& cur_node->children_count > 0)
{
colors_--;

View file

@ -255,6 +255,8 @@ inline MAPNIK_DECL std::string save_to_string(image_32 const& image,
return save_to_string<image_data_32>(image.data(), type, palette);
}
///////////////////////////////////////////////////////////////////////////
#ifdef _MSC_VER
template MAPNIK_DECL void save_to_file<image_data_32>(image_data_32 const&,
std::string const&,
@ -263,19 +265,32 @@ template MAPNIK_DECL void save_to_file<image_data_32>(image_data_32 const&,
template MAPNIK_DECL void save_to_file<image_data_32>(image_data_32 const&,
std::string const&,
rgba_palette const&);
template MAPNIK_DECL void save_to_file<image_data_32>(image_data_32 const&,
std::string const&);
template MAPNIK_DECL void save_to_file<image_view<image_data_32> > (image_view<image_data_32> const&,
std::string const&,
std::string const&,
rgba_palette const&);
template MAPNIK_DECL void save_to_file<image_view<image_data_32> > (image_view<image_data_32> const&,
std::string const&,
std::string const&);
template MAPNIK_DECL void save_to_file<image_view<image_data_32> > (image_view<image_data_32> const&,
std::string const&,
rgba_palette const&);
template MAPNIK_DECL void save_to_file<image_view<image_data_32> > (image_view<image_data_32> const&,
std::string const&);
template MAPNIK_DECL std::string save_to_string<image_data_32>(image_data_32 const&,
std::string const&,
rgba_palette const&);
template MAPNIK_DECL void save_to_file<image_view<image_data_32> > (image_view<image_data_32> const&,
std::string const&,
std::string const&,
rgba_palette const&);
template MAPNIK_DECL void save_to_file<image_view<image_data_32> > (image_view<image_data_32> const&,
std::string const&,
rgba_palette const&);
template MAPNIK_DECL std::string save_to_string<image_view<image_data_32> > (image_view<image_data_32> const&,
std::string const&,
rgba_palette const&);

View file

@ -138,6 +138,7 @@ public:
//quad tree based label collission detector so labels dont appear within a given distance
class label_collision_detector4 : boost::noncopyable
{
public:
struct label
{
label(box2d<double> const& b) : box(b) {}
@ -147,10 +148,12 @@ class label_collision_detector4 : boost::noncopyable
UnicodeString text;
};
private:
typedef quad_tree< label > tree_t;
tree_t tree_;
public:
typedef tree_t::query_iterator query_iterator;
explicit label_collision_detector4(box2d<double> const& extent)
: tree_(extent) {}
@ -224,6 +227,9 @@ public:
{
return tree_.extent();
}
query_iterator begin() { return tree_.query_in_box(extent()); }
query_iterator end() { return tree_.query_end(); }
};
}

View file

@ -25,6 +25,7 @@
#define METAWRITER_INMEM_HPP
// mapnik
#include <mapnik/config.hpp>
#include <mapnik/metawriter.hpp>
// boost
@ -50,7 +51,7 @@ namespace mapnik {
* very common in the rendered image will increase memory usage, especially if
* many attributes are also kept.
*/
class metawriter_inmem
class MAPNIK_DECL metawriter_inmem
: public metawriter, private boost::noncopyable {
public:
/**
@ -87,7 +88,7 @@ public:
* are the intersection of the features' properties and the "kept"
* properties of the metawriter.
*/
struct meta_instance {
struct MAPNIK_DECL meta_instance {
box2d<double> box;
std::map<std::string, value> properties;
};

View file

@ -26,6 +26,7 @@
// mapnik
#include <mapnik/config.hpp>
#include <mapnik/global.hpp>
#include <mapnik/config_error.hpp>
@ -124,7 +125,7 @@ struct rgba
typedef boost::unordered_map<unsigned, unsigned> rgba_hash_table;
class rgba_palette : private boost::noncopyable {
class MAPNIK_DECL rgba_palette : private boost::noncopyable {
public:
enum palette_type { PALETTE_RGBA = 0, PALETTE_RGB = 1, PALETTE_ACT = 2 };

View file

@ -24,6 +24,7 @@
#define MAPNIK_PARSE_PATH_HPP
// mapnik
#include <mapnik/config.hpp>
#include <mapnik/attribute.hpp>
#include <mapnik/feature.hpp>
#include <mapnik/value.hpp>
@ -41,7 +42,7 @@ typedef boost::variant<std::string, attribute> path_component;
typedef std::vector<path_component> path_expression;
typedef boost::shared_ptr<path_expression> path_expression_ptr;
path_expression_ptr parse_path(std::string const & str);
MAPNIK_DECL path_expression_ptr parse_path(std::string const & str);
template <typename T>
struct path_processor

View file

@ -51,7 +51,7 @@
namespace mapnik
{
using namespace boost;
namespace qi = boost::spirit::qi;
namespace phoenix = boost::phoenix;
namespace standard_wide = boost::spirit::standard_wide;
@ -79,7 +79,7 @@ struct path_expression_grammar : qi::grammar<Iterator, std::vector<path_componen
* (
str [ push_back(_val, _1)]
|
( '[' >> attr [ push_back(_val, construct<attribute>( _1 )) ] >> ']')
( '[' >> attr [ push_back(_val, construct<mapnik::attribute>( _1 )) ] >> ']')
)
;

View file

@ -68,7 +68,7 @@ enum colorizer_mode_enum
DEFINE_ENUM( colorizer_mode, colorizer_mode_enum );
//! \brief Structure to represent a stop position.
class colorizer_stop {
class MAPNIK_DECL colorizer_stop {
public:
//! \brief Constructor
@ -142,7 +142,7 @@ typedef std::vector<colorizer_stop> colorizer_stops;
//! \brief Class representing the raster colorizer
class raster_colorizer {
class MAPNIK_DECL raster_colorizer {
public:
//! \brief Constructor
raster_colorizer(colorizer_mode mode = COLORIZER_LINEAR, const color& _color = color(0,0,0,0));

View file

@ -23,11 +23,15 @@
#ifndef SVG_COMMANDS_HPP
#define SVG_COMMANDS_HPP
// mapnik
#include <mapnik/global.hpp>
//
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix_function.hpp>
#include <boost/spirit/include/phoenix_core.hpp>
#include <boost/spirit/include/phoenix_operator.hpp>
namespace mapnik { namespace svg {
using namespace boost::fusion;

View file

@ -23,6 +23,7 @@
#ifndef SVG_PATH_PARSER_HPP
#define SVG_PATH_PARSER_HPP
#include <mapnik/config.hpp>
#include <string>
namespace mapnik { namespace svg {
@ -34,10 +35,10 @@ template <typename PathType>
bool parse_points(const char * wkt, PathType & p);
template <typename TransformType>
bool parse_transform(const char * wkt, TransformType & tr);
bool MAPNIK_DECL parse_transform(const char * wkt, TransformType & tr);
template <typename TransformType>
bool parse_transform(std::string const& wkt, TransformType & tr);
//template <typename TransformType>
//bool MAPNIK_DECL parse_transform(std::string const& wkt, TransformType & tr);
}}

View file

@ -25,7 +25,8 @@
#ifndef SVG_TRANSFORM_GRAMMAR_HPP
#define SVG_TRANSFORM_GRAMMAR_HPP
// mapnik
#include <mapnik/global.hpp>
// agg
#include <agg_trans_affine.h>
// spirit
@ -35,7 +36,6 @@
#include <boost/spirit/include/phoenix_operator.hpp>
#include <boost/spirit/home/phoenix/object/construct.hpp>
namespace mapnik { namespace svg {
using namespace boost::spirit;

View file

@ -23,6 +23,7 @@
#define TEXT_PLACEMENTS_HPP
//mapnik
#include <mapnik/config.hpp>
#include <mapnik/enumeration.hpp>
//stl
@ -154,14 +155,14 @@ typedef boost::shared_ptr<text_placements> text_placements_ptr;
class text_placements_info_dummy;
class text_placements_dummy: public text_placements
class MAPNIK_DECL text_placements_dummy: public text_placements
{
public:
text_placement_info_ptr get_placement_info() const;
friend class text_placement_info_dummy;
};
class text_placement_info_dummy : public text_placement_info
class MAPNIK_DECL text_placement_info_dummy : public text_placement_info
{
public:
text_placement_info_dummy(text_placements_dummy const* parent) : text_placement_info(parent),

View file

@ -47,12 +47,10 @@ struct MAPNIK_DECL text_symbolizer : public symbolizer_base
{
text_symbolizer(expression_ptr name, std::string const& face_name,
unsigned size, color const& fill,
text_placements_ptr placements = text_placements_ptr(
boost::make_shared<text_placements_dummy>())
text_placements_ptr placements = boost::make_shared<text_placements_dummy>()
);
text_symbolizer(expression_ptr name, unsigned size, color const& fill,
text_placements_ptr placements = text_placements_ptr(
boost::make_shared<text_placements_dummy>())
text_placements_ptr placements = boost::make_shared<text_placements_dummy>()
);
text_symbolizer(text_symbolizer const& rhs);
text_symbolizer& operator=(text_symbolizer const& rhs);

View file

@ -25,9 +25,12 @@
#define VALUE_HPP
// mapnik
#include <mapnik/global.hpp>
#include <mapnik/unicode.hpp>
#include <mapnik/config_error.hpp>
// boost
#include <boost/variant.hpp>
#include <boost/scoped_array.hpp>
#include <boost/concept_check.hpp>
@ -49,9 +52,9 @@ inline void to_utf8(UnicodeString const& input, std::string & target)
{
if (input.length() == 0) return;
const int32_t BUF_SIZE = 256;
const int BUF_SIZE = 256;
char buf [BUF_SIZE];
int32_t len;
int len;
UErrorCode err = U_ZERO_ERROR;
u_strToUTF8(buf, BUF_SIZE, &len, input.getBuffer(), input.length(), &err);
@ -106,10 +109,9 @@ struct equals
bool operator() (value_null, value_null) const
{
// this changed from false to true - see http://trac.mapnik.org/ticket/794
// this changed from false to true - https://github.com/mapnik/mapnik/issues/794
return true;
}
};
struct not_equals
@ -145,21 +147,21 @@ struct not_equals
bool operator() (value_null, value_null) const
{
// TODO - needs review http://trac.mapnik.org/ticket/794
// TODO - needs review - https://github.com/mapnik/mapnik/issues/794
return false;
}
template <typename T>
bool operator() (value_null, const T &) const
{
// TODO - needs review http://trac.mapnik.org/ticket/794
// TODO - needs review - https://github.com/mapnik/mapnik/issues/794
return false;
}
template <typename T>
bool operator() (const T &, value_null) const
{
// TODO - needs review http://trac.mapnik.org/ticket/794
// TODO - needs review - https://github.com/mapnik/mapnik/issues/794
return false;
}
};
@ -533,7 +535,7 @@ struct to_bool : public boost::static_visitor<bool>
template <typename T>
bool operator() (T val) const
{
return bool(val);
return val > 0 ? true : false;
}
};

View file

@ -23,13 +23,16 @@
#ifndef MAPNIK_WKT_FACTORY_HPP
#define MAPNIK_WKT_FACTORY_HPP
#include <string>
// mapnik
#include <mapnik/config.hpp>
#include <mapnik/geometry.hpp>
#include <boost/ptr_container/ptr_vector.hpp>
// stl
#include <string>
namespace mapnik {
bool from_wkt(std::string const& wkt, boost::ptr_vector<geometry_type> & paths);
MAPNIK_DECL bool from_wkt(std::string const& wkt, boost::ptr_vector<geometry_type> & paths);
}

View file

@ -115,7 +115,6 @@ void csv_datasource::bind() const
parse_csv(in,escape_, separator_, quote_);
in.close();
}
is_bound_ = true;
}
@ -124,11 +123,12 @@ void csv_datasource::parse_csv(T& stream,
std::string const& escape,
std::string const& separator,
std::string const& quote) const
{
if (filesize_max_ > 0)
{
stream.seekg (0, std::ios::end);
int file_length_ = stream.tellg();
if (filesize_max_ > 0)
{
double file_mb = static_cast<double>(file_length_)/1048576;
// throw if this is an unreasonably large file to read into memory
@ -140,35 +140,49 @@ void csv_datasource::parse_csv(T& stream,
<< " to render this data (set 'filesize_max=0' to disable this restriction if you have lots of memory)";
throw mapnik::datasource_exception(s.str());
}
}
// set back to start
stream.seekg (0, std::ios::beg);
}
char newline;
std::string csv_line;
// autodetect newlines
bool found_break = false;
if (std::getline(stream,csv_line,'\n'))
char newline = '\n';
int newline_count = 0;
int carriage_count = 0;
for(std::size_t idx = 0; idx < file_length_; idx++)
{
found_break = true;
newline = '\n';
char c = static_cast<char>(stream.get());
if (c == '\n')
{
++newline_count;
}
else if (std::getline(stream,csv_line,'\r'))
else if (c == '\r')
{
++carriage_count;
}
// read at least 2000 bytes before testing
if (idx == file_length_-1 || idx > 4000)
{
if (newline_count > carriage_count)
{
break;
}
else if (carriage_count > newline_count)
{
found_break = true;
newline = '\r';
break;
}
}
else
{
throw mapnik::datasource_exception("CSV Plugin: could not detect any line breaks in this csv (http://en.wikipedia.org/wiki/Newline)\n");
}
// set back to start
stream.seekg (0, std::ios::beg);
// if user has not passed separator manuall
// get first line
std::string csv_line;
std::getline(stream,csv_line,newline);
// if user has not passed a separator manually
// then attempt to detect by reading first line
std::string sep = boost::trim_copy(separator);
if (sep.empty())
@ -190,6 +204,9 @@ void csv_datasource::parse_csv(T& stream,
}
}
// set back to start
stream.seekg (0, std::ios::beg);
typedef boost::escaped_list_separator<char> escape_type;
std::string esc = boost::trim_copy(escape);
@ -239,12 +256,17 @@ void csv_datasource::parse_csv(T& stream,
wkt_idx = idx;
has_wkt_field = true;
}
if (lower_val == "x" || (lower_val.find("longitude") != std::string::npos))
if (lower_val == "x"
|| lower_val == "lon"
|| lower_val == "long"
|| (lower_val.find("longitude") != std::string::npos))
{
lon_idx = idx;
has_lon_field = true;
}
if (lower_val == "y" || (lower_val.find("latitude") != std::string::npos))
if (lower_val == "y"
|| lower_val == "lat"
|| (lower_val.find("latitude") != std::string::npos))
{
lat_idx = idx;
has_lat_field = true;
@ -293,12 +315,17 @@ void csv_datasource::parse_csv(T& stream,
wkt_idx = idx;
has_wkt_field = true;
}
if (lower_val == "x" || (lower_val.find("longitude") != std::string::npos))
if (lower_val == "x"
|| lower_val == "lon"
|| lower_val == "long"
|| (lower_val.find("longitude") != std::string::npos))
{
lon_idx = idx;
has_lon_field = true;
}
if (lower_val == "y" || (lower_val.find("latitude") != std::string::npos))
if (lower_val == "y"
|| lower_val == "lat"
|| (lower_val.find("latitude") != std::string::npos))
{
lat_idx = idx;
has_lat_field = true;
@ -322,7 +349,7 @@ void csv_datasource::parse_csv(T& stream,
if (!has_wkt_field && (!has_lon_field || !has_lat_field) )
{
std::ostringstream s;
s << "CSV Plugin: could not detect column headers with the name of 'wkt' or lat/lon - this is required for reading geometry data";
s << "CSV Plugin: could not detect column headers with the name of wkt ,x/y, or latitude/longitude - this is required for reading geometry data";
throw mapnik::datasource_exception(s.str());
}
@ -373,7 +400,6 @@ void csv_datasource::parse_csv(T& stream,
bool parsed_x = false;
bool parsed_y = false;
bool parsed_wkt = false;
bool first_feature = true;
bool skip = false;
bool null_geom = false;
std::vector<std::string> collected;
@ -433,7 +459,20 @@ void csv_datasource::parse_csv(T& stream,
}
else
{
std::clog << "could not parse: " << value << "\n";
std::ostringstream s;
s << "CSV Plugin: expected well known text geometry: could not parse row "
<< line_number
<< ",column "
<< i << " - found: '"
<< value << "'";
if (strict_)
{
throw mapnik::datasource_exception(s.str());
}
else
{
if (!quiet_) std::clog << s.str() << "\n";
}
}
}
else
@ -538,11 +577,16 @@ void csv_datasource::parse_csv(T& stream,
boost::put(*feature,fld_name,mapnik::value_null());
}
// only true strings are this long
else if (value_length > 20)
else if (value_length > 20
// TODO - clean up this messiness which is here temporarily
// to protect against the improperly working spirit parsing below
|| value.find(",") != std::string::npos
|| value.find(":") != std::string::npos
|| (std::count(value.begin(), value.end(), '-') > 1))
{
UnicodeString ustr = tr.transcode(value.c_str());
boost::put(*feature,fld_name,ustr);
if (first_feature)
if (!feature_count)
desc_.add_descriptor(mapnik::attribute_descriptor(fld_name,mapnik::String));
}
@ -557,14 +601,14 @@ void csv_datasource::parse_csv(T& stream,
if (value.find(".") != std::string::npos)
{
boost::put(*feature,fld_name,float_val);
if (first_feature)
if (!feature_count)
desc_.add_descriptor(mapnik::attribute_descriptor(fld_name,mapnik::Double));
}
else
{
int val = static_cast<int>(float_val);
boost::put(*feature,fld_name,val);
if (first_feature)
if (!feature_count)
desc_.add_descriptor(mapnik::attribute_descriptor(fld_name,mapnik::Integer));
}
}
@ -573,22 +617,23 @@ void csv_datasource::parse_csv(T& stream,
// fallback to normal string
UnicodeString ustr = tr.transcode(value.c_str());
boost::put(*feature,fld_name,ustr);
if (first_feature)
if (!feature_count)
desc_.add_descriptor(mapnik::attribute_descriptor(fld_name,mapnik::String));
}
}
else
{
if (value == "true")
std::string value_lower = boost::algorithm::to_lower_copy(value);
if (value_lower == "true")
{
boost::put(*feature,fld_name,true);
if (first_feature)
if (!feature_count)
desc_.add_descriptor(mapnik::attribute_descriptor(fld_name,mapnik::Boolean));
}
else if(value == "false")
else if(value_lower == "false")
{
boost::put(*feature,fld_name,false);
if (first_feature)
if (!feature_count)
desc_.add_descriptor(mapnik::attribute_descriptor(fld_name,mapnik::Boolean));
}
else
@ -596,14 +641,12 @@ void csv_datasource::parse_csv(T& stream,
// fallback to normal string
UnicodeString ustr = tr.transcode(value.c_str());
boost::put(*feature,fld_name,ustr);
if (first_feature)
if (!feature_count)
desc_.add_descriptor(mapnik::attribute_descriptor(fld_name,mapnik::String));
}
}
}
first_feature = false;
if (skip)
{
++line_number;

View file

@ -241,14 +241,18 @@ void occi_featureset::convert_geometry (SDOGeometry* geom, feature_ptr feature,
{
if (ordinates_size >= dimensions)
{
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,
true, // is_single_geom
false, // is_point_type
false); // multiple_geometries
is_single_geom,
is_point_type,
multiple_geoms);
}
}
break;
@ -256,14 +260,18 @@ void occi_featureset::convert_geometry (SDOGeometry* geom, feature_ptr feature,
{
if (ordinates_size >= dimensions)
{
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,
true, // is_single_geom
false, // is_point_type
false); // multiple_geometries
is_single_geom,
is_point_type,
multiple_geoms);
}
}
break;
@ -273,6 +281,7 @@ void occi_featureset::convert_geometry (SDOGeometry* geom, feature_ptr feature,
{
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
@ -282,9 +291,9 @@ void occi_featureset::convert_geometry (SDOGeometry* geom, feature_ptr feature,
elem_info,
ordinates,
dimensions,
false, // is_single_geom
true, // is_point_type
true); // multiple_geometries
is_single_geom,
is_point_type,
multiple_geoms);
}
}
break;
@ -292,13 +301,16 @@ void occi_featureset::convert_geometry (SDOGeometry* geom, feature_ptr feature,
{
if (ordinates_size >= dimensions)
{
const bool is_single_geom = false;
const bool is_point_type = false;
convert_ordinates (feature,
mapnik::LineString,
elem_info,
ordinates,
dimensions,
false, // is_single_geom
false, // is_point_type
is_single_geom,
is_point_type,
multiple_geometries);
}
@ -308,13 +320,16 @@ void occi_featureset::convert_geometry (SDOGeometry* geom, feature_ptr feature,
{
if (ordinates_size >= dimensions)
{
const bool is_single_geom = false;
const bool is_point_type = false;
convert_ordinates (feature,
mapnik::Polygon,
elem_info,
ordinates,
dimensions,
false, // is_single_geom
false, // is_point_type
is_single_geom,
is_point_type,
multiple_geometries);
}
@ -332,8 +347,8 @@ void occi_featureset::convert_geometry (SDOGeometry* geom, feature_ptr feature,
elem_info,
ordinates,
dimensions,
false, // is_single_geom,
false, // is_point_type
is_single_geom,
is_point_type,
multiple_geometries);
}
}

View file

@ -65,6 +65,10 @@ raster_datasource::raster_datasource(const parameters& params, bool bind)
else
filename_ = *file;
multi_tiles_ = *params_.get<bool>("multi", false);
tile_size_ = *params_.get<unsigned>("tile_size", 256);
tile_stride_ = *params_.get<unsigned>("tile_stride", 1);
format_=*params_.get<std::string>("format","tiff");
boost::optional<double> lox = params_.get<double>("lox");
@ -96,6 +100,22 @@ void raster_datasource::bind() const
{
if (is_bound_) return;
if (multi_tiles_)
{
boost::optional<unsigned> x_width = params_.get<unsigned>("x_width");
boost::optional<unsigned> y_width = params_.get<unsigned>("y_width");
if (!x_width)
throw datasource_exception("Raster Plugin: x-width parameter not supplied for multi-tiled data source.");
if (!y_width)
throw datasource_exception("Raster Plugin: y-width parameter not supplied for multi-tiled data source.");
width_ = x_width.get() * tile_size_;
height_ = y_width.get() * tile_size_;
}
else
{
if (! boost::filesystem::exists(filename_))
throw datasource_exception("Raster Plugin: " + filename_ + " does not exist");
@ -106,10 +126,6 @@ void raster_datasource::bind() const
{
width_ = reader->width();
height_ = reader->height();
#ifdef MAPNIK_DEBUG
std::clog << "Raster Plugin: RASTER SIZE(" << width_ << "," << height_ << ")" << std::endl;
#endif
}
}
catch (mapnik::image_reader_exception const& ex)
@ -122,6 +138,11 @@ void raster_datasource::bind() const
std::cerr << "Raster Plugin: exception caught" << std::endl;
throw;
}
}
#ifdef MAPNIK_DEBUG
std::clog << "Raster Plugin: RASTER SIZE(" << width_ << "," << height_ << ")" << std::endl;
#endif
is_bound_ = true;
}
@ -165,7 +186,16 @@ featureset_ptr raster_datasource::features(query const& q) const
std::clog << "Raster Plugin: BOX SIZE(" << width << " " << height << ")" << std::endl;
#endif
if (width * height > 512*512)
if (multi_tiles_)
{
#ifdef MAPNIK_DEBUG
std::clog << "Raster Plugin: MULTI-TILED policy" << std::endl;
#endif
tiled_multi_file_policy policy(filename_, format_, tile_size_, extent_, q.get_bbox(), width_, height_, tile_stride_);
return boost::make_shared<raster_featureset<tiled_multi_file_policy> >(policy, extent_, q);
}
else if (width * height > 512*512)
{
#ifdef MAPNIK_DEBUG
std::clog << "Raster Plugin: TILED policy" << std::endl;

View file

@ -37,6 +37,9 @@ class raster_datasource : public mapnik::datasource
std::string format_;
mapnik::box2d<double> extent_;
bool extent_initialized_;
bool multi_tiles_;
unsigned tile_size_;
unsigned tile_stride_;
mutable unsigned width_;
mutable unsigned height_;
public:

View file

@ -27,6 +27,7 @@
#include "raster_featureset.hpp"
#include <boost/algorithm/string/replace.hpp>
using mapnik::query;
using mapnik::CoordTransform;
@ -67,16 +68,18 @@ feature_ptr raster_featureset<LookupPolicy>::next()
std::clog << "Raster Plugin: READER = " << curIter_->format() << " " << curIter_->file()
<< " size(" << curIter_->width() << "," << curIter_->height() << ")" << std::endl;
#endif
if (reader.get())
{
int image_width=reader->width();
int image_height=reader->height();
int image_width = policy_.img_width(reader->width());
int image_height = policy_.img_height(reader->height());
if (image_width>0 && image_height>0)
{
CoordTransform t(image_width,image_height,extent_,0,0);
box2d<double> intersect=bbox_.intersect(curIter_->envelope());
box2d<double> ext=t.forward(intersect);
box2d<double> rem=policy_.transform(ext);
if ( ext.width()>0.5 && ext.height()>0.5 )
{
//select minimum raster containing whole ext
@ -96,7 +99,8 @@ feature_ptr raster_featureset<LookupPolicy>::next()
int width = end_x - x_off;
int height = end_y - y_off;
//calculate actual box2d of returned raster
box2d<double> feature_raster_extent(x_off, y_off, x_off+width, y_off+height);
box2d<double> feature_raster_extent(rem.minx() + x_off, rem.miny() + y_off,
rem.maxx() + x_off + width, rem.maxy() + y_off + height);
intersect = t.backward(feature_raster_extent);
image_data_32 image(width,height);
@ -121,5 +125,20 @@ feature_ptr raster_featureset<LookupPolicy>::next()
return feature_ptr();
}
std::string
tiled_multi_file_policy::interpolate(std::string const &pattern, int x, int y) const
{
// TODO: make from some sort of configurable interpolation
int tms_y = tile_stride_ * ((image_height_ / tile_size_) - y - 1);
int tms_x = tile_stride_ * x;
std::string xs = (boost::format("%03d/%03d/%03d") % (tms_x / 1000000) % ((tms_x / 1000) % 1000) % (tms_x % 1000)).str();
std::string ys = (boost::format("%03d/%03d/%03d") % (tms_y / 1000000) % ((tms_y / 1000) % 1000) % (tms_y % 1000)).str();
std::string rv(pattern);
boost::algorithm::replace_all(rv, "${x}", xs);
boost::algorithm::replace_all(rv, "${y}", ys);
return rv;
}
template class raster_featureset<single_file_policy>;
template class raster_featureset<tiled_file_policy>;
template class raster_featureset<tiled_multi_file_policy>;

View file

@ -29,7 +29,7 @@
// boost
#include <boost/utility.hpp>
#include <boost/format.hpp>
class single_file_policy
{
@ -95,6 +95,21 @@ public:
{
return const_iterator();
}
inline int img_width(int reader_width) const
{
return reader_width;
}
inline int img_height(int reader_height) const
{
return reader_height;
}
inline box2d<double> transform(box2d<double> &) const
{
return box2d<double>(0, 0, 0, 0);
}
};
class tiled_file_policy
@ -154,11 +169,125 @@ public:
return infos_.end();
}
inline int img_width(int reader_width) const
{
return reader_width;
}
inline int img_height(int reader_height) const
{
return reader_height;
}
inline box2d<double> transform(box2d<double> &) const
{
return box2d<double>(0, 0, 0, 0);
}
private:
std::vector<raster_info> infos_;
};
class tiled_multi_file_policy
{
public:
typedef std::vector<raster_info>::const_iterator const_iterator;
tiled_multi_file_policy(std::string const& file_pattern, std::string const& format, unsigned tile_size,
box2d<double> extent, box2d<double> bbox,unsigned width, unsigned height,
unsigned tile_stride)
: image_width_(width), image_height_(height), tile_size_(tile_size), tile_stride_(tile_stride)
{
double lox = extent.minx();
double loy = extent.miny();
int max_x = int(std::ceil(double(width)/double(tile_size)));
int max_y = int(std::ceil(double(height)/double(tile_size)));
double pixel_x = extent.width()/double(width);
double pixel_y = extent.height()/double(height);
#ifdef MAPNIK_DEBUG
std::clog << "Raster Plugin: PIXEL SIZE("<< pixel_x << "," << pixel_y << ")" << std::endl;
#endif
// intersection of query with extent => new query
box2d<double> e = bbox.intersect(extent);
const int x_min = int(std::floor((e.minx() - lox) / (tile_size * pixel_x)));
const int y_min = int(std::floor((e.miny() - loy) / (tile_size * pixel_y)));
const int x_max = int(std::ceil((e.maxx() - lox) / (tile_size * pixel_x)));
const int y_max = int(std::ceil((e.maxy() - loy) / (tile_size * pixel_y)));
for (int x = x_min ; x < x_max ; ++x)
{
for (int y = y_min ; y < y_max ; ++y)
{
// x0, y0, x1, y1 => projection-space image coordinates.
double x0 = lox + x*tile_size*pixel_x;
double y0 = loy + y*tile_size*pixel_y;
double x1 = x0 + tile_size*pixel_x;
double y1 = y0 + tile_size*pixel_y;
// check if it intersects the query
if (e.intersects(box2d<double>(x0,y0,x1,y1)))
{
// tile_box => intersection of tile with query in projection-space.
box2d<double> tile_box = e.intersect(box2d<double>(x0,y0,x1,y1));
std::string file = interpolate(file_pattern, x, y);
raster_info info(file,format,tile_box,tile_size,tile_size);
infos_.push_back(info);
}
}
}
#ifdef MAPNIK_DEBUG
std::clog << "Raster Plugin: INFO SIZE=" << infos_.size() << " " << file_pattern << std::endl;
#endif
}
const_iterator begin()
{
return infos_.begin();
}
const_iterator end()
{
return infos_.end();
}
inline int img_width(int) const
{
return image_width_;
}
inline int img_height(int) const
{
return image_height_;
}
inline box2d<double> transform(box2d<double> &box) const
{
int x_offset = int(std::floor(box.minx() / tile_size_));
int y_offset = int(std::floor(box.miny() / tile_size_));
box2d<double> rem(x_offset * tile_size_, y_offset * tile_size_,
x_offset * tile_size_, y_offset * tile_size_);
box.init(box.minx() - rem.minx(),
box.miny() - rem.miny(),
box.maxx() - rem.maxx(),
box.maxy() - rem.maxy());
return rem;
}
private:
std::string interpolate(std::string const &pattern, int x, int y) const;
unsigned int image_width_, image_height_, tile_size_, tile_stride_;
std::vector<raster_info> infos_;
};
template <typename LookupPolicy>
class raster_featureset : public mapnik::Featureset

View file

@ -32,6 +32,7 @@
// boost
#include <boost/shared_ptr.hpp>
#include <boost/algorithm/string.hpp>
// sqlite
extern "C" {
@ -45,13 +46,11 @@ class sqlite_utils
{
public:
static void dequote(std::string& s)
static void dequote(std::string & z)
{
if (s[0] == '[' || s[0] == '\'' || s[0] == '"' || s[0] == '`')
{
s = s.substr(1, s.length() - 1);
}
boost::algorithm::trim_if(z,boost::algorithm::is_any_of("[]'\"`"));
}
};
@ -135,9 +134,8 @@ public:
const char* column_text (int col, int& len)
{
const char* text = (const char*) sqlite3_column_text (stmt_, col);
len = sqlite3_column_bytes (stmt_, col);
return text;
return (const char*) sqlite3_column_text (stmt_, col);
}
const char* column_text (int col)
@ -147,9 +145,8 @@ public:
const void* column_blob (int col, int& bytes)
{
const char* blob = (const char*) sqlite3_column_blob (stmt_, col);
bytes = sqlite3_column_bytes (stmt_, col);
return blob;
return (const char*) sqlite3_column_blob (stmt_, col);
}
sqlite3_stmt* get_statement()

View file

@ -73,7 +73,7 @@
// boost
#include <boost/utility.hpp>
#include <boost/make_shared.hpp>
// stl
#ifdef MAPNIK_DEBUG
@ -121,8 +121,31 @@ agg_renderer<T>::agg_renderer(Map const& m, T & pixmap, double scale_factor, uns
t_(m.width(),m.height(),m.get_current_extent(),offset_x,offset_y),
font_engine_(),
font_manager_(font_engine_),
detector_(box2d<double>(-m.buffer_size(), -m.buffer_size(), m.width() + m.buffer_size() ,m.height() + m.buffer_size())),
detector_(boost::make_shared<label_collision_detector4>(box2d<double>(-m.buffer_size(), -m.buffer_size(), m.width() + m.buffer_size() ,m.height() + m.buffer_size()))),
ras_ptr(new rasterizer)
{
setup(m);
}
template <typename T>
agg_renderer<T>::agg_renderer(Map const& m, T & pixmap, boost::shared_ptr<label_collision_detector4> detector,
double scale_factor, unsigned offset_x, unsigned offset_y)
: feature_style_processor<agg_renderer>(m, scale_factor),
pixmap_(pixmap),
width_(pixmap_.width()),
height_(pixmap_.height()),
scale_factor_(scale_factor),
t_(m.width(),m.height(),m.get_current_extent(),offset_x,offset_y),
font_engine_(),
font_manager_(font_engine_),
detector_(detector),
ras_ptr(new rasterizer)
{
setup(m);
}
template <typename T>
void agg_renderer<T>::setup(Map const &m)
{
boost::optional<color> const& bg = m.background();
if (bg) pixmap_.set_background(*bg);
@ -189,7 +212,7 @@ void agg_renderer<T>::start_layer_processing(layer const& lay)
#endif
if (lay.clear_label_cache())
{
detector_.clear();
detector_->clear();
}
}

View file

@ -77,12 +77,12 @@ void agg_renderer<T>::process(glyph_symbolizer const& sym,
// final box so we can check for a valid placement
box2d<double> dim = ren.prepare_glyphs(path.get());
box2d<double> ext(x-dim.width()/2, y-dim.height()/2, x+dim.width()/2, y+dim.height()/2);
if ((sym.get_allow_overlap() || detector_.has_placement(ext)) &&
(!sym.get_avoid_edges() || detector_.extent().contains(ext)))
if ((sym.get_allow_overlap() || detector_->has_placement(ext)) &&
(!sym.get_avoid_edges() || detector_->extent().contains(ext)))
{
// Placement is valid, render glyph and update detector.
ren.render(x, y);
detector_.insert(ext);
detector_->insert(ext);
metawriter_with_properties writer = sym.get_metawriter();
if (writer.first) writer.first->add_box(ext, feature, t_, writer.second);
}

View file

@ -109,7 +109,7 @@ void agg_renderer<T>::process(markers_symbolizer const& sym,
}
path_type path(t_,geom,prj_trans);
markers_placement<path_type, label_collision_detector4> placement(path, extent, detector_,
markers_placement<path_type, label_collision_detector4> placement(path, extent, *detector_,
sym.get_spacing() * scale_factor_,
sym.get_max_error(),
sym.get_allow_overlap());
@ -194,7 +194,7 @@ void agg_renderer<T>::process(markers_symbolizer const& sym,
box2d<double> label_ext (px, py, px + dx +1, py + dy +1);
if (sym.get_allow_overlap() ||
detector_.has_placement(label_ext))
detector_->has_placement(label_ext))
{
agg::ellipse c(x, y, w, h);
marker.concat_path(c);
@ -215,7 +215,7 @@ void agg_renderer<T>::process(markers_symbolizer const& sym,
ren.color(agg::rgba8(s_r, s_g, s_b, int(s_a*stroke_.get_opacity())));
agg::render_scanlines(*ras_ptr, sl_line, ren);
}
detector_.insert(label_ext);
detector_->insert(label_ext);
if (writer.first) writer.first->add_box(label_ext, feature, t_, writer.second);
}
}
@ -226,7 +226,7 @@ void agg_renderer<T>::process(markers_symbolizer const& sym,
marker.concat_path(arrow_);
path_type path(t_,geom,prj_trans);
markers_placement<path_type, label_collision_detector4> placement(path, extent, detector_,
markers_placement<path_type, label_collision_detector4> placement(path, extent, *detector_,
sym.get_spacing() * scale_factor_,
sym.get_max_error(),
sym.get_allow_overlap());

View file

@ -99,13 +99,13 @@ void agg_renderer<T>::process(point_symbolizer const& sym,
label_ext.re_center(x,y);
if (sym.get_allow_overlap() ||
detector_.has_placement(label_ext))
detector_->has_placement(label_ext))
{
render_marker(floor(x - 0.5 * w),floor(y - 0.5 * h) ,**marker,tr, sym.get_opacity());
if (!sym.get_ignore_placement())
detector_.insert(label_ext);
detector_->insert(label_ext);
metawriter_with_properties writer = sym.get_metawriter();
if (writer.first) writer.first->add_box(label_ext, feature, t_, writer.second);
}

View file

@ -135,7 +135,7 @@ void agg_renderer<T>::process(shield_symbolizer const& sym,
ren.set_halo_radius(sym.get_halo_radius() * scale_factor_);
ren.set_opacity(sym.get_text_opacity());
placement_finder<label_collision_detector4> finder(detector_);
placement_finder<label_collision_detector4> finder(*detector_);
string_info info(text);
@ -210,13 +210,13 @@ void agg_renderer<T>::process(shield_symbolizer const& sym,
label_ext.re_center(label_x,label_y);
}
if ( sym.get_allow_overlap() || detector_.has_placement(label_ext) )
if ( sym.get_allow_overlap() || detector_->has_placement(label_ext) )
{
render_marker(px,py,**marker,tr,sym.get_opacity());
box2d<double> dim = ren.prepare_glyphs(&text_placement.placements[0]);
ren.render(x,y);
detector_.insert(label_ext);
detector_->insert(label_ext);
finder.update_detector(text_placement);
if (writer.first) {
writer.first->add_box(label_ext, feature, t_, writer.second);

View file

@ -110,7 +110,7 @@ void agg_renderer<T>::process(text_symbolizer const& sym,
ren.set_opacity(sym.get_text_opacity());
box2d<double> dims(0,0,width_,height_);
placement_finder<label_collision_detector4> finder(detector_,dims);
placement_finder<label_collision_detector4> finder(*detector_,dims);
string_info info(text);

View file

@ -384,14 +384,6 @@ box2d<T>& box2d<T>::operator+=(box2d<T> const& other)
return *this;
}
/*
template <typename T>
box2d<T>& box2d<T>::operator-=(box2d<T> const& other)
{
// not sure what to do here. intersect?
return *this;
}
*/
template <typename T>
box2d<T>& box2d<T>::operator*=(T t)

View file

@ -173,5 +173,7 @@ void grid_renderer<T>::render_marker(Feature const& feature, unsigned int step,
pixmap_.add_feature(feature);
}
template class hit_grid<boost::uint16_t>;
template class grid_renderer<grid>;
}

View file

@ -896,7 +896,7 @@ void map_parser::parse_point_symbolizer( rule & rule, ptree const & sym )
if (transform_wkt)
{
agg::trans_affine tr;
if (!mapnik::svg::parse_transform(*transform_wkt,tr))
if (!mapnik::svg::parse_transform((*transform_wkt).c_str(),tr))
{
std::stringstream ss;
ss << "Could not parse transform from '" << transform_wkt
@ -1025,7 +1025,7 @@ void map_parser::parse_markers_symbolizer( rule & rule, ptree const & sym )
if (transform_wkt)
{
agg::trans_affine tr;
if (!mapnik::svg::parse_transform(*transform_wkt,tr))
if (!mapnik::svg::parse_transform((*transform_wkt).c_str(),tr))
{
std::stringstream ss;
ss << "Could not parse transform from '" << transform_wkt
@ -1671,7 +1671,7 @@ void map_parser::parse_shield_symbolizer( rule & rule, ptree const & sym )
if (transform_wkt)
{
agg::trans_affine tr;
if (!mapnik::svg::parse_transform(*transform_wkt,tr))
if (!mapnik::svg::parse_transform((*transform_wkt).c_str(),tr))
{
std::stringstream ss;
ss << "Could not parse transform from '" << transform_wkt << "', expected string like: 'matrix(1, 0, 0, 1, 0, 0)'";

View file

@ -23,6 +23,7 @@
//$Id$
// mapnik
#include <mapnik/global.hpp>
#include <mapnik/proj_transform.hpp>
#include <mapnik/coord.hpp>
#include <mapnik/utils.hpp>

View file

@ -118,10 +118,13 @@ void raster_colorizer::colorize(raster_ptr const& raster,const std::map<std::str
bool hasNoData = false;
float noDataValue = 0;
if (Props.count("NODATA")>0)
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 = Props.at("NODATA").to_double();
noDataValue = fi->second.to_double();
}
for (int i=0; i<len; ++i)

View file

@ -42,6 +42,7 @@ bool parse_transform(const char * wkt, TransformType & p)
return qi::phrase_parse(first, last, g, skip_type());
}
/*
template <typename TransformType>
bool parse_transform(std::string const& wkt, TransformType & p)
{
@ -53,8 +54,9 @@ bool parse_transform(std::string const& wkt, TransformType & p)
iterator_type last = wkt.end();
return qi::phrase_parse(first, last, g, skip_type());
}
*/
template bool parse_transform<agg::trans_affine>(const char*, agg::trans_affine&);
template bool parse_transform<agg::trans_affine>(std::string const& , agg::trans_affine&);
template MAPNIK_DECL bool parse_transform<agg::trans_affine>(const char*, agg::trans_affine&);
//template bool parse_transform<agg::trans_affine>(std::string const& , agg::trans_affine&);
}}

View file

@ -168,7 +168,7 @@ void text_placements_simple::set_positions(std::string positions)
std::string::iterator first = positions.begin(), last = positions.end();
qi::phrase_parse(first, last,
(direction_name[push_back(ref(direction_), _1)] % ',') >> *(',' >> qi::int_[push_back(ref(text_sizes_), _1)]),
(direction_name[push_back(phoenix::ref(direction_), _1)] % ',') >> *(',' >> qi::int_[push_back(phoenix::ref(text_sizes_), _1)]),
space
);
if (first != last) {

View file

@ -29,6 +29,7 @@
// boost
#include <boost/utility.hpp>
#include <boost/format.hpp>
namespace mapnik
{
@ -56,7 +57,14 @@ public:
wkbMultiPoint=4,
wkbMultiLineString=5,
wkbMultiPolygon=6,
wkbGeometryCollection=7
wkbGeometryCollection=7,
wkbPointZ=1001,
wkbLineStringZ=1002,
wkbPolygonZ=1003,
wkbMultiPointZ=1004,
wkbMultiLineStringZ=1005,
wkbMultiPolygonZ=1006,
wkbGeometryCollectionZ=1007
};
wkb_reader(const char* wkb,unsigned size, wkbFormat format)
@ -68,10 +76,9 @@ public:
// try to determine WKB format automatically
if (format_ == wkbAuto)
{
if (size > 38
&& wkb_[0] == 0x00
&& (wkb_[1] == 0x00 || wkb_[1] == 0x01)
&& wkb_[38] == 0x7C)
if (size >= 44
&& (unsigned char)(wkb_[0]) == (unsigned char)(0x00)
&& (unsigned char)(wkb_[38]) == (unsigned char)(0x7C))
{
format_ = wkbSpatiaLite;
}
@ -86,12 +93,18 @@ public:
case wkbSpatiaLite:
byteOrder_ = (wkbByteOrder) wkb_[1];
pos_ = 39;
#ifdef MAPNIK_DEBUG_WKB
std::clog << "wkb_reader: format is wkbSpatiaLite" << std::endl;
#endif
break;
case wkbGeneric:
default:
byteOrder_ = (wkbByteOrder) wkb_[0];
pos_ = 1;
#ifdef MAPNIK_DEBUG_WKB
std::clog << "wkb_reader: format is wkbGeneric" << std::endl;
#endif
break;
}
@ -107,6 +120,12 @@ public:
void read_multi(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;
#endif
switch (type)
{
case wkbPoint:
@ -130,6 +149,27 @@ public:
case wkbGeometryCollection:
read_collection(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(paths);
break;
case wkbMultiLineStringZ:
read_multilinestring_xyz(paths);
break;
case wkbMultiPolygonZ:
read_multipolygon_xyz(paths);
break;
case wkbGeometryCollectionZ:
read_collection(paths);
break;
default:
break;
}
@ -138,6 +178,11 @@ public:
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:
@ -161,6 +206,27 @@ public:
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;
}
@ -202,11 +268,14 @@ private:
void read_coords(CoordinateArray& ar)
{
int size=sizeof(coord<double,2>)*ar.size();
if (! needSwap_)
{
std::memcpy(&ar[0],wkb_+pos_,size);
pos_+=size;
for (unsigned i = 0; i < ar.size(); ++i)
{
read_double_ndr(wkb_ + pos_, ar[i].x);
read_double_ndr(wkb_ + pos_ + 8, ar[i].y);
pos_ += 16; // skip XY
}
}
else
{
@ -214,11 +283,33 @@ private:
{
read_double_xdr(wkb_ + pos_, ar[i].x);
read_double_xdr(wkb_ + pos_ + 8, ar[i].y);
pos_ += 16;
pos_ += 16; // skip XY
}
}
}
void read_coords_xyz(CoordinateArray& ar)
{
if (! needSwap_)
{
for (unsigned i = 0; i < ar.size(); ++i)
{
read_double_ndr(wkb_ + pos_, ar[i].x);
read_double_ndr(wkb_ + pos_ + 8, ar[i].y);
pos_ += 24; // skip XYZ
}
}
else
{
for (unsigned i = 0; i < ar.size(); ++i)
{
read_double_xdr(wkb_ + pos_, ar[i].x);
read_double_xdr(wkb_ + pos_ + 8, ar[i].y);
pos_ += 24; // skip XYZ
}
}
}
void read_point(boost::ptr_vector<geometry_type> & paths)
{
@ -253,6 +344,42 @@ private:
paths.push_back(pt);
}
void read_point_xyz(boost::ptr_vector<geometry_type> & paths)
{
geometry_type* pt = new geometry_type(Point);
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_multipoint_xyz(boost::ptr_vector<geometry_type> & paths)
{
int num_points = read_integer();
for (int i = 0; i < num_points; ++i)
{
pos_ += 5;
read_point_xyz(paths);
}
}
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);
@ -300,6 +427,54 @@ private:
paths.push_back(line);
}
void read_linestring_xyz(boost::ptr_vector<geometry_type> & paths)
{
geometry_type* line = new geometry_type(LineString);
int num_points = read_integer();
CoordinateArray ar(num_points);
read_coords_xyz(ar);
line->set_capacity(num_points);
line->move_to(ar[0].x, ar[0].y);
for (int i = 1; i < num_points; ++i)
{
line->line_to(ar[i].x, ar[i].y);
}
paths.push_back(line);
}
void read_multilinestring_xyz(boost::ptr_vector<geometry_type> & paths)
{
int num_lines = read_integer();
for (int i = 0; i < num_lines; ++i)
{
pos_ += 5;
read_linestring_xyz(paths);
}
}
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);
@ -358,6 +533,65 @@ private:
paths.push_back(poly);
}
void read_polygon_xyz(boost::ptr_vector<geometry_type> & paths)
{
geometry_type* poly = new geometry_type(Polygon);
int num_rings = read_integer();
unsigned capacity = 0;
for (int i = 0; i < num_rings; ++i)
{
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);
}
}
paths.push_back(poly);
}
void read_multipolygon_xyz(boost::ptr_vector<geometry_type> & paths)
{
int num_polys = read_integer();
for (int i = 0; i < num_polys; ++i)
{
pos_ += 5;
read_polygon_xyz(paths);
}
}
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();
@ -377,6 +611,35 @@ private:
read_multi(paths);
}
}
#ifdef MAPNIK_DEBUG_WKB
std::string wkb_geometry_type_string(int type)
{
std::stringstream s;
switch (type)
{
case wkbPoint: s << "wkbPoint"; break;
case wkbLineString: s << "wkbLineString"; break;
case wkbPolygon: s << "wkbPolygon"; break;
case wkbMultiPoint: s << "wkbMultiPoint"; break;
case wkbMultiLineString: s << "wkbMultiLineString"; break;
case wkbMultiPolygon: s << "wkbMultiPolygon"; break;
case wkbGeometryCollection: s << "wkbGeometryCollection"; break;
case wkbPointZ: s << "wkbPointZ"; break;
case wkbLineStringZ: s << "wkbLineStringZ"; break;
case wkbPolygonZ: s << "wkbPolygonZ"; break;
case wkbMultiPointZ: s << "wkbMultiPointZ"; break;
case wkbMultiLineStringZ: s << "wkbMultiLineStringZ"; break;
case wkbMultiPolygonZ: s << "wkbMultiPolygonZ"; break;
case wkbGeometryCollectionZ: s << "wkbGeometryCollectionZ"; break;
default: s << "wkbUknown"; break;
}
return s.str();
}
#endif
};
void geometry_utils::from_wkb (boost::ptr_vector<geometry_type>& paths,
@ -387,8 +650,12 @@ void geometry_utils::from_wkb (boost::ptr_vector<geometry_type>& paths,
{
wkb_reader reader(wkb, size, format);
if (multiple_geometries)
{
return reader.read_multi(paths);
}
else
{
return reader.read(paths);
}
}
}

View file

@ -0,0 +1,9 @@
x,y,name
0,0,a
0,0,b
1 x y name
2 0 0 a
3 0 0 b

View file

@ -0,0 +1,5 @@
x,y,text,date,integer,boolean,float,time,datetime,empty_column
0,0,a b,1971-01-01,40,True,1.0,04:14:00,1971-01-01T04:14:00,
0,0,c d,1948-01-01,63,True,1.27,14:57:13,1948-01-01T14:57:13,
0,0,e f,1920-01-01,164,False,41800000.01,00:00:00,1920-01-01T00:00:00,
0,0,This row has empties,,,,,,,
1 x y text date integer boolean float time datetime empty_column
2 0 0 a b 1971-01-01 40 True 1.0 04:14:00 1971-01-01T04:14:00
3 0 0 c d 1948-01-01 63 True 1.27 14:57:13 1948-01-01T14:57:13
4 0 0 e f 1920-01-01 164 False 41800000.01 00:00:00 1920-01-01T00:00:00
5 0 0 This row has empties

View file

@ -0,0 +1 @@

View file

@ -0,0 +1,3 @@
x,y,z
-122a,48b,bogus
-122,48,fine
1 x y z
2 -122a 48b bogus
3 -122 48 fine

View file

@ -0,0 +1,2 @@
wkt,name
"POINT (a b)",one
1 wkt name
2 POINT (a b) one

View file

@ -0,0 +1,2 @@
x y name
-122, 48, hello
1 x y name
2 -122, 48, hello

View file

@ -0,0 +1,2 @@
a,b,c,d,e,f,g
1,2,3,4,5,6,7
1 a b c d e f g
2 1 2 3 4 5 6 7

View file

@ -0,0 +1 @@
-122,48,place
1 -122 48 place

View file

@ -0,0 +1,4 @@
x,y,name
0,0,a/a
1,4,b/b
10,2.5,c/c
1 x y name
2 0 0 a/a
3 1 4 b/b
4 10 2.5 c/c

View file

@ -0,0 +1,2 @@
latitude,longitude
0,0
1 latitude longitude
2 0 0

View file

@ -0,0 +1,2 @@
this_is_longitude_yo,this_is_latitude_yo
0,0
1 this_is_longitude_yo this_is_latitude_yo
2 0 0

View file

@ -0,0 +1,2 @@
lon,lat
0,0
1 lon lat
2 0 0

View file

@ -0,0 +1,2 @@
long,lat
0,0
1 long lat
2 0 0

View file

@ -0,0 +1 @@
x,y,z 1,10,0
1 x y z 1 10 0

3
tests/data/csv/tabs.tsv Normal file
View file

@ -0,0 +1,3 @@
x y name
-122 48 hello
0 0 "null island"
1 x y name
2 -122 48 hello
3 0 0 null island

View file

@ -0,0 +1,2 @@
x, y,z
-122 , 48,0
1 x y z
2 -122 48 0

View file

@ -0,0 +1,11 @@
geonameid name asciiname alternatenames latitude longitude feature_class feature_code country_code cc2 admin1 admin2 admin3 admin4 population elevation gtopo3 timezone mod_date
725712 Vratsa Vratsa Vraca,Vratca,Vratsa,Vrattsa,Vratza,Wraza,Враца 43.21 23.5625 P PPLA BG 64 VRC10 64941 341 Europe/Sofia 2011-10-10
725816 Sveti Vlas Sveti Vlas Manasturkioy,Manastŭrkioy,Monasturkioy,Monastŭrkioy,Saint Vlas,Sveti Vlas,Sveti-Vlas,Sweti Wlas,Vlas,Влас,Свети-Влас 42.7136 27.75867 P PPL BG BG 39 BGS15 BGS15-02 3875 50 -9999 Europe/Sofia 2010-03-07
725905 Vidin Vidin Vidin,Vidine,Widin,wydyn,Видин,ویدین 43.99 22.8725 P PPLA BG 63 VID09 54409 35 Europe/Sofia 2011-10-10
725924 Vetrino Vetrino Asya-Tepe,Jasi Tepe,Vetrino,Vyetreno,Vyetrino,Wetrino,Yasa-Tepe,Yase-Tepe,Yasu-Tepe,Yasă-Tepe,Yasŭ-Tepe,Ветрино 43.31667 27.43333 P PPL BG BG 61 VAR08 1368 223 Europe/Sofia 2011-10-10
725935 Vetovo Vetovo Vetova,Vetovo,Vjetevo,Vyetovo,Wetowo,Ветово 43.7 26.26667 P PPL BG 53 RSE05 5175 184 Europe/Sofia 2007-04-05
725967 Venets Venets K'okledzha,K'oklyudzha,K'okyudzha,Kiokhudza,Kiokhudža,Kokedzha,Kokledzha,Koklyudzha,Kokyudzha,Venec,Venets,Vyenets,Wenez,Венец 43.55 26.93333 P PPL BG BG 54 SHU07 1450 334 Europe/Sofia 2011-10-10
725988 Velingrad Velingrad Velingrad,Велинград 42.02724 23.99569 P PPL BG 48 PAZ08 24036 745 Europe/Sofia 2010-05-28
725993 Veliko Tŭrnovo Veliko Turnovo Tarnovo,Tarnowo,Ternovo,Tirnovo,Trnova,Trnovo,Turnovo,Tărnovo,Tărnowo,Tŭrnovo,Veliko T\"rnovo,Veliko Tarnovo,Veliko Tărnovo,Weliko Tarnowo,Weliko Tyrnowo,vu~erikotarunovu~o,Велико Търново,ヴェリコタルノヴォ 43.08124 25.62904 P PPLA BG 62 VTR04 66217 162 Europe/Sofia 2007-07-01
726050 Varna Varna Barna,Odessos,Odessus,Stalin,Varna,Warna,farna,varna,vu~aruna,wa er na,wrnh,Βάρνα,Варна,ורנה,فارنا,ვარნა,ヴァルナ,瓦爾納 43.21667 27.91667 P PPLA BG 61 VAR06 312770 95 Europe/Sofia 2011-10-10
726114 Ugŭrchin Ugurchin Ugarchin,Ugarcin,Ugartschin,Ugarčin,Ugirkin,Ugrchin,Ugrcin,Ugrčin,Ugurchin,Ugurcin,Ugürčin,Ugărchin,Ugărtschin,Угърчин 43.1 24.41667 P PPL BG 46 LOV36 2965 298 Europe/Sofia 2007-04-05
Can't render this file because it contains an unexpected character in line 9 and column 129.

View file

View file

@ -0,0 +1,3 @@
x,y,z
-122a,48b,bogus
-122,48,fine
1 x y z
2 -122a 48b bogus
3 -122 48 fine

View file

@ -0,0 +1,2 @@
x,y,z
0,0,0
1 x y z
2 0 0 0

9
tests/data/csv/wkt.csv Normal file
View file

@ -0,0 +1,9 @@
type,WKT
point, "POINT (30 10)"
linestring, "LINESTRING (30 10, 10 30, 40 40)"
polygon, "POLYGON ((30 10, 10 20, 20 40, 40 40, 30 10))"
polygon, "POLYGON ((35 10, 10 20, 15 40, 45 45, 35 10),(20 30, 35 35, 30 20, 20 30))"
multipoint, "MULTIPOINT ((10 40), (40 30), (20 20), (30 10))"
multilinestring, "MULTILINESTRING ((10 10, 20 20, 10 40),(40 40, 30 30, 40 20, 30 10))"
multipolygon, "MULTIPOLYGON (((30 20, 10 40, 45 40, 30 20)),((15 5, 40 10, 10 20, 5 10, 15 5)))"
multipolygon, "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)))"
1 type WKT
2 point POINT (30 10)
3 linestring LINESTRING (30 10, 10 30, 40 40)
4 polygon POLYGON ((30 10, 10 20, 20 40, 40 40, 30 10))
5 polygon POLYGON ((35 10, 10 20, 15 40, 45 45, 35 10),(20 30, 35 35, 30 20, 20 30))
6 multipoint MULTIPOINT ((10 40), (40 30), (20 20), (30 10))
7 multilinestring MULTILINESTRING ((10 10, 20 20, 10 40),(40 40, 30 30, 40 20, 30 10))
8 multipolygon MULTIPOLYGON (((30 20, 10 40, 45 40, 30 20)),((15 5, 40 10, 10 20, 5 10, 15 5)))
9 multipolygon 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)))

2
tests/data/csv/x_y.csv Normal file
View file

@ -0,0 +1,2 @@
x,y
0,0
1 x y
2 0 0

View file

@ -22,7 +22,7 @@
<Layer name="point" srs="+init=epsg:4326">
<StyleName>1</StyleName>
<Datasource>
<Parameter name="file">../csv/points.vrt</Parameter>
<Parameter name="file">../vrt/points.vrt</Parameter>
<Parameter name="layer_by_index">0</Parameter>
<Parameter name="type">ogr</Parameter>
</Datasource>

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View file

@ -0,0 +1,8 @@
<OGRVRTDataSource>
<OGRVRTLayer name="points">
<SrcDataSource relativeToVRT="1">../csv/points.csv</SrcDataSource>
<GeometryType>wkbPoint</GeometryType>
<LayerSRS>WGS84</LayerSRS>
<GeometryField encoding="PointFromColumns" x="x" y="y"/>
</OGRVRTLayer>
</OGRVRTDataSource>

View file

@ -18,10 +18,6 @@ class FeatureTest(unittest.TestCase):
f = self.makeOne(1, 'POLYGON ((35 10, 10 20, 15 40, 45 45, 35 10),(20 30, 35 35, 30 20, 20 30))', foo="bar")
self.failUnlessEqual(f['foo'], 'bar')
self.failUnlessEqual(f.envelope(),Box2d(10.0,10.0,45.0,45.0))
area = 0.0
for g in f.geometries():
area += g.area()
self.failUnlessEqual(area,-450.0)
def test_set_get_properties(self):
f = self.makeOne(1)

View file

@ -0,0 +1,70 @@
#!/usr/bin/env python
from nose.tools import *
from utilities import execution_path, save_data, contains_word
import os, mapnik2
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_multi_tile_policy():
srs = '+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs'
lyr = mapnik2.Layer('raster')
lyr.datasource = mapnik2.Raster(
file = '../data/raster_tiles/${x}/${y}.tif',
lox = -180,
loy = -90,
hix = 180,
hiy = 90,
multi = 1,
tile_size = 256,
x_width = 2,
y_width = 2
)
lyr.srs = srs
_map = mapnik2.Map(256, 256, srs)
style = mapnik2.Style()
rule = mapnik2.Rule()
sym = mapnik2.RasterSymbolizer()
rule.symbols.append(sym)
style.rules.append(rule)
_map.append_style('foo', style)
lyr.styles.append('foo')
_map.layers.append(lyr)
_map.zoom_to_box(lyr.envelope())
im = mapnik2.Image(_map.width, _map.height)
mapnik2.render(_map, im)
save_data('test_multi_tile_policy.png', im.tostring('png'))
# test green chunk
assert im.view(0,64,1,1).tostring() == '\x00\xff\x00\xff'
assert im.view(127,64,1,1).tostring() == '\x00\xff\x00\xff'
assert im.view(0,127,1,1).tostring() == '\x00\xff\x00\xff'
assert im.view(127,127,1,1).tostring() == '\x00\xff\x00\xff'
# test blue chunk
assert im.view(128,64,1,1).tostring() == '\x00\x00\xff\xff'
assert im.view(255,64,1,1).tostring() == '\x00\x00\xff\xff'
assert im.view(128,127,1,1).tostring() == '\x00\x00\xff\xff'
assert im.view(255,127,1,1).tostring() == '\x00\x00\xff\xff'
# test red chunk
assert im.view(0,128,1,1).tostring() == '\xff\x00\x00\xff'
assert im.view(127,128,1,1).tostring() == '\xff\x00\x00\xff'
assert im.view(0,191,1,1).tostring() == '\xff\x00\x00\xff'
assert im.view(127,191,1,1).tostring() == '\xff\x00\x00\xff'
# test magenta chunk
assert im.view(128,128,1,1).tostring() == '\xff\x00\xff\xff'
assert im.view(255,128,1,1).tostring() == '\xff\x00\xff\xff'
assert im.view(128,191,1,1).tostring() == '\xff\x00\xff\xff'
assert im.view(255,191,1,1).tostring() == '\xff\x00\xff\xff'
if __name__ == "__main__":
setup()
[eval(run)() for run in dir() if 'test_' in run]

View file

@ -58,6 +58,37 @@ def test_attachdb_with_explicit_index():
'insert into scratch.myindex values (1,-7799225.5,-7778571.0,1393264.125,1417719.375)\n'
)
def test_dequoting_of_subqueries():
# The point table and index is in the qgis_spatiallite.sqlite
# database. If either is not found, then this fails
ds = mapnik2.SQLite(file='../data/sqlite/world.sqlite',
table='world_merc',
)
fs = ds.featureset()
feature = fs.next()
eq_(feature['OGC_FID'],1)
eq_(feature['fips'],u'AC')
# TODO:
# select * from world_merc fails
# as rowid is dropped
ds = mapnik2.SQLite(file='../data/sqlite/world.sqlite',
table='(select *,rowid from world_merc)',
)
fs = ds.featureset()
feature = fs.next()
print feature
eq_(feature['OGC_FID'],1)
eq_(feature['fips'],u'AC')
ds = mapnik2.SQLite(file='../data/sqlite/world.sqlite',
table='(select GEOMETRY,OGC_FID as rowid,fips from world_merc)',
)
fs = ds.featureset()
feature = fs.next()
print feature
eq_(feature['rowid'],1)
eq_(feature['fips'],u'AC')
if __name__ == "__main__":
setup()

49
workspace/bindings.pri Normal file
View file

@ -0,0 +1,49 @@
HEADERS += \
$$PWD/../bindings/python/mapnik_enumeration.hpp \
$$PWD/../bindings/python/mapnik_svg.hpp \
$$PWD/../bindings/python/mapnik_value_converter.hpp \
$$PWD/../bindings/python/python_grid_utils.hpp \
$$PWD/../bindings/python/python_optional.hpp
SOURCES += \
$$PWD/../bindings/python/mapnik_color.cpp \
$$PWD/../bindings/python/mapnik_coord.cpp \
$$PWD/../bindings/python/mapnik_datasource.cpp \
$$PWD/../bindings/python/mapnik_datasource_cache.cpp \
$$PWD/../bindings/python/mapnik_envelope.cpp \
$$PWD/../bindings/python/mapnik_expression.cpp \
$$PWD/../bindings/python/mapnik_feature.cpp \
$$PWD/../bindings/python/mapnik_featureset.cpp \
$$PWD/../bindings/python/mapnik_font_engine.cpp \
$$PWD/../bindings/python/mapnik_geometry.cpp \
$$PWD/../bindings/python/mapnik_glyph_symbolizer.cpp \
$$PWD/../bindings/python/mapnik_grid.cpp \
$$PWD/../bindings/python/mapnik_grid_view.cpp \
$$PWD/../bindings/python/mapnik_image.cpp \
$$PWD/../bindings/python/mapnik_image_view.cpp \
$$PWD/../bindings/python/mapnik_inmem_metawriter.cpp \
$$PWD/../bindings/python/mapnik_layer.cpp \
$$PWD/../bindings/python/mapnik_line_pattern_symbolizer.cpp \
$$PWD/../bindings/python/mapnik_line_symbolizer.cpp \
$$PWD/../bindings/python/mapnik_map.cpp \
$$PWD/../bindings/python/mapnik_markers_symbolizer.cpp \
$$PWD/../bindings/python/mapnik_palette.cpp \
$$PWD/../bindings/python/mapnik_parameters.cpp \
$$PWD/../bindings/python/mapnik_point_symbolizer.cpp \
$$PWD/../bindings/python/mapnik_polygon_pattern_symbolizer.cpp \
$$PWD/../bindings/python/mapnik_polygon_symbolizer.cpp \
$$PWD/../bindings/python/mapnik_proj_transform.cpp \
$$PWD/../bindings/python/mapnik_projection.cpp \
$$PWD/../bindings/python/mapnik_python.cpp \
$$PWD/../bindings/python/mapnik_query.cpp \
$$PWD/../bindings/python/mapnik_raster_colorizer.cpp \
$$PWD/../bindings/python/mapnik_raster_symbolizer.cpp \
$$PWD/../bindings/python/mapnik_rule.cpp \
$$PWD/../bindings/python/mapnik_shield_symbolizer.cpp \
$$PWD/../bindings/python/mapnik_stroke.cpp \
$$PWD/../bindings/python/mapnik_style.cpp \
$$PWD/../bindings/python/mapnik_symbolizer.cpp \
$$PWD/../bindings/python/mapnik_text_symbolizer.cpp \
$$PWD/../bindings/python/mapnik_view_transform.cpp \
$$PWD/../bindings/python/python_cairo.cpp

View file

@ -202,7 +202,12 @@ SOURCES += \
../src/warp.cpp \
../src/wkb.cpp
OTHER_FILES += \
../SConstruct \
../config.py
include(plugins.pri)
include(bindings.pri)
unix {
DEFINES += LINUX=1