From dbd4258079dd250f5f0a67c4e9869c008e43ce75 Mon Sep 17 00:00:00 2001 From: Dane Springmeyer Date: Tue, 27 Mar 2012 18:54:59 -0400 Subject: [PATCH 001/134] more markers_symbolizer test maps --- .../good_maps/markers_symbolizer_lines.xml | 2 +- .../markers_symbolizer_lines_file.xml | 19 +++++++++++ .../markers_symbolizer_points_file.xml | 33 +++++++++++++++++++ 3 files changed, 53 insertions(+), 1 deletion(-) create mode 100644 tests/data/good_maps/markers_symbolizer_lines_file.xml create mode 100644 tests/data/good_maps/markers_symbolizer_points_file.xml diff --git a/tests/data/good_maps/markers_symbolizer_lines.xml b/tests/data/good_maps/markers_symbolizer_lines.xml index 1336f56bc..74adff287 100644 --- a/tests/data/good_maps/markers_symbolizer_lines.xml +++ b/tests/data/good_maps/markers_symbolizer_lines.xml @@ -2,8 +2,8 @@ diff --git a/tests/data/good_maps/markers_symbolizer_lines_file.xml b/tests/data/good_maps/markers_symbolizer_lines_file.xml new file mode 100644 index 000000000..39d2f1dbd --- /dev/null +++ b/tests/data/good_maps/markers_symbolizer_lines_file.xml @@ -0,0 +1,19 @@ + + + + + + 1 + + sqlite + ../sqlite/qgis_spatiallite.sqlite + lines + + + + \ No newline at end of file diff --git a/tests/data/good_maps/markers_symbolizer_points_file.xml b/tests/data/good_maps/markers_symbolizer_points_file.xml new file mode 100644 index 000000000..304adc572 --- /dev/null +++ b/tests/data/good_maps/markers_symbolizer_points_file.xml @@ -0,0 +1,33 @@ + + + + + + 1 + + sqlite + ../sqlite/qgis_spatiallite.sqlite + point + + + + \ No newline at end of file From 67f6d0f6724b7181fd83dda0b17c6123ab9be1d9 Mon Sep 17 00:00:00 2001 From: Dane Springmeyer Date: Tue, 27 Mar 2012 18:55:33 -0400 Subject: [PATCH 002/134] fixup pycairo rendering test --- tests/python_tests/cairo_test.py | 70 +++++++++++++++++--------------- 1 file changed, 37 insertions(+), 33 deletions(-) diff --git a/tests/python_tests/cairo_test.py b/tests/python_tests/cairo_test.py index ff2ab76fe..bd566a373 100644 --- a/tests/python_tests/cairo_test.py +++ b/tests/python_tests/cairo_test.py @@ -10,49 +10,53 @@ def setup(): # from another directory we need to chdir() os.chdir(execution_path('.')) -def _pycairo_surface(type,sym): - if mapnik.has_pycairo(): - import cairo - test_cairo_file = 'test.%s' % type - m = mapnik.Map(256,256) - mapnik.load_map(m,'../data/good_maps/%s_symbolizer.xml' % sym) - surface = getattr(cairo,'%sSurface' % type.upper())(test_cairo_file, m.width,m.height) - mapnik.render(m, surface) - surface.finish() +if mapnik.has_pycairo(): - if os.path.exists(test_cairo_file): - os.remove(test_cairo_file) - return True - else: - # Fail, the file wasn't written - return False + def _pycairo_surface(type,sym): + import cairo + test_cairo_file = '/tmp/test.%s' % type + m = mapnik.Map(256,256) + mapnik.load_map(m,'../data/good_maps/%s_symbolizer.xml' % sym) + if hasattr(cairo,'%sSurface' % type.upper()): + surface = getattr(cairo,'%sSurface' % type.upper())(test_cairo_file, m.width,m.height) + mapnik.render(m, surface) + surface.finish() + if os.path.exists(test_cairo_file): + os.remove(test_cairo_file) + return True + else: + # Fail, the file wasn't written + return False + else: + print 'skipping cairo.%s test since surface is not available' % type.upper() + return True -def test_pycairo_svg_surface(): - return _pycairo_surface('svg','point') + def test_pycairo_svg_surface1(): + eq_(_pycairo_surface('svg','point'),True) -def test_pycairo_svg_surface(): - return _pycairo_surface('svg','building') + def test_pycairo_svg_surface2(): + eq_(_pycairo_surface('svg','building'),True) -def test_pycairo_svg_surface(): - return _pycairo_surface('svg','polygon') + def test_pycairo_svg_surface3(): + eq_(_pycairo_surface('svg','polygon'),True) -def test_pycairo_svg_surface(): - return _pycairo_surface('pdf','point') + def test_pycairo_pdf_surface1(): + eq_(_pycairo_surface('pdf','point'),True) -def test_pycairo_svg_surface(): - return _pycairo_surface('pdf','building') + def test_pycairo_pdf_surface2(): + eq_(_pycairo_surface('pdf','building'),True) -def test_pycairo_svg_surface(): - return _pycairo_surface('pdf','polygon') + def test_pycairo_pdf_surface3(): + eq_(_pycairo_surface('pdf','polygon'),True) -def test_pycairo_svg_surface(): - return _pycairo_surface('ps','point') + def test_pycairo_ps_surface1(): + eq_(_pycairo_surface('ps','point'),True) -def test_pycairo_svg_surface(): - return _pycairo_surface('ps','building') + def test_pycairo_ps_surface2(): + eq_(_pycairo_surface('ps','building'),True) -def test_pycairo_svg_surface(): - return _pycairo_surface('ps','polygon') + def test_pycairo_ps_surface3(): + eq_(_pycairo_surface('ps','polygon'),True) if __name__ == "__main__": setup() From e22e47dfccdcdb3f2ff5a91bf7fc898e34e288d2 Mon Sep 17 00:00:00 2001 From: Dane Springmeyer Date: Tue, 27 Mar 2012 19:14:01 -0400 Subject: [PATCH 003/134] scons: when statically linking: link extra icu libs needed by regex --- SConstruct | 3 +++ 1 file changed, 3 insertions(+) diff --git a/SConstruct b/SConstruct index c014b9bb5..95726262f 100644 --- a/SConstruct +++ b/SConstruct @@ -810,6 +810,9 @@ int main() return False def boost_regex_has_icu(context): + if env['RUNTIME_LINK'] == 'static': + context.env.Append(LIBS='icui18n') + context.env.Append(LIBS='icudata') ret = context.TryRun(""" #include From 2edaefd0d661b34c0c888ecc0d01707f8f853f46 Mon Sep 17 00:00:00 2001 From: Dane Springmeyer Date: Tue, 27 Mar 2012 19:21:11 -0400 Subject: [PATCH 004/134] cairo: match AGG functionality, adding support for dynamic ellipse drawing and loading from svg icons - closes #1071 (refs #952 - this is stopgap until we refactor and merge with point_symbolizer) --- include/mapnik/cairo_renderer.hpp | 2 +- src/cairo_renderer.cpp | 281 +++++++++++++++++++++++++++--- 2 files changed, 254 insertions(+), 29 deletions(-) diff --git a/include/mapnik/cairo_renderer.hpp b/include/mapnik/cairo_renderer.hpp index dd37ac906..408662ef9 100644 --- a/include/mapnik/cairo_renderer.hpp +++ b/include/mapnik/cairo_renderer.hpp @@ -123,7 +123,7 @@ public: } protected: - void render_marker(pixel_position const& pos, marker const& marker, const agg::trans_affine & mtx, double opacity=1.0); + void render_marker(pixel_position const& pos, marker const& marker, const agg::trans_affine & mtx, double opacity=1.0, bool recenter=true); Map const& m_; Cairo::RefPtr context_; diff --git a/src/cairo_renderer.cpp b/src/cairo_renderer.cpp index 589247e0f..a87f48749 100644 --- a/src/cairo_renderer.cpp +++ b/src/cairo_renderer.cpp @@ -55,6 +55,11 @@ #include "agg_conv_clip_polygon.h" #include "agg_conv_smooth_poly1.h" +// markers +#include "agg_path_storage.h" +#include "agg_ellipse.h" + + // stl #ifdef MAPNIK_DEBUG #include @@ -907,7 +912,7 @@ void cairo_renderer_base::start_map_processing(Map const& map) context.stroke(); } - void cairo_renderer_base::render_marker(pixel_position const& pos, marker const& marker, const agg::trans_affine & tr, double opacity) + void cairo_renderer_base::render_marker(pixel_position const& pos, marker const& marker, const agg::trans_affine & tr, double opacity, bool recenter) { cairo_context context(context_); @@ -916,15 +921,21 @@ void cairo_renderer_base::start_map_processing(Map const& map) box2d bbox; bbox = (*marker.get_vector_data())->bounding_box(); - coord c = bbox.center(); - // center the svg marker on '0,0' - agg::trans_affine mtx = agg::trans_affine_translation(-c.x,-c.y); - // apply symbol transformation to get to map space - mtx *= tr; - // render the marker at the center of the marker box - mtx.translate(pos.x+0.5 * marker.width(), pos.y+0.5 * marker.height()); + agg::trans_affine mtx = tr; + + if (recenter) + { + coord c = bbox.center(); + // center the svg marker on '0,0' + mtx = agg::trans_affine_translation(-c.x,-c.y); + // apply symbol transformation to get to map space + mtx *= tr; + // render the marker at the center of the marker box + mtx.translate(pos.x+0.5 * marker.width(), pos.y+0.5 * marker.height()); + } typedef coord_transform2 path_type; + agg::trans_affine transform; mapnik::path_ptr vmarker = *marker.get_vector_data(); using namespace mapnik::svg; agg::pod_bvector const & attributes_ = vmarker->attributes(); @@ -936,10 +947,13 @@ void cairo_renderer_base::start_map_processing(Map const& map) context.save(); - agg::trans_affine transform = attr.transform; + transform = attr.transform; transform *= mtx; - if (transform.is_valid() && !transform.is_identity()) + // TODO - this 'is_valid' check is not used in the AGG renderer and also + // appears to lead to bogus results with + // tests/data/good_maps/markers_symbolizer_lines_file.xml + if (/*transform.is_valid() && */ !transform.is_identity()) { double m[6]; transform.store_to(m); @@ -974,7 +988,6 @@ void cairo_renderer_base::start_map_processing(Map const& map) } } - if(attr.stroke_gradient.get_gradient_type() != NO_GRADIENT || attr.stroke_flag) { context.add_agg_path(svg_path,attr.index); @@ -1243,37 +1256,249 @@ void cairo_renderer_base::start_map_processing(Map const& map) } } -// TODO - this is woefully behind the AGG version. void cairo_renderer_base::process(markers_symbolizer const& sym, mapnik::feature_ptr const& feature, proj_transform const& prj_trans) { - typedef coord_transform2 path_type; - arrow arrow_; cairo_context context(context_); - color const& fill_ = sym.get_fill(); - context.set_color(fill_.red(), fill_.green(), fill_.blue(), fill_.alpha()); + double scale_factor_(1); - for (unsigned i = 0; i < feature->num_geometries(); ++i) + typedef agg::conv_clip_polyline clipped_geometry_type; + typedef coord_transform2 path_type; + + agg::trans_affine tr; + boost::array const& m = sym.get_transform(); + tr.load_from(&m[0]); + // TODO - use this? + //tr = agg::trans_affine_scaling(scale_factor_) * tr; + std::string filename = path_processor_type::evaluate(*sym.get_filename(), *feature); + marker_placement_e placement_method = sym.get_marker_placement(); + marker_type_e marker_type = sym.get_marker_type(); + metawriter_with_properties writer = sym.get_metawriter(); + + if (!filename.empty()) { - geometry_type & geom = feature->get_geometry(i); - - if (geom.num_points() > 1) + boost::optional mark = mapnik::marker_cache::instance()->find(filename, true); + if (mark && *mark) { + if (!(*mark)->is_vector()) { + std::clog << "### Warning only svg markers are supported in the markers_symbolizer\n"; + return; + } + boost::optional marker = (*mark)->get_vector_data(); + box2d const& bbox = (*marker)->bounding_box(); + double x1 = bbox.minx(); + double y1 = bbox.miny(); + double x2 = bbox.maxx(); + double y2 = bbox.maxy(); + double w = (*mark)->width(); + double h = (*mark)->height(); - path_type path(t_, geom, prj_trans); + agg::trans_affine recenter = agg::trans_affine_translation(-0.5*(x1+x2),-0.5*(y1+y2)); + tr.transform(&x1,&y1); + tr.transform(&x2,&y2); + box2d extent(x1,y1,x2,y2); + using namespace mapnik::svg; - markers_placement placement(path, arrow_.extent(), detector_, sym.get_spacing(), sym.get_max_error(), sym.get_allow_overlap()); + for (unsigned i=0; inum_geometries(); ++i) + { + geometry_type & geom = feature->get_geometry(i); + // TODO - merge this code with point_symbolizer rendering + if (placement_method == MARKER_POINT_PLACEMENT || geom.num_points() <= 1) + { + double x; + double y; + double z=0; + geom.label_interior_position(&x, &y); + prj_trans.backward(x,y,z); + t_.forward(&x,&y); + extent.re_center(x,y); - double x, y, angle; - while (placement.get_point(&x, &y, &angle)) { - Cairo::Matrix matrix = Cairo::rotation_matrix(angle) * Cairo::translation_matrix(x,y) ; - context.set_matrix(matrix); - context.add_path(arrow_); + if (sym.get_allow_overlap() || + detector_.has_placement(extent)) + { + render_marker(pixel_position(x - 0.5 * w, y - 0.5 * h) ,**mark, tr, sym.get_opacity()); + + // TODO - impl this for markers? + //if (!sym.get_ignore_placement()) + // detector_.insert(label_ext); + metawriter_with_properties writer = sym.get_metawriter(); + if (writer.first) writer.first->add_box(extent, *feature, t_, writer.second); + } + } + else + { + clipped_geometry_type clipped(geom); + clipped.clip_box(query_extent_.minx(),query_extent_.miny(),query_extent_.maxx(),query_extent_.maxy()); + path_type path(t_,clipped,prj_trans); + markers_placement placement(path, extent, detector_, + sym.get_spacing() * scale_factor_, + sym.get_max_error(), + sym.get_allow_overlap()); + double x, y, angle; + + while (placement.get_point(&x, &y, &angle)) + { + agg::trans_affine matrix = recenter * tr * agg::trans_affine_rotation(angle) * agg::trans_affine_translation(x, y); + render_marker(pixel_position(x - 0.5 * w, y - 0.5 * h), **mark, matrix, sym.get_opacity(),false); + + if (writer.first) + //writer.first->add_box(label_ext, feature, t_, writer.second); + std::clog << "### Warning metawriter not yet supported for LINE placement\n"; + } + } + context.fill(); + } + } + } + else + { + color const& fill_ = sym.get_fill(); + unsigned r = fill_.red(); + unsigned g = fill_.green(); + unsigned b = fill_.blue(); + unsigned a = fill_.alpha(); + stroke const& stroke_ = sym.get_stroke(); + color const& col = stroke_.get_color(); + double strk_width = stroke_.get_width(); + unsigned s_r=col.red(); + unsigned s_g=col.green(); + unsigned s_b=col.blue(); + unsigned s_a=col.alpha(); + double w = sym.get_width(); + double h = sym.get_height(); + double rx = w/2.0; + double ry = h/2.0; + + arrow arrow_; + box2d extent; + + double dx = w + (2*strk_width); + double dy = h + (2*strk_width); + + if (marker_type == ARROW) + { + extent = arrow_.extent(); + double x1 = extent.minx(); + double y1 = extent.miny(); + double x2 = extent.maxx(); + double y2 = extent.maxy(); + tr.transform(&x1,&y1); + tr.transform(&x2,&y2); + extent.init(x1,y1,x2,y2); + } + else + { + double x1 = -1 *(dx); + double y1 = -1 *(dy); + double x2 = dx; + double y2 = dy; + tr.transform(&x1,&y1); + tr.transform(&x2,&y2); + extent.init(x1,y1,x2,y2); + } + + double x; + double y; + double z=0; + + agg::path_storage marker; + + for (unsigned i=0; inum_geometries(); ++i) + { + geometry_type & geom = feature->get_geometry(i); + if (placement_method == MARKER_POINT_PLACEMENT || geom.num_points() <= 1) + { + geom.label_position(&x,&y); + prj_trans.backward(x,y,z); + t_.forward(&x,&y); + int px = int(floor(x - 0.5 * dx)); + int py = int(floor(y - 0.5 * dy)); + box2d label_ext (px, py, px + dx +1, py + dy +1); + if (sym.get_allow_overlap() || + detector_.has_placement(label_ext)) + { + agg::ellipse c(x, y, rx, ry); + marker.concat_path(c); + context.set_color(fill_,sym.get_opacity()); + context.add_agg_path(marker); + context.fill(); + + if (strk_width) + { + //context.restore(); + context.set_color(col,stroke_.get_opacity()); + context.set_line_width(stroke_.get_width()); + if (stroke_.has_dash()) + { + context.set_dash(stroke_.get_dash_array()); + } + context.add_agg_path(marker); + context.stroke(); + } + if (!sym.get_ignore_placement()) + detector_.insert(label_ext); + if (writer.first) writer.first->add_box(label_ext, *feature, t_, writer.second); + } + } + else + { + if (marker_type == ARROW) + marker.concat_path(arrow_); + + clipped_geometry_type clipped(geom); + clipped.clip_box(query_extent_.minx(),query_extent_.miny(),query_extent_.maxx(),query_extent_.maxy()); + path_type path(t_,clipped,prj_trans); + markers_placement placement(path, extent, detector_, + sym.get_spacing() * scale_factor_, + sym.get_max_error(), + sym.get_allow_overlap()); + double x_t, y_t, angle; + + while (placement.get_point(&x_t, &y_t, &angle)) + { + agg::trans_affine matrix; + + if (marker_type == ELLIPSE) + { + agg::ellipse c(x_t, y_t, rx, ry); + marker.concat_path(c); + agg::trans_affine matrix; + matrix *= agg::trans_affine_translation(-x_t,-y_t); + matrix *= agg::trans_affine_rotation(angle); + matrix *= agg::trans_affine_translation(x_t,y_t); + marker.transform(matrix); + } + else + { + matrix = tr * agg::trans_affine_rotation(angle) * agg::trans_affine_translation(x_t, y_t); + } + + // TODO + if (writer.first) + //writer.first->add_box(label_ext, feature, t_, writer.second); + std::clog << "### Warning metawriter not yet supported for LINE placement\n"; + + agg::conv_transform trans(marker, matrix); + context.set_color(fill_,sym.get_opacity()); + context.add_agg_path(trans); + context.fill(); + + if (strk_width) + { + context.set_color(col,stroke_.get_opacity()); + context.set_line_width(stroke_.get_width()); + if (stroke_.has_dash()) + { + context.set_dash(stroke_.get_dash_array()); + } + context.add_agg_path(trans); + context.stroke(); + } + } } } - context.fill(); } } From d516cf9f46d2d6b905252d3565e1013fcea95320 Mon Sep 17 00:00:00 2001 From: kunitoki Date: Wed, 28 Mar 2012 21:59:40 +0200 Subject: [PATCH 005/134] - cosmetics --- include/mapnik/datasource.hpp | 45 +++++++++++++++++++---------------- 1 file changed, 24 insertions(+), 21 deletions(-) diff --git a/include/mapnik/datasource.hpp b/include/mapnik/datasource.hpp index 5cfd1bde5..6ae828a94 100644 --- a/include/mapnik/datasource.hpp +++ b/include/mapnik/datasource.hpp @@ -45,25 +45,30 @@ typedef MAPNIK_DECL boost::shared_ptr feature_ptr; struct MAPNIK_DECL Featureset : private boost::noncopyable { - virtual feature_ptr next()=0; - virtual ~Featureset() {}; + virtual feature_ptr next() = 0; + virtual ~Featureset() {} }; typedef MAPNIK_DECL boost::shared_ptr featureset_ptr; class MAPNIK_DECL datasource_exception : public std::exception { -private: - std::string message_; public: - datasource_exception(const std::string& message=std::string("no reason")) - :message_(message) {} + datasource_exception(const std::string& message = std::string("no reason")) + : message_(message) + { + } + + ~datasource_exception() throw() + { + } - ~datasource_exception() throw() {} virtual const char* what() const throw() { return message_.c_str(); } +private: + std::string message_; }; class MAPNIK_DECL datasource : private boost::noncopyable @@ -82,9 +87,10 @@ public: }; datasource (parameters const& params) - : params_(params), + : params_(params), is_bound_(false) - {} + { + } /*! * @brief Get the configuration parameters of the data source. @@ -102,19 +108,19 @@ public: * @brief Get the type of the datasource * @return The type of the datasource (Vector or Raster) */ - virtual datasource_t type() const=0; + virtual datasource_t type() const = 0; /*! * @brief Connect to the datasource */ - virtual void bind() const {}; + virtual void bind() const {} - virtual featureset_ptr features(const query& q) const=0; - virtual featureset_ptr features_at_point(coord2d const& pt) const=0; - virtual box2d envelope() const=0; - virtual boost::optional get_geometry_type() const=0; - virtual layer_descriptor get_descriptor() const=0; - virtual ~datasource() {}; + virtual featureset_ptr features(const query& q) const = 0; + virtual featureset_ptr features_at_point(coord2d const& pt) const = 0; + virtual box2d envelope() const = 0; + virtual boost::optional get_geometry_type() const = 0; + virtual layer_descriptor get_descriptor() const = 0; + virtual ~datasource() {} protected: parameters params_; mutable bool is_bound_; @@ -124,7 +130,6 @@ typedef std::string datasource_name(); typedef datasource* create_ds(const parameters& params, bool bind); typedef void destroy_ds(datasource *ds); - class datasource_deleter { public: @@ -136,7 +141,6 @@ public: typedef boost::shared_ptr datasource_ptr; - #define DATASOURCE_PLUGIN(classname) \ extern "C" MAPNIK_EXP std::string datasource_name() \ { \ @@ -149,8 +153,7 @@ typedef boost::shared_ptr datasource_ptr; extern "C" MAPNIK_EXP void destroy(datasource *ds) \ { \ delete ds; \ - } \ - // + } } From 1ee425519563f2a3e041fd6d1b58f0cec842c056 Mon Sep 17 00:00:00 2001 From: kunitoki Date: Wed, 28 Mar 2012 22:01:26 +0200 Subject: [PATCH 006/134] - updated linux project files --- workspace/mapnik.pro | 2 ++ workspace/plugins.pri | 6 ++++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/workspace/mapnik.pro b/workspace/mapnik.pro index 5f9f9c615..6afa5ce50 100644 --- a/workspace/mapnik.pro +++ b/workspace/mapnik.pro @@ -35,6 +35,7 @@ HEADERS += \ ../include/mapnik/svg/svg_renderer.hpp \ ../include/mapnik/svg/svg_storage.hpp \ ../include/mapnik/svg/svg_transform_grammar.hpp \ + ../include/mapnik/util/conversions.hpp \ ../include/mapnik/wkt/wkt_factory.hpp \ ../include/mapnik/wkt/wkt_grammar.hpp \ ../include/mapnik/agg_pattern_source.hpp \ @@ -45,6 +46,7 @@ HEADERS += \ ../include/mapnik/attribute_descriptor.hpp \ ../include/mapnik/attribute.hpp \ ../include/mapnik/box2d.hpp \ + ../include/mapnik/boolean.hpp \ ../include/mapnik/cairo_renderer.hpp \ ../include/mapnik/color_factory.hpp \ ../include/mapnik/color.hpp \ diff --git a/workspace/plugins.pri b/workspace/plugins.pri index 623ab4567..0f52001e8 100644 --- a/workspace/plugins.pri +++ b/workspace/plugins.pri @@ -30,8 +30,8 @@ HEADERS += \ $$PWD/../plugins/input/postgis/connection.hpp \ $$PWD/../plugins/input/postgis/connection_manager.hpp \ $$PWD/../plugins/input/postgis/cursorresultset.hpp \ - $$PWD/../plugins/input/postgis/postgis.hpp \ - $$PWD/../plugins/input/postgis/property_index.hpp \ + $$PWD/../plugins/input/postgis/postgis_datasource.hpp \ + $$PWD/../plugins/input/postgis/postgis_featureset.hpp \ $$PWD/../plugins/input/postgis/resultset.hpp \ $$PWD/../plugins/input/raster/raster_info.hpp \ $$PWD/../plugins/input/raster/raster_featureset.hpp \ @@ -41,6 +41,7 @@ HEADERS += \ $$PWD/../plugins/input/rasterlite/rasterlite_datasource.hpp \ $$PWD/../plugins/input/shape/dbffile.hpp \ $$PWD/../plugins/input/shape/shape.hpp \ + $$PWD/../plugins/input/shape/shape_datasource.hpp \ $$PWD/../plugins/input/shape/shape_featureset.hpp \ $$PWD/../plugins/input/shape/shapefile.hpp \ $$PWD/../plugins/input/shape/shape_index_featureset.hpp \ @@ -83,6 +84,7 @@ SOURCES += \ $$PWD/../plugins/input/rasterlite/rasterlite_datasource.cpp \ $$PWD/../plugins/input/shape/dbffile.cpp \ $$PWD/../plugins/input/shape/shape.cpp \ + $$PWD/../plugins/input/shape/shape_datasource.cpp \ $$PWD/../plugins/input/shape/shape_featureset.cpp \ $$PWD/../plugins/input/shape/shape_index_featureset.cpp \ $$PWD/../plugins/input/shape/shape_io.cpp \ From 7dbe1279bf27ee3c553073e991b4bf9696d8f223 Mon Sep 17 00:00:00 2001 From: kunitoki Date: Wed, 28 Mar 2012 22:01:45 +0200 Subject: [PATCH 007/134] - reorder constructor initialization list to avoid warnings in raster datasource --- plugins/input/raster/raster_featureset.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/input/raster/raster_featureset.cpp b/plugins/input/raster/raster_featureset.cpp index 2d08d117b..2ed50cd9d 100644 --- a/plugins/input/raster/raster_featureset.cpp +++ b/plugins/input/raster/raster_featureset.cpp @@ -45,11 +45,11 @@ raster_featureset::raster_featureset(LookupPolicy const& policy, query const& q) : policy_(policy), feature_id_(1), + ctx_(boost::make_shared()), extent_(extent), bbox_(q.get_bbox()), curIter_(policy_.begin()), - endIter_(policy_.end()), - ctx_(boost::make_shared()) + endIter_(policy_.end()) { } From 14bc34489811c0dd515bb861fe91ff17b4b23940 Mon Sep 17 00:00:00 2001 From: kunitoki Date: Wed, 28 Mar 2012 22:10:48 +0200 Subject: [PATCH 008/134] - cosmetics in postgis datasource --- plugins/input/postgis/postgis_datasource.cpp | 362 +++++++++++-------- plugins/input/postgis/postgis_datasource.hpp | 41 ++- plugins/input/postgis/postgis_featureset.cpp | 149 +++++--- plugins/input/postgis/postgis_featureset.hpp | 15 +- 4 files changed, 339 insertions(+), 228 deletions(-) diff --git a/plugins/input/postgis/postgis_datasource.cpp b/plugins/input/postgis/postgis_datasource.cpp index 316ee02c1..e992ea051 100644 --- a/plugins/input/postgis/postgis_datasource.cpp +++ b/plugins/input/postgis/postgis_datasource.cpp @@ -43,12 +43,11 @@ #include #include -#define FMAX std::numeric_limits::max() - DATASOURCE_PLUGIN(postgis_datasource) -const std::string postgis_datasource::GEOMETRY_COLUMNS="geometry_columns"; -const std::string postgis_datasource::SPATIAL_REF_SYS="spatial_ref_system"; +const double postgis_datasource::FMAX = std::numeric_limits::max(); +const std::string postgis_datasource::GEOMETRY_COLUMNS = "geometry_columns"; +const std::string postgis_datasource::SPATIAL_REF_SYS = "spatial_ref_system"; using boost::shared_ptr; using mapnik::PoolGuard; @@ -56,36 +55,42 @@ using mapnik::attribute_descriptor; postgis_datasource::postgis_datasource(parameters const& params, bool bind) : datasource(params), - table_(*params_.get("table","")), + table_(*params_.get("table", "")), schema_(""), - geometry_table_(*params_.get("geometry_table","")), - geometry_field_(*params_.get("geometry_field","")), - key_field_(*params_.get("key_field","")), - cursor_fetch_size_(*params_.get("cursor_size",0)), - row_limit_(*params_.get("row_limit",0)), + geometry_table_(*params_.get("geometry_table", "")), + geometry_field_(*params_.get("geometry_field", "")), + key_field_(*params_.get("key_field", "")), + cursor_fetch_size_(*params_.get("cursor_size", 0)), + row_limit_(*params_.get("row_limit", 0)), type_(datasource::Vector), - srid_(*params_.get("srid",0)), + srid_(*params_.get("srid", 0)), extent_initialized_(false), - desc_(*params_.get("type"),"utf-8"), + desc_(*params_.get("type"), "utf-8"), creator_(params.get("host"), params.get("port"), params.get("dbname"), params.get("user"), params.get("password"), - params.get("connect_timeout","4")), + params.get("connect_timeout", "4")), bbox_token_("!bbox!"), scale_denom_token_("!scale_denominator!"), - persist_connection_(*params_.get("persist_connection",true)), - extent_from_subquery_(*params_.get("extent_from_subquery",false)), + persist_connection_(*params_.get("persist_connection", true)), + extent_from_subquery_(*params_.get("extent_from_subquery", false)), // params below are for testing purposes only (will likely be removed at any time) - intersect_min_scale_(*params_.get("intersect_min_scale",0)), - intersect_max_scale_(*params_.get("intersect_max_scale",0)) + intersect_min_scale_(*params_.get("intersect_min_scale", 0)), + intersect_max_scale_(*params_.get("intersect_max_scale", 0)) //show_queries_(*params_.get("show_queries",false)) { - if (table_.empty()) throw mapnik::datasource_exception("Postgis Plugin: missing parameter"); + if (table_.empty()) + { + throw mapnik::datasource_exception("Postgis Plugin: missing
parameter"); + } - boost::optional ext = params_.get("extent"); - if (ext) extent_initialized_ = extent_.from_string(*ext); + boost::optional ext = params_.get("extent"); + if (ext) + { + extent_initialized_ = extent_.from_string(*ext); + } if (bind) { @@ -95,37 +100,38 @@ postgis_datasource::postgis_datasource(parameters const& params, bool bind) void postgis_datasource::bind() const { - if (is_bound_) return; + if (is_bound_) + { + return; + } - boost::optional initial_size = params_.get("initial_size",1); - boost::optional max_size = params_.get("max_size",10); + boost::optional initial_size = params_.get("initial_size", 1); + boost::optional max_size = params_.get("max_size", 10); - ConnectionManager *mgr=ConnectionManager::instance(); + ConnectionManager* mgr = ConnectionManager::instance(); mgr->registerPool(creator_, *initial_size, *max_size); - std::string g_type; - - shared_ptr > pool=mgr->getPool(creator_.id()); + shared_ptr< Pool > pool = mgr->getPool(creator_.id()); if (pool) { shared_ptr conn = pool->borrowObject(); if (conn && conn->isOK()) { - PoolGuard, - shared_ptr > > guard(conn,pool); + shared_ptr< Pool > > guard(conn, pool); desc_.set_encoding(conn->client_encoding()); - if(geometry_table_.empty()) + if (geometry_table_.empty()) { geometry_table_ = mapnik::sql_utils::table_from_sql(table_); } + std::string::size_type idx = geometry_table_.find_last_of('.'); - if (idx!=std::string::npos) + if (idx != std::string::npos) { - schema_ = geometry_table_.substr(0,idx); - geometry_table_ = geometry_table_.substr(idx+1); + schema_ = geometry_table_.substr(0, idx); + geometry_table_ = geometry_table_.substr(idx + 1); } else { @@ -139,7 +145,7 @@ void postgis_datasource::bind() const // the table parameter references a table, view, or subselect not // registered in the geometry columns. geometryColumn_ = geometry_field_; - if (!geometryColumn_.length() > 0 || srid_ == 0) + if (geometryColumn_.empty() || srid_ == 0) { std::ostringstream s; s << "SELECT f_geometry_column, srid FROM " @@ -147,15 +153,19 @@ void postgis_datasource::bind() const << mapnik::sql_utils::unquote_double(geometry_table_) << "'"; - if (schema_.length() > 0) + if (! schema_.empty()) + { s << " AND f_table_schema='" << mapnik::sql_utils::unquote_double(schema_) << "'"; + } - if (geometry_field_.length() > 0) + if (! geometry_field_.empty()) + { s << " AND f_geometry_column='" << mapnik::sql_utils::unquote_double(geometry_field_) << "'"; + } /* if (show_queries_) @@ -171,12 +181,14 @@ void postgis_datasource::bind() const if (srid_ == 0) { - const char * srid_c = rs->getValue("srid"); + const char* srid_c = rs->getValue("srid"); if (srid_c != NULL) { - int result; - if (mapnik::util::string2int(srid_c,result)) + int result = 0; + if (mapnik::util::string2int(srid_c, result)) + { srid_ = result; + } } } } @@ -185,11 +197,12 @@ void postgis_datasource::bind() const // If we still do not know the srid then we can try to fetch // it from the 'table_' parameter, which should work even if it is // a subselect as long as we know the geometry_field to query - if (geometryColumn_.length() && srid_ <= 0) + if (! geometryColumn_.empty() && srid_ <= 0) { s.str(""); - s << "SELECT ST_SRID(\"" << geometryColumn_ << "\") AS srid FROM "; - s << populate_tokens(table_) << " WHERE \"" << geometryColumn_ << "\" IS NOT NULL LIMIT 1;"; + + s << "SELECT ST_SRID(\"" << geometryColumn_ << "\") AS srid FROM " + << populate_tokens(table_) << " WHERE \"" << geometryColumn_ << "\" IS NOT NULL LIMIT 1;"; /* if (show_queries_) @@ -201,12 +214,14 @@ void postgis_datasource::bind() const shared_ptr rs = conn->executeQuery(s.str()); if (rs->next()) { - const char * srid_c = rs->getValue("srid"); + const char* srid_c = rs->getValue("srid"); if (srid_c != NULL) { - int result; - if (mapnik::util::string2int(srid_c,result)) + int result = 0; + if (mapnik::util::string2int(srid_c, result)) + { srid_ = result; + } } } rs->close(); @@ -216,7 +231,10 @@ void postgis_datasource::bind() const if (srid_ == 0) { srid_ = -1; + +#ifdef MAPNIK_DEBUG std::clog << "Postgis Plugin: SRID warning, using srid=-1 for '" << table_ << "'" << std::endl; +#endif } // At this point the geometry_field may still not be known @@ -242,25 +260,27 @@ void postgis_datasource::bind() const shared_ptr rs = conn->executeQuery(s.str()); int count = rs->getNumFields(); bool found_key_field = false; - for (int i=0;igetFieldName(i); + std::string fld_name = rs->getFieldName(i); int type_oid = rs->getTypeOID(i); // validate type of key_field - if (!found_key_field && !key_field_.empty() && fld_name == key_field_) + if (! found_key_field && ! key_field_.empty() && fld_name == key_field_) { found_key_field = true; if (type_oid == 20 || type_oid == 21 || type_oid == 23) { - desc_.add_descriptor(attribute_descriptor(fld_name,mapnik::Integer)); + desc_.add_descriptor(attribute_descriptor(fld_name, mapnik::Integer)); } else { std::ostringstream error_s; error_s << "invalid type '"; + std::ostringstream type_s; type_s << "SELECT oid, typname FROM pg_type WHERE oid = " << type_oid; + shared_ptr rs_oid = conn->executeQuery(type_s.str()); if (rs_oid->next()) { @@ -271,11 +291,13 @@ void postgis_datasource::bind() const { error_s << "oid:" << type_oid << "'"; } + rs_oid->close(); error_s << " for key_field '" << fld_name << "' - " << "must be an integer primary key"; + rs->close(); - throw mapnik::datasource_exception( error_s.str() ); + throw mapnik::datasource_exception(error_s.str()); } } else @@ -283,21 +305,21 @@ void postgis_datasource::bind() const switch (type_oid) { case 16: // bool - desc_.add_descriptor(attribute_descriptor(fld_name,mapnik::Boolean)); + desc_.add_descriptor(attribute_descriptor(fld_name, mapnik::Boolean)); break; case 20: // int8 case 21: // int2 case 23: // int4 - desc_.add_descriptor(attribute_descriptor(fld_name,mapnik::Integer)); + desc_.add_descriptor(attribute_descriptor(fld_name, mapnik::Integer)); break; case 700: // float4 case 701: // float8 case 1700: // numeric ?? - desc_.add_descriptor(attribute_descriptor(fld_name,mapnik::Double)); + desc_.add_descriptor(attribute_descriptor(fld_name, mapnik::Double)); case 1042: // bpchar case 1043: // varchar case 25: // text - desc_.add_descriptor(attribute_descriptor(fld_name,mapnik::String)); + desc_.add_descriptor(attribute_descriptor(fld_name, mapnik::String)); break; default: // should not get here #ifdef MAPNIK_DEBUG @@ -331,7 +353,6 @@ void postgis_datasource::bind() const rs->close(); is_bound_ = true; - } } } @@ -348,22 +369,33 @@ mapnik::datasource::datasource_t postgis_datasource::type() const layer_descriptor postgis_datasource::get_descriptor() const { - if (!is_bound_) bind(); + if (! is_bound_) + { + bind(); + } + return desc_; } - std::string postgis_datasource::sql_bbox(box2d const& env) const { std::ostringstream b; + if (srid_ > 0) + { b << "ST_SetSRID("; + } + b << "'BOX3D("; b << std::setprecision(16); b << env.minx() << " " << env.miny() << ","; b << env.maxx() << " " << env.maxy() << ")'::box3d"; + if (srid_ > 0) + { b << ", " << srid_ << ")"; + } + return b.str(); } @@ -371,18 +403,20 @@ std::string postgis_datasource::populate_tokens(const std::string& sql) const { std::string populated_sql = sql; - if ( boost::algorithm::icontains(sql,bbox_token_) ) + if (boost::algorithm::icontains(sql, bbox_token_)) { - box2d max_env(-1 * FMAX,-1 * FMAX,FMAX,FMAX); - std::string max_box = sql_bbox(max_env); - boost::algorithm::replace_all(populated_sql,bbox_token_,max_box); + box2d max_env(-1.0 * FMAX, -1.0 * FMAX, FMAX, FMAX); + const std::string max_box = sql_bbox(max_env); + boost::algorithm::replace_all(populated_sql, bbox_token_, max_box); } - if ( boost::algorithm::icontains(sql,scale_denom_token_) ) + + if (boost::algorithm::icontains(sql, scale_denom_token_)) { std::ostringstream ss; ss << FMAX; - boost::algorithm::replace_all(populated_sql,scale_denom_token_,ss.str()); + boost::algorithm::replace_all(populated_sql, scale_denom_token_, ss.str()); } + return populated_sql; } @@ -391,26 +425,27 @@ std::string postgis_datasource::populate_tokens(const std::string& sql, double s std::string populated_sql = sql; std::string box = sql_bbox(env); - if ( boost::algorithm::icontains(populated_sql,scale_denom_token_) ) + if (boost::algorithm::icontains(populated_sql, scale_denom_token_)) { std::ostringstream ss; ss << scale_denom; - boost::algorithm::replace_all(populated_sql,scale_denom_token_,ss.str()); + boost::algorithm::replace_all(populated_sql, scale_denom_token_, ss.str()); } - if ( boost::algorithm::icontains(populated_sql,bbox_token_) ) + if (boost::algorithm::icontains(populated_sql, bbox_token_)) { - boost::algorithm::replace_all(populated_sql,bbox_token_,box); + boost::algorithm::replace_all(populated_sql, bbox_token_, box); return populated_sql; } else { std::ostringstream s; - if (intersect_min_scale_ > 0 && (scale_denom <= intersect_min_scale_ )) + + if (intersect_min_scale_ > 0 && (scale_denom <= intersect_min_scale_)) { s << " WHERE ST_Intersects(\"" << geometryColumn_ << "\"," << box << ")"; } - else if (intersect_max_scale_ > 0 && (scale_denom >= intersect_max_scale_ )) + else if (intersect_max_scale_ > 0 && (scale_denom >= intersect_max_scale_)) { // do no bbox restriction } @@ -418,6 +453,7 @@ std::string postgis_datasource::populate_tokens(const std::string& sql, double s { s << " WHERE \"" << geometryColumn_ << "\" && " << box; } + return populated_sql + s.str(); } } @@ -440,9 +476,11 @@ boost::shared_ptr postgis_datasource::get_resultset(boost::shared_pt } */ - if (!conn->execute(csql.str())) + if (! conn->execute(csql.str())) + { // TODO - better error throw mapnik::datasource_exception("Postgis Plugin: error creating cursor for data select." ); + } return boost::make_shared(conn, cursor_name, cursor_fetch_size_); @@ -458,41 +496,48 @@ boost::shared_ptr postgis_datasource::get_resultset(boost::shared_pt } */ - return conn->executeQuery(sql,1); + return conn->executeQuery(sql, 1); } } featureset_ptr postgis_datasource::features(const query& q) const { - if (!is_bound_) bind(); + if (! is_bound_) + { + bind(); + } box2d const& box = q.get_bbox(); double scale_denom = q.scale_denominator(); - ConnectionManager *mgr=ConnectionManager::instance(); - shared_ptr > pool=mgr->getPool(creator_.id()); + + ConnectionManager* mgr = ConnectionManager::instance(); + shared_ptr< Pool > pool = mgr->getPool(creator_.id()); if (pool) { shared_ptr conn = pool->borrowObject(); if (conn && conn->isOK()) { - PoolGuard,shared_ptr > > guard(conn,pool); + PoolGuard, shared_ptr< Pool > > guard(conn ,pool); - if (!geometryColumn_.length() > 0) + if (geometryColumn_.empty()) { std::ostringstream s_error; s_error << "PostGIS: geometry name lookup failed for table '"; - if (schema_.length() > 0) + + if (! schema_.empty()) { s_error << schema_ << "."; } s_error << geometry_table_ << "'. Please manually provide the 'geometry_field' parameter or add an entry " << "in the geometry_columns for '"; - if (schema_.length() > 0) + + if (! schema_.empty()) { s_error << schema_ << "."; } s_error << geometry_table_ << "'."; + throw mapnik::datasource_exception(s_error.str()); } @@ -501,27 +546,28 @@ featureset_ptr postgis_datasource::features(const query& q) const mapnik::context_ptr ctx = boost::make_shared(); - if (!key_field_.empty()) + if (! key_field_.empty()) { - mapnik::sql_utils::quote_attr(s,key_field_); + mapnik::sql_utils::quote_attr(s, key_field_); ctx->push(key_field_); } - std::set const& props=q.property_names(); - std::set::const_iterator pos=props.begin(); - std::set::const_iterator end=props.end(); + std::set const& props = q.property_names(); + std::set::const_iterator pos = props.begin(); + std::set::const_iterator end = props.end(); - for ( ;pos != end;++pos) + for (; pos != end; ++pos) { - mapnik::sql_utils::quote_attr(s,*pos); + mapnik::sql_utils::quote_attr(s, *pos); ctx->push(*pos); } - std::string table_with_bbox = populate_tokens(table_,scale_denom,box); + std::string table_with_bbox = populate_tokens(table_, scale_denom, box); - s << " from " << table_with_bbox; + s << " FROM " << table_with_bbox; - if (row_limit_ > 0) { + if (row_limit_ > 0) + { s << " LIMIT " << row_limit_; } @@ -533,38 +579,45 @@ featureset_ptr postgis_datasource::features(const query& q) const throw mapnik::datasource_exception("Postgis Plugin: bad connection"); } } + return featureset_ptr(); } featureset_ptr postgis_datasource::features_at_point(coord2d const& pt) const { - if (!is_bound_) bind(); + if (! is_bound_) + { + bind(); + } - ConnectionManager *mgr=ConnectionManager::instance(); - shared_ptr > pool=mgr->getPool(creator_.id()); + ConnectionManager* mgr = ConnectionManager::instance(); + shared_ptr< Pool > pool = mgr->getPool(creator_.id()); if (pool) { shared_ptr conn = pool->borrowObject(); if (conn && conn->isOK()) { - PoolGuard,shared_ptr > > guard(conn,pool); + PoolGuard, shared_ptr< Pool > > guard(conn, pool); - if (!geometryColumn_.length() > 0) + if (geometryColumn_.empty()) { std::ostringstream s_error; s_error << "PostGIS: geometry name lookup failed for table '"; - if (schema_.length() > 0) + + if (! schema_.empty()) { s_error << schema_ << "."; } s_error << geometry_table_ << "'. Please manually provide the 'geometry_field' parameter or add an entry " << "in the geometry_columns for '"; - if (schema_.length() > 0) + + if (! schema_.empty()) { s_error << schema_ << "."; } s_error << geometry_table_ << "'."; + throw mapnik::datasource_exception(s_error.str()); } @@ -573,27 +626,28 @@ featureset_ptr postgis_datasource::features_at_point(coord2d const& pt) const mapnik::context_ptr ctx = boost::make_shared(); - if (!key_field_.empty()) + if (! key_field_.empty()) { - mapnik::sql_utils::quote_attr(s,key_field_); + mapnik::sql_utils::quote_attr(s, key_field_); ctx->push(key_field_); } std::vector::const_iterator itr = desc_.get_descriptors().begin(); std::vector::const_iterator end = desc_.get_descriptors().end(); - for ( ; itr != end; ++itr) + for (; itr != end; ++itr) { - mapnik::sql_utils::quote_attr(s,itr->get_name()); + mapnik::sql_utils::quote_attr(s, itr->get_name()); ctx->push(itr->get_name()); } - box2d box(pt.x,pt.y,pt.x,pt.y); - std::string table_with_bbox = populate_tokens(table_,FMAX,box); + box2d box(pt.x, pt.y, pt.x, pt.y); + std::string table_with_bbox = populate_tokens(table_, FMAX, box); - s << " from " << table_with_bbox; + s << " FROM " << table_with_bbox; - if (row_limit_ > 0) { + if (row_limit_ > 0) + { s << " LIMIT " << row_limit_; } @@ -601,30 +655,42 @@ featureset_ptr postgis_datasource::features_at_point(coord2d const& pt) const return boost::make_shared(rs, ctx, desc_.get_encoding(), !key_field_.empty()); } } + return featureset_ptr(); } box2d postgis_datasource::envelope() const { - if (extent_initialized_) return extent_; - if (!is_bound_) bind(); + if (extent_initialized_) + { + return extent_; + } - ConnectionManager *mgr=ConnectionManager::instance(); - shared_ptr > pool=mgr->getPool(creator_.id()); + if (! is_bound_) + { + bind(); + } + + ConnectionManager* mgr = ConnectionManager::instance(); + shared_ptr< Pool > pool = mgr->getPool(creator_.id()); if (pool) { shared_ptr conn = pool->borrowObject(); if (conn && conn->isOK()) { - PoolGuard,shared_ptr > > guard(conn,pool); - std::ostringstream s; - boost::optional estimate_extent = params_.get("estimate_extent",false); + PoolGuard, shared_ptr< Pool > > guard(conn, pool); - if (!geometryColumn_.length() > 0) + std::ostringstream s; + + boost::optional estimate_extent = + params_.get("estimate_extent", false); + + if (geometryColumn_.empty()) { std::ostringstream s_error; s_error << "PostGIS: unable to query the layer extent of table '"; - if (schema_.length() > 0) + + if (! schema_.empty()) { s_error << schema_ << "."; } @@ -632,6 +698,7 @@ box2d postgis_datasource::envelope() const << "\nPlease provide either an 'extent' parameter to skip this query, " << "a 'geometry_field' and/or 'geometry_table' parameter, or add a " << "record to the 'geometry_columns' for your table."; + throw mapnik::datasource_exception("Postgis Plugin: " + s_error.str()); } @@ -640,7 +707,7 @@ box2d postgis_datasource::envelope() const s << "SELECT ST_XMin(ext),ST_YMin(ext),ST_XMax(ext),ST_YMax(ext)" << " FROM (SELECT ST_Estimated_Extent('"; - if (schema_.length() > 0) + if (! schema_.empty()) { s << mapnik::sql_utils::unquote_double(schema_) << "','"; } @@ -652,6 +719,7 @@ box2d postgis_datasource::envelope() const { s << "SELECT ST_XMin(ext),ST_YMin(ext),ST_XMax(ext),ST_YMax(ext)" << " FROM (SELECT ST_Extent(" < postgis_datasource::envelope() const } else { - if (schema_.length() > 0) + if (! schema_.empty()) { s << schema_ << "."; } @@ -679,18 +747,15 @@ box2d postgis_datasource::envelope() const */ shared_ptr rs = conn->executeQuery(s.str()); - if (rs->next() && !rs->isNull(0)) + if (rs->next() && ! rs->isNull(0)) { - double lox; - double loy; - double hix; - double hiy; - if (mapnik::util::string2double(rs->getValue(0),lox) && - mapnik::util::string2double(rs->getValue(1),loy) && - mapnik::util::string2double(rs->getValue(2),hix) && - mapnik::util::string2double(rs->getValue(3),hiy)) + double lox, loy, hix, hiy; + if (mapnik::util::string2double(rs->getValue(0), lox) && + mapnik::util::string2double(rs->getValue(1), loy) && + mapnik::util::string2double(rs->getValue(2), hix) && + mapnik::util::string2double(rs->getValue(3), hiy)) { - extent_.init(lox,loy,hix,hiy); + extent_.init(lox, loy, hix, hiy); extent_initialized_ = true; } else @@ -701,22 +766,27 @@ box2d postgis_datasource::envelope() const rs->close(); } } + return extent_; } boost::optional postgis_datasource::get_geometry_type() const { - if (! is_bound_) bind(); + if (! is_bound_) + { + bind(); + } + boost::optional result; - ConnectionManager *mgr=ConnectionManager::instance(); - shared_ptr > pool=mgr->getPool(creator_.id()); + ConnectionManager* mgr = ConnectionManager::instance(); + shared_ptr< Pool > pool = mgr->getPool(creator_.id()); if (pool) { shared_ptr conn = pool->borrowObject(); if (conn && conn->isOK()) { - PoolGuard,shared_ptr > > guard(conn,pool); + PoolGuard, shared_ptr< Pool > > guard(conn, pool); std::ostringstream s; std::string g_type; @@ -726,31 +796,35 @@ boost::optional postgis_datasource::get_geometry << mapnik::sql_utils::unquote_double(geometry_table_) << "'"; - if (schema_.length() > 0) + if (! schema_.empty()) + { s << " AND f_table_schema='" << mapnik::sql_utils::unquote_double(schema_) << "'"; + } - if (geometry_field_.length() > 0) + if (! geometry_field_.empty()) + { s << " AND f_geometry_column='" << mapnik::sql_utils::unquote_double(geometry_field_) << "'"; + } shared_ptr rs = conn->executeQuery(s.str()); if (rs->next()) { g_type = rs->getValue("type"); - if (boost::algorithm::contains(g_type,"line")) + if (boost::algorithm::contains(g_type, "line")) { result.reset(mapnik::datasource::LineString); return result; } - else if (boost::algorithm::contains(g_type,"point")) + else if (boost::algorithm::contains(g_type, "point")) { result.reset(mapnik::datasource::Point); return result; } - else if (boost::algorithm::contains(g_type,"polygon")) + else if (boost::algorithm::contains(g_type, "polygon")) { result.reset(mapnik::datasource::Polygon); return result; @@ -763,13 +837,16 @@ boost::optional postgis_datasource::get_geometry } // fallback to querying first several features - if (g_type.empty() && !geometryColumn_.empty()) + if (g_type.empty() && ! geometryColumn_.empty()) { s.str(""); + std::string prev_type(""); + s << "SELECT ST_GeometryType(\"" << geometryColumn_ << "\") AS geom" << " FROM " << populate_tokens(table_); + if (row_limit_ > 0 && row_limit_ < 5) { s << " LIMIT " << row_limit_; @@ -778,21 +855,22 @@ boost::optional postgis_datasource::get_geometry { s << " LIMIT 5"; } + shared_ptr rs = conn->executeQuery(s.str()); - while (rs->next() && !rs->isNull(0)) + while (rs->next() && ! rs->isNull(0)) { const char* data = rs->getValue(0); - if (boost::algorithm::icontains(data,"line")) + if (boost::algorithm::icontains(data, "line")) { g_type = "linestring"; result.reset(mapnik::datasource::LineString); } - else if (boost::algorithm::icontains(data,"point")) + else if (boost::algorithm::icontains(data, "point")) { g_type = "point"; result.reset(mapnik::datasource::Point); } - else if (boost::algorithm::icontains(data,"polygon")) + else if (boost::algorithm::icontains(data, "polygon")) { g_type = "polygon"; result.reset(mapnik::datasource::Polygon); @@ -802,7 +880,7 @@ boost::optional postgis_datasource::get_geometry result.reset(mapnik::datasource::Collection); return result; } - if (!prev_type.empty() && g_type != prev_type) + if (! prev_type.empty() && g_type != prev_type) { result.reset(mapnik::datasource::Collection); return result; @@ -818,10 +896,10 @@ boost::optional postgis_datasource::get_geometry postgis_datasource::~postgis_datasource() { - if (is_bound_ && !persist_connection_) + if (is_bound_ && ! persist_connection_) { - ConnectionManager *mgr=ConnectionManager::instance(); - shared_ptr > pool=mgr->getPool(creator_.id()); + ConnectionManager* mgr = ConnectionManager::instance(); + shared_ptr< Pool > pool = mgr->getPool(creator_.id()); if (pool) { shared_ptr conn = pool->borrowObject(); diff --git a/plugins/input/postgis/postgis_datasource.hpp b/plugins/input/postgis/postgis_datasource.hpp index 047796e4f..c353c5216 100644 --- a/plugins/input/postgis/postgis_datasource.hpp +++ b/plugins/input/postgis/postgis_datasource.hpp @@ -49,8 +49,30 @@ using mapnik::coord2d; class postgis_datasource : public datasource { +public: + postgis_datasource(const parameters ¶ms, bool bind=true); + ~postgis_datasource(); + mapnik::datasource::datasource_t type() const; + static std::string name(); + featureset_ptr features(const query& q) const; + featureset_ptr features_at_point(coord2d const& pt) const; + mapnik::box2d envelope() const; + boost::optional get_geometry_type() const; + layer_descriptor get_descriptor() const; + void bind() const; + +private: + std::string sql_bbox(box2d const& env) const; + std::string populate_tokens(const std::string& sql, double scale_denom, box2d const& env) const; + std::string populate_tokens(const std::string& sql) const; + static std::string unquote(const std::string& sql); + boost::shared_ptr get_resultset(boost::shared_ptr const &conn, std::string const& sql) const; + postgis_datasource(const postgis_datasource&); + postgis_datasource& operator=(const postgis_datasource&); + static const std::string GEOMETRY_COLUMNS; static const std::string SPATIAL_REF_SYS; + static const double FMAX; const std::string uri_; const std::string username_; const std::string password_; @@ -76,25 +98,6 @@ class postgis_datasource : public datasource int intersect_min_scale_; int intersect_max_scale_; //bool show_queries_; -public: - static std::string name(); - mapnik::datasource::datasource_t type() const; - featureset_ptr features(const query& q) const; - featureset_ptr features_at_point(coord2d const& pt) const; - mapnik::box2d envelope() const; - boost::optional get_geometry_type() const; - layer_descriptor get_descriptor() const; - postgis_datasource(const parameters ¶ms, bool bind=true); - ~postgis_datasource(); - void bind() const; -private: - std::string sql_bbox(box2d const& env) const; - std::string populate_tokens(const std::string& sql, double scale_denom, box2d const& env) const; - std::string populate_tokens(const std::string& sql) const; - static std::string unquote(const std::string& sql); - boost::shared_ptr get_resultset(boost::shared_ptr const &conn, std::string const& sql) const; - postgis_datasource(const postgis_datasource&); - postgis_datasource& operator=(const postgis_datasource&); }; #endif //POSTGIS_DATASOURCE_HPP diff --git a/plugins/input/postgis/postgis_featureset.cpp b/plugins/input/postgis/postgis_featureset.cpp index 177413fee..ac2f8d9b4 100644 --- a/plugins/input/postgis/postgis_featureset.cpp +++ b/plugins/input/postgis/postgis_featureset.cpp @@ -56,22 +56,25 @@ postgis_featureset::postgis_featureset(boost::shared_ptr const& rs, tr_(new transcoder(encoding)), totalGeomSize_(0), feature_id_(1), - key_field_(key_field) {} + key_field_(key_field) +{ +} feature_ptr postgis_featureset::next() { if (rs_->next()) { // new feature + unsigned pos = 1; feature_ptr feature; - unsigned pos = 1; - - if (key_field_) { + if (key_field_) + { // create feature with user driven id from attribute int oid = rs_->getTypeOID(pos); const char* buf = rs_->getValue(pos); std::string name = rs_->getFieldName(pos); + // validation happens of this type at bind() int val; if (oid == 20) @@ -86,15 +89,18 @@ feature_ptr postgis_featureset::next() { val = int4net(buf); } + feature = feature_factory::create(ctx_, val); // TODO - extend feature class to know // that its id is also an attribute to avoid // this duplication feature->put(name,val); ++pos; - } else { + } + else + { // fallback to auto-incrementing id - feature = feature_factory::create(ctx_,feature_id_); + feature = feature_factory::create(ctx_, feature_id_); ++feature_id_; } @@ -102,74 +108,97 @@ feature_ptr postgis_featureset::next() int size = rs_->getFieldLength(0); const char *data = rs_->getValue(0); geometry_utils::from_wkb(feature->paths(), data, size); - totalGeomSize_+=size; + totalGeomSize_ += size; int num_attrs = ctx_->size() + 1; - for ( ; pos < num_attrs; ++pos) + for (; pos < num_attrs; ++pos) { std::string name = rs_->getFieldName(pos); if (rs_->isNull(pos)) { - feature->put(name,mapnik::value_null()); + feature->put(name, mapnik::value_null()); } else { const char* buf = rs_->getValue(pos); - int oid = rs_->getTypeOID(pos); + const int oid = rs_->getTypeOID(pos); + switch (oid) + { + case 16: //bool + { + feature->put(name, (buf[0] != 0)); + break; + } - if (oid==16) //bool - { - feature->put(name,(buf[0] != 0)); - } - else if (oid==23) //int4 - { - int val = int4net(buf); - feature->put(name,val); - } - else if (oid==21) //int2 - { - int val = int2net(buf); - feature->put(name,val); - } - else if (oid==20) //int8/BigInt - { - int val = int8net(buf); - feature->put(name,val); - } - else if (oid == 700) // float4 - { - float val; - float4net(val,buf); - feature->put(name,val); - } - else if (oid == 701) // float8 - { - double val; - float8net(val,buf); - feature->put(name,val); - } - else if (oid==25 || oid==1043) // text or varchar - { - feature->put(name,tr_->transcode(buf)); - } - else if (oid==1042) - { - // bpchar - feature->put(name,tr_->transcode(trim_copy(std::string(buf)).c_str())); - } - else if (oid == 1700) // numeric - { - std::string str = mapnik::sql_utils::numeric2string(buf); - double val; - if (mapnik::util::string2double(str,val)) - feature->put(name,val); - } - else - { + case 23: //int4 + { + int val = int4net(buf); + feature->put(name, val); + break; + } + + case 21: //int2 + { + int val = int2net(buf); + feature->put(name, val); + break; + } + + case 20: //int8/BigInt + { + int val = int8net(buf); + feature->put(name, val); + break; + } + + case 700: //float4 + { + float val; + float4net(val, buf); + feature->put(name, val); + break; + } + + case 701: //float8 + { + double val; + float8net(val, buf); + feature->put(name, val); + break; + } + + case 25: //text + case 1043: //varchar + { + feature->put(name, tr_->transcode(buf)); + break; + } + + case 1042: //bpchar + { + feature->put(name, tr_->transcode(trim_copy(std::string(buf)).c_str())); + break; + } + + case 1700: //numeric + { + double val; + std::string str = mapnik::sql_utils::numeric2string(buf); + if (mapnik::util::string2double(str, val)) + { + feature->put(name, val); + } + break; + } + + default: + { #ifdef MAPNIK_DEBUG - std::clog << "Postgis Plugin: uknown OID = " << oid << " FIXME " << std::endl; + std::clog << "Postgis Plugin: uknown OID = " << oid << std::endl; #endif + break; + } } } } diff --git a/plugins/input/postgis/postgis_featureset.hpp b/plugins/input/postgis/postgis_featureset.hpp index 7ed317a32..80c011c83 100644 --- a/plugins/input/postgis/postgis_featureset.hpp +++ b/plugins/input/postgis/postgis_featureset.hpp @@ -43,13 +43,6 @@ class IResultSet; class postgis_featureset : public mapnik::Featureset { -private: - boost::shared_ptr rs_; - context_ptr ctx_; - boost::scoped_ptr tr_; - int totalGeomSize_; - int feature_id_; - bool key_field_; public: postgis_featureset(boost::shared_ptr const& rs, context_ptr const& ctx, @@ -57,6 +50,14 @@ public: bool key_field = false); feature_ptr next(); ~postgis_featureset(); + +private: + boost::shared_ptr rs_; + context_ptr ctx_; + boost::scoped_ptr tr_; + int totalGeomSize_; + int feature_id_; + bool key_field_; }; #endif // POSTGIS_FEATURESET_HPP From 4a7966498c76e98684a06a32c572167aef9f90de Mon Sep 17 00:00:00 2001 From: kunitoki Date: Sat, 31 Mar 2012 22:24:32 +0200 Subject: [PATCH 009/134] - postgis resultset cosmetics --- plugins/input/postgis/resultset.hpp | 95 ++++++++++++++++------------- 1 file changed, 54 insertions(+), 41 deletions(-) diff --git a/plugins/input/postgis/resultset.hpp b/plugins/input/postgis/resultset.hpp index 4e43763a3..beab2d729 100644 --- a/plugins/input/postgis/resultset.hpp +++ b/plugins/input/postgis/resultset.hpp @@ -47,57 +47,61 @@ public: class ResultSet : public IResultSet { -private: - PGresult* res_; - int pos_; - int numTuples_; - int *refCount_; - public: ResultSet(PGresult *res) - : res_(res), - pos_(-1), - refCount_(new int(1)) + : res_(res), + pos_(-1), + refCount_(new int(1)) { - numTuples_=PQntuples(res_); + numTuples_ = PQntuples(res_); } ResultSet(const ResultSet& rhs) - : res_(rhs.res_), - pos_(rhs.pos_), - numTuples_(rhs.numTuples_), - refCount_(rhs.refCount_) + : res_(rhs.res_), + pos_(rhs.pos_), + numTuples_(rhs.numTuples_), + refCount_(rhs.refCount_) { (*refCount_)++; } ResultSet& operator=(const ResultSet& rhs) { - if (this==&rhs) return *this; - if (--(refCount_)==0) + if (this == &rhs) + { + return *this; + } + + if (--(refCount_) == 0) { close(); - delete refCount_,refCount_=0; + + delete refCount_; + refCount_ = 0; } - res_=rhs.res_; - pos_=rhs.pos_; - numTuples_=rhs.numTuples_; - refCount_=rhs.refCount_; + + res_ = rhs.res_; + pos_ = rhs.pos_; + numTuples_ = rhs.numTuples_; + refCount_ = rhs.refCount_; (*refCount_)++; return *this; } virtual void close() { - PQclear(res_),res_=0; + PQclear(res_); + res_ = 0; } virtual ~ResultSet() { - if (--(*refCount_)==0) + if (--(*refCount_) == 0) { PQclear(res_); - delete refCount_,refCount_=0; + + delete refCount_; + refCount_ = 0; } } @@ -118,60 +122,69 @@ public: virtual bool next() { - return (++pos_=0) - return PQgetlength(res_,pos_,col); + int col = PQfnumber(res_, name); + if (col >= 0) + { + return PQgetlength(res_, pos_, col); + } return 0; } virtual int getTypeOID(int index) const { - return PQftype(res_,index); + return PQftype(res_, index); } virtual int getTypeOID(const char* name) const { - int col=PQfnumber(res_,name); - if (col>=0) - return PQftype(res_,col); + int col = PQfnumber(res_, name); + if (col >= 0) + { + return PQftype(res_, col); + } return 0; } virtual bool isNull(int index) const { - return static_cast(PQgetisnull(res_,pos_,index)); + return static_cast(PQgetisnull(res_, pos_, index)); } virtual const char* getValue(int index) const { - return PQgetvalue(res_,pos_,index); + return PQgetvalue(res_, pos_, index); } virtual const char* getValue(const char* name) const { - int col=PQfnumber(res_,name); - if (col>=0) + int col = PQfnumber(res_, name); + if (col >= 0) + { return getValue(col); + } return 0; } + +private: + PGresult* res_; + int pos_; + int numTuples_; + int *refCount_; }; #endif //RESULTSET_HPP - - - From 9d6c47844cd892be6e8fbe36a62cd88c0d99b32b Mon Sep 17 00:00:00 2001 From: Dane Springmeyer Date: Mon, 2 Apr 2012 11:33:29 -0700 Subject: [PATCH 010/134] use more robust transform method in map.zoom_all --- src/map.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/map.cpp b/src/map.cpp index 428c796c1..e04ffd4db 100644 --- a/src/map.cpp +++ b/src/map.cpp @@ -28,6 +28,7 @@ #include #include #include +#include // for PROJ_ENVELOPE_POINTS // boost #include @@ -405,8 +406,7 @@ void Map::zoom_all() proj_transform prj_trans(proj0,proj1); box2d layer_ext = itr->envelope(); - // TODO - consider using more robust method: http://trac.mapnik.org/ticket/751 - if (prj_trans.backward(layer_ext)) + if (prj_trans.backward(layer_ext, PROJ_ENVELOPE_POINTS)) { success = true; #ifdef MAPNIK_DEBUG From f6a0f80f323903cde32b0672e22582b58712908c Mon Sep 17 00:00:00 2001 From: Dane Springmeyer Date: Mon, 2 Apr 2012 15:42:52 -0700 Subject: [PATCH 011/134] make note of need for 64bit int support in code comments for postgis plugin - refs #895 --- plugins/input/postgis/postgis_featureset.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/plugins/input/postgis/postgis_featureset.cpp b/plugins/input/postgis/postgis_featureset.cpp index ac2f8d9b4..66d65c4ab 100644 --- a/plugins/input/postgis/postgis_featureset.cpp +++ b/plugins/input/postgis/postgis_featureset.cpp @@ -147,6 +147,8 @@ feature_ptr postgis_featureset::next() case 20: //int8/BigInt { + // TODO - need to support boost::uint64_t in mapnik::value + // https://github.com/mapnik/mapnik/issues/895 int val = int8net(buf); feature->put(name, val); break; From 763e84a6e9c39c3b0bc5f454da607e6b674aaf43 Mon Sep 17 00:00:00 2001 From: Dane Springmeyer Date: Mon, 2 Apr 2012 16:20:41 -0700 Subject: [PATCH 012/134] postgis: add support for auto-detection of primary key field - closes #804 - refs #753 --- plugins/input/postgis/postgis_datasource.cpp | 119 ++++++++++++++--- plugins/input/postgis/postgis_datasource.hpp | 2 +- tests/python_tests/postgis_test.py | 131 ++++++++++++++++++- 3 files changed, 232 insertions(+), 20 deletions(-) diff --git a/plugins/input/postgis/postgis_datasource.cpp b/plugins/input/postgis/postgis_datasource.cpp index e992ea051..34f95d495 100644 --- a/plugins/input/postgis/postgis_datasource.cpp +++ b/plugins/input/postgis/postgis_datasource.cpp @@ -107,6 +107,7 @@ void postgis_datasource::bind() const boost::optional initial_size = params_.get("initial_size", 1); boost::optional max_size = params_.get("max_size", 10); + boost::optional require_key = params_.get("require_key", false); ConnectionManager* mgr = ConnectionManager::instance(); mgr->registerPool(creator_, *initial_size, *max_size); @@ -228,6 +229,71 @@ void postgis_datasource::bind() const } } + // detect primary key + if (key_field_.empty()) + { + std::ostringstream s; + s << "SELECT a.attname, a.attnum, t.typname, t.typname in ('int2','int4','int8') " + "AS is_int FROM pg_class c, pg_attribute a, pg_type t, pg_namespace n, pg_index i " + "WHERE a.attnum > 0 AND a.attrelid = c.oid " + "AND a.atttypid = t.oid AND c.relnamespace = n.oid " + "AND c.oid = i.indrelid AND i.indisprimary = 't' " + "AND t.typname !~ '^geom' AND c.relname =" + << " '" << mapnik::sql_utils::unquote_double(geometry_table_) << "' " + //"AND a.attnum = ANY (i.indkey) " // postgres >= 8.1 + << "AND (i.indkey[0]=a.attnum OR i.indkey[1]=a.attnum OR i.indkey[2]=a.attnum " + "OR i.indkey[3]=a.attnum OR i.indkey[4]=a.attnum OR i.indkey[5]=a.attnum " + "OR i.indkey[6]=a.attnum OR i.indkey[7]=a.attnum OR i.indkey[8]=a.attnum " + "OR i.indkey[9]=a.attnum) "; + if (! schema_.empty()) + { + s << "AND n.nspname='" + << mapnik::sql_utils::unquote_double(schema_) + << "' "; + } + s << "ORDER BY a.attnum"; + + shared_ptr rs_key = conn->executeQuery(s.str()); + if (rs_key->next()) + { + unsigned int result_rows = rs_key->size(); + if (result_rows == 1) + { + bool is_int = (std::string(rs_key->getValue(3)) == "t"); + if (is_int) + { + const char* key_field_string = rs_key->getValue(0); + if (key_field_string) + { + key_field_ = std::string(key_field_string); +#ifdef MAPNIK_DEBUG + std::clog << "Postgis Plugin: auto-detected key field of '" << key_field_ << "' on '" << geometry_table_ << "'\n"; +#endif + } + } + } + else if (result_rows > 1) + { + std::clog << "PostGIS Plugin: warning, multi column primary key detected but is not supported\n"; + } + } +#ifdef MAPNIK_DEBUG + else + { + std::clog << "Postgis Plugin: no primary key could be detected for '" << geometry_table_ << "'\n"; + } +#endif + rs_key->close(); + } + + // if a globally unique key field/primary key is required + // but still not known at this point, then throw + if (*require_key && key_field_.empty()) + { + throw mapnik::datasource_exception(std::string("PostGIS Plugin: Error: primary key required for table '") + + geometry_table_ + "', please supply 'key_field' option to specify field to use for primary key"); + } + if (srid_ == 0) { srid_ = -1; @@ -268,9 +334,9 @@ void postgis_datasource::bind() const // validate type of key_field if (! found_key_field && ! key_field_.empty() && fld_name == key_field_) { - found_key_field = true; if (type_oid == 20 || type_oid == 21 || type_oid == 23) { + found_key_field = true; desc_.add_descriptor(attribute_descriptor(fld_name, mapnik::Integer)); } else @@ -314,7 +380,7 @@ void postgis_datasource::bind() const break; case 700: // float4 case 701: // float8 - case 1700: // numeric ?? + case 1700: // numeric desc_.add_descriptor(attribute_descriptor(fld_name, mapnik::Double)); case 1042: // bpchar case 1043: // varchar @@ -545,21 +611,31 @@ featureset_ptr postgis_datasource::features(const query& q) const s << "SELECT ST_AsBinary(\"" << geometryColumn_ << "\") AS geom"; mapnik::context_ptr ctx = boost::make_shared(); + std::set const& props = q.property_names(); + std::set::const_iterator pos = props.begin(); + std::set::const_iterator end = props.end(); if (! key_field_.empty()) { mapnik::sql_utils::quote_attr(s, key_field_); ctx->push(key_field_); + + for (; pos != end; ++pos) + { + if (*pos != key_field_) + { + mapnik::sql_utils::quote_attr(s, *pos); + ctx->push(*pos); + } + } } - - std::set const& props = q.property_names(); - std::set::const_iterator pos = props.begin(); - std::set::const_iterator end = props.end(); - - for (; pos != end; ++pos) + else { - mapnik::sql_utils::quote_attr(s, *pos); - ctx->push(*pos); + for (; pos != end; ++pos) + { + mapnik::sql_utils::quote_attr(s, *pos); + ctx->push(*pos); + } } std::string table_with_bbox = populate_tokens(table_, scale_denom, box); @@ -625,20 +701,29 @@ featureset_ptr postgis_datasource::features_at_point(coord2d const& pt) const s << "SELECT ST_AsBinary(\"" << geometryColumn_ << "\") AS geom"; mapnik::context_ptr ctx = boost::make_shared(); + std::vector::const_iterator itr = desc_.get_descriptors().begin(); + std::vector::const_iterator end = desc_.get_descriptors().end(); if (! key_field_.empty()) { mapnik::sql_utils::quote_attr(s, key_field_); ctx->push(key_field_); + for (; itr != end; ++itr) + { + if (itr->get_name() != key_field_) + { + mapnik::sql_utils::quote_attr(s, itr->get_name()); + ctx->push(itr->get_name()); + } + } } - - std::vector::const_iterator itr = desc_.get_descriptors().begin(); - std::vector::const_iterator end = desc_.get_descriptors().end(); - - for (; itr != end; ++itr) + else { - mapnik::sql_utils::quote_attr(s, itr->get_name()); - ctx->push(itr->get_name()); + for (; itr != end; ++itr) + { + mapnik::sql_utils::quote_attr(s, itr->get_name()); + ctx->push(itr->get_name()); + } } box2d box(pt.x, pt.y, pt.x, pt.y); diff --git a/plugins/input/postgis/postgis_datasource.hpp b/plugins/input/postgis/postgis_datasource.hpp index c353c5216..f309f47fe 100644 --- a/plugins/input/postgis/postgis_datasource.hpp +++ b/plugins/input/postgis/postgis_datasource.hpp @@ -80,7 +80,7 @@ private: mutable std::string schema_; mutable std::string geometry_table_; const std::string geometry_field_; - const std::string key_field_; + mutable std::string key_field_; const int cursor_fetch_size_; const int row_limit_; mutable std::string geometryColumn_; diff --git a/tests/python_tests/postgis_test.py b/tests/python_tests/postgis_test.py index aec77cabc..b77922a30 100644 --- a/tests/python_tests/postgis_test.py +++ b/tests/python_tests/postgis_test.py @@ -63,7 +63,8 @@ def createdb_and_dropdb_on_path(): print 'Notice: skipping postgis tests (createdb/dropdb)' return False -insert_sql = """ +insert_table_1 = """ +CREATE TABLE test(gid serial PRIMARY KEY, geom geometry); INSERT INTO test(geom) values (GeomFromEWKT('SRID=4326;POINT(0 0)')); INSERT INTO test(geom) values (GeomFromEWKT('SRID=4326;POINT(-2 2)')); INSERT INTO test(geom) values (GeomFromEWKT('SRID=4326;MULTIPOINT(2 1,1 2)')); @@ -74,12 +75,46 @@ INSERT INTO test(geom) values (GeomFromEWKT('SRID=4326;MULTIPOLYGON(((1 1,3 1,3 INSERT INTO test(geom) values (GeomFromEWKT('SRID=4326;GEOMETRYCOLLECTION(POLYGON((1 1, 2 1, 2 2, 1 2,1 1)),POINT(2 3),LINESTRING(2 3,3 4))')); """ +insert_table_2 = """ +CREATE TABLE test2(manual_id int4 PRIMARY KEY, geom geometry); +INSERT INTO test2(manual_id, geom) values (0, GeomFromEWKT('SRID=4326;POINT(0 0)')); +INSERT INTO test2(manual_id, geom) values (1, GeomFromEWKT('SRID=4326;POINT(0 0)')); +INSERT INTO test2(manual_id, geom) values (1000, GeomFromEWKT('SRID=4326;POINT(0 0)')); +INSERT INTO test2(manual_id, geom) values (-1000, GeomFromEWKT('SRID=4326;POINT(0 0)')); +INSERT INTO test2(manual_id, geom) values (2147483647, GeomFromEWKT('SRID=4326;POINT(0 0)')); +INSERT INTO test2(manual_id, geom) values (-2147483648, GeomFromEWKT('SRID=4326;POINT(0 0)')); +""" + +insert_table_3 = """ +CREATE TABLE test3(non_id bigint, manual_id int4, geom geometry); +INSERT INTO test3(non_id, manual_id, geom) values (9223372036854775807, 0, GeomFromEWKT('SRID=4326;POINT(0 0)')); +INSERT INTO test3(non_id, manual_id, geom) values (9223372036854775807, 1, GeomFromEWKT('SRID=4326;POINT(0 0)')); +INSERT INTO test3(non_id, manual_id, geom) values (9223372036854775807, 1000, GeomFromEWKT('SRID=4326;POINT(0 0)')); +INSERT INTO test3(non_id, manual_id, geom) values (9223372036854775807, -1000, GeomFromEWKT('SRID=4326;POINT(0 0)')); +INSERT INTO test3(non_id, manual_id, geom) values (9223372036854775807, 2147483647, GeomFromEWKT('SRID=4326;POINT(0 0)')); +INSERT INTO test3(non_id, manual_id, geom) values (9223372036854775807, -2147483648, GeomFromEWKT('SRID=4326;POINT(0 0)')); +""" + +insert_table_4 = """ +CREATE TABLE test4(non_id int4, manual_id int8 PRIMARY KEY, geom geometry); +INSERT INTO test4(non_id, manual_id, geom) values (0, 0, GeomFromEWKT('SRID=4326;POINT(0 0)')); +INSERT INTO test4(non_id, manual_id, geom) values (0, 1, GeomFromEWKT('SRID=4326;POINT(0 0)')); +INSERT INTO test4(non_id, manual_id, geom) values (0, 1000, GeomFromEWKT('SRID=4326;POINT(0 0)')); +INSERT INTO test4(non_id, manual_id, geom) values (0, -1000, GeomFromEWKT('SRID=4326;POINT(0 0)')); +INSERT INTO test4(non_id, manual_id, geom) values (0, 2147483647, GeomFromEWKT('SRID=4326;POINT(0 0)')); +INSERT INTO test4(non_id, manual_id, geom) values (0, -2147483648, GeomFromEWKT('SRID=4326;POINT(0 0)')); +""" + def postgis_setup(): call('dropdb %s' % MAPNIK_TEST_DBNAME,silent=True) call('createdb -T %s %s' % (POSTGIS_TEMPLATE_DBNAME,MAPNIK_TEST_DBNAME),silent=False) call('shp2pgsql -s 3857 -g geom -W LATIN1 %s world_merc | psql -q %s' % (SHAPEFILE,MAPNIK_TEST_DBNAME), silent=True) call('''psql -q %s -c "CREATE TABLE \"empty\" (key serial);SELECT AddGeometryColumn('','empty','geom','-1','GEOMETRY',4);"''' % MAPNIK_TEST_DBNAME,silent=False) - call('''psql -q %s -c "create table test(gid serial PRIMARY KEY, geom geometry);%s"''' % (MAPNIK_TEST_DBNAME,insert_sql),silent=False) + call('''psql -q %s -c "%s"''' % (MAPNIK_TEST_DBNAME,insert_table_1),silent=False) + call('''psql -q %s -c "%s"''' % (MAPNIK_TEST_DBNAME,insert_table_2),silent=False) + call('''psql -q %s -c "%s"''' % (MAPNIK_TEST_DBNAME,insert_table_3),silent=False) + call('''psql -q %s -c "%s"''' % (MAPNIK_TEST_DBNAME,insert_table_4),silent=False) + def postgis_takedown(): pass # fails as the db is in use: https://github.com/mapnik/mapnik/issues/960 @@ -182,6 +217,98 @@ if 'postgis' in mapnik.DatasourceCache.instance().plugin_names() \ query.add_property_name('bogus') fs = ds.features(query) + def test_auto_detection_of_unique_feature_id_32_bit(): + ds = mapnik.PostGIS(dbname=MAPNIK_TEST_DBNAME,table='test2', + geometry_field='geom') + fs = ds.featureset() + eq_(fs.next()['manual_id'],0) + eq_(fs.next()['manual_id'],1) + eq_(fs.next()['manual_id'],1000) + eq_(fs.next()['manual_id'],-1000) + eq_(fs.next()['manual_id'],2147483647) + eq_(fs.next()['manual_id'],-2147483648) + + fs = ds.featureset() + eq_(fs.next().id(),0) + eq_(fs.next().id(),1) + eq_(fs.next().id(),1000) + eq_(fs.next().id(),-1000) + eq_(fs.next().id(),2147483647) + eq_(fs.next().id(),-2147483648) + + def test_auto_detection_will_fail_since_no_primary_key(): + ds = mapnik.PostGIS(dbname=MAPNIK_TEST_DBNAME,table='test3', + geometry_field='geom', + require_key=False) + fs = ds.featureset() + feat = fs.next() + eq_(feat['manual_id'],0) + # will fail: https://github.com/mapnik/mapnik/issues/895 + #eq_(feat['non_id'],9223372036854775807) + eq_(fs.next()['manual_id'],1) + eq_(fs.next()['manual_id'],1000) + eq_(fs.next()['manual_id'],-1000) + eq_(fs.next()['manual_id'],2147483647) + eq_(fs.next()['manual_id'],-2147483648) + + # since no valid primary key will be detected the fallback + # is auto-incrementing counter + fs = ds.featureset() + eq_(fs.next().id(),1) + eq_(fs.next().id(),2) + eq_(fs.next().id(),3) + eq_(fs.next().id(),4) + eq_(fs.next().id(),5) + eq_(fs.next().id(),6) + + @raises(RuntimeError) + def test_auto_detection_will_fail_and_should_throw(): + ds = mapnik.PostGIS(dbname=MAPNIK_TEST_DBNAME,table='test3', + geometry_field='geom', + require_key=True) + fs = ds.featureset() + + def test_auto_detection_of_unique_feature_id_64_bit(): + ds = mapnik.PostGIS(dbname=MAPNIK_TEST_DBNAME,table='test4', + geometry_field='geom', + require_key=False) + fs = ds.featureset() + eq_(fs.next()['manual_id'],0) + eq_(fs.next()['manual_id'],1) + eq_(fs.next()['manual_id'],1000) + eq_(fs.next()['manual_id'],-1000) + eq_(fs.next()['manual_id'],2147483647) + eq_(fs.next()['manual_id'],-2147483648) + + fs = ds.featureset() + eq_(fs.next().id(),0) + eq_(fs.next().id(),1) + eq_(fs.next().id(),1000) + eq_(fs.next().id(),-1000) + eq_(fs.next().id(),2147483647) + eq_(fs.next().id(),-2147483648) + + def test_manually_specified_feature_id_field(): + ds = mapnik.PostGIS(dbname=MAPNIK_TEST_DBNAME,table='test4', + geometry_field='geom', + key_field='manual_id', + require_key=True) + fs = ds.featureset() + eq_(fs.next()['manual_id'],0) + eq_(fs.next()['manual_id'],1) + eq_(fs.next()['manual_id'],1000) + eq_(fs.next()['manual_id'],-1000) + eq_(fs.next()['manual_id'],2147483647) + eq_(fs.next()['manual_id'],-2147483648) + + fs = ds.featureset() + eq_(fs.next().id(),0) + eq_(fs.next().id(),1) + eq_(fs.next().id(),1000) + eq_(fs.next().id(),-1000) + eq_(fs.next().id(),2147483647) + eq_(fs.next().id(),-2147483648) + atexit.register(postgis_takedown) if __name__ == "__main__": From f99db72e5ad717f6c82454136b3a6a8e7f225211 Mon Sep 17 00:00:00 2001 From: Dane Springmeyer Date: Mon, 2 Apr 2012 16:23:08 -0700 Subject: [PATCH 013/134] update changelog after fixing #804 --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 66bc71981..4e42b0dda 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,8 @@ For a complete change history, see the SVN log. ## Mapnik 2.1.0 +- PostGIS: the primary key, for tables containing one, is now auto-detected allowing for globally unique feature id values (#804) + - Fix Markers rendering so that ellipse height/width units are pixels (previously were unintentially radii) - Removed PointDatasource - use more robust MemoryDatasource instead (#1032) From 10848f9d0455fc9af41f0ad8f711368200f8cc30 Mon Sep 17 00:00:00 2001 From: Dane Springmeyer Date: Mon, 2 Apr 2012 18:13:27 -0700 Subject: [PATCH 014/134] postgis: warn in the unlikely case of a numeric primary key --- plugins/input/postgis/postgis_datasource.cpp | 6 +++++- tests/python_tests/postgis_test.py | 19 +++++++++++++++++++ 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/plugins/input/postgis/postgis_datasource.cpp b/plugins/input/postgis/postgis_datasource.cpp index 34f95d495..6ff78bcd5 100644 --- a/plugins/input/postgis/postgis_datasource.cpp +++ b/plugins/input/postgis/postgis_datasource.cpp @@ -267,10 +267,14 @@ void postgis_datasource::bind() const { key_field_ = std::string(key_field_string); #ifdef MAPNIK_DEBUG - std::clog << "Postgis Plugin: auto-detected key field of '" << key_field_ << "' on '" << geometry_table_ << "'\n"; + std::clog << "PostGIS Plugin: auto-detected key field of '" << key_field_ << "' on table '" << geometry_table_ << "'\n"; #endif } } + else // warn with odd cases like numeric primary key + { + std::clog << "PostGIS Plugin: Warning: '" << rs_key->getValue(0) << "' on table '" << geometry_table_ << "' is not a valid integer primary key field\n"; + } } else if (result_rows > 1) { diff --git a/tests/python_tests/postgis_test.py b/tests/python_tests/postgis_test.py index b77922a30..e4908e1e9 100644 --- a/tests/python_tests/postgis_test.py +++ b/tests/python_tests/postgis_test.py @@ -105,6 +105,12 @@ INSERT INTO test4(non_id, manual_id, geom) values (0, 2147483647, GeomFromEWKT(' INSERT INTO test4(non_id, manual_id, geom) values (0, -2147483648, GeomFromEWKT('SRID=4326;POINT(0 0)')); """ +insert_table_5 = """ +CREATE TABLE test5(non_id int4, manual_id numeric PRIMARY KEY, geom geometry); +INSERT INTO test5(non_id, manual_id, geom) values (0, -1, GeomFromEWKT('SRID=4326;POINT(0 0)')); +INSERT INTO test5(non_id, manual_id, geom) values (0, 1, GeomFromEWKT('SRID=4326;POINT(0 0)')); +""" + def postgis_setup(): call('dropdb %s' % MAPNIK_TEST_DBNAME,silent=True) call('createdb -T %s %s' % (POSTGIS_TEMPLATE_DBNAME,MAPNIK_TEST_DBNAME),silent=False) @@ -114,6 +120,7 @@ def postgis_setup(): call('''psql -q %s -c "%s"''' % (MAPNIK_TEST_DBNAME,insert_table_2),silent=False) call('''psql -q %s -c "%s"''' % (MAPNIK_TEST_DBNAME,insert_table_3),silent=False) call('''psql -q %s -c "%s"''' % (MAPNIK_TEST_DBNAME,insert_table_4),silent=False) + call('''psql -q %s -c "%s"''' % (MAPNIK_TEST_DBNAME,insert_table_5),silent=False) def postgis_takedown(): pass @@ -309,6 +316,18 @@ if 'postgis' in mapnik.DatasourceCache.instance().plugin_names() \ eq_(fs.next().id(),2147483647) eq_(fs.next().id(),-2147483648) + def test_numeric_type_feature_id_field(): + ds = mapnik.PostGIS(dbname=MAPNIK_TEST_DBNAME,table='test5', + geometry_field='geom', + require_key=False) + fs = ds.featureset() + eq_(fs.next()['manual_id'],-1) + eq_(fs.next()['manual_id'],1) + + fs = ds.featureset() + eq_(fs.next().id(),1) + eq_(fs.next().id(),2) + atexit.register(postgis_takedown) if __name__ == "__main__": From 253a1e4b4bd588ef49a64641552e5dac9ac6ae42 Mon Sep 17 00:00:00 2001 From: Dane Springmeyer Date: Mon, 2 Apr 2012 19:20:09 -0700 Subject: [PATCH 015/134] occi: fix invalid concatenation uncovered by latest clang++ --- plugins/input/occi/occi_datasource.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/plugins/input/occi/occi_datasource.cpp b/plugins/input/occi/occi_datasource.cpp index e4d3fa4a3..16fc1b780 100644 --- a/plugins/input/occi/occi_datasource.cpp +++ b/plugins/input/occi/occi_datasource.cpp @@ -540,15 +540,15 @@ featureset_ptr occi_datasource::features(query const& q) const if (row_limit_ > 0) { - std::string row_limit_string = "rownum < " + row_limit_; - + std::ostringstream row_limit_string; + row_limit_string << "rownum < " << row_limit_; if (boost::algorithm::ifind_first(query, "WHERE")) { - boost::algorithm::ireplace_first(query, "WHERE", row_limit_string + " AND "); + boost::algorithm::ireplace_first(query, "WHERE", row_limit_string.str() + " AND "); } else if (boost::algorithm::ifind_first(query, table_name_)) { - boost::algorithm::ireplace_first(query, table_name_, table_name_ + " " + row_limit_string); + boost::algorithm::ireplace_first(query, table_name_, table_name_ + " " + row_limit_string.str()); } else { @@ -621,15 +621,15 @@ featureset_ptr occi_datasource::features_at_point(coord2d const& pt) const if (row_limit_ > 0) { - std::string row_limit_string = "rownum < " + row_limit_; - + std::ostringstream row_limit_string; + row_limit_string << "rownum < " << row_limit_; if (boost::algorithm::ifind_first(query, "WHERE")) { - boost::algorithm::ireplace_first(query, "WHERE", row_limit_string + " AND "); + boost::algorithm::ireplace_first(query, "WHERE", row_limit_string.str() + " AND "); } else if (boost::algorithm::ifind_first(query, table_name_)) { - boost::algorithm::ireplace_first(query, table_name_, table_name_ + " " + row_limit_string); + boost::algorithm::ireplace_first(query, table_name_, table_name_ + " " + row_limit_string.str()); } else { From d9cb76f7a1637ed9252f81709ecff4c86506f303 Mon Sep 17 00:00:00 2001 From: Dane Springmeyer Date: Mon, 2 Apr 2012 19:21:14 -0700 Subject: [PATCH 016/134] postgis: support mixed case table names - closes #1159 --- include/mapnik/sql_utils.hpp | 9 +++++---- tests/python_tests/postgis_test.py | 31 ++++++++++++++++++++++++++++++ 2 files changed, 36 insertions(+), 4 deletions(-) diff --git a/include/mapnik/sql_utils.hpp b/include/mapnik/sql_utils.hpp index d4a3b05ec..3a6d2e34e 100644 --- a/include/mapnik/sql_utils.hpp +++ b/include/mapnik/sql_utils.hpp @@ -31,14 +31,14 @@ namespace mapnik { namespace sql_utils { inline std::string unquote_double(const std::string& sql) { - std::string table_name = boost::algorithm::to_lower_copy(sql); + std::string table_name = sql; boost::algorithm::trim_if(table_name,boost::algorithm::is_any_of("\"")); return table_name; } inline std::string unquote(const std::string& sql) { - std::string table_name = boost::algorithm::to_lower_copy(sql); + std::string table_name = sql; boost::algorithm::trim_if(table_name,boost::algorithm::is_any_of("\"\'")); return table_name; } @@ -58,10 +58,11 @@ namespace mapnik { namespace sql_utils { inline std::string table_from_sql(const std::string& sql) { - std::string table_name = boost::algorithm::to_lower_copy(sql); + std::string table_name = sql; boost::algorithm::replace_all(table_name,"\n"," "); + boost::algorithm::ireplace_all(table_name," from "," FROM "); - std::string::size_type idx = table_name.rfind(" from "); + std::string::size_type idx = table_name.rfind(" FROM "); if (idx!=std::string::npos) { idx = table_name.find_first_not_of(" ",idx+5); diff --git a/tests/python_tests/postgis_test.py b/tests/python_tests/postgis_test.py index e4908e1e9..6259a379c 100644 --- a/tests/python_tests/postgis_test.py +++ b/tests/python_tests/postgis_test.py @@ -111,6 +111,14 @@ INSERT INTO test5(non_id, manual_id, geom) values (0, -1, GeomFromEWKT('SRID=432 INSERT INTO test5(non_id, manual_id, geom) values (0, 1, GeomFromEWKT('SRID=4326;POINT(0 0)')); """ +insert_table_6 = ''' +CREATE TABLE "tableWithMixedCase"(gid serial PRIMARY KEY, geom geometry); +INSERT INTO "tableWithMixedCase"(geom) values (ST_MakePoint(0,0)); +INSERT INTO "tableWithMixedCase"(geom) values (ST_MakePoint(0,1)); +INSERT INTO "tableWithMixedCase"(geom) values (ST_MakePoint(1,0)); +INSERT INTO "tableWithMixedCase"(geom) values (ST_MakePoint(1,1)); +''' + def postgis_setup(): call('dropdb %s' % MAPNIK_TEST_DBNAME,silent=True) call('createdb -T %s %s' % (POSTGIS_TEMPLATE_DBNAME,MAPNIK_TEST_DBNAME),silent=False) @@ -121,6 +129,7 @@ def postgis_setup(): call('''psql -q %s -c "%s"''' % (MAPNIK_TEST_DBNAME,insert_table_3),silent=False) call('''psql -q %s -c "%s"''' % (MAPNIK_TEST_DBNAME,insert_table_4),silent=False) call('''psql -q %s -c "%s"''' % (MAPNIK_TEST_DBNAME,insert_table_5),silent=False) + call("""psql -q %s -c '%s'""" % (MAPNIK_TEST_DBNAME,insert_table_6),silent=False) def postgis_takedown(): pass @@ -328,6 +337,28 @@ if 'postgis' in mapnik.DatasourceCache.instance().plugin_names() \ eq_(fs.next().id(),1) eq_(fs.next().id(),2) + def test_querying_table_with_mixed_case(): + ds = mapnik.PostGIS(dbname=MAPNIK_TEST_DBNAME,table='"tableWithMixedCase"', + geometry_field='geom', + require_key=True) + fs = ds.featureset() + eq_(fs.next().id(),1) + eq_(fs.next().id(),2) + eq_(fs.next().id(),3) + eq_(fs.next().id(),4) + eq_(fs.next(),None) + + def test_querying_subquery_with_mixed_case(): + ds = mapnik.PostGIS(dbname=MAPNIK_TEST_DBNAME,table='(SeLeCt * FrOm "tableWithMixedCase") as MixedCaseQuery', + geometry_field='geom', + require_key=True) + fs = ds.featureset() + eq_(fs.next().id(),1) + eq_(fs.next().id(),2) + eq_(fs.next().id(),3) + eq_(fs.next().id(),4) + eq_(fs.next(),None) + atexit.register(postgis_takedown) if __name__ == "__main__": From a7e150a59319831415fc1120e7f4b8efbc22953d Mon Sep 17 00:00:00 2001 From: Dane Springmeyer Date: Mon, 2 Apr 2012 19:29:06 -0700 Subject: [PATCH 017/134] tests: add simple tests for postgis 'bbox' token replacement --- plugins/input/sqlite/sqlite_datasource.cpp | 26 ++++++++++++++-------- tests/python_tests/postgis_test.py | 24 ++++++++++++++++++++ 2 files changed, 41 insertions(+), 9 deletions(-) diff --git a/plugins/input/sqlite/sqlite_datasource.cpp b/plugins/input/sqlite/sqlite_datasource.cpp index 77015ef82..57569cfb5 100644 --- a/plugins/input/sqlite/sqlite_datasource.cpp +++ b/plugins/input/sqlite/sqlite_datasource.cpp @@ -548,23 +548,31 @@ featureset_ptr sqlite_datasource::features(query const& q) const std::ostringstream s; mapnik::context_ptr ctx = boost::make_shared(); + std::set const& props = q.property_names(); + std::set::const_iterator pos = props.begin(); + std::set::const_iterator end = props.end(); s << "SELECT " << geometry_field_; if (!key_field_.empty()) { s << "," << key_field_; ctx->push(key_field_); + for ( ;pos != end;++pos) + { + if (*pos != key_field_) + { + s << ",[" << *pos << "]"; + ctx->push(*pos); + } + } } - std::set const& props = q.property_names(); - std::set::const_iterator pos = props.begin(); - std::set::const_iterator end = props.end(); - - for ( ;pos != end;++pos) + else { - // TODO - should we restrict duplicate key query? - //if (*pos != key_field_) - s << ",[" << *pos << "]"; - ctx->push(*pos); + for ( ;pos != end;++pos) + { + s << ",[" << *pos << "]"; + ctx->push(*pos); + } } s << " FROM "; diff --git a/tests/python_tests/postgis_test.py b/tests/python_tests/postgis_test.py index 6259a379c..128d4c998 100644 --- a/tests/python_tests/postgis_test.py +++ b/tests/python_tests/postgis_test.py @@ -359,6 +359,30 @@ if 'postgis' in mapnik.DatasourceCache.instance().plugin_names() \ eq_(fs.next().id(),4) eq_(fs.next(),None) + def test_bbox_token_in_subquery1(): + ds = mapnik.PostGIS(dbname=MAPNIK_TEST_DBNAME,table=''' + (SeLeCt * FrOm "tableWithMixedCase" where geom && !bbox! ) as MixedCaseQuery''', + geometry_field='geom', + require_key=True) + fs = ds.featureset() + eq_(fs.next().id(),1) + eq_(fs.next().id(),2) + eq_(fs.next().id(),3) + eq_(fs.next().id(),4) + eq_(fs.next(),None) + + def test_bbox_token_in_subquery2(): + ds = mapnik.PostGIS(dbname=MAPNIK_TEST_DBNAME,table=''' + (SeLeCt * FrOm "tableWithMixedCase" where ST_Intersects(geom,!bbox!) ) as MixedCaseQuery''', + geometry_field='geom', + require_key=True) + fs = ds.featureset() + eq_(fs.next().id(),1) + eq_(fs.next().id(),2) + eq_(fs.next().id(),3) + eq_(fs.next().id(),4) + eq_(fs.next(),None) + atexit.register(postgis_takedown) if __name__ == "__main__": From 46b16c917e404befe471998f56ba0fe6dea66001 Mon Sep 17 00:00:00 2001 From: Dane Springmeyer Date: Tue, 3 Apr 2012 16:06:36 -0700 Subject: [PATCH 018/134] support nodata for paletted images and allow user to set nodata on-the-fly - closes #1160 and #1161 - refs #688 and refs #730 and refs #50 and refs #1018 --- CHANGELOG.md | 4 + plugins/input/gdal/gdal_datasource.cpp | 9 +- plugins/input/gdal/gdal_datasource.hpp | 1 + plugins/input/gdal/gdal_featureset.cpp | 79 +++++++++++++++--- plugins/input/gdal/gdal_featureset.hpp | 5 +- tests/data/good_maps/tiff_colortable.xml | 16 ++++ tests/data/good_maps/vrt_colortable.xml | 15 ++++ tests/data/raster/dataraster.vrt | 45 ++++++++++ .../images/support/tif_colortable.png | Bin 0 -> 26726 bytes .../images/support/vrt_colortable.png | Bin 0 -> 7308 bytes tests/python_tests/raster_colormapped_test.py | 38 +++++++++ 11 files changed, 196 insertions(+), 16 deletions(-) create mode 100644 tests/data/good_maps/tiff_colortable.xml create mode 100644 tests/data/good_maps/vrt_colortable.xml create mode 100644 tests/data/raster/dataraster.vrt create mode 100644 tests/python_tests/images/support/tif_colortable.png create mode 100644 tests/python_tests/images/support/vrt_colortable.png create mode 100644 tests/python_tests/raster_colormapped_test.py diff --git a/CHANGELOG.md b/CHANGELOG.md index 4e42b0dda..e84eb42f1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,10 @@ For a complete change history, see the SVN log. ## Mapnik 2.1.0 +- GDAL: allow setting nodata value on the fly (will override value if nodata is set in data) (#1161) + +- GDAL: respect nodata for paletted/colormapped images (#1160) + - PostGIS: the primary key, for tables containing one, is now auto-detected allowing for globally unique feature id values (#804) - Fix Markers rendering so that ellipse height/width units are pixels (previously were unintentially radii) diff --git a/plugins/input/gdal/gdal_datasource.cpp b/plugins/input/gdal/gdal_datasource.cpp index 1bdf85ce1..29303bd5e 100644 --- a/plugins/input/gdal/gdal_datasource.cpp +++ b/plugins/input/gdal/gdal_datasource.cpp @@ -78,7 +78,8 @@ inline GDALDataset* gdal_datasource::open_dataset() const gdal_datasource::gdal_datasource(parameters const& params, bool bind) : datasource(params), desc_(*params.get("type"), "utf-8"), - filter_factor_(*params_.get("filter_factor", 0.0)) + filter_factor_(*params_.get("filter_factor", 0.0)), + nodata_value_(params_.get("nodata")) { #ifdef MAPNIK_DEBUG std::clog << "GDAL Plugin: Initializing..." << std::endl; @@ -242,7 +243,8 @@ featureset_ptr gdal_datasource::features(query const& q) const nbands_, dx_, dy_, - filter_factor_)); + filter_factor_, + nodata_value_)); } featureset_ptr gdal_datasource::features_at_point(coord2d const& pt) const @@ -261,5 +263,6 @@ featureset_ptr gdal_datasource::features_at_point(coord2d const& pt) const nbands_, dx_, dy_, - filter_factor_)); + filter_factor_, + nodata_value_)); } diff --git a/plugins/input/gdal/gdal_datasource.hpp b/plugins/input/gdal/gdal_datasource.hpp index 4aa841371..4b2d2ea9d 100644 --- a/plugins/input/gdal/gdal_datasource.hpp +++ b/plugins/input/gdal/gdal_datasource.hpp @@ -57,6 +57,7 @@ private: mutable int nbands_; mutable bool shared_dataset_; double filter_factor_; + boost::optional nodata_value_; inline GDALDataset* open_dataset() const; }; diff --git a/plugins/input/gdal/gdal_featureset.cpp b/plugins/input/gdal/gdal_featureset.cpp index 7546adf3f..14bf11ee5 100644 --- a/plugins/input/gdal/gdal_featureset.cpp +++ b/plugins/input/gdal/gdal_featureset.cpp @@ -53,7 +53,8 @@ gdal_featureset::gdal_featureset(GDALDataset& dataset, int nbands, double dx, double dy, - double filter_factor) + double filter_factor, + boost::optional const& nodata) : dataset_(dataset), ctx_(boost::make_shared()), band_(band), @@ -65,6 +66,7 @@ gdal_featureset::gdal_featureset(GDALDataset& dataset, dy_(dy), nbands_(nbands), filter_factor_(filter_factor), + nodata_value_(nodata), first_(true) { ctx_->push("value"); @@ -241,8 +243,17 @@ feature_ptr gdal_featureset::get_feature(mapnik::query const& q) float* imageData = (float*)image.getBytes(); GDALRasterBand * band = dataset_.GetRasterBand(band_); - int hasNoData; - double nodata = band->GetNoDataValue(&hasNoData); + int hasNoData(0); + double nodata(0); + if (nodata_value_) + { + hasNoData = 1; + nodata = *nodata_value_; + } + else + { + nodata = band->GetNoDataValue(&hasNoData); + } band->RasterIO(GF_Read, x_off, y_off, width, height, imageData, image.width(), image.height(), GDT_Float32, 0, 0); @@ -340,8 +351,21 @@ feature_ptr gdal_featureset::get_feature(mapnik::query const& q) #ifdef MAPNIK_DEBUG std::clog << "GDAL Plugin: processing rgb bands..." << std::endl; #endif - int hasNoData; - float nodata = red->GetNoDataValue(&hasNoData); + int hasNoData(0); + double nodata(0); + if (nodata_value_) + { + hasNoData = 1; + nodata = *nodata_value_; + } + else + { + nodata = red->GetNoDataValue(&hasNoData); + } + if (hasNoData) + { + feature->put("NODATA",nodata); + } GDALColorTable *color_table = red->GetColorTable(); if (! alpha && hasNoData && ! color_table) @@ -380,12 +404,25 @@ feature_ptr gdal_featureset::get_feature(mapnik::query const& q) #ifdef MAPNIK_DEBUG std::clog << "GDAL Plugin: processing gray band..." << std::endl; #endif - int hasNoData; - float nodata = grey->GetNoDataValue(&hasNoData); + int hasNoData(0); + double nodata(0); + if (nodata_value_) + { + hasNoData = 1; + nodata = *nodata_value_; + } + else + { + nodata = grey->GetNoDataValue(&hasNoData); + } GDALColorTable* color_table = grey->GetColorTable(); if (hasNoData && ! color_table) { + if (hasNoData) + { + feature->put("NODATA",nodata); + } #ifdef MAPNIK_DEBUG std::clog << "\tno data value for layer: " << nodata << std::endl; #endif @@ -422,23 +459,41 @@ feature_ptr gdal_featureset::get_feature(mapnik::query const& q) #ifdef MAPNIK_DEBUG std::clog << "GDAL Plugin: Loading colour table..." << std::endl; #endif + unsigned nodata_value = static_cast(nodata); + if (hasNoData) + { + feature->put("NODATA",static_cast(nodata_value)); + } for (unsigned y = 0; y < image.height(); ++y) { unsigned int* row = image.getRow(y); for (unsigned x = 0; x < image.width(); ++x) { unsigned value = row[x] & 0xff; - const GDALColorEntry *ce = color_table->GetColorEntry(value); - if (ce ) + if (hasNoData && (value == nodata_value)) { - // TODO - big endian support - row[x] = (ce->c4 << 24)| (ce->c3 << 16) | (ce->c2 << 8) | (ce->c1) ; + // make no data fully alpha + row[x] = 0; + } + else + { + const GDALColorEntry *ce = color_table->GetColorEntry(value); + if (ce) + { + // TODO - big endian support + row[x] = (ce->c4 << 24)| (ce->c3 << 16) | (ce->c2 << 8) | (ce->c1) ; + } + else + { + // make lacking color entry fully alpha + // note - gdal_translate makes black + row[x] = 0; + } } } } } } - if (alpha) { #ifdef MAPNIK_DEBUG diff --git a/plugins/input/gdal/gdal_featureset.hpp b/plugins/input/gdal/gdal_featureset.hpp index d4a2e9db8..b812da815 100644 --- a/plugins/input/gdal/gdal_featureset.hpp +++ b/plugins/input/gdal/gdal_featureset.hpp @@ -29,6 +29,7 @@ // boost #include +#include class GDALDataset; class GDALRasterBand; @@ -47,7 +48,8 @@ public: int nbands, double dx, double dy, - double filter_factor); + double filter_factor, + boost::optional const& nodata); virtual ~gdal_featureset(); mapnik::feature_ptr next(); private: @@ -67,6 +69,7 @@ private: double dy_; int nbands_; double filter_factor_; + boost::optional nodata_value_; bool first_; }; diff --git a/tests/data/good_maps/tiff_colortable.xml b/tests/data/good_maps/tiff_colortable.xml new file mode 100644 index 000000000..c102ff363 --- /dev/null +++ b/tests/data/good_maps/tiff_colortable.xml @@ -0,0 +1,16 @@ + + + + + 2011_5km_vrt_nodata_style + + ../raster/dataraster.tif + 20 + gdal + + + \ No newline at end of file diff --git a/tests/data/good_maps/vrt_colortable.xml b/tests/data/good_maps/vrt_colortable.xml new file mode 100644 index 000000000..d20367c72 --- /dev/null +++ b/tests/data/good_maps/vrt_colortable.xml @@ -0,0 +1,15 @@ + + + + + 2011_5km_vrt_nodata_style + + ../raster/dataraster.vrt + gdal + + + \ No newline at end of file diff --git a/tests/data/raster/dataraster.vrt b/tests/data/raster/dataraster.vrt new file mode 100644 index 000000000..26f6b5cfe --- /dev/null +++ b/tests/data/raster/dataraster.vrt @@ -0,0 +1,45 @@ + + PROJCS["WGS 84 / UTM zone 30N",GEOGCS["WGS 84",DATUM["WGS_1984",SPHEROID["WGS 84",6378137,298.257223563,AUTHORITY["EPSG","7030"]],AUTHORITY["EPSG","6326"]],PRIMEM["Greenwich",0],UNIT["degree",0.0174532925199433],AUTHORITY["EPSG","4326"]],PROJECTION["Transverse_Mercator"],PARAMETER["latitude_of_origin",0],PARAMETER["central_meridian",-3],PARAMETER["scale_factor",0.9996],PARAMETER["false_easting",500000],PARAMETER["false_northing",0],UNIT["metre",1,AUTHORITY["EPSG","9001"]],AUTHORITY["EPSG","32630"]] + -1.4637000000000000e+04, 5.0000000000000000e+02, 0.0000000000000000e+00, 4.8596780000000000e+06, 0.0000000000000000e+00, -5.0000000000000000e+02 + + -9.99000000000000E+02 + 0 + Palette + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + dataraster.tif + 1 + + + + -999 + + + diff --git a/tests/python_tests/images/support/tif_colortable.png b/tests/python_tests/images/support/tif_colortable.png new file mode 100644 index 0000000000000000000000000000000000000000..aa0021b38d731fbd7d0b259d07341fff6893cd8b GIT binary patch literal 26726 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 Date: Tue, 3 Apr 2012 16:33:06 -0700 Subject: [PATCH 019/134] revert unintended change to sqlite in a7e150a59319831 --- plugins/input/sqlite/sqlite_datasource.cpp | 29 ++++++++-------------- 1 file changed, 10 insertions(+), 19 deletions(-) diff --git a/plugins/input/sqlite/sqlite_datasource.cpp b/plugins/input/sqlite/sqlite_datasource.cpp index 57569cfb5..b14cf1dbc 100644 --- a/plugins/input/sqlite/sqlite_datasource.cpp +++ b/plugins/input/sqlite/sqlite_datasource.cpp @@ -548,33 +548,24 @@ featureset_ptr sqlite_datasource::features(query const& q) const std::ostringstream s; mapnik::context_ptr ctx = boost::make_shared(); - std::set const& props = q.property_names(); - std::set::const_iterator pos = props.begin(); - std::set::const_iterator end = props.end(); s << "SELECT " << geometry_field_; if (!key_field_.empty()) { s << "," << key_field_; ctx->push(key_field_); - for ( ;pos != end;++pos) - { - if (*pos != key_field_) - { - s << ",[" << *pos << "]"; - ctx->push(*pos); - } - } - } - else - { - for ( ;pos != end;++pos) - { - s << ",[" << *pos << "]"; - ctx->push(*pos); - } } + std::set const& props = q.property_names(); + std::set::const_iterator pos = props.begin(); + std::set::const_iterator end = props.end(); + for ( ;pos != end;++pos) + { + // TODO - should we restrict duplicate key query? + //if (*pos != key_field_) + s << ",[" << *pos << "]"; + ctx->push(*pos); + } s << " FROM "; std::string query(table_); From 40e8ceca55c40be9c828a0bbf9f1663a154252ee Mon Sep 17 00:00:00 2001 From: Dane Springmeyer Date: Tue, 3 Apr 2012 16:49:05 -0700 Subject: [PATCH 020/134] add missing set_color_to_alpha impl - TODO - add advanced algo that supports tolerance - refs #1018 --- src/graphics.cpp | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/src/graphics.cpp b/src/graphics.cpp index 4b276562a..0f0a708c4 100644 --- a/src/graphics.cpp +++ b/src/graphics.cpp @@ -25,6 +25,7 @@ #include #include #include +#include // cairo #ifdef HAVE_CAIRO @@ -117,9 +118,23 @@ void image_32::set_grayscale_to_alpha() } } -void image_32::set_color_to_alpha(const color& /*c*/) +void image_32::set_color_to_alpha(const color& c) { - // TODO - function to set all pixels to a % alpha based on distance to a given color + for (unsigned y = 0; y < height_; ++y) + { + unsigned int* row_from = data_.getRow(y); + for (unsigned x = 0; x < width_; ++x) + { + unsigned rgba = row_from[x]; + unsigned r = rgba & 0xff; + unsigned g = (rgba >> 8 ) & 0xff; + unsigned b = (rgba >> 16) & 0xff; + if (r == c.red() && g == c.green() && b == c.blue()) + { + row_from[x] = 0; + } + } + } } void image_32::set_alpha(float opacity) From 8c41bdc040b285b8e45b033db11f04101fed4713 Mon Sep 17 00:00:00 2001 From: Dane Springmeyer Date: Wed, 4 Apr 2012 10:30:37 -0700 Subject: [PATCH 021/134] remove unused variables --- src/cairo_renderer.cpp | 8 -------- 1 file changed, 8 deletions(-) diff --git a/src/cairo_renderer.cpp b/src/cairo_renderer.cpp index a87f48749..9a15e055d 100644 --- a/src/cairo_renderer.cpp +++ b/src/cairo_renderer.cpp @@ -1355,17 +1355,9 @@ void cairo_renderer_base::start_map_processing(Map const& map) else { color const& fill_ = sym.get_fill(); - unsigned r = fill_.red(); - unsigned g = fill_.green(); - unsigned b = fill_.blue(); - unsigned a = fill_.alpha(); stroke const& stroke_ = sym.get_stroke(); color const& col = stroke_.get_color(); double strk_width = stroke_.get_width(); - unsigned s_r=col.red(); - unsigned s_g=col.green(); - unsigned s_b=col.blue(); - unsigned s_a=col.alpha(); double w = sym.get_width(); double h = sym.get_height(); double rx = w/2.0; From d3cc8f92941dedfaff9e9daa8a388d6047b88eec Mon Sep 17 00:00:00 2001 From: Dane Springmeyer Date: Wed, 4 Apr 2012 11:47:20 -0700 Subject: [PATCH 022/134] update changelog with cairo markers work --- CHANGELOG.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e84eb42f1..9a453f6a3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,7 +15,11 @@ For a complete change history, see the SVN log. - PostGIS: the primary key, for tables containing one, is now auto-detected allowing for globally unique feature id values (#804) -- Fix Markers rendering so that ellipse height/width units are pixels (previously were unintentially radii) +- Cairo: Add full rendering support for markers to match AGG renderer functionality (#1071) + +- Fix Markers rendering so that ellipse height/width units are pixels (previously were unintentially radii) (#1134) + +- Added 'ignore-placement` attribute to markers-symbolizer (#1135) - Removed PointDatasource - use more robust MemoryDatasource instead (#1032) From d29ae14104dfebdd3119e01fde50dc3d362c0f47 Mon Sep 17 00:00:00 2001 From: Dane Springmeyer Date: Wed, 4 Apr 2012 12:07:15 -0700 Subject: [PATCH 023/134] make it possible to set the map.maximum_extent back to None/uninitialized from python --- bindings/python/mapnik_map.cpp | 19 ++++++++++++++++--- include/mapnik/map.hpp | 4 ++++ src/map.cpp | 5 +++++ tests/python_tests/object_test.py | 10 +++++++++- 4 files changed, 34 insertions(+), 4 deletions(-) diff --git a/bindings/python/mapnik_map.cpp b/bindings/python/mapnik_map.cpp index 542cc08f3..c6e2467cd 100644 --- a/bindings/python/mapnik_map.cpp +++ b/bindings/python/mapnik_map.cpp @@ -118,6 +118,7 @@ struct map_pickle_suite : boost::python::pickle_suite std::vector& (Map::*layers_nonconst)() = &Map::layers; std::vector const& (Map::*layers_const)() const = &Map::layers; mapnik::parameters& (Map::*params_nonconst)() = &Map::get_extra_parameters; +boost::optional > const& (Map::*maximum_extent_const)() const = &Map::maximum_extent; mapnik::feature_type_style find_style(mapnik::Map const& m, std::string const& name) { @@ -150,7 +151,7 @@ bool has_metawriter(mapnik::Map const& m) // returns empty shared_ptr when the metawriter isn't found, or is // of the wrong type. empty pointers make it back to Python as a None. -mapnik::metawriter_inmem_ptr find_inmem_metawriter(const mapnik::Map &m, std::string const&name) { +mapnik::metawriter_inmem_ptr find_inmem_metawriter(const mapnik::Map & m, std::string const& name) { mapnik::metawriter_ptr metawriter = m.find_metawriter(name); mapnik::metawriter_inmem_ptr inmem; @@ -192,6 +193,18 @@ mapnik::Map map_deepcopy(mapnik::Map & m, boost::python::dict memo) return result; } +// TODO - find a simplier way to set optional to uninitialized +void set_maximum_extent(mapnik::Map & m, boost::optional > const& box) +{ + if (box) + { + m.set_maximum_extent(*box); + } + else + { + m.maximum_extent().reset(); + } +} void export_map() { @@ -550,8 +563,8 @@ void export_map() ) .add_property("maximum_extent",make_function - (&Map::maximum_extent,return_value_policy()), - &Map::set_maximum_extent, + (maximum_extent_const,return_value_policy()), + &set_maximum_extent, "The maximum extent of the map.\n" "\n" "Usage:\n" diff --git a/include/mapnik/map.hpp b/include/mapnik/map.hpp index 95663360b..bfbf87edd 100644 --- a/include/mapnik/map.hpp +++ b/include/mapnik/map.hpp @@ -337,6 +337,10 @@ public: */ boost::optional > const& maximum_extent() const; + /*! \brief Get the non-const map maximum extent as box2d + */ + boost::optional > & maximum_extent(); + /*! \brief Get the map base path where paths should be relative to. */ std::string const& base_path() const; diff --git a/src/map.cpp b/src/map.cpp index e04ffd4db..ed5ba50b3 100644 --- a/src/map.cpp +++ b/src/map.cpp @@ -357,6 +357,11 @@ boost::optional > const& Map::maximum_extent() const return maximum_extent_; } +boost::optional > & Map::maximum_extent() +{ + return maximum_extent_; +} + std::string const& Map::base_path() const { return base_path_; diff --git a/tests/python_tests/object_test.py b/tests/python_tests/object_test.py index cf0920d55..109efc6dd 100644 --- a/tests/python_tests/object_test.py +++ b/tests/python_tests/object_test.py @@ -221,10 +221,19 @@ def test_map_init(): eq_(m.height, 256) eq_(m.srs, '+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs') eq_(m.base, '') + eq_(m.maximum_extent, None) m = mapnik.Map(256, 256, '+proj=latlong') eq_(m.srs, '+proj=latlong') +def test_map_maximum_extent_modification(): + m = mapnik.Map(256, 256) + eq_(m.maximum_extent, None) + m.maximum_extent = mapnik.Box2d() + eq_(m.maximum_extent, mapnik.Box2d()) + m.maximum_extent = None + eq_(m.maximum_extent, None) + # Map initialization from string def test_map_init_from_string(): map_string = ''' @@ -267,7 +276,6 @@ def test_map_init_from_string(): raise RuntimeError(e) # Color initialization - @raises(Exception) # Boost.Python.ArgumentError def test_color_init_errors(): c = mapnik.Color() From 4dbadaa7cddb31f858f5256cac48ecf8d5e2ec1f Mon Sep 17 00:00:00 2001 From: Dane Springmeyer Date: Wed, 4 Apr 2012 12:43:32 -0700 Subject: [PATCH 024/134] ensure proper reprojection of unbuffered bbox used for geometry clipping - closes #1138 --- src/feature_style_processor.cpp | 44 ++++++--- .../mapnik-merc2merc-reprojection-render1.png | Bin 0 -> 43573 bytes .../mapnik-merc2merc-reprojection-render2.png | Bin 0 -> 43689 bytes .../mapnik-merc2wgs84-reprojection-render.png | Bin 0 -> 41304 bytes .../mapnik-wgs842merc-reprojection-render.png | Bin 0 -> 49146 bytes tests/python_tests/reprojection_test.py | 88 ++++++++++++++++++ 6 files changed, 121 insertions(+), 11 deletions(-) create mode 100644 tests/python_tests/images/support/mapnik-merc2merc-reprojection-render1.png create mode 100644 tests/python_tests/images/support/mapnik-merc2merc-reprojection-render2.png create mode 100644 tests/python_tests/images/support/mapnik-merc2wgs84-reprojection-render.png create mode 100644 tests/python_tests/images/support/mapnik-wgs842merc-reprojection-render.png create mode 100644 tests/python_tests/reprojection_test.py diff --git a/src/feature_style_processor.cpp b/src/feature_style_processor.cpp index 7cb02042b..55888d6d2 100644 --- a/src/feature_style_processor.cpp +++ b/src/feature_style_processor.cpp @@ -203,8 +203,6 @@ void feature_style_processor::apply_to_layer(layer const& lay, Proces return; } - - #if defined(RENDERING_STATS) progress_timer layer_timer(std::clog, "rendering total for layer: '" + lay.name() + "'"); #endif @@ -219,20 +217,22 @@ void feature_style_processor::apply_to_layer(layer const& lay, Proces << m_.srs() << "'\n"; #endif - box2d map_ext = m_.get_buffered_extent(); + box2d buffered_query_ext = m_.get_buffered_extent(); // buffered // clip buffered extent by maximum extent, if supplied boost::optional > const& maximum_extent = m_.maximum_extent(); if (maximum_extent) { - map_ext.clip(*maximum_extent); + buffered_query_ext.clip(*maximum_extent); } box2d layer_ext = lay.envelope(); + bool fw_success = false; // first, try intersection of map extent forward projected into layer srs - if (prj_trans.forward(map_ext, PROJ_ENVELOPE_POINTS) && map_ext.intersects(layer_ext)) + if (prj_trans.forward(buffered_query_ext, PROJ_ENVELOPE_POINTS) && buffered_query_ext.intersects(layer_ext)) { - layer_ext.clip(map_ext); + fw_success = true; + layer_ext.clip(buffered_query_ext); } // if no intersection and projections are also equal, early return else if (prj_trans.equal()) @@ -243,9 +243,9 @@ void feature_style_processor::apply_to_layer(layer const& lay, Proces return; } // next try intersection of layer extent back projected into map srs - else if (prj_trans.backward(layer_ext, PROJ_ENVELOPE_POINTS) && map_ext.intersects(layer_ext)) + else if (prj_trans.backward(layer_ext, PROJ_ENVELOPE_POINTS) && buffered_query_ext.intersects(layer_ext)) { - layer_ext.clip(map_ext); + layer_ext.clip(buffered_query_ext); // forward project layer extent back into native projection if (!prj_trans.forward(layer_ext, PROJ_ENVELOPE_POINTS)) { @@ -263,15 +263,37 @@ void feature_style_processor::apply_to_layer(layer const& lay, Proces return; } - box2d query_ext = m_.get_current_extent(); - prj_trans.forward(query_ext, PROJ_ENVELOPE_POINTS); + // if we've got this far, now prepare the unbuffered extent + // which is used as a bbox for clipping geometries + box2d query_ext = m_.get_current_extent(); // unbuffered + if (maximum_extent) { + query_ext.clip(*maximum_extent); + } + box2d layer_ext2 = lay.envelope(); + if (fw_success) + { + if (prj_trans.forward(query_ext, PROJ_ENVELOPE_POINTS)) + { + layer_ext2.clip(query_ext); + } + } + else + { + if (prj_trans.backward(layer_ext2, PROJ_ENVELOPE_POINTS)) + { + layer_ext2.clip(query_ext); + prj_trans.forward(layer_ext2, PROJ_ENVELOPE_POINTS); + } + } + + p.start_layer_processing(lay, layer_ext2); + double qw = query_ext.width()>0 ? query_ext.width() : 1; double qh = query_ext.height()>0 ? query_ext.height() : 1; query::resolution_type res(m_.width()/qw, m_.height()/qh); query q(layer_ext,res,scale_denom,m_.get_current_extent()); - p.start_layer_processing(lay, query_ext); std::vector active_styles; attribute_collector collector(names); double filt_factor = 1; diff --git a/tests/python_tests/images/support/mapnik-merc2merc-reprojection-render1.png b/tests/python_tests/images/support/mapnik-merc2merc-reprojection-render1.png new file mode 100644 index 0000000000000000000000000000000000000000..ca1ed8ff387e05f86ae034e4fd16b89c2b08af93 GIT binary patch literal 43573 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 Y))R{#WaU5opATxN>pri3YV+}b0c{5yr2qf` literal 0 HcmV?d00001 diff --git a/tests/python_tests/images/support/mapnik-merc2merc-reprojection-render2.png b/tests/python_tests/images/support/mapnik-merc2merc-reprojection-render2.png new file mode 100644 index 0000000000000000000000000000000000000000..58cb69120fa56bc19d6e5ae78136db25a164fa7a GIT binary patch literal 43689 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 P?t#L^HDqZ?K$Q0mxR9B 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 z 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

4d;zdu;fpdr~BD52$;=E&nK7XH(ZPA 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 Date: Wed, 4 Apr 2012 14:37:27 -0700 Subject: [PATCH 025/134] add missing test files --- .../data/good_maps/merc2wgs84_reprojection.xml | 15 +++++++++++++++ .../data/good_maps/wgs842merc_reprojection.xml | 15 +++++++++++++++ tests/data/shp/ne_110m_admin_0_countries.dbf | Bin 0 -> 84860 bytes tests/data/shp/ne_110m_admin_0_countries.prj | 1 + tests/data/shp/ne_110m_admin_0_countries.shp | Bin 0 -> 179876 bytes tests/data/shp/ne_110m_admin_0_countries.shx | Bin 0 -> 1516 bytes 6 files changed, 31 insertions(+) create mode 100644 tests/data/good_maps/merc2wgs84_reprojection.xml create mode 100644 tests/data/good_maps/wgs842merc_reprojection.xml create mode 100644 tests/data/shp/ne_110m_admin_0_countries.dbf create mode 100644 tests/data/shp/ne_110m_admin_0_countries.prj create mode 100644 tests/data/shp/ne_110m_admin_0_countries.shp create mode 100644 tests/data/shp/ne_110m_admin_0_countries.shx diff --git a/tests/data/good_maps/merc2wgs84_reprojection.xml b/tests/data/good_maps/merc2wgs84_reprojection.xml new file mode 100644 index 000000000..df53e6e28 --- /dev/null +++ b/tests/data/good_maps/merc2wgs84_reprojection.xml @@ -0,0 +1,15 @@ + + + + + My Style + + shape + ../shp/world_merc.shp + + + \ No newline at end of file diff --git a/tests/data/good_maps/wgs842merc_reprojection.xml b/tests/data/good_maps/wgs842merc_reprojection.xml new file mode 100644 index 000000000..a18b65f29 --- /dev/null +++ b/tests/data/good_maps/wgs842merc_reprojection.xml @@ -0,0 +1,15 @@ + + + + + My Style + + shape + + ../shp/ne_110m_admin_0_countries.shp + + + \ No newline at end of file diff --git a/tests/data/shp/ne_110m_admin_0_countries.dbf b/tests/data/shp/ne_110m_admin_0_countries.dbf new file mode 100644 index 0000000000000000000000000000000000000000..5fc769dd7d77e26591b18d3dcb5a15e405e0f693 GIT binary patch literal 84860 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 C+CyRAwb}G$~0Dk~yIiQi+wMNK%v% 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 z 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 literal 0 HcmV?d00001 diff --git a/tests/data/shp/ne_110m_admin_0_countries.shx b/tests/data/shp/ne_110m_admin_0_countries.shx new file mode 100644 index 0000000000000000000000000000000000000000..eacce7b013ebcfbabd9d4635b2aa2e4080be3e06 GIT binary patch literal 1516 zcmai!eQ1?s7>BRtY)x4)hK!g|xXR|7Yi_pmgf>nhvOr=)%{9h2M64A>!_3zD@bo?U zuw@o&m972|3yNiBOGHm8>sVHj5oTdy3|YfsNXQ|Ebv>MagATmA-rxQG-0%AimXz|J zzr?xeBDg@`Kk>JajPC#8&e=F2i z$RsTH9&0shkmfXMkNq1b^!LFv){lLgD%HlV)L+sIYX-Ep%PEwEO8o2`+U52<6Y zuoiARum1#eob(*;Lzj8;hN0VY1n=+MW4s}E?bSaG_j;Bv0{3~2q9km3LM`tRlB*2`?xpNGeL)uZs_ zV)cm3sb}Ho{jvp~HJ+o=I+!=G&U*L2bD!uhhv#Fw{a)Oq-^bAy z+i#Ngc_kjYRkoS;HN0xy;v~GDRyV-#4%rTG%*qLP>qlwdw^Qb29kEzl4)0XLd`<6N zYQFIw^eHlO&c402@(Kog^oaH`*prmU;Ny$*Tl3Q?wK03mjdOh#?auOfllvcn{l>=k z>Oh5TfP9w8oJ*MUvm~WqOS+g7@Ec!u~6D~hp$h-1(*+N+Sq47Dw zRsC{|P;Eco*RW)P{v@Hs_tWn(EOkD=n^0^0P(@faqux!ZdrjR=xcaQxdF#97EMa+^ z*Z9Wu>QVW({VNGg?lq(d*V-@S2&o<40zZ${~J_E9ZwLb5%QXgsTYu%fx&Ce5Vy+YkbXxnLAKVhT$kM%ZY3ikFn>zLQ+ MvrlO1D)Ue3Ut*LG;Q#;t literal 0 HcmV?d00001 From 0e64cc157ecef02046edb2921e8c8b7e6d60c3b5 Mon Sep 17 00:00:00 2001 From: Dane Springmeyer Date: Wed, 4 Apr 2012 14:54:07 -0700 Subject: [PATCH 026/134] tests: allow the visual tests to be run in quiet mode --- tests/visual_tests/compare.py | 12 +++++++---- tests/visual_tests/test.py | 39 +++++++++++++++++++++-------------- 2 files changed, 31 insertions(+), 20 deletions(-) diff --git a/tests/visual_tests/compare.py b/tests/visual_tests/compare.py index 46bba923e..b558e38ea 100644 --- a/tests/visual_tests/compare.py +++ b/tests/visual_tests/compare.py @@ -1,3 +1,5 @@ +# -*- coding: utf-8 -*- + #import math, operator import Image import sys @@ -5,6 +7,7 @@ import sys COMPUTE_THRESHOLD = 16 errors = [] +passed = 0 # returns true if pixels are not identical def compare_pixels(pixel1, pixel2): @@ -19,6 +22,7 @@ def compare_pixels(pixel1, pixel2): # compare tow images and return number of different pixels def compare(fn1, fn2): global errors + global passed im1 = Image.open(fn1) try: im2 = Image.open(fn2) @@ -38,21 +42,21 @@ def compare(fn1, fn2): diff = diff + 1 if diff != 0: errors.append((fn1, diff)) + passed += 1 return diff def summary(): global errors + global passed print "-"*80 - print "Summary:" + print "Visual text rendering summary:", if len(errors) != 0: for error in errors: if (error[1] is None): print "Could not verify %s: No reference image found!" % error[0] else: print "%s failed: %d different pixels" % error - print "-"*80 sys.exit(1) else: - print 'No errors detected!' - print "-"*80 + print 'All %s tests passed: \x1b[1;32m✓ \x1b[0m' % passed sys.exit(0) diff --git a/tests/visual_tests/test.py b/tests/visual_tests/test.py index 29716e6bd..15c9640e6 100755 --- a/tests/visual_tests/test.py +++ b/tests/visual_tests/test.py @@ -47,10 +47,10 @@ files = [ 'bbox': mapnik.Box2d(-5.192, 50.189, -5.174, 50.195)} ] -def render(filename, width, height, bbox): - print "-"*80 - print "Rendering style \"%s\" with size %dx%d ... " % (filename, width, height) - print "-"*80 +def render(filename, width, height, bbox, quiet=False): + if not quiet: + print "Rendering style \"%s\" with size %dx%d ... \x1b[1;32m✓ \x1b[0m" % (filename, width, height) + print "-"*80 m = mapnik.Map(width, height) mapnik.load_map(m, os.path.join(dirname, "styles", "%s.xml" % filename), False) if bbox is not None: @@ -62,21 +62,28 @@ def render(filename, width, height, bbox): diff = compare(basefn + '-agg.png', basefn + '-reference.png') if diff > 0: print "-"*80 - print 'Error: %u different pixels' % diff + print '\x1b[33mError:\x1b[0m %u different pixels' % diff print "-"*80 return m -if len(sys.argv) == 2: - files = [(sys.argv[1], (500, 500))] -elif len(sys.argv) > 2: - files = [sys.argv[1:]] +if __name__ == "__main__": + if '-q' in sys.argv: + quiet = True + sys.argv.remove('-q') + else: + quiet = False -for f in files: - config = dict(defaults) - config.update(f) - for size in config['sizes']: - m = render(config['name'], size[0], size[1], config['bbox']) - mapnik.save_map(m, os.path.join(dirname, 'xml_output', "%s-out.xml" % config['name'])) + if len(sys.argv) == 2: + files = [(sys.argv[1], (500, 500))] + elif len(sys.argv) > 2: + files = [sys.argv[1:]] -summary() + for f in files: + config = dict(defaults) + config.update(f) + for size in config['sizes']: + m = render(config['name'], size[0], size[1], config['bbox'], quiet=quiet) + mapnik.save_map(m, os.path.join(dirname, 'xml_output', "%s-out.xml" % config['name'])) + + summary() From d6c4e7f7fcc68db7dec5ee0cd15a7f0565d7ecbb Mon Sep 17 00:00:00 2001 From: Dane Springmeyer Date: Wed, 4 Apr 2012 15:17:37 -0700 Subject: [PATCH 027/134] fix encoding of rundemo.cpp (windows1 -> utf8) and correctly declare the encoding of the boundaries shapefile (fixing white background to be green) --- demo/c++/rundemo.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/demo/c++/rundemo.cpp b/demo/c++/rundemo.cpp index cb6c26c90..eb22729e9 100644 --- a/demo/c++/rundemo.cpp +++ b/demo/c++/rundemo.cpp @@ -70,7 +70,7 @@ int main ( int argc , char** argv) provpoly_style.add_rule(provpoly_rule_on); rule provpoly_rule_qc; - provpoly_rule_qc.set_filter(parse_expression("[NOM_FR] = 'Québec'")); + provpoly_rule_qc.set_filter(parse_expression("[NOM_FR] = 'Québec'")); provpoly_rule_qc.append(polygon_symbolizer(color(217, 235, 203))); provpoly_style.add_rule(provpoly_rule_qc); @@ -175,6 +175,7 @@ int main ( int argc , char** argv) parameters p; p["type"]="shape"; p["file"]="../data/boundaries"; + p["encoding"]="latin1"; layer lyr("Provinces"); lyr.set_datasource(datasource_cache::instance()->create(p)); From b5af9e36392795913c2d7a1809ff3fee3fce833e Mon Sep 17 00:00:00 2001 From: Dane Springmeyer Date: Wed, 4 Apr 2012 15:17:52 -0700 Subject: [PATCH 028/134] use default env compiler --- demo/c++/Makefile | 2 -- 1 file changed, 2 deletions(-) diff --git a/demo/c++/Makefile b/demo/c++/Makefile index 09ba0378c..d30b71b40 100644 --- a/demo/c++/Makefile +++ b/demo/c++/Makefile @@ -1,5 +1,3 @@ -CXX = g++ - CXXFLAGS = $(shell mapnik-config --cflags) LDFLAGS = $(shell mapnik-config --libs --dep-libs --ldflags) From 3e3bdf66070dd9b116a025d09084374a628f5516 Mon Sep 17 00:00:00 2001 From: Dane Springmeyer Date: Wed, 4 Apr 2012 15:18:28 -0700 Subject: [PATCH 029/134] compile rundemo even during install --- demo/c++/build.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/demo/c++/build.py b/demo/c++/build.py index a9b87265c..9738347f9 100644 --- a/demo/c++/build.py +++ b/demo/c++/build.py @@ -47,7 +47,6 @@ rundemo = demo_env.Program('rundemo', source, LIBS=libraries, LINKFLAGS=env["CUS Depends(rundemo, env.subst('../../src/%s' % env['MAPNIK_LIB_NAME'])) -# we don't install this app because the datasource paths are relative -# and we're not going to install the sample data. -#env.Install(install_prefix + '/bin', rundemo) -#env.Alias('install', install_prefix + '/bin') +# build locally if installing +if 'install' in COMMAND_LINE_TARGETS: + env.Alias('install',rundemo) From a50ea0750e032bece7528c9c51e248443362af38 Mon Sep 17 00:00:00 2001 From: Dane Springmeyer Date: Wed, 4 Apr 2012 15:19:37 -0700 Subject: [PATCH 030/134] compile c++ tests even if only installing and hook them all up automatically to make test target --- Makefile | 5 ++--- tests/cpp_tests/build.py | 5 ++++- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/Makefile b/Makefile index 624f1cb69..ac4e62b99 100755 --- a/Makefile +++ b/Makefile @@ -18,9 +18,8 @@ uninstall: python scons/scons.py uninstall test: - @python tests/visual_tests/test.py - @tests/cpp_tests/font_registration_test - @tests/cpp_tests/params_test + @python tests/visual_tests/test.py -q + @tests/cpp_tests/*-bin @python tests/run_tests.py -q pep8: diff --git a/tests/cpp_tests/build.py b/tests/cpp_tests/build.py index bcc31bc94..3750717fd 100644 --- a/tests/cpp_tests/build.py +++ b/tests/cpp_tests/build.py @@ -14,5 +14,8 @@ libraries.append('mapnik') test_env.Append(CXXFLAGS='-g') for cpp_test in glob.glob('*_test.cpp'): - test_program = test_env.Program(cpp_test.replace('.cpp',''), [cpp_test], CPPPATH=headers, LIBS=libraries, LINKFLAGS=env['CUSTOM_LDFLAGS']) + test_program = test_env.Program(cpp_test.replace('.cpp','-bin'), [cpp_test], CPPPATH=headers, LIBS=libraries, LINKFLAGS=env['CUSTOM_LDFLAGS']) Depends(test_program, env.subst('../../src/%s' % env['MAPNIK_LIB_NAME'])) + # build locally if installing + if 'install' in COMMAND_LINE_TARGETS: + env.Alias('install',test_program) From ba4d81597258a8817ede06d9a43a5396158fdd54 Mon Sep 17 00:00:00 2001 From: Dane Springmeyer Date: Wed, 4 Apr 2012 15:20:18 -0700 Subject: [PATCH 031/134] compile the c++ demo by default --- SConstruct | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SConstruct b/SConstruct index 95726262f..569ff4b09 100644 --- a/SConstruct +++ b/SConstruct @@ -359,7 +359,7 @@ opts.AddVariables( EnumVariable('THREADING','Set threading support','multi', ['multi','single']), EnumVariable('XMLPARSER','Set xml parser','libxml2', ['libxml2','ptree']), ('JOBS', 'Set the number of parallel compilations', "1", lambda key, value, env: int(value), int), - BoolVariable('DEMO', 'Compile demo c++ application', 'False'), + BoolVariable('DEMO', 'Compile demo c++ application', 'True'), BoolVariable('PGSQL2SQLITE', 'Compile and install a utility to convert postgres tables to sqlite', 'False'), BoolVariable('COLOR_PRINT', 'Print build status information in color', 'True'), BoolVariable('SAMPLE_INPUT_PLUGINS', 'Compile and install sample plugins', 'False'), From 9084ea600ba2553040aa4e9581bf5405e89539cf Mon Sep 17 00:00:00 2001 From: Dane Springmeyer Date: Wed, 4 Apr 2012 15:20:48 -0700 Subject: [PATCH 032/134] ignore the tif output --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 1da77f7c9..ecef215ae 100644 --- a/.gitignore +++ b/.gitignore @@ -39,6 +39,7 @@ tests/data/sqlite/*index demo/c++/cairo-demo.pdf demo/c++/cairo-demo.png demo/c++/cairo-demo256.png +demo/c++/demo.tif demo/c++/demo.jpg demo/c++/demo.png demo/c++/demo256.png From 977f78a237ba4734a5570bc0a6f9295be2b993b1 Mon Sep 17 00:00:00 2001 From: Dane Springmeyer Date: Wed, 4 Apr 2012 15:21:16 -0700 Subject: [PATCH 033/134] ignore the c++ test programs --- .gitignore | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index ecef215ae..5d2536c3e 100644 --- a/.gitignore +++ b/.gitignore @@ -43,4 +43,4 @@ demo/c++/demo.tif demo/c++/demo.jpg demo/c++/demo.png demo/c++/demo256.png - +tests/cpp_tests/*-bin From 9c3d3ab285cf0ea804aece9c5373f5acae162678 Mon Sep 17 00:00:00 2001 From: Dane Springmeyer Date: Thu, 5 Apr 2012 08:35:28 -0700 Subject: [PATCH 034/134] more concise output from c++ tests --- tests/cpp_tests/font_registration_test.cpp | 21 ++++++++++++--------- tests/cpp_tests/params_test.cpp | 6 +++++- 2 files changed, 17 insertions(+), 10 deletions(-) diff --git a/tests/cpp_tests/font_registration_test.cpp b/tests/cpp_tests/font_registration_test.cpp index 55715b9b1..e051fd3c1 100644 --- a/tests/cpp_tests/font_registration_test.cpp +++ b/tests/cpp_tests/font_registration_test.cpp @@ -49,36 +49,39 @@ int main( int, char*[] ) BOOST_TEST( mapnik::freetype_engine::register_fonts("tests/data/fonts/fake.ttf") == false ); BOOST_TEST( mapnik::freetype_engine::face_names().size() == 0 ); - BOOST_TEST( mapnik::freetype_engine::register_font("tests/data/fonts/intentionally-broken.ttf") == false ); - BOOST_TEST( mapnik::freetype_engine::register_fonts("tests/data/fonts/intentionally-broken.ttf") == false ); - BOOST_TEST( mapnik::freetype_engine::face_names().size() == 0 ); + //BOOST_TEST( mapnik::freetype_engine::register_font("tests/data/fonts/intentionally-broken.ttf") == false ); + //BOOST_TEST( mapnik::freetype_engine::register_fonts("tests/data/fonts/intentionally-broken.ttf") == false ); + //BOOST_TEST( mapnik::freetype_engine::face_names().size() == 0 ); // register unifont, since we know it sits in the root fonts/ dir BOOST_TEST( mapnik::freetype_engine::register_fonts(fontdir) ); face_names = mapnik::freetype_engine::face_names(); - std::clog << "number of registered fonts: " << face_names.size() << std::endl; + //std::clog << "number of registered fonts: " << face_names.size() << std::endl; BOOST_TEST( face_names.size() > 0 ); BOOST_TEST( face_names.size() == 1 ); // re-register unifont, should not have any affect BOOST_TEST( mapnik::freetype_engine::register_fonts(fontdir, false) ); face_names = mapnik::freetype_engine::face_names(); - std::clog << "number of registered fonts: " << face_names.size() << std::endl; + //std::clog << "number of registered fonts: " << face_names.size() << std::endl; BOOST_TEST( face_names.size() == 1 ); // register a single dejavu font std::string dejavu_bold_oblique("tests/data/fonts/DejaVuSansMono-BoldOblique.ttf"); BOOST_TEST( mapnik::freetype_engine::register_font(dejavu_bold_oblique) ); face_names = mapnik::freetype_engine::face_names(); - std::clog << "number of registered fonts: " << face_names.size() << std::endl; + //std::clog << "number of registered fonts: " << face_names.size() << std::endl; BOOST_TEST( face_names.size() == 2 ); - // recurse to find all dejavu fonts BOOST_TEST( mapnik::freetype_engine::register_fonts(fontdir, true) ); face_names = mapnik::freetype_engine::face_names(); - std::clog << "number of registered fonts: " << face_names.size() << std::endl; + //std::clog << "number of registered fonts: " << face_names.size() << std::endl; BOOST_TEST( face_names.size() == 22 ); - return ::boost::report_errors(); + if (!::boost::detail::test_errors()) { + std::clog << "C++ fonts registration: \x1b[1;32m✓ \x1b[0m\n"; + } else { + return ::boost::report_errors(); + } } diff --git a/tests/cpp_tests/params_test.cpp b/tests/cpp_tests/params_test.cpp index 86e702366..9caecafcd 100644 --- a/tests/cpp_tests/params_test.cpp +++ b/tests/cpp_tests/params_test.cpp @@ -53,5 +53,9 @@ int main( int, char*[] ) params["bool"] = "no"; BOOST_TEST( (params.get("bool") && *params.get("bool") == false)); - return ::boost::report_errors(); + if (!::boost::detail::test_errors()) { + std::clog << "C++ parameters: \x1b[1;32m✓ \x1b[0m\n"; + } else { + return ::boost::report_errors(); + } } From 8e708c89fd61cc9ffc5ed36e04c85ab3eb6b77da Mon Sep 17 00:00:00 2001 From: Dane Springmeyer Date: Thu, 5 Apr 2012 08:41:01 -0700 Subject: [PATCH 035/134] run all cpp tests available --- Makefile | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index ac4e62b99..e6a05572f 100755 --- a/Makefile +++ b/Makefile @@ -18,8 +18,13 @@ uninstall: python scons/scons.py uninstall test: + @echo "*** Running visual tests…" @python tests/visual_tests/test.py -q - @tests/cpp_tests/*-bin + @echo "*** Running C++ tests..." + @for FILE in tests/cpp_tests/*-bin; do \ + $${FILE}; \ + done + @echo "*** Running python tests..." @python tests/run_tests.py -q pep8: From 17e2b831179bcb51360e67d93f51a4fa69a5678b Mon Sep 17 00:00:00 2001 From: Dane Springmeyer Date: Thu, 5 Apr 2012 08:48:46 -0700 Subject: [PATCH 036/134] run valgrind over all C++ tests but only output 'definitely lost' values --- Makefile | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index e6a05572f..cd956cedc 100755 --- a/Makefile +++ b/Makefile @@ -34,6 +34,8 @@ pep8: @pep8 -r --select=W391 -q --filename=*.py `pwd`/tests/ | xargs gsed -i -e :a -e '/^\n*$/{$d;N;ba' -e '}' grind: - @valgrind --leak-check=full tests/cpp_tests/font_registration_test + @for FILE in tests/cpp_tests/*-bin; do \ + valgrind --leak-check=full --log-fd=1 $${FILE} | grep definitely; \ + done .PHONY: clean reset uninstall test install From b7f714f7ec7eb38be9536fb68e981f0bc8cb4ffd Mon Sep 17 00:00:00 2001 From: Dane Springmeyer Date: Thu, 5 Apr 2012 11:05:14 -0700 Subject: [PATCH 037/134] postgis: primary key autodetection will now only happen if 'autodetect_key_field' is set to true - maintains current behavior - refs #804 --- CHANGELOG.md | 4 +- plugins/input/postgis/postgis_datasource.cpp | 36 +++++--- tests/python_tests/postgis_test.py | 90 +++++++++++++++++--- 3 files changed, 105 insertions(+), 25 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9a453f6a3..a2fa8c594 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,7 +13,9 @@ For a complete change history, see the SVN log. - GDAL: respect nodata for paletted/colormapped images (#1160) -- PostGIS: the primary key, for tables containing one, is now auto-detected allowing for globally unique feature id values (#804) +- PostGIS: Added a new option called 'autodetect_key_field' (by default false) that if true will + trigger autodetection of a given tables' primary key allowing for feature.id() to represent + globally unique ids. This option has no effect if the user has not manually supplied the 'key_field' option. (#804) - Cairo: Add full rendering support for markers to match AGG renderer functionality (#1071) diff --git a/plugins/input/postgis/postgis_datasource.cpp b/plugins/input/postgis/postgis_datasource.cpp index 6ff78bcd5..59434803a 100644 --- a/plugins/input/postgis/postgis_datasource.cpp +++ b/plugins/input/postgis/postgis_datasource.cpp @@ -107,7 +107,7 @@ void postgis_datasource::bind() const boost::optional initial_size = params_.get("initial_size", 1); boost::optional max_size = params_.get("max_size", 10); - boost::optional require_key = params_.get("require_key", false); + boost::optional autodetect_key_field = params_.get("autodetect_key_field", false); ConnectionManager* mgr = ConnectionManager::instance(); mgr->registerPool(creator_, *initial_size, *max_size); @@ -230,7 +230,7 @@ void postgis_datasource::bind() const } // detect primary key - if (key_field_.empty()) + if (*autodetect_key_field && key_field_.empty()) { std::ostringstream s; s << "SELECT a.attname, a.attnum, t.typname, t.typname in ('int2','int4','int8') " @@ -267,34 +267,42 @@ void postgis_datasource::bind() const { key_field_ = std::string(key_field_string); #ifdef MAPNIK_DEBUG - std::clog << "PostGIS Plugin: auto-detected key field of '" << key_field_ << "' on table '" << geometry_table_ << "'\n"; + std::clog << "PostGIS Plugin: auto-detected key field of '" + << key_field_ << "' on table '" + << geometry_table_ << "'\n"; #endif } } - else // warn with odd cases like numeric primary key + else { - std::clog << "PostGIS Plugin: Warning: '" << rs_key->getValue(0) << "' on table '" << geometry_table_ << "' is not a valid integer primary key field\n"; + // throw for cases like a numeric primary key, which is invalid + // as it should be floating point (int numerics are useless) + std::ostringstream err; + err << "PostGIS Plugin: Error: '" + << rs_key->getValue(0) + << "' on table '" + << geometry_table_ + << "' is not a valid integer primary key field\n"; + throw mapnik::datasource_exception(err.str()); } } else if (result_rows > 1) { - std::clog << "PostGIS Plugin: warning, multi column primary key detected but is not supported\n"; + std::ostringstream err; + err << "PostGIS Plugin: Error: '" + << "multi column primary key detected but is not supported"; + throw mapnik::datasource_exception(err.str()); } } -#ifdef MAPNIK_DEBUG - else - { - std::clog << "Postgis Plugin: no primary key could be detected for '" << geometry_table_ << "'\n"; - } -#endif rs_key->close(); } // if a globally unique key field/primary key is required // but still not known at this point, then throw - if (*require_key && key_field_.empty()) + if (*autodetect_key_field && key_field_.empty()) { - throw mapnik::datasource_exception(std::string("PostGIS Plugin: Error: primary key required for table '") + + throw mapnik::datasource_exception(std::string("PostGIS Plugin: Error: primary key required") + + " but could not be detected for table '" + geometry_table_ + "', please supply 'key_field' option to specify field to use for primary key"); } diff --git a/tests/python_tests/postgis_test.py b/tests/python_tests/postgis_test.py index 128d4c998..9c8604f3d 100644 --- a/tests/python_tests/postgis_test.py +++ b/tests/python_tests/postgis_test.py @@ -119,6 +119,11 @@ INSERT INTO "tableWithMixedCase"(geom) values (ST_MakePoint(1,0)); INSERT INTO "tableWithMixedCase"(geom) values (ST_MakePoint(1,1)); ''' +insert_table_7 = ''' +CREATE TABLE test6(first_id int4, second_id int4,PRIMARY KEY (first_id,second_id), geom geometry); +INSERT INTO test6(first_id, second_id, geom) values (0, 0, GeomFromEWKT('SRID=4326;POINT(0 0)')); +''' + def postgis_setup(): call('dropdb %s' % MAPNIK_TEST_DBNAME,silent=True) call('createdb -T %s %s' % (POSTGIS_TEMPLATE_DBNAME,MAPNIK_TEST_DBNAME),silent=False) @@ -130,6 +135,7 @@ def postgis_setup(): call('''psql -q %s -c "%s"''' % (MAPNIK_TEST_DBNAME,insert_table_4),silent=False) call('''psql -q %s -c "%s"''' % (MAPNIK_TEST_DBNAME,insert_table_5),silent=False) call("""psql -q %s -c '%s'""" % (MAPNIK_TEST_DBNAME,insert_table_6),silent=False) + call('''psql -q %s -c "%s"''' % (MAPNIK_TEST_DBNAME,insert_table_7),silent=False) def postgis_takedown(): pass @@ -235,7 +241,8 @@ if 'postgis' in mapnik.DatasourceCache.instance().plugin_names() \ def test_auto_detection_of_unique_feature_id_32_bit(): ds = mapnik.PostGIS(dbname=MAPNIK_TEST_DBNAME,table='test2', - geometry_field='geom') + geometry_field='geom', + autodetect_key_field=True) fs = ds.featureset() eq_(fs.next()['manual_id'],0) eq_(fs.next()['manual_id'],1) @@ -255,7 +262,7 @@ if 'postgis' in mapnik.DatasourceCache.instance().plugin_names() \ def test_auto_detection_will_fail_since_no_primary_key(): ds = mapnik.PostGIS(dbname=MAPNIK_TEST_DBNAME,table='test3', geometry_field='geom', - require_key=False) + autodetect_key_field=False) fs = ds.featureset() feat = fs.next() eq_(feat['manual_id'],0) @@ -281,13 +288,13 @@ if 'postgis' in mapnik.DatasourceCache.instance().plugin_names() \ def test_auto_detection_will_fail_and_should_throw(): ds = mapnik.PostGIS(dbname=MAPNIK_TEST_DBNAME,table='test3', geometry_field='geom', - require_key=True) + autodetect_key_field=True) fs = ds.featureset() def test_auto_detection_of_unique_feature_id_64_bit(): ds = mapnik.PostGIS(dbname=MAPNIK_TEST_DBNAME,table='test4', geometry_field='geom', - require_key=False) + autodetect_key_field=True) fs = ds.featureset() eq_(fs.next()['manual_id'],0) eq_(fs.next()['manual_id'],1) @@ -304,11 +311,73 @@ if 'postgis' in mapnik.DatasourceCache.instance().plugin_names() \ eq_(fs.next().id(),2147483647) eq_(fs.next().id(),-2147483648) + def test_disabled_auto_detection_and_subquery(): + ds = mapnik.PostGIS(dbname=MAPNIK_TEST_DBNAME,table='''(select geom, 'a'::varchar as name from test2) as t''', + geometry_field='geom', + autodetect_key_field=False) + fs = ds.featureset() + feat = fs.next() + eq_(feat.id(),1) + eq_(feat['name'],'a') + feat = fs.next() + eq_(feat.id(),2) + eq_(feat['name'],'a') + feat = fs.next() + eq_(feat.id(),3) + eq_(feat['name'],'a') + feat = fs.next() + eq_(feat.id(),4) + eq_(feat['name'],'a') + feat = fs.next() + eq_(feat.id(),5) + eq_(feat['name'],'a') + feat = fs.next() + eq_(feat.id(),6) + eq_(feat['name'],'a') + + def test_auto_detection_and_subquery_including_key(): + ds = mapnik.PostGIS(dbname=MAPNIK_TEST_DBNAME,table='''(select geom, manual_id from test2) as t''', + geometry_field='geom', + autodetect_key_field=True) + fs = ds.featureset() + eq_(fs.next()['manual_id'],0) + eq_(fs.next()['manual_id'],1) + eq_(fs.next()['manual_id'],1000) + eq_(fs.next()['manual_id'],-1000) + eq_(fs.next()['manual_id'],2147483647) + eq_(fs.next()['manual_id'],-2147483648) + + fs = ds.featureset() + eq_(fs.next().id(),0) + eq_(fs.next().id(),1) + eq_(fs.next().id(),1000) + eq_(fs.next().id(),-1000) + eq_(fs.next().id(),2147483647) + eq_(fs.next().id(),-2147483648) + + @raises(RuntimeError) + def test_auto_detection_of_invalid_numeric_primary_key(): + ds = mapnik.PostGIS(dbname=MAPNIK_TEST_DBNAME,table='''(select geom, manual_id::numeric from test2) as t''', + geometry_field='geom', + autodetect_key_field=True) + + @raises(RuntimeError) + def test_auto_detection_of_invalid_multiple_keys(): + ds = mapnik.PostGIS(dbname=MAPNIK_TEST_DBNAME,table='''test6''', + geometry_field='geom', + autodetect_key_field=True) + + @raises(RuntimeError) + def test_auto_detection_of_invalid_multiple_keys_subquery(): + ds = mapnik.PostGIS(dbname=MAPNIK_TEST_DBNAME,table='''(select first_id,second_id,geom from test6) as t''', + geometry_field='geom', + autodetect_key_field=True) + def test_manually_specified_feature_id_field(): ds = mapnik.PostGIS(dbname=MAPNIK_TEST_DBNAME,table='test4', geometry_field='geom', key_field='manual_id', - require_key=True) + autodetect_key_field=True) fs = ds.featureset() eq_(fs.next()['manual_id'],0) eq_(fs.next()['manual_id'],1) @@ -328,7 +397,7 @@ if 'postgis' in mapnik.DatasourceCache.instance().plugin_names() \ def test_numeric_type_feature_id_field(): ds = mapnik.PostGIS(dbname=MAPNIK_TEST_DBNAME,table='test5', geometry_field='geom', - require_key=False) + autodetect_key_field=False) fs = ds.featureset() eq_(fs.next()['manual_id'],-1) eq_(fs.next()['manual_id'],1) @@ -340,7 +409,7 @@ if 'postgis' in mapnik.DatasourceCache.instance().plugin_names() \ def test_querying_table_with_mixed_case(): ds = mapnik.PostGIS(dbname=MAPNIK_TEST_DBNAME,table='"tableWithMixedCase"', geometry_field='geom', - require_key=True) + autodetect_key_field=True) fs = ds.featureset() eq_(fs.next().id(),1) eq_(fs.next().id(),2) @@ -351,7 +420,7 @@ if 'postgis' in mapnik.DatasourceCache.instance().plugin_names() \ def test_querying_subquery_with_mixed_case(): ds = mapnik.PostGIS(dbname=MAPNIK_TEST_DBNAME,table='(SeLeCt * FrOm "tableWithMixedCase") as MixedCaseQuery', geometry_field='geom', - require_key=True) + autodetect_key_field=True) fs = ds.featureset() eq_(fs.next().id(),1) eq_(fs.next().id(),2) @@ -363,7 +432,7 @@ if 'postgis' in mapnik.DatasourceCache.instance().plugin_names() \ ds = mapnik.PostGIS(dbname=MAPNIK_TEST_DBNAME,table=''' (SeLeCt * FrOm "tableWithMixedCase" where geom && !bbox! ) as MixedCaseQuery''', geometry_field='geom', - require_key=True) + autodetect_key_field=True) fs = ds.featureset() eq_(fs.next().id(),1) eq_(fs.next().id(),2) @@ -375,7 +444,7 @@ if 'postgis' in mapnik.DatasourceCache.instance().plugin_names() \ ds = mapnik.PostGIS(dbname=MAPNIK_TEST_DBNAME,table=''' (SeLeCt * FrOm "tableWithMixedCase" where ST_Intersects(geom,!bbox!) ) as MixedCaseQuery''', geometry_field='geom', - require_key=True) + autodetect_key_field=True) fs = ds.featureset() eq_(fs.next().id(),1) eq_(fs.next().id(),2) @@ -387,4 +456,5 @@ if 'postgis' in mapnik.DatasourceCache.instance().plugin_names() \ if __name__ == "__main__": setup() + #test_auto_detection_and_subquery() [eval(run)() for run in dir() if 'test_' in run] From f90a07eb94dec7fec108da0577670f066a01c7f6 Mon Sep 17 00:00:00 2001 From: Dane Springmeyer Date: Thu, 5 Apr 2012 14:41:52 -0700 Subject: [PATCH 038/134] add explicit include for MAPNIK_DECL --- include/mapnik/load_map.hpp | 1 + 1 file changed, 1 insertion(+) diff --git a/include/mapnik/load_map.hpp b/include/mapnik/load_map.hpp index 7858c9395..231a8bd37 100644 --- a/include/mapnik/load_map.hpp +++ b/include/mapnik/load_map.hpp @@ -25,6 +25,7 @@ // mapnik #include +#include // for MAPNIK_DECL // stl #include From 7b84a2ce94889caf73520b28e145af8799a67d51 Mon Sep 17 00:00:00 2001 From: Dane Springmeyer Date: Thu, 5 Apr 2012 16:59:36 -0700 Subject: [PATCH 039/134] fix linking of postgis.input by using MAPNIK_DECL and ensuring the header is included in src/conversions.cpp - closes #1127 --- include/mapnik/util/conversions.hpp | 13 +++++++------ src/conversions.cpp | 3 +++ 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/include/mapnik/util/conversions.hpp b/include/mapnik/util/conversions.hpp index b57f55ff9..266b0f844 100644 --- a/include/mapnik/util/conversions.hpp +++ b/include/mapnik/util/conversions.hpp @@ -24,20 +24,21 @@ #define MAPNIK_UTIL_CONVERSIONS_HPP // mapnik +#include // stl #include namespace mapnik { namespace util { - bool string2int(const char * value, int & result); - bool string2int(std::string const& value, int & result); + MAPNIK_DECL bool string2int(std::string const& value, int & result); + MAPNIK_DECL bool string2int(const char * value, int & result); - bool string2double(std::string const& value, double & result); - bool string2double(const char * value, double & result); + MAPNIK_DECL bool string2double(std::string const& value, double & result); + MAPNIK_DECL bool string2double(const char * value, double & result); - bool string2float(std::string const& value, float & result); - bool string2float(const char * value, float & result); + MAPNIK_DECL bool string2float(std::string const& value, float & result); + MAPNIK_DECL bool string2float(const char * value, float & result); }} diff --git a/src/conversions.cpp b/src/conversions.cpp index 76e9d0531..6411388c1 100644 --- a/src/conversions.cpp +++ b/src/conversions.cpp @@ -20,6 +20,9 @@ * *****************************************************************************/ +// mapnik +#include + // boost #include From 43d646c759e3caf794dc59b84f3bf86b37f5c907 Mon Sep 17 00:00:00 2001 From: Dane Springmeyer Date: Fri, 6 Apr 2012 11:42:36 -0700 Subject: [PATCH 040/134] formatting --- src/xml_tree.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/xml_tree.cpp b/src/xml_tree.cpp index 36995166f..940832782 100644 --- a/src/xml_tree.cpp +++ b/src/xml_tree.cpp @@ -104,7 +104,8 @@ inline boost::optional fast_cast(xml_tree const& tree, std::stri if (expression_factory::parse_from_string(expr, value, tree.expr_grammar)) { return expr; - } else + } + else { throw mapnik::config_error("Failed to parse expression '" + value + "'"); } From cb048b92d46041180afef71b9b80556e1ef43d8f Mon Sep 17 00:00:00 2001 From: Dane Springmeyer Date: Fri, 6 Apr 2012 12:29:51 -0700 Subject: [PATCH 041/134] formatting --- include/mapnik/enumeration.hpp | 38 +++++++++++++++++++++------------- 1 file changed, 24 insertions(+), 14 deletions(-) diff --git a/include/mapnik/enumeration.hpp b/include/mapnik/enumeration.hpp index b3c00dfa0..db7c7d6d3 100644 --- a/include/mapnik/enumeration.hpp +++ b/include/mapnik/enumeration.hpp @@ -73,7 +73,7 @@ protected: * underscores (_) and dashes (-). * * - * @warning At the moment the verify() method is called during static initialization. + * @warning At the moment the verify_mapnik_enum() method is called during static initialization. * It quits the application with exit code 1 if any error is detected. The other solution * i thought of is to do the checks at compile time (using boost::mpl). * @@ -139,22 +139,27 @@ template class MAPNIK_DECL enumeration { public: typedef ENUM native_type; - enumeration(): - value_() {}; - enumeration( ENUM v ) : value_(v) {} - enumeration( const enumeration & other ) : value_(other.value_) {} + + enumeration() + : value_() {} + + enumeration( ENUM v ) + : value_(v) {} + + enumeration( const enumeration & other ) + : value_(other.value_) {} /** Assignment operator for native enum values. */ void operator=(ENUM v) - { - value_ = v; - } + { + value_ = v; + } /** Assignment operator. */ void operator=(const enumeration & other) - { - value_ = other.value_; - } + { + value_ = other.value_; + } /** Conversion operator for native enum values. */ operator ENUM() const @@ -166,10 +171,12 @@ public: { MAX = THE_MAX }; + ENUM max() const { return THE_MAX; } + /** Converts @p str to an enum. * @throw illegal_enum_value @p str is not a legal identifier. * */ @@ -247,7 +254,7 @@ public: /** Performs some simple checks and quits the application if * any error is detected. Tries to print helpful error messages. */ - static bool verify(const char * filename, unsigned line_no) + static bool verify_mapnik_enum(const char * filename, unsigned line_no) { for (unsigned i = 0; i < THE_MAX; ++i) { @@ -269,10 +276,12 @@ public: } return true; } + static std::string const& get_full_qualified_name() { return our_name_; } + static std::string get_name() { std::string::size_type idx = our_name_.find_last_of(":"); @@ -283,6 +292,7 @@ public: return our_name_.substr( idx + 1 ); } } + private: ENUM value_; static const char ** our_strings_ ; @@ -320,13 +330,13 @@ operator>>(std::istream & is, mapnik::enumeration & e) #define DEFINE_ENUM( name, e) \ typedef enumeration name -/** Helper macro. Runs the verify() method during static initialization. +/** Helper macro. Runs the verify_mapnik_enum() method during static initialization. * @relates mapnik::enumeration */ #define IMPLEMENT_ENUM( name, strings ) \ template <> const char ** name ::our_strings_ = strings; \ template <> std::string name ::our_name_ = #name; \ - template <> bool name ::our_verified_flag_( name ::verify(__FILE__, __LINE__)); + template <> bool name ::our_verified_flag_( name ::verify_mapnik_enum(__FILE__, __LINE__)); #endif // MAPNIK_ENUMERATION_HPP From ab776edbf51096ac50d33ed565c0ebf92a8b6b92 Mon Sep 17 00:00:00 2001 From: Dane Springmeyer Date: Fri, 6 Apr 2012 12:58:08 -0700 Subject: [PATCH 042/134] reduce string copying slightly in populate_tree - refs #1055 --- include/mapnik/xml_node.hpp | 4 ++-- src/libxml2_loader.cpp | 3 ++- src/xml_tree.cpp | 4 ++-- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/include/mapnik/xml_node.hpp b/include/mapnik/xml_node.hpp index f0db516e1..82c8ded0b 100644 --- a/include/mapnik/xml_node.hpp +++ b/include/mapnik/xml_node.hpp @@ -51,7 +51,7 @@ public: class node_not_found: public std::exception { public: - node_not_found(std::string node_name); + node_not_found(std::string const& node_name); virtual const char* what() const throw(); ~node_not_found() throw (); private: @@ -84,7 +84,7 @@ class xml_node public: typedef std::list::const_iterator const_iterator; typedef std::map attribute_map; - xml_node(xml_tree &tree, std::string name, unsigned line=0, bool text_node = false); + xml_node(xml_tree &tree, std::string const& name, unsigned line=0, bool text_node = false); std::string const& name() const; std::string const& text() const; diff --git a/src/libxml2_loader.cpp b/src/libxml2_loader.cpp index d95e145ca..31b235cb6 100644 --- a/src/libxml2_loader.cpp +++ b/src/libxml2_loader.cpp @@ -185,7 +185,8 @@ private: break; case XML_TEXT_NODE: { - std::string trimmed = boost::algorithm::trim_copy(std::string((char*)cur_node->content)); + std::string trimmed((char*)cur_node->content); + boost::algorithm::trim(trimmed); if (trimmed.empty()) break; //Don't add empty text nodes node.add_child(trimmed, cur_node->line, true); } diff --git a/src/xml_tree.cpp b/src/xml_tree.cpp index 940832782..26c3a3bf7 100644 --- a/src/xml_tree.cpp +++ b/src/xml_tree.cpp @@ -200,7 +200,7 @@ xml_attribute::xml_attribute(std::string const& value_) /****************************************************************************/ -node_not_found::node_not_found(std::string node_name) +node_not_found::node_not_found(std::string const& node_name) : node_name_(node_name) { @@ -255,7 +255,7 @@ more_than_one_child::~more_than_one_child() throw() /****************************************************************************/ -xml_node::xml_node(xml_tree &tree, std::string name, unsigned line, bool text_node) +xml_node::xml_node(xml_tree &tree, std::string const& name, unsigned line, bool text_node) : tree_(tree), name_(name), text_node_(text_node), From e57eb47ba0fcf70c2523d32b09bb397226213f88 Mon Sep 17 00:00:00 2001 From: Dane Springmeyer Date: Fri, 6 Apr 2012 13:05:59 -0700 Subject: [PATCH 043/134] cast to const char --- src/libxml2_loader.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/libxml2_loader.cpp b/src/libxml2_loader.cpp index 31b235cb6..bbf2d55ae 100644 --- a/src/libxml2_loader.cpp +++ b/src/libxml2_loader.cpp @@ -165,7 +165,7 @@ private: { for (; attributes; attributes = attributes->next ) { - node.add_attribute((char *)attributes->name, (char *)attributes->children->content); + node.add_attribute((const char *)attributes->name, (const char *)attributes->children->content); } } @@ -178,14 +178,14 @@ private: case XML_ELEMENT_NODE: { - xml_node &new_node = node.add_child((char *)cur_node->name, cur_node->line, false); + xml_node &new_node = node.add_child((const char *)cur_node->name, cur_node->line, false); append_attributes(cur_node->properties, new_node); populate_tree(cur_node->children, new_node); } break; case XML_TEXT_NODE: { - std::string trimmed((char*)cur_node->content); + std::string trimmed((const char*)cur_node->content); boost::algorithm::trim(trimmed); if (trimmed.empty()) break; //Don't add empty text nodes node.add_child(trimmed, cur_node->line, true); From 98e470903cec463a5b61baaac8fc73de132582e8 Mon Sep 17 00:00:00 2001 From: Dane Springmeyer Date: Fri, 6 Apr 2012 13:39:13 -0700 Subject: [PATCH 044/134] less lexical cast - refs #1055 --- src/box2d.cpp | 27 ++++++++++++++------------- src/load_map.cpp | 15 ++++++--------- src/projection.cpp | 3 ++- src/rapidxml_loader.cpp | 3 ++- 4 files changed, 24 insertions(+), 24 deletions(-) diff --git a/src/box2d.cpp b/src/box2d.cpp index c6061dc06..68cda38c3 100644 --- a/src/box2d.cpp +++ b/src/box2d.cpp @@ -21,6 +21,7 @@ *****************************************************************************/ //$Id: envelope.cpp 17 2005-03-08 23:58:43Z pavlenko $ +// mapnik #include // stl @@ -28,8 +29,8 @@ // boost #include -#include #include +#include namespace mapnik { @@ -332,31 +333,31 @@ inline #endif bool box2d::from_string(const std::string& s) { - bool success = false; - - boost::char_separator sep(", "); - boost::tokenizer > tok(s, sep); - unsigned i = 0; double d[4]; + bool success = false; + boost::char_separator sep(", "); + boost::tokenizer > tok(s, sep); for (boost::tokenizer >::iterator beg = tok.begin(); beg != tok.end(); ++beg) { - try - { - d[i] = boost::lexical_cast(boost::trim_copy(*beg)); - } - catch (boost::bad_lexical_cast & ex) + std::string item(*beg); + boost::trim(item); + // note: we intentionally do not use mapnik::util::conversions::string2double + // here to ensure that shapeindex can statically compile mapnik::box2d without + // needing to link to libmapnik + std::string::const_iterator str_beg = item.begin(); + std::string::const_iterator str_end = item.end(); + bool r = boost::spirit::qi::phrase_parse(str_beg,str_end,boost::spirit::qi::double_,boost::spirit::ascii::space,d[i]); + if (!(r && (str_beg == str_end))) { break; } - if (i == 3) { success = true; break; } - ++i; } diff --git a/src/load_map.cpp b/src/load_map.cpp index 68239b48a..901098411 100644 --- a/src/load_map.cpp +++ b/src/load_map.cpp @@ -50,12 +50,12 @@ #include #include #include +#include // boost #include #include #include -#include #include #include #include @@ -69,8 +69,6 @@ #include #include -using boost::lexical_cast; -using boost::bad_lexical_cast; using boost::tokenizer; using std::endl; @@ -260,13 +258,12 @@ void map_parser::parse_map(Map & map, xml_node const& pt, std::string const& bas for (boost::tokenizer >::iterator beg = tokens.begin(); beg != tokens.end(); ++beg) { - try + std::string item(*beg); + boost::trim(item); + if (!mapnik::util::string2int(item,n[i])) { - n[i] = boost::lexical_cast(boost::trim_copy(*beg)); - } - catch (boost::bad_lexical_cast & ex) - { - std::clog << *beg << " : " << ex.what() << "\n"; + throw config_error(std::string("Invalid version string encountered: '") + + *beg + "' in '" + *min_version_string + "'"); break; } if (i==2) diff --git a/src/projection.cpp b/src/projection.cpp index 5fc97e150..4c6ec153a 100644 --- a/src/projection.cpp +++ b/src/projection.cpp @@ -149,7 +149,8 @@ std::string projection::expanded() const if (proj_) { std::string def(pj_get_def( proj_, 0 )); //boost::algorithm::ireplace_first(def,params_,""); - return boost::trim_copy(def); + boost::trim(def); + return def; } return std::string(""); } diff --git a/src/rapidxml_loader.cpp b/src/rapidxml_loader.cpp index 4a9293f54..4c8398a69 100644 --- a/src/rapidxml_loader.cpp +++ b/src/rapidxml_loader.cpp @@ -144,7 +144,8 @@ private: case rapidxml::node_data: case rapidxml::node_cdata: { - std::string trimmed = boost::algorithm::trim_copy(std::string(cur_node->value())); + std::string trimmed(cur_node->value()); + boost::trim(trimmed); if (trimmed.empty()) break; //Don't add empty text nodes node.add_child(trimmed, 0, true); } From 8220acce829835705706137649ddcd96ace6a0df Mon Sep 17 00:00:00 2001 From: Dane Springmeyer Date: Fri, 6 Apr 2012 14:20:04 -0700 Subject: [PATCH 045/134] more params tests --- tests/cpp_tests/params_test.cpp | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/tests/cpp_tests/params_test.cpp b/tests/cpp_tests/params_test.cpp index 9caecafcd..baf430e19 100644 --- a/tests/cpp_tests/params_test.cpp +++ b/tests/cpp_tests/params_test.cpp @@ -53,6 +53,22 @@ int main( int, char*[] ) params["bool"] = "no"; BOOST_TEST( (params.get("bool") && *params.get("bool") == false)); + // strings + params["string"] = "hello"; + BOOST_TEST( (params.get("string") && *params.get("string") == "hello") ); + + // int + params["int"] = 1; + BOOST_TEST( (params.get("int") && *params.get("int") == 1) ); + + // double + params["double"] = 1.5; + BOOST_TEST( (params.get("double") && *params.get("double") == 1.5) ); + + // value_null + params["null"] = mapnik::value_null(); + //BOOST_TEST( (params.get("null")/* && *params.get("null") == mapnik::value_null()*/) ); + if (!::boost::detail::test_errors()) { std::clog << "C++ parameters: \x1b[1;32m✓ \x1b[0m\n"; } else { From 215f7a911cbf703b0523e8c97117f92ba7ca65a2 Mon Sep 17 00:00:00 2001 From: Dane Springmeyer Date: Fri, 6 Apr 2012 14:20:32 -0700 Subject: [PATCH 046/134] remove lexical cast from value_type conversions - refs #1055 --- include/mapnik/value.hpp | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/include/mapnik/value.hpp b/include/mapnik/value.hpp index a3cef23b4..a45d17c74 100644 --- a/include/mapnik/value.hpp +++ b/include/mapnik/value.hpp @@ -26,12 +26,12 @@ // mapnik #include #include +#include // boost #include #include #include -#include // stl #include @@ -651,13 +651,17 @@ struct to_double : public boost::static_visitor double operator() (std::string const& val) const { - return boost::lexical_cast(val); + double ret(0); + mapnik::util::string2double(val,ret); + return ret; } double operator() (UnicodeString const& val) const { std::string utf8; to_utf8(val,utf8); - return boost::lexical_cast(utf8); + double ret(0); + mapnik::util::string2double(utf8,ret); + return ret; } double operator() (value_null const& val) const @@ -681,13 +685,17 @@ struct to_int : public boost::static_visitor int operator() (std::string const& val) const { - return boost::lexical_cast(val); + int ret(0); + mapnik::util::string2int(val,ret); + return ret; } int operator() (UnicodeString const& val) const { std::string utf8; to_utf8(val,utf8); - return boost::lexical_cast(utf8); + int ret(0); + mapnik::util::string2int(utf8,ret); + return ret; } int operator() (value_null const& val) const From b21d8a995789778615f363d6e2cc88b8794a3e5a Mon Sep 17 00:00:00 2001 From: Dane Springmeyer Date: Fri, 6 Apr 2012 14:29:13 -0700 Subject: [PATCH 047/134] avoid copy --- plugins/input/postgis/postgis_featureset.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/plugins/input/postgis/postgis_featureset.cpp b/plugins/input/postgis/postgis_featureset.cpp index 66d65c4ab..dbd8d529c 100644 --- a/plugins/input/postgis/postgis_featureset.cpp +++ b/plugins/input/postgis/postgis_featureset.cpp @@ -40,7 +40,6 @@ #include #include -using boost::trim_copy; using mapnik::geometry_type; using mapnik::byte; using mapnik::geometry_utils; @@ -179,7 +178,9 @@ feature_ptr postgis_featureset::next() case 1042: //bpchar { - feature->put(name, tr_->transcode(trim_copy(std::string(buf)).c_str())); + std::string str(buf); + boost::trim(str); + feature->put(name, tr_->transcode(str.c_str())); break; } From 19f5f7741752ea9d2d251b07d994aadeb60ea0ab Mon Sep 17 00:00:00 2001 From: Dane Springmeyer Date: Fri, 6 Apr 2012 16:50:11 -0700 Subject: [PATCH 048/134] reuse path_expression_grammar - finishes and closes #1028 --- include/mapnik/parse_path.hpp | 5 +++ include/mapnik/path_expression_grammar.hpp | 1 + include/mapnik/xml_node.hpp | 5 +++ include/mapnik/xml_tree.hpp | 2 ++ src/load_map.cpp | 38 ++++++++++++++++++---- src/parse_path.cpp | 13 +++++++- src/xml_tree.cpp | 3 +- 7 files changed, 59 insertions(+), 8 deletions(-) diff --git a/include/mapnik/parse_path.hpp b/include/mapnik/parse_path.hpp index 7990e9fb5..66cf0ddfe 100644 --- a/include/mapnik/parse_path.hpp +++ b/include/mapnik/parse_path.hpp @@ -43,8 +43,13 @@ namespace mapnik { typedef boost::variant path_component; typedef std::vector path_expression; typedef boost::shared_ptr path_expression_ptr; +template struct path_expression_grammar; MAPNIK_DECL path_expression_ptr parse_path(std::string const & str); +MAPNIK_DECL bool parse_path_from_string(path_expression_ptr const& path, + std::string const & str, + path_expression_grammar const& g); + template struct path_processor diff --git a/include/mapnik/path_expression_grammar.hpp b/include/mapnik/path_expression_grammar.hpp index 5da749b11..9c11e29eb 100644 --- a/include/mapnik/path_expression_grammar.hpp +++ b/include/mapnik/path_expression_grammar.hpp @@ -60,6 +60,7 @@ namespace standard_wide = boost::spirit::standard_wide; using standard_wide::space_type; using standard_wide::space; +typedef boost::variant path_component; template struct path_expression_grammar : qi::grammar(), space_type> diff --git a/include/mapnik/xml_node.hpp b/include/mapnik/xml_node.hpp index 82c8ded0b..8d2858e46 100644 --- a/include/mapnik/xml_node.hpp +++ b/include/mapnik/xml_node.hpp @@ -119,6 +119,11 @@ public: std::string get_text() const; + xml_tree const& get_tree() const + { + return tree_; + } + template T get_value() const; private: diff --git a/include/mapnik/xml_tree.hpp b/include/mapnik/xml_tree.hpp index 27893d262..d5beb9614 100644 --- a/include/mapnik/xml_tree.hpp +++ b/include/mapnik/xml_tree.hpp @@ -25,6 +25,7 @@ //mapnik #include #include +#include // boost #include @@ -55,6 +56,7 @@ private: public: mapnik::css_color_grammar color_grammar; mapnik::expression_grammar expr_grammar; + path_expression_grammar path_expr_grammar; }; } //ns mapnik diff --git a/src/load_map.cpp b/src/load_map.cpp index 901098411..0db27b8c3 100644 --- a/src/load_map.cpp +++ b/src/load_map.cpp @@ -782,7 +782,13 @@ void map_parser::parse_point_symbolizer(rule & rule, xml_node const & sym) *file = ensure_relative_to_xml(file); - symbol.set_filename(parse_path(*file)); + path_expression_ptr expr(boost::make_shared()); + if (!parse_path_from_string(expr, *file, sym.get_tree().path_expr_grammar)) + { + throw mapnik::config_error("Failed to parse path_expression '" + *file + "'"); + } + + symbol.set_filename(expr); if (transform_wkt) { @@ -865,7 +871,13 @@ void map_parser::parse_markers_symbolizer(rule & rule, xml_node const& sym) } } - markers_symbolizer symbol(parse_path(filename)); + path_expression_ptr expr(boost::make_shared()); + if (!parse_path_from_string(expr, filename, sym.get_tree().path_expr_grammar)) + { + throw mapnik::config_error("Failed to parse path_expression '" + filename + "'"); + } + markers_symbolizer symbol(expr); + optional opacity = sym.get_opt_attr("opacity"); if (opacity) symbol.set_opacity(*opacity); @@ -961,8 +973,12 @@ void map_parser::parse_line_pattern_symbolizer(rule & rule, xml_node const & sym } file = ensure_relative_to_xml(file); - - line_pattern_symbolizer symbol(parse_path(file)); + path_expression_ptr expr(boost::make_shared()); + if (!parse_path_from_string(expr, file, sym.get_tree().path_expr_grammar)) + { + throw mapnik::config_error("Failed to parse path_expression '" + file + "'"); + } + line_pattern_symbolizer symbol(expr); parse_metawriter_in_symbolizer(symbol, sym); rule.append(symbol); @@ -1009,7 +1025,12 @@ void map_parser::parse_polygon_pattern_symbolizer(rule & rule, file = ensure_relative_to_xml(file); - polygon_pattern_symbolizer symbol(parse_path(file)); + path_expression_ptr expr(boost::make_shared()); + if (!parse_path_from_string(expr, file, sym.get_tree().path_expr_grammar)) + { + throw mapnik::config_error("Failed to parse path_expression '" + file + "'"); + } + polygon_pattern_symbolizer symbol(expr); // pattern alignment pattern_alignment_e p_alignment = sym.get_attr("alignment",LOCAL_ALIGNMENT); @@ -1159,7 +1180,12 @@ void map_parser::parse_shield_symbolizer(rule & rule, xml_node const& sym) } image_file = ensure_relative_to_xml(image_file); - shield_symbol.set_filename(parse_path(image_file)); + path_expression_ptr expr(boost::make_shared()); + if (!parse_path_from_string(expr, image_file, sym.get_tree().path_expr_grammar)) + { + throw mapnik::config_error("Failed to parse path_expression '" + image_file + "'"); + } + shield_symbol.set_filename(expr); } catch (image_reader_exception const & ex) { diff --git a/src/parse_path.cpp b/src/parse_path.cpp index 2c9fb9030..9e564653a 100644 --- a/src/parse_path.cpp +++ b/src/parse_path.cpp @@ -29,7 +29,7 @@ namespace mapnik { path_expression_ptr parse_path(std::string const & str) { - path_expression_ptr path = boost::make_shared() ; + path_expression_ptr path = boost::make_shared(); path_expression_grammar g; std::string::const_iterator itr = str.begin(); @@ -44,4 +44,15 @@ path_expression_ptr parse_path(std::string const & str) throw std::runtime_error("Failed to parse path expression"); } } + +bool parse_path_from_string(path_expression_ptr const& path, + std::string const & str, + path_expression_grammar const& g) +{ + std::string::const_iterator itr = str.begin(); + std::string::const_iterator end = str.end(); + bool r = qi::phrase_parse(itr, end, g, space, *path); + return (r && itr==end); +} + } diff --git a/src/xml_tree.cpp b/src/xml_tree.cpp index 26c3a3bf7..6ff31e7d9 100644 --- a/src/xml_tree.cpp +++ b/src/xml_tree.cpp @@ -171,7 +171,8 @@ xml_tree::xml_tree(std::string const& encoding) file_(), tr_(encoding), color_grammar(), - expr_grammar(tr_) + expr_grammar(tr_), + path_expr_grammar() { node_.set_processed(true); //root node is always processed } From 1f351e0e097270940c7c9257b5b685176737fac2 Mon Sep 17 00:00:00 2001 From: kunitoki Date: Sun, 8 Apr 2012 02:20:56 +0200 Subject: [PATCH 049/134] implement new debug system --- SConstruct | 33 +++- bindings/python/mapnik_color.cpp | 1 - bindings/python/mapnik_coord.cpp | 1 - bindings/python/mapnik_datasource.cpp | 4 +- bindings/python/mapnik_datasource_cache.cpp | 2 - bindings/python/mapnik_envelope.cpp | 1 - bindings/python/mapnik_expression.cpp | 5 +- bindings/python/mapnik_feature.cpp | 3 - bindings/python/mapnik_featureset.cpp | 2 +- bindings/python/mapnik_font_engine.cpp | 1 - bindings/python/mapnik_geometry.cpp | 1 - bindings/python/mapnik_grid.cpp | 1 - bindings/python/mapnik_grid_view.cpp | 1 - bindings/python/mapnik_image.cpp | 1 - bindings/python/mapnik_image_view.cpp | 1 - bindings/python/mapnik_inmem_metawriter.cpp | 1 - bindings/python/mapnik_layer.cpp | 2 - .../python/mapnik_line_pattern_symbolizer.cpp | 1 - bindings/python/mapnik_line_symbolizer.cpp | 1 - bindings/python/mapnik_map.cpp | 1 - bindings/python/mapnik_markers_symbolizer.cpp | 2 +- bindings/python/mapnik_palette.cpp | 1 - bindings/python/mapnik_parameters.cpp | 5 +- bindings/python/mapnik_point_symbolizer.cpp | 1 - .../mapnik_polygon_pattern_symbolizer.cpp | 1 - bindings/python/mapnik_polygon_symbolizer.cpp | 1 - bindings/python/mapnik_proj_transform.cpp | 2 +- bindings/python/mapnik_projection.cpp | 3 +- bindings/python/mapnik_query.cpp | 5 +- bindings/python/mapnik_raster_colorizer.cpp | 4 +- bindings/python/mapnik_raster_symbolizer.cpp | 4 +- bindings/python/mapnik_rule.cpp | 3 +- bindings/python/mapnik_shield_symbolizer.cpp | 4 +- bindings/python/mapnik_stroke.cpp | 1 - bindings/python/mapnik_style.cpp | 3 +- bindings/python/mapnik_symbolizer.cpp | 3 +- bindings/python/mapnik_view_transform.cpp | 1 - bindings/python/python_cairo.cpp | 1 - bindings/python/python_grid_utils.hpp | 5 +- bindings/python/python_optional.hpp | 1 - include/mapnik/ctrans.hpp | 41 ++--- include/mapnik/datasource.hpp | 11 ++ include/mapnik/debug.hpp | 127 +++++++++++++ include/mapnik/font_engine_freetype.hpp | 12 +- include/mapnik/grid/grid.hpp | 10 +- .../json/feature_collection_grammar.hpp | 2 +- include/mapnik/memory_featureset.hpp | 8 +- include/mapnik/metawriter_json.hpp | 2 +- include/mapnik/pool.hpp | 17 +- include/mapnik/rule.hpp | 2 +- include/mapnik/svg/svg_renderer.hpp | 13 +- include/mapnik/timer.hpp | 80 ++++++--- include/mapnik/utils.hpp | 24 ++- plugins/input/csv/csv_datasource.cpp | 123 ++++++++----- plugins/input/csv/csv_datasource.hpp | 25 ++- plugins/input/gdal/gdal_datasource.cpp | 49 +++-- plugins/input/gdal/gdal_datasource.hpp | 3 +- plugins/input/gdal/gdal_featureset.cpp | 128 ++++++------- plugins/input/gdal/gdal_featureset.hpp | 2 +- plugins/input/geos/geos_datasource.cpp | 59 ++++-- plugins/input/geos/geos_featureset.cpp | 5 +- plugins/input/kismet/kismet_datasource.cpp | 40 +++-- plugins/input/occi/occi_datasource.cpp | 145 ++++++++++----- plugins/input/occi/occi_datasource.hpp | 4 +- plugins/input/occi/occi_featureset.cpp | 82 +++++---- plugins/input/occi/occi_featureset.hpp | 5 + plugins/input/occi/occi_types.hpp | 9 +- plugins/input/ogr/ogr_converter.cpp | 9 +- plugins/input/ogr/ogr_datasource.cpp | 50 ++++-- plugins/input/ogr/ogr_featureset.cpp | 27 +-- plugins/input/ogr/ogr_index_featureset.cpp | 22 +-- plugins/input/ogr/ogr_layer_ptr.hpp | 27 +-- plugins/input/osm/dataset_deliverer.cpp | 13 +- plugins/input/osm/osm.cpp | 38 ++-- plugins/input/osm/osm_datasource.cpp | 21 ++- plugins/input/osm/osm_datasource.hpp | 6 +- plugins/input/postgis/connection.hpp | 102 ++++++----- plugins/input/postgis/connection_manager.hpp | 19 +- plugins/input/postgis/cursorresultset.hpp | 100 +++++++---- plugins/input/postgis/postgis_datasource.cpp | 168 ++++++++---------- plugins/input/postgis/postgis_datasource.hpp | 7 +- plugins/input/postgis/postgis_featureset.cpp | 5 +- plugins/input/postgis/resultset.hpp | 6 +- plugins/input/raster/raster_datasource.cpp | 38 ++-- plugins/input/raster/raster_datasource.hpp | 5 +- plugins/input/raster/raster_featureset.cpp | 7 +- plugins/input/raster/raster_featureset.hpp | 21 ++- .../rasterlite/rasterlite_datasource.cpp | 71 ++++---- .../rasterlite/rasterlite_datasource.hpp | 3 +- .../rasterlite/rasterlite_featureset.cpp | 32 ++-- plugins/input/shape/shape_datasource.cpp | 89 +++++++--- plugins/input/shape/shape_datasource.hpp | 6 +- plugins/input/shape/shape_featureset.cpp | 11 +- .../input/shape/shape_index_featureset.cpp | 9 +- plugins/input/shape/shape_io.cpp | 5 +- plugins/input/sqlite/sqlite_connection.hpp | 13 +- plugins/input/sqlite/sqlite_datasource.cpp | 81 ++++++--- plugins/input/sqlite/sqlite_datasource.hpp | 10 +- plugins/input/sqlite/sqlite_featureset.cpp | 6 +- src/agg/agg_renderer.cpp | 30 ++-- src/agg/process_line_pattern_symbolizer.cpp | 5 +- src/agg/process_markers_symbolizer.cpp | 26 ++- .../process_polygon_pattern_symbolizer.cpp | 9 +- src/cairo_renderer.cpp | 51 +++--- src/datasource_cache.cpp | 35 ++-- src/feature_style_processor.cpp | 38 ++-- src/font_engine_freetype.cpp | 12 +- src/grid/grid_renderer.cpp | 38 ++-- src/grid/process_markers_symbolizer.cpp | 6 +- src/grid/process_raster_symbolizer.cpp | 5 +- src/jpeg_reader.cpp | 4 - src/libxml2_loader.cpp | 4 +- src/load_map.cpp | 86 ++++++--- src/map.cpp | 28 ++- src/memory.cpp | 4 +- src/memory_datasource.cpp | 8 +- src/metawriter.cpp | 19 +- src/placement_finder.cpp | 16 +- src/png_reader.cpp | 11 +- src/proj_transform.cpp | 2 +- src/raster_colorizer.cpp | 26 +-- src/save_map.cpp | 1 - src/svg/svg_renderer.cpp | 20 +-- src/svg_parser.cpp | 6 +- src/text_properties.cpp | 5 +- src/text_symbolizer.cpp | 7 +- src/tiff_reader.cpp | 12 +- src/unicode.cpp | 4 - src/wkb.cpp | 18 +- tests/python_tests/csv_test.py | 81 +++++++-- tests/python_tests/datasource_test.py | 18 +- workspace/mapnik.pro | 127 +++++++++---- workspace/plugins.pri | 3 +- 133 files changed, 1870 insertions(+), 1065 deletions(-) create mode 100644 include/mapnik/debug.hpp diff --git a/SConstruct b/SConstruct index 569ff4b09..419bc56d5 100644 --- a/SConstruct +++ b/SConstruct @@ -325,7 +325,7 @@ opts.AddVariables( # Variables affecting rendering back-ends BoolVariable('RENDERING_STATS', 'Output rendering statistics during style processing', 'False'), - + BoolVariable('INTERNAL_LIBAGG', 'Use provided libagg', 'True'), BoolVariable('SVG_RENDERER', 'build support for native svg renderer', 'False'), @@ -345,7 +345,12 @@ opts.AddVariables( PathVariable('SQLITE_LIBS', 'Search path for SQLITE library files', '/usr/' + LIBDIR_SCHEMA, PathVariable.PathAccept), PathVariable('RASTERLITE_INCLUDES', 'Search path for RASTERLITE include files', '/usr/include/', PathVariable.PathAccept), PathVariable('RASTERLITE_LIBS', 'Search path for RASTERLITE library files', '/usr/' + LIBDIR_SCHEMA, PathVariable.PathAccept), - + + # Variables for logging and statistics + BoolVariable('ENABLE_LOG', 'Enable logging, which is enabled by default when building in *debug*', 'False'), + BoolVariable('ENABLE_STATS', 'Enable global statistics during map processing', 'False'), + ('LOG_FORMAT_STRING', 'The format string used before log output string, piped through strftime (max length of 255 characters)', 'Mapnik LOG> %Y-%m-%d %H:%M:%S:'), + # Other variables BoolVariable('SHAPE_MEMORY_MAPPED_FILE', 'Utilize memory-mapped files in Shapefile Plugin (higher memory usage, better performance)', 'True'), ('SYSTEM_FONTS','Provide location for python bindings to register fonts (if given aborts installation of bundled DejaVu fonts)',''), @@ -1163,7 +1168,7 @@ if not preconfigured: env.Append(CXXFLAGS = '-DBOOST_REGEX_HAS_ICU') else: env['SKIPPED_DEPS'].append('boost_regex_icu') - + env['REQUESTED_PLUGINS'] = [ driver.strip() for driver in Split(env['INPUT_PLUGINS'])] if len(env['REQUESTED_PLUGINS']): @@ -1411,10 +1416,26 @@ if not preconfigured: # Common debugging flags. # http://lists.fedoraproject.org/pipermail/devel/2010-November/144952.html debug_flags = '-g -fno-omit-frame-pointer -DDEBUG -DMAPNIK_DEBUG' - ndebug_flags = '-DNDEBUG' - - + + # Enable logging in debug mode (always) and release mode (when specified) + log_enabled = ' -DMAPNIK_LOG -DMAPNIK_LOG_FORMAT="%s"' % env['LOG_FORMAT_STRING'] + + if env['DEBUG']: + debug_flags += log_enabled + else: + if env['ENABLE_LOG']: + ndebug_flags += log_enabled + + # Enable statistics reporting + if env['ENABLE_STATS']: + debug_flags += ' -DMAPNIK_STATS' + ndebug_flags += ' -DMAPNIK_STATS' + + # Add rdynamic to allow using statics between application and plugins + # http://stackoverflow.com/questions/8623657/multiple-instances-of-singleton-across-shared-libraries-on-linux + env.MergeFlags('-rdynamic') + # Customizing the C++ compiler flags depending on: # (1) the C++ compiler used; and # (2) whether debug binaries are requested. diff --git a/bindings/python/mapnik_color.cpp b/bindings/python/mapnik_color.cpp index 1b6e34fb2..82611ff48 100644 --- a/bindings/python/mapnik_color.cpp +++ b/bindings/python/mapnik_color.cpp @@ -19,7 +19,6 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * *****************************************************************************/ -//$Id$ // boost #include diff --git a/bindings/python/mapnik_coord.cpp b/bindings/python/mapnik_coord.cpp index 103dad3f8..b9b4e6277 100644 --- a/bindings/python/mapnik_coord.cpp +++ b/bindings/python/mapnik_coord.cpp @@ -19,7 +19,6 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * *****************************************************************************/ -//$Id$ // boost #include diff --git a/bindings/python/mapnik_datasource.cpp b/bindings/python/mapnik_datasource.cpp index d7b83040e..7d424431d 100644 --- a/bindings/python/mapnik_datasource.cpp +++ b/bindings/python/mapnik_datasource.cpp @@ -19,10 +19,11 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * *****************************************************************************/ -//$Id$ + // boost #include #include + // stl #include #include @@ -89,6 +90,7 @@ boost::python::dict describe(boost::shared_ptr const& ds) description["name"] = ld.get_name(); description["geometry_type"] = ds->get_geometry_type(); description["encoding"] = ld.get_encoding(); + description["log"] = ds->log_enabled(); return description; } diff --git a/bindings/python/mapnik_datasource_cache.cpp b/bindings/python/mapnik_datasource_cache.cpp index 6b62b7129..c4381837b 100644 --- a/bindings/python/mapnik_datasource_cache.cpp +++ b/bindings/python/mapnik_datasource_cache.cpp @@ -20,8 +20,6 @@ * *****************************************************************************/ -//$Id$ - #include #include diff --git a/bindings/python/mapnik_envelope.cpp b/bindings/python/mapnik_envelope.cpp index 5aa35a0bf..099f319cc 100644 --- a/bindings/python/mapnik_envelope.cpp +++ b/bindings/python/mapnik_envelope.cpp @@ -19,7 +19,6 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * *****************************************************************************/ -//$Id: mapnik_envelope.cc 27 2005-03-30 21:45:40Z pavlenko $ // boost #include diff --git a/bindings/python/mapnik_expression.cpp b/bindings/python/mapnik_expression.cpp index d95d5879b..b75281394 100644 --- a/bindings/python/mapnik_expression.cpp +++ b/bindings/python/mapnik_expression.cpp @@ -19,9 +19,11 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * *****************************************************************************/ -//$Id$ +// boost #include +#include + // mapnik #include #include @@ -30,7 +32,6 @@ #include #include -#include using mapnik::Feature; using mapnik::expression_ptr; diff --git a/bindings/python/mapnik_feature.cpp b/bindings/python/mapnik_feature.cpp index e55842e26..c4d7f75b6 100644 --- a/bindings/python/mapnik_feature.cpp +++ b/bindings/python/mapnik_feature.cpp @@ -19,13 +19,10 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * *****************************************************************************/ -//$Id$ // boost - #include //#include - #include #include #include diff --git a/bindings/python/mapnik_featureset.cpp b/bindings/python/mapnik_featureset.cpp index c7f4722d3..21eb7b796 100644 --- a/bindings/python/mapnik_featureset.cpp +++ b/bindings/python/mapnik_featureset.cpp @@ -19,10 +19,10 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * *****************************************************************************/ -//$Id$ // boost #include + // mapnik #include #include diff --git a/bindings/python/mapnik_font_engine.cpp b/bindings/python/mapnik_font_engine.cpp index 1b2596e3c..5f4160756 100644 --- a/bindings/python/mapnik_font_engine.cpp +++ b/bindings/python/mapnik_font_engine.cpp @@ -19,7 +19,6 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * *****************************************************************************/ -//$Id$ #include #include diff --git a/bindings/python/mapnik_geometry.cpp b/bindings/python/mapnik_geometry.cpp index 06aa96207..cd2506628 100644 --- a/bindings/python/mapnik_geometry.cpp +++ b/bindings/python/mapnik_geometry.cpp @@ -17,7 +17,6 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * *****************************************************************************/ -//$Id$ // boost #include diff --git a/bindings/python/mapnik_grid.cpp b/bindings/python/mapnik_grid.cpp index 2cfce2b7b..95a20efaf 100644 --- a/bindings/python/mapnik_grid.cpp +++ b/bindings/python/mapnik_grid.cpp @@ -19,7 +19,6 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * *****************************************************************************/ -//$Id$ // boost #include diff --git a/bindings/python/mapnik_grid_view.cpp b/bindings/python/mapnik_grid_view.cpp index bb39a5b88..926ee18f6 100644 --- a/bindings/python/mapnik_grid_view.cpp +++ b/bindings/python/mapnik_grid_view.cpp @@ -19,7 +19,6 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * *****************************************************************************/ -//$Id$ // boost #include diff --git a/bindings/python/mapnik_image.cpp b/bindings/python/mapnik_image.cpp index 5ade76573..ff4d17c0b 100644 --- a/bindings/python/mapnik_image.cpp +++ b/bindings/python/mapnik_image.cpp @@ -19,7 +19,6 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * *****************************************************************************/ -//$Id$ extern "C" { diff --git a/bindings/python/mapnik_image_view.cpp b/bindings/python/mapnik_image_view.cpp index 9e07a29e6..f3cf2e44f 100644 --- a/bindings/python/mapnik_image_view.cpp +++ b/bindings/python/mapnik_image_view.cpp @@ -19,7 +19,6 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * *****************************************************************************/ -//$Id$ extern "C" { diff --git a/bindings/python/mapnik_inmem_metawriter.cpp b/bindings/python/mapnik_inmem_metawriter.cpp index 44ebbdd08..34760f45b 100644 --- a/bindings/python/mapnik_inmem_metawriter.cpp +++ b/bindings/python/mapnik_inmem_metawriter.cpp @@ -19,7 +19,6 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * *****************************************************************************/ -//$Id$ // boost #include diff --git a/bindings/python/mapnik_layer.cpp b/bindings/python/mapnik_layer.cpp index 512d895b4..0b2e8d63b 100644 --- a/bindings/python/mapnik_layer.cpp +++ b/bindings/python/mapnik_layer.cpp @@ -19,8 +19,6 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * *****************************************************************************/ -//$Id: mapnik_layer.cc 17 2005-03-08 23:58:43Z pavlenko $ - // boost #include diff --git a/bindings/python/mapnik_line_pattern_symbolizer.cpp b/bindings/python/mapnik_line_pattern_symbolizer.cpp index aae24bac0..e982edf05 100644 --- a/bindings/python/mapnik_line_pattern_symbolizer.cpp +++ b/bindings/python/mapnik_line_pattern_symbolizer.cpp @@ -19,7 +19,6 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * *****************************************************************************/ -//$Id$ #include diff --git a/bindings/python/mapnik_line_symbolizer.cpp b/bindings/python/mapnik_line_symbolizer.cpp index 9c7053b90..93f96e693 100644 --- a/bindings/python/mapnik_line_symbolizer.cpp +++ b/bindings/python/mapnik_line_symbolizer.cpp @@ -19,7 +19,6 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * *****************************************************************************/ -//$Id$ #include #include "mapnik_enumeration.hpp" diff --git a/bindings/python/mapnik_map.cpp b/bindings/python/mapnik_map.cpp index c6e2467cd..3bc1ca983 100644 --- a/bindings/python/mapnik_map.cpp +++ b/bindings/python/mapnik_map.cpp @@ -19,7 +19,6 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * *****************************************************************************/ -//$Id: mapnik_map.cc 17 2005-03-08 23:58:43Z pavlenko $ // boost #include diff --git a/bindings/python/mapnik_markers_symbolizer.cpp b/bindings/python/mapnik_markers_symbolizer.cpp index 17d860f11..d6388c6f7 100644 --- a/bindings/python/mapnik_markers_symbolizer.cpp +++ b/bindings/python/mapnik_markers_symbolizer.cpp @@ -19,9 +19,9 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * *****************************************************************************/ -//$Id$ #include + #include #include #include diff --git a/bindings/python/mapnik_palette.cpp b/bindings/python/mapnik_palette.cpp index 4e6c39666..54b0b3146 100644 --- a/bindings/python/mapnik_palette.cpp +++ b/bindings/python/mapnik_palette.cpp @@ -19,7 +19,6 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * *****************************************************************************/ -//$Id$ // boost #include diff --git a/bindings/python/mapnik_parameters.cpp b/bindings/python/mapnik_parameters.cpp index 5a015c0ae..1bc7d853a 100644 --- a/bindings/python/mapnik_parameters.cpp +++ b/bindings/python/mapnik_parameters.cpp @@ -25,6 +25,7 @@ #include // mapnik +#include #include #include #include @@ -102,7 +103,9 @@ struct parameters_pickle_suite : boost::python::pickle_suite } else { - std::clog << "could not unpickle key: " << key << "\n"; +#ifdef MAPNIK_LOG + mapnik::log() << "parameters_pickle_suite: Could not unpickle key=" << key; +#endif } } } diff --git a/bindings/python/mapnik_point_symbolizer.cpp b/bindings/python/mapnik_point_symbolizer.cpp index ddd10bf41..2ca6c9acb 100644 --- a/bindings/python/mapnik_point_symbolizer.cpp +++ b/bindings/python/mapnik_point_symbolizer.cpp @@ -19,7 +19,6 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * *****************************************************************************/ -//$Id$ #include #include "mapnik_enumeration.hpp" diff --git a/bindings/python/mapnik_polygon_pattern_symbolizer.cpp b/bindings/python/mapnik_polygon_pattern_symbolizer.cpp index 6aee342b8..dc155c5f6 100644 --- a/bindings/python/mapnik_polygon_pattern_symbolizer.cpp +++ b/bindings/python/mapnik_polygon_pattern_symbolizer.cpp @@ -19,7 +19,6 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * *****************************************************************************/ -//$Id$ #include #include diff --git a/bindings/python/mapnik_polygon_symbolizer.cpp b/bindings/python/mapnik_polygon_symbolizer.cpp index dd809ac5d..06f35f0d8 100644 --- a/bindings/python/mapnik_polygon_symbolizer.cpp +++ b/bindings/python/mapnik_polygon_symbolizer.cpp @@ -19,7 +19,6 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * *****************************************************************************/ -//$Id$ #include #include "mapnik_enumeration.hpp" diff --git a/bindings/python/mapnik_proj_transform.cpp b/bindings/python/mapnik_proj_transform.cpp index ed5e7c9a0..7dec3b36b 100644 --- a/bindings/python/mapnik_proj_transform.cpp +++ b/bindings/python/mapnik_proj_transform.cpp @@ -19,10 +19,10 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * *****************************************************************************/ -//$Id$ // mapnik #include + // boost #include diff --git a/bindings/python/mapnik_projection.cpp b/bindings/python/mapnik_projection.cpp index f555ab11a..54fba845f 100644 --- a/bindings/python/mapnik_projection.cpp +++ b/bindings/python/mapnik_projection.cpp @@ -19,9 +19,8 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * *****************************************************************************/ -//$Id$ -//boost +// boost #include // mapnik diff --git a/bindings/python/mapnik_query.cpp b/bindings/python/mapnik_query.cpp index 08133b17a..f2b5c368f 100644 --- a/bindings/python/mapnik_query.cpp +++ b/bindings/python/mapnik_query.cpp @@ -19,11 +19,14 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * *****************************************************************************/ -//$Id$ +// boost #include + +// mapnik #include #include + using mapnik::query; using mapnik::box2d; diff --git a/bindings/python/mapnik_raster_colorizer.cpp b/bindings/python/mapnik_raster_colorizer.cpp index 0aa43b3f2..7d9d6b755 100644 --- a/bindings/python/mapnik_raster_colorizer.cpp +++ b/bindings/python/mapnik_raster_colorizer.cpp @@ -19,10 +19,12 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * *****************************************************************************/ -//$Id$ +// boost #include #include + +// mapnik #include using mapnik::raster_colorizer; diff --git a/bindings/python/mapnik_raster_symbolizer.cpp b/bindings/python/mapnik_raster_symbolizer.cpp index 63a18b851..dacaea5de 100644 --- a/bindings/python/mapnik_raster_symbolizer.cpp +++ b/bindings/python/mapnik_raster_symbolizer.cpp @@ -19,9 +19,11 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * *****************************************************************************/ -//$Id$ +// boost #include + +// mapnik #include using mapnik::raster_symbolizer; diff --git a/bindings/python/mapnik_rule.cpp b/bindings/python/mapnik_rule.cpp index 528a87a63..378e22f10 100644 --- a/bindings/python/mapnik_rule.cpp +++ b/bindings/python/mapnik_rule.cpp @@ -19,13 +19,14 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * *****************************************************************************/ -//$Id$ +// boost #include #include #include #include +// mapnik #include #include #include diff --git a/bindings/python/mapnik_shield_symbolizer.cpp b/bindings/python/mapnik_shield_symbolizer.cpp index 41eff7536..28ae7083e 100644 --- a/bindings/python/mapnik_shield_symbolizer.cpp +++ b/bindings/python/mapnik_shield_symbolizer.cpp @@ -20,9 +20,11 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * *****************************************************************************/ -//$Id$ +// boost #include + +// mapnik #include #include #include diff --git a/bindings/python/mapnik_stroke.cpp b/bindings/python/mapnik_stroke.cpp index a75f614c6..1f21071c3 100644 --- a/bindings/python/mapnik_stroke.cpp +++ b/bindings/python/mapnik_stroke.cpp @@ -19,7 +19,6 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * *****************************************************************************/ -//$Id$ // boost #include diff --git a/bindings/python/mapnik_style.cpp b/bindings/python/mapnik_style.cpp index 1ab130c04..9437e87d5 100644 --- a/bindings/python/mapnik_style.cpp +++ b/bindings/python/mapnik_style.cpp @@ -19,11 +19,12 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * *****************************************************************************/ -//$Id$ +// boost #include #include +// mapnik #include "mapnik_enumeration.hpp" #include diff --git a/bindings/python/mapnik_symbolizer.cpp b/bindings/python/mapnik_symbolizer.cpp index a4c4c3512..bd87b0db8 100644 --- a/bindings/python/mapnik_symbolizer.cpp +++ b/bindings/python/mapnik_symbolizer.cpp @@ -19,10 +19,11 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * *****************************************************************************/ -//$Id$ +// boost #include +// mapnik //symbolizer typdef here rather than mapnik/symbolizer.hpp #include diff --git a/bindings/python/mapnik_view_transform.cpp b/bindings/python/mapnik_view_transform.cpp index 7a9da32d5..090e65f9c 100644 --- a/bindings/python/mapnik_view_transform.cpp +++ b/bindings/python/mapnik_view_transform.cpp @@ -19,7 +19,6 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * *****************************************************************************/ -//$Id$ // boost #include diff --git a/bindings/python/python_cairo.cpp b/bindings/python/python_cairo.cpp index e5420c1b1..ee6c900c3 100644 --- a/bindings/python/python_cairo.cpp +++ b/bindings/python/python_cairo.cpp @@ -19,7 +19,6 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * *****************************************************************************/ -//$Id$ #if defined(HAVE_CAIRO) && defined(HAVE_PYCAIRO) diff --git a/bindings/python/python_grid_utils.hpp b/bindings/python/python_grid_utils.hpp index 09b72573c..2a9b21cf4 100644 --- a/bindings/python/python_grid_utils.hpp +++ b/bindings/python/python_grid_utils.hpp @@ -28,6 +28,7 @@ #include // mapnik +#include #include #include #include @@ -271,7 +272,9 @@ static void write_features(T const& grid_type, } else { - std::clog << "should not get here: key '" << key << "' not found in grid feature properties\n"; +#ifdef MAPNIK_LOG + mapnik::log() << "write_features: Should not get here: key " << key << " not found in grid feature properties"; +#endif } } } diff --git a/bindings/python/python_optional.hpp b/bindings/python/python_optional.hpp index 7707f0053..29c1990db 100644 --- a/bindings/python/python_optional.hpp +++ b/bindings/python/python_optional.hpp @@ -19,7 +19,6 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * *****************************************************************************/ -//$Id$ #include #include diff --git a/include/mapnik/ctrans.hpp b/include/mapnik/ctrans.hpp index 31c62f391..2d8423d85 100644 --- a/include/mapnik/ctrans.hpp +++ b/include/mapnik/ctrans.hpp @@ -24,6 +24,7 @@ #define MAPNIK_CTRANS_HPP // mapnik +#include #include #include #include @@ -239,9 +240,9 @@ struct MAPNIK_DECL coord_transform_parallel angle_a = atan2((m_pre_y-m_cur_y),(m_pre_x-m_cur_x)); dx_pre = cos(angle_a + pi_by_2); dy_pre = sin(angle_a + pi_by_2); -#ifdef MAPNIK_DEBUG - std::clog << "offsetting line by: " << offset_ << "\n"; - std::clog << "initial dx=" << (dx_pre * offset_) << " dy=" << (dy_pre * offset_) << "\n"; +#ifdef MAPNIK_LOG + mapnik::log() << "coord_transform_parallel: Offsetting line by=" << offset_; + mapnik::log() << "coord_transform_parallel: Initial dx=" << (dx_pre * offset_) << ",dy=" << (dy_pre * offset_); #endif *x = m_pre_x + (dx_pre * offset_); *y = m_pre_y + (dy_pre * offset_); @@ -290,14 +291,14 @@ struct MAPNIK_DECL coord_transform_parallel else // skip sharp spikes { -#ifdef MAPNIK_DEBUG +#ifdef MAPNIK_LOG dx_curr = cos(angle_a + pi_by_2); dy_curr = sin(angle_a + pi_by_2); sin_curve = dx_curr*dy_pre-dy_curr*dx_pre; - std::clog << "angle a: " << angle_a << "\n"; - std::clog << "angle b: " << angle_b << "\n"; - std::clog << "h: " << h << "\n"; - std::clog << "sin_curve: " << sin_curve << "\n"; + mapnik::log() << "coord_transform_parallel: angle a=" << angle_a; + mapnik::log() << "coord_transform_parallel: angle b=" << angle_b; + mapnik::log() << "coord_transform_parallel: h=" << h; + mapnik::log() << "coord_transform_parallel: sin_curve=" << sin_curve; #endif m_status = process; break; @@ -309,21 +310,21 @@ struct MAPNIK_DECL coord_transform_parallel sin_curve = dx_curr*dy_pre-dy_curr*dx_pre; cos_curve = -dx_pre*dx_curr-dy_pre*dy_curr; - #ifdef MAPNIK_DEBUG - std::clog << "sin_curve value: " << sin_curve << "\n"; + #ifdef MAPNIK_LOG + mapnik::log() << "coord_transform_parallel: sin_curve value=" << sin_curve; #endif if(sin_curve > -0.3 && sin_curve < 0.3) { - angle_b = atan2((m_cur_y-m_next_y),(m_cur_x-m_next_x)); - h = tan((angle_b - angle_a)/2.0); - *x = m_cur_x + (dx_curr * offset_) - h * (dy_curr * offset_); - *y = m_cur_y + (dy_curr * offset_) + h * (dx_curr * offset_); + angle_b = atan2((m_cur_y-m_next_y),(m_cur_x-m_next_x)); + h = tan((angle_b - angle_a)/2.0); + *x = m_cur_x + (dx_curr * offset_) - h * (dy_curr * offset_); + *y = m_cur_y + (dy_curr * offset_) + h * (dx_curr * offset_); } else { - if (angle_b - angle_a > 0) - h = -1.0*(1.0+cos_curve)/sin_curve; - else - h = (1.0+cos_curve)/sin_curve; - *x = m_cur_x + (dx_curr + base_shift*dy_curr)*offset_; - *y = m_cur_y + (dy_curr - base_shift*dx_curr)*offset_; + if (angle_b - angle_a > 0) + h = -1.0*(1.0+cos_curve)/sin_curve; + else + h = (1.0+cos_curve)/sin_curve; + *x = m_cur_x + (dx_curr + base_shift*dy_curr)*offset_; + *y = m_cur_y + (dy_curr - base_shift*dx_curr)*offset_; } */ diff --git a/include/mapnik/datasource.hpp b/include/mapnik/datasource.hpp index 6ae828a94..0e7b71f7c 100644 --- a/include/mapnik/datasource.hpp +++ b/include/mapnik/datasource.hpp @@ -88,6 +88,7 @@ public: datasource (parameters const& params) : params_(params), + log_enabled_(false), is_bound_(false) { } @@ -104,6 +105,15 @@ public: return params_; } + /*! + * @brief Get the status of detasource logging + * @return Return true if log is enabled, false otherwise + */ + bool log_enabled() const + { + return log_enabled_; + } + /*! * @brief Get the type of the datasource * @return The type of the datasource (Vector or Raster) @@ -123,6 +133,7 @@ public: virtual ~datasource() {} protected: parameters params_; + bool log_enabled_; mutable bool is_bound_; }; diff --git a/include/mapnik/debug.hpp b/include/mapnik/debug.hpp new file mode 100644 index 000000000..3abe24538 --- /dev/null +++ b/include/mapnik/debug.hpp @@ -0,0 +1,127 @@ +/***************************************************************************** + * + * This file is part of Mapnik (c++ mapping toolkit) + * + * Copyright (C) 2011 Artem Pavlenko + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + *****************************************************************************/ + +#ifndef MAPNIK_DEBUG_HPP +#define MAPNIK_DEBUG_HPP + +// mapnik +#include + +// boost +#ifdef MAPNIK_THREADSAFE +#include +#endif + +// std +#include +#include +#include +#include +#include +#include + +#ifdef MAPNIK_DEBUG +#define MAPNIK_DEBUG_AS_BOOL true +#else +#define MAPNIK_DEBUG_AS_BOOL false +#endif + +#ifndef MAPNIK_LOG_FORMAT +#error Must run configure again to regenerate the correct log format string. See LOG_FORMAT_STRING scons option. +#endif + +namespace mapnik { + + namespace logger { + +#define __xstr__(s) __str__(s) +#define __str__(s) #s + + static inline std::string format_logger() { + char buf[256]; + const time_t tm = time(0); + strftime(buf, sizeof(buf), __xstr__(MAPNIK_LOG_FORMAT), localtime(&tm)); + return buf; + } + +#undef __xstr__ +#undef __str__ + + template + class no_output { + private: + struct null_buffer { + template + null_buffer &operator<<(const T &) { + return *this; + } + }; + public: + typedef null_buffer stream_buffer; + + public: + void operator()(const stream_buffer &) { + } + }; + + template + class output_to_clog { + public: + typedef std::basic_ostringstream stream_buffer; + public: + void operator()(const stream_buffer &s) { +#ifdef MAPNIK_THREADSAFE + static boost::mutex mutex; + boost::mutex::scoped_lock lock(mutex); +#endif + std::clog << format_logger() << " " << s.str() << std::endl; + } + }; + + template