From 46ee60b398555dfd1de88382d713b9703dd3fda7 Mon Sep 17 00:00:00 2001 From: Dane Springmeyer Date: Wed, 28 Nov 2012 14:15:53 -0800 Subject: [PATCH 01/15] fix row_limit behavior in shape.input to stop reading when count = row_limit, not just when count > row_limit --- plugins/input/shape/shape_featureset.cpp | 2 +- plugins/input/shape/shape_index_featureset.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/input/shape/shape_featureset.cpp b/plugins/input/shape/shape_featureset.cpp index 6a817d80a..18caa19c3 100644 --- a/plugins/input/shape/shape_featureset.cpp +++ b/plugins/input/shape/shape_featureset.cpp @@ -57,7 +57,7 @@ shape_featureset::shape_featureset(filterT const& filter, template feature_ptr shape_featureset::next() { - if (row_limit_ && count_ > row_limit_) + if (row_limit_ && count_ >= row_limit_) { return feature_ptr(); } diff --git a/plugins/input/shape/shape_index_featureset.cpp b/plugins/input/shape/shape_index_featureset.cpp index 7a90fc408..bff1a1e5c 100644 --- a/plugins/input/shape/shape_index_featureset.cpp +++ b/plugins/input/shape/shape_index_featureset.cpp @@ -75,7 +75,7 @@ shape_index_featureset::shape_index_featureset(filterT const& filter, template feature_ptr shape_index_featureset::next() { - if (row_limit_ && count_ > row_limit_) + if (row_limit_ && count_ >= row_limit_) { return feature_ptr(); } From 1f7459d29d82578e2454fa7bfc39293c1116137d Mon Sep 17 00:00:00 2001 From: Dane Springmeyer Date: Wed, 28 Nov 2012 17:21:38 -0800 Subject: [PATCH 02/15] install svg/output headers if SVG_RENDERER is requested --- include/build.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/build.py b/include/build.py index e12e19dea..02d3d0032 100644 --- a/include/build.py +++ b/include/build.py @@ -6,8 +6,8 @@ Import('env') base = './mapnik/' subdirs = ['','svg','wkt','grid','json','util','text_placements','formatting'] -#if env['SVG_RENDERER']: -# subdirs.append('svg/output') +if env['SVG_RENDERER']: + subdirs.append('svg/output') if 'install' in COMMAND_LINE_TARGETS: for subdir in subdirs: From 46f8ce3ce7e99565c5bd035df7a8ee80c25fcd3d Mon Sep 17 00:00:00 2001 From: Dane Springmeyer Date: Wed, 28 Nov 2012 17:45:05 -0800 Subject: [PATCH 03/15] finish bringing back to life the SVG_RENDERER - now outputs geometries again - closes #1438 --- include/mapnik/ctrans.hpp | 5 + include/mapnik/svg/output/svg_generator.hpp | 15 ++- .../mapnik/svg/output/svg_output_grammars.hpp | 77 --------------- .../mapnik/util/geometry_svg_generator.hpp | 93 +++++++++++++++---- include/mapnik/util/geometry_to_svg.hpp | 2 +- src/svg/output/process_symbolizers.cpp | 8 +- src/svg/output/svg_generator.cpp | 12 --- 7 files changed, 94 insertions(+), 118 deletions(-) diff --git a/include/mapnik/ctrans.hpp b/include/mapnik/ctrans.hpp index 7186667d1..7f19721db 100644 --- a/include/mapnik/ctrans.hpp +++ b/include/mapnik/ctrans.hpp @@ -100,6 +100,11 @@ struct MAPNIK_DECL coord_transform geom_.rewind(pos); } + unsigned type() const + { + return static_cast(geom_.type()); + } + Geometry const& geom() const { return geom_; diff --git a/include/mapnik/svg/output/svg_generator.hpp b/include/mapnik/svg/output/svg_generator.hpp index b55fa19b8..973f32c75 100644 --- a/include/mapnik/svg/output/svg_generator.hpp +++ b/include/mapnik/svg/output/svg_generator.hpp @@ -27,6 +27,7 @@ #include #include #include +#include #include #include @@ -44,11 +45,8 @@ namespace mapnik { namespace svg { template class svg_generator : private boost::noncopyable { - typedef coord_transform path_type; - typedef svg::svg_root_attributes_grammar root_attributes_grammar; typedef svg::svg_rect_attributes_grammar rect_attributes_grammar; - //typedef svg::svg_path_data_grammar path_data_grammar; typedef svg::svg_path_attributes_grammar path_attributes_grammar; typedef svg::svg_path_dash_array_grammar path_dash_array_grammar; @@ -60,7 +58,16 @@ namespace mapnik { namespace svg { void generate_opening_root(root_output_attributes const& root_attributes); void generate_closing_root(); void generate_rect(rect_output_attributes const& rect_attributes); - //void generate_path(path_type const& path, path_output_attributes const& path_attributes); + template + void generate_path(PathType const& path, path_output_attributes const& path_attributes) + { + util::svg_generator svg_path_grammer; + karma::generate(output_iterator_, lit("\n"), path_attributes); + } private: OutputIterator& output_iterator_; diff --git a/include/mapnik/svg/output/svg_output_grammars.hpp b/include/mapnik/svg/output/svg_output_grammars.hpp index 591c5b47d..818624c05 100644 --- a/include/mapnik/svg/output/svg_output_grammars.hpp +++ b/include/mapnik/svg/output/svg_output_grammars.hpp @@ -87,88 +87,11 @@ BOOST_FUSION_ADAPT_STRUCT( (std::string, svg_namespace_url_) ) -/*! - * mapnik::geometry_type is adapted to conform to the concepts - * required by Karma to be recognized as a container of - * attributes for output generation. - */ -/* -namespace boost { namespace spirit { namespace traits { - - typedef mapnik::coord_transform path_type; - - template <> - struct is_container - : mpl::true_ {}; - - template <> - struct container_iterator - { - typedef mapnik::svg::path_iterator_type type; - }; - - template <> - struct begin_container - { - static mapnik::svg::path_iterator_type - call(path_type const& path) - { - return mapnik::svg::path_iterator_type(0, path); - } - }; - - template <> - struct end_container - { - static mapnik::svg::path_iterator_type - call(path_type const& path) - { - return mapnik::svg::path_iterator_type(path); - } - }; -}}} -*/ - namespace mapnik { namespace svg { using namespace boost::spirit; using namespace boost::phoenix; -/* - template - struct svg_path_data_grammar : karma::grammar - { - typedef path_iterator_type::value_type vertex_type; - - explicit svg_path_data_grammar(PathType const& path_type) - : svg_path_data_grammar::base_type(svg_path), - path_type_(path_type) - { - using karma::int_; - using karma::double_; - using repository::confix; - - svg_path = - lit("d=") - << confix('"', '"')[ - -(path_vertex % lit(' '))]; - - path_vertex = - path_vertex_command - << double_ - << lit(' ') - << double_; - - path_vertex_command = &int_(1) << lit('M') | lit('L'); - } - - karma::rule svg_path; - karma::rule path_vertex; - karma::rule path_vertex_command; - - PathType const& path_type_; - }; -*/ template struct svg_path_attributes_grammar : karma::grammar diff --git a/include/mapnik/util/geometry_svg_generator.hpp b/include/mapnik/util/geometry_svg_generator.hpp index b229e73c1..2c9dc0c6c 100644 --- a/include/mapnik/util/geometry_svg_generator.hpp +++ b/include/mapnik/util/geometry_svg_generator.hpp @@ -25,7 +25,8 @@ // mapnik #include -#include +#include // for container stuff +#include // for container stuff #include #include @@ -38,35 +39,84 @@ #include #include #include +#include //#define BOOST_SPIRIT_USE_PHOENIX_V3 1 +/*! + * adapted to conform to the concepts + * required by Karma to be recognized as a container of + * attributes for output generation. + */ +namespace boost { namespace spirit { namespace traits { + +// TODO - this needs to be made generic to any path type +typedef mapnik::coord_transform path_type; + +template <> +struct is_container : mpl::true_ {} ; + +template <> +struct container_iterator +{ + typedef mapnik::util::path_iterator type; +}; + +template <> +struct begin_container +{ + static mapnik::util::path_iterator + call (path_type const& g) + { + return mapnik::util::path_iterator(g); + } +}; + +template <> +struct end_container +{ + static mapnik::util::path_iterator + call (path_type const& g) + { + return mapnik::util::path_iterator(); + } +}; + +}}} + + namespace mapnik { namespace util { namespace karma = boost::spirit::karma; namespace phoenix = boost::phoenix; namespace svg_detail { + + template struct get_type { template struct result { typedef int type; }; - int operator() (geometry_type const& geom) const + int operator() (Geometry const& geom) const { - return (int)geom.type(); + return static_cast(geom.type()); } }; + template struct get_first { - template - struct result { typedef geometry_type::value_type const type; }; + typedef T geometry_type; - geometry_type::value_type const operator() (geometry_type const& geom) const + template + struct result { typedef typename geometry_type::value_type const type; }; + + typename geometry_type::value_type const operator() (geometry_type const& geom) const { - geometry_type::value_type coord; - boost::get<0>(coord) = geom.vertex(0,&boost::get<1>(coord),&boost::get<2>(coord)); + typename geometry_type::value_type coord; + geom.rewind(0); + boost::get<0>(coord) = geom.vertex(&boost::get<1>(coord),&boost::get<2>(coord)); return coord; } }; @@ -80,11 +130,14 @@ namespace mapnik { namespace util { }; } - template + template struct svg_generator : - karma::grammar + karma::grammar { + typedef Geometry geometry_type; + typedef typename boost::remove_pointer::type coord_type; + svg_generator() : svg_generator::base_type(svg) { @@ -102,22 +155,22 @@ namespace mapnik { namespace util { ; svg_point = &uint_ - << lit("cx=\"") << coord_type - << lit("\" cy=\"") << coord_type + << lit("cx=\"") << coordinate + << lit("\" cy=\"") << coordinate << lit('\"') ; linestring = &uint_(mapnik::LineString)[_1 = _type(_val)] - << svg_path + << svg_path << lit('\"') ; polygon = &uint_(mapnik::Polygon)[_1 = _type(_val)] - << svg_path + << svg_path << lit('\"') ; - svg_path %= ((&uint_(mapnik::SEG_MOVETO) << lit('M') + svg_path %= ((&uint_(mapnik::SEG_MOVETO) << lit("d=\"") << lit('M') | &uint_(mapnik::SEG_LINETO) [_a +=1] << karma::string [if_(_a == 1) [_1 = "L" ] ]) - << lit(' ') << coord_type << lit(' ') << coord_type) % lit(' ') + << lit(' ') << coordinate << lit(' ') << coordinate) % lit(' ') ; @@ -129,14 +182,14 @@ namespace mapnik { namespace util { karma::rule linestring; karma::rule polygon; - karma::rule svg_point; + karma::rule svg_point; karma::rule, geometry_type const& ()> svg_path; // phoenix functions - phoenix::function _type; - phoenix::function _first; + phoenix::function > _type; + phoenix::function > _first; // - karma::real_generator > coord_type; + karma::real_generator > coordinate; }; diff --git a/include/mapnik/util/geometry_to_svg.hpp b/include/mapnik/util/geometry_to_svg.hpp index d65d14d6c..d7294d878 100644 --- a/include/mapnik/util/geometry_to_svg.hpp +++ b/include/mapnik/util/geometry_to_svg.hpp @@ -39,7 +39,7 @@ bool to_svg(std::string & svg, mapnik::geometry_type const& geom) { typedef std::back_insert_iterator sink_type; sink_type sink(svg); - svg_generator generator; + svg_generator generator; bool result = karma::generate(sink, generator, geom); return result; } diff --git a/src/svg/output/process_symbolizers.cpp b/src/svg/output/process_symbolizers.cpp index 6c8268a37..8df8472b8 100644 --- a/src/svg/output/process_symbolizers.cpp +++ b/src/svg/output/process_symbolizers.cpp @@ -44,11 +44,11 @@ bool svg_renderer::process(rule::symbolizers const& syms, // generate path output for each geometry of the current feature. for(unsigned i=0; i 1) + geometry_type & geom = feature.get_geometry(i); + if(geom.size() > 0) { - //path_type path(t_, geom, prj_trans); - //generator_.generate_path(path, path_attributes_); + path_type path(t_, geom, prj_trans); + generator_.generate_path(path, path_attributes_); } } diff --git a/src/svg/output/svg_generator.cpp b/src/svg/output/svg_generator.cpp index ffaf5320f..f5d955e07 100644 --- a/src/svg/output/svg_generator.cpp +++ b/src/svg/output/svg_generator.cpp @@ -65,17 +65,5 @@ namespace mapnik { namespace svg { karma::generate(output_iterator_, lit("\n"), rect_attributes); } - /*template - void svg_generator::generate_path(path_type const& path, path_output_attributes const& path_attributes) - { - path_data_grammar data_grammar(path); - path_attributes_grammar attributes_grammar; - path_dash_array_grammar dash_array_grammar; - - karma::generate(output_iterator_, lit("\n"), path_attributes); - }*/ - template class svg_generator >; }} From 1baeb7036c799c4e1223bb2c8a3d262400ab815a Mon Sep 17 00:00:00 2001 From: Dane Springmeyer Date: Wed, 28 Nov 2012 18:20:09 -0800 Subject: [PATCH 04/15] cleanup unused code --- plugins/input/postgis/connection_manager.hpp | 23 -------------------- 1 file changed, 23 deletions(-) diff --git a/plugins/input/postgis/connection_manager.hpp b/plugins/input/postgis/connection_manager.hpp index 7c0521bca..4fbcce2d6 100644 --- a/plugins/input/postgis/connection_manager.hpp +++ b/plugins/input/postgis/connection_manager.hpp @@ -33,10 +33,6 @@ #include #include #include -#ifdef MAPNIK_THREADSAFE -#include -//using boost::mutex; -#endif // stl #include @@ -115,9 +111,6 @@ public: bool registerPool(const ConnectionCreator& creator,unsigned initialSize,unsigned maxSize) { -#ifdef MAPNIK_THREADSAFE - //mutex::scoped_lock lock(mutex_); -#endif ContType::const_iterator itr = pools_.find(creator.id()); if (itr != pools_.end()) @@ -137,9 +130,6 @@ public: boost::shared_ptr getPool(std::string const& key) { -#ifdef MAPNIK_THREADSAFE - //mutex::scoped_lock lock(mutex_); -#endif ContType::const_iterator itr=pools_.find(key); if (itr!=pools_.end()) { @@ -149,19 +139,6 @@ public: return emptyPool; } - HolderType get(std::string const& key) - { -#ifdef MAPNIK_THREADSAFE - //mutex::scoped_lock lock(mutex_); -#endif - ContType::const_iterator itr=pools_.find(key); - if (itr!=pools_.end()) - { - boost::shared_ptr pool=itr->second; - return pool->borrowObject(); - } - return HolderType(); - } ConnectionManager() {} private: ConnectionManager(const ConnectionManager&); From 0548d6037b921d27235cea8d2a66a67d4b4c1804 Mon Sep 17 00:00:00 2001 From: Dane Springmeyer Date: Wed, 28 Nov 2012 18:20:34 -0800 Subject: [PATCH 05/15] fix postgres null connection error adding space for better formatting --- plugins/input/postgis/postgis_datasource.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/input/postgis/postgis_datasource.cpp b/plugins/input/postgis/postgis_datasource.cpp index 26017f532..45a711715 100644 --- a/plugins/input/postgis/postgis_datasource.cpp +++ b/plugins/input/postgis/postgis_datasource.cpp @@ -711,7 +711,7 @@ featureset_ptr postgis_datasource::features(const query& q) const } else { - err_msg += "Null connection"; + err_msg += " Null connection"; } throw mapnik::datasource_exception(err_msg); } From a2d82af5c174f1a1a05750e894307e4f35d805b7 Mon Sep 17 00:00:00 2001 From: Dane Springmeyer Date: Wed, 28 Nov 2012 19:15:29 -0800 Subject: [PATCH 06/15] add postgis threaded stress test (though queries still runs serially) --- tests/python_tests/postgis_test.py | 32 +++++++++++++++++++++++++++++- 1 file changed, 31 insertions(+), 1 deletion(-) diff --git a/tests/python_tests/postgis_test.py b/tests/python_tests/postgis_test.py index c5f5dd629..c0bd56b54 100644 --- a/tests/python_tests/postgis_test.py +++ b/tests/python_tests/postgis_test.py @@ -6,6 +6,9 @@ import time from utilities import execution_path from subprocess import Popen, PIPE import os, mapnik +from Queue import Queue +import threading + MAPNIK_TEST_DBNAME = 'mapnik-tmp-postgis-test-db' POSTGIS_TEMPLATE_DBNAME = 'template_postgis' @@ -443,9 +446,36 @@ if 'postgis' in mapnik.DatasourceCache.plugin_names() \ fs = ds.featureset() eq_(fs.next()['gid'],1) + def create_ds(): + ds = mapnik.PostGIS(dbname=MAPNIK_TEST_DBNAME, + table='test', + max_size=20) + fs = ds.all_features() + + def test_threaded_create(NUM_THREADS=100): + for i in range(NUM_THREADS): + t = threading.Thread(target=create_ds) + t.start() + t.join() + + def create_ds_and_error(): + try: + ds = mapnik.PostGIS(dbname=MAPNIK_TEST_DBNAME, + table='asdfasdfasdfasdfasdf', + max_size=20) + fs = ds.all_features() + except: pass + + def test_threaded_create2(NUM_THREADS=10): + for i in range(NUM_THREADS): + t = threading.Thread(target=create_ds_and_error) + t.start() + t.join() + + + atexit.register(postgis_takedown) if __name__ == "__main__": setup() - #test_auto_detection_and_subquery() [eval(run)() for run in dir() if 'test_' in run] From f2276d97a021538e370b2885999b02c411bb5215 Mon Sep 17 00:00:00 2001 From: Dane Springmeyer Date: Wed, 28 Nov 2012 19:22:10 -0800 Subject: [PATCH 07/15] modify agg conv classes to support type() member - closes #1607 refs #1604 --- deps/agg/include/agg_conv_adaptor_vcgen.h | 2 ++ deps/agg/include/agg_conv_adaptor_vpgen.h | 1 + deps/agg/include/agg_conv_clip_polygon.h | 1 + deps/agg/include/agg_conv_clip_polyline.h | 1 + deps/agg/include/agg_conv_smooth_poly1.h | 2 ++ 5 files changed, 7 insertions(+) diff --git a/deps/agg/include/agg_conv_adaptor_vcgen.h b/deps/agg/include/agg_conv_adaptor_vcgen.h index a79f2208c..ddbcef738 100644 --- a/deps/agg/include/agg_conv_adaptor_vcgen.h +++ b/deps/agg/include/agg_conv_adaptor_vcgen.h @@ -29,6 +29,7 @@ namespace agg void rewind(unsigned) {} unsigned vertex(double*, double*) { return path_cmd_stop; } + unsigned type() const { return 0; } }; @@ -64,6 +65,7 @@ namespace agg } unsigned vertex(double* x, double* y); + unsigned type() const { return m_source->type(); } private: // Prohibit copying diff --git a/deps/agg/include/agg_conv_adaptor_vpgen.h b/deps/agg/include/agg_conv_adaptor_vpgen.h index d6b545ef1..ae8d59320 100644 --- a/deps/agg/include/agg_conv_adaptor_vpgen.h +++ b/deps/agg/include/agg_conv_adaptor_vpgen.h @@ -33,6 +33,7 @@ namespace agg void rewind(unsigned path_id); unsigned vertex(double* x, double* y); + unsigned type() const { return m_source->type(); } private: conv_adaptor_vpgen(const conv_adaptor_vpgen&); diff --git a/deps/agg/include/agg_conv_clip_polygon.h b/deps/agg/include/agg_conv_clip_polygon.h index 87537638d..79aceedf3 100644 --- a/deps/agg/include/agg_conv_clip_polygon.h +++ b/deps/agg/include/agg_conv_clip_polygon.h @@ -51,6 +51,7 @@ namespace agg double y1() const { return base_type::vpgen().y1(); } double x2() const { return base_type::vpgen().x2(); } double y2() const { return base_type::vpgen().y2(); } + unsigned type() const { return base_type::type(); } private: conv_clip_polygon(const conv_clip_polygon&); diff --git a/deps/agg/include/agg_conv_clip_polyline.h b/deps/agg/include/agg_conv_clip_polyline.h index f3fc2888c..8bad5964f 100644 --- a/deps/agg/include/agg_conv_clip_polyline.h +++ b/deps/agg/include/agg_conv_clip_polyline.h @@ -51,6 +51,7 @@ namespace agg double y1() const { return base_type::vpgen().y1(); } double x2() const { return base_type::vpgen().x2(); } double y2() const { return base_type::vpgen().y2(); } + unsigned type() const { return base_type::type(); } private: conv_clip_polyline(const conv_clip_polyline&); diff --git a/deps/agg/include/agg_conv_smooth_poly1.h b/deps/agg/include/agg_conv_smooth_poly1.h index 4ac4e3d6e..00ab6b6af 100644 --- a/deps/agg/include/agg_conv_smooth_poly1.h +++ b/deps/agg/include/agg_conv_smooth_poly1.h @@ -42,6 +42,7 @@ namespace agg void smooth_value(double v) { base_type::generator().smooth_value(v); } double smooth_value() const { return base_type::generator().smooth_value(); } + unsigned type() const { return base_type::type(); } private: conv_smooth_poly1(const conv_smooth_poly1&); @@ -64,6 +65,7 @@ namespace agg void smooth_value(double v) { m_smooth.generator().smooth_value(v); } double smooth_value() const { return m_smooth.generator().smooth_value(); } + unsigned type() const { return m_smooth.type(); } private: conv_smooth_poly1_curve(const conv_smooth_poly1_curve&); From 629d768eae5a2feb2e4c3ef9ac84c647239bd8ee Mon Sep 17 00:00:00 2001 From: Dane Springmeyer Date: Wed, 28 Nov 2012 19:23:56 -0800 Subject: [PATCH 08/15] use middle_point placement algorithm for marker POINT placement on lines - closes #1604 - refs #1350 and refs #1607 --- include/mapnik/marker_helpers.hpp | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/include/mapnik/marker_helpers.hpp b/include/mapnik/marker_helpers.hpp index fd1a923d8..594617702 100644 --- a/include/mapnik/marker_helpers.hpp +++ b/include/mapnik/marker_helpers.hpp @@ -91,7 +91,12 @@ struct vector_markers_rasterizer_dispatch { double x = 0; double y = 0; - if (placement_method == MARKER_INTERIOR_PLACEMENT) + if (path.type() == LineString) + { + if (!label::middle_point(path, x, y)) + return; + } + else if (placement_method == MARKER_INTERIOR_PLACEMENT) { if (!label::interior_position(path, x, y)) return; @@ -187,7 +192,12 @@ struct raster_markers_rasterizer_dispatch { double x = 0; double y = 0; - if (placement_method == MARKER_INTERIOR_PLACEMENT) + if (path.type() == LineString) + { + if (!label::middle_point(path, x, y)) + return; + } + else if (placement_method == MARKER_INTERIOR_PLACEMENT) { if (!label::interior_position(path, x, y)) return; From 5f900206d1b6467ac7183ef17568c5efd2045891 Mon Sep 17 00:00:00 2001 From: Dane Springmeyer Date: Wed, 28 Nov 2012 19:33:09 -0800 Subject: [PATCH 09/15] formatting --- src/symbolizer.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/symbolizer.cpp b/src/symbolizer.cpp index 2a876b4e8..5144d139a 100644 --- a/src/symbolizer.cpp +++ b/src/symbolizer.cpp @@ -89,9 +89,13 @@ transform_type const& symbolizer_base::get_transform() const std::string symbolizer_base::get_transform_string() const { if (affine_transform_) + { return transform_processor_type::to_string(*affine_transform_); + } else + { return std::string(); + } } void symbolizer_base::set_clip(bool clip) @@ -189,9 +193,13 @@ transform_type const& symbolizer_with_image::get_image_transform() const std::string symbolizer_with_image::get_image_transform_string() const { if (image_transform_) + { return transform_processor_type::to_string(*image_transform_); + } else + { return std::string(); + } } } // end of namespace mapnik From 8bfc33001517bcf06798a361358721b7a979382e Mon Sep 17 00:00:00 2001 From: Dane Springmeyer Date: Wed, 28 Nov 2012 20:19:11 -0800 Subject: [PATCH 10/15] postgis: do not fatally throw if metadata queries fail - closes #1609 and closes #1565 --- plugins/input/postgis/postgis_datasource.cpp | 146 ++++++++++--------- 1 file changed, 76 insertions(+), 70 deletions(-) diff --git a/plugins/input/postgis/postgis_datasource.cpp b/plugins/input/postgis/postgis_datasource.cpp index 45a711715..30719541b 100644 --- a/plugins/input/postgis/postgis_datasource.cpp +++ b/plugins/input/postgis/postgis_datasource.cpp @@ -160,46 +160,49 @@ void postgis_datasource::bind() const #ifdef MAPNIK_STATS mapnik::progress_timer __stats2__(std::clog, "postgis_datasource::bind(get_srid_and_geometry_column)"); #endif - std::ostringstream s; - s << "SELECT f_geometry_column, srid FROM " - << GEOMETRY_COLUMNS <<" WHERE f_table_name='" - << mapnik::sql_utils::unquote_double(geometry_table_) - << "'"; - if (! schema_.empty()) + try { - s << " AND f_table_schema='" - << mapnik::sql_utils::unquote_double(schema_) + s << "SELECT f_geometry_column, srid FROM " + << GEOMETRY_COLUMNS <<" WHERE f_table_name='" + << mapnik::sql_utils::unquote_double(geometry_table_) << "'"; - } - - 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()) - { - geometryColumn_ = rs->getValue("f_geometry_column"); - - if (srid_ == 0) + if (! schema_.empty()) { - const char* srid_c = rs->getValue("srid"); - if (srid_c != NULL) + s << " AND f_table_schema='" + << mapnik::sql_utils::unquote_double(schema_) + << "'"; + } + 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()) + { + geometryColumn_ = rs->getValue("f_geometry_column"); + if (srid_ == 0) { - int result = 0; - if (mapnik::util::string2int(srid_c, result)) + const char* srid_c = rs->getValue("srid"); + if (srid_c != NULL) { - srid_ = result; + int result = 0; + if (mapnik::util::string2int(srid_c, result)) + { + srid_ = result; + } } } } + rs->close(); + } + catch (mapnik::datasource_exception const& ex) { + // let this pass on query error and use the fallback below + MAPNIK_LOG_WARN(postgis) << "postgis_datasource: metadata query failed: " << ex.what(); } - rs->close(); // 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 @@ -929,50 +932,53 @@ boost::optional postgis_datasource::get_geometry std::ostringstream s; std::string g_type; - - s << "SELECT lower(type) as type FROM " - << GEOMETRY_COLUMNS <<" WHERE f_table_name='" - << mapnik::sql_utils::unquote_double(geometry_table_) - << "'"; - - if (! schema_.empty()) + try { - s << " AND f_table_schema='" - << mapnik::sql_utils::unquote_double(schema_) + s << "SELECT lower(type) as type FROM " + << GEOMETRY_COLUMNS <<" WHERE f_table_name='" + << mapnik::sql_utils::unquote_double(geometry_table_) << "'"; + if (! schema_.empty()) + { + s << " AND f_table_schema='" + << mapnik::sql_utils::unquote_double(schema_) + << "'"; + } + 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")) + { + result.reset(mapnik::datasource::LineString); + return result; + } + else if (boost::algorithm::contains(g_type, "point")) + { + result.reset(mapnik::datasource::Point); + return result; + } + else if (boost::algorithm::contains(g_type, "polygon")) + { + result.reset(mapnik::datasource::Polygon); + return result; + } + else // geometry + { + result.reset(mapnik::datasource::Collection); + return result; + } + } } - - 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")) - { - result.reset(mapnik::datasource::LineString); - return result; - } - else if (boost::algorithm::contains(g_type, "point")) - { - result.reset(mapnik::datasource::Point); - return result; - } - else if (boost::algorithm::contains(g_type, "polygon")) - { - result.reset(mapnik::datasource::Polygon); - return result; - } - else // geometry - { - result.reset(mapnik::datasource::Collection); - return result; - } + catch (mapnik::datasource_exception const& ex) { + // let this pass on query error and use the fallback below + MAPNIK_LOG_WARN(postgis) << "postgis_datasource: metadata query failed: " << ex.what(); } // fallback to querying first several features From 57aa6dd05230876bf7c022d3554436e4d35de77f Mon Sep 17 00:00:00 2001 From: Dane Springmeyer Date: Wed, 28 Nov 2012 20:21:22 -0800 Subject: [PATCH 11/15] add serialization of line_symbolizer offset - closes #1562 --- src/save_map.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/save_map.cpp b/src/save_map.cpp index 5b330b5e7..95fbac3a3 100644 --- a/src/save_map.cpp +++ b/src/save_map.cpp @@ -98,6 +98,10 @@ public: { set_attr( sym_node, "rasterizer", sym.get_rasterizer() ); } + if ( sym.get_offset() != dfl.get_offset() || explicit_defaults_ ) + { + set_attr( sym_node, "offset", sym.get_offset() ); + } serialize_symbolizer_base(sym_node, sym); } From 65c995ce0eccee9eac9218b6553b6640bd3c0409 Mon Sep 17 00:00:00 2001 From: Dane Springmeyer Date: Wed, 28 Nov 2012 20:24:20 -0800 Subject: [PATCH 12/15] add #1562 to master changelog --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8e5335396..f0d6bfd47 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,8 @@ For a complete change history, see the git log. ## Future +- Added serialization of `line-offset` to save_map (#1562) + - Enabled default input plugin directory and fonts path to be set inherited from environment settings in python bindings to make it easier to run tests locally (#1594). New environment settings are: - MAPNIK_INPUT_PLUGINS_DIRECTORY From 53922be94e00acb1da1bf676335fca6536f25ad1 Mon Sep 17 00:00:00 2001 From: Dane Springmeyer Date: Wed, 28 Nov 2012 20:54:39 -0800 Subject: [PATCH 13/15] fix method name - refs #1562 --- src/save_map.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/save_map.cpp b/src/save_map.cpp index 95fbac3a3..6e22beab0 100644 --- a/src/save_map.cpp +++ b/src/save_map.cpp @@ -98,9 +98,9 @@ public: { set_attr( sym_node, "rasterizer", sym.get_rasterizer() ); } - if ( sym.get_offset() != dfl.get_offset() || explicit_defaults_ ) + if ( sym.offset() != dfl.offset() || explicit_defaults_ ) { - set_attr( sym_node, "offset", sym.get_offset() ); + set_attr( sym_node, "offset", sym.offset() ); } serialize_symbolizer_base(sym_node, sym); } From 52c3f8ff6ee4dcdae6777152e2a797fb2bfa3489 Mon Sep 17 00:00:00 2001 From: Dane Springmeyer Date: Wed, 28 Nov 2012 20:56:08 -0800 Subject: [PATCH 14/15] disable bbox intersection testing when caching features on the fly during rendering - closes #1543 --- .../mapnik/feature_style_processor_impl.hpp | 4 +-- include/mapnik/memory_datasource.hpp | 3 +- include/mapnik/memory_featureset.hpp | 32 +++++++++++++------ src/memory_datasource.cpp | 7 ++-- 4 files changed, 31 insertions(+), 15 deletions(-) diff --git a/include/mapnik/feature_style_processor_impl.hpp b/include/mapnik/feature_style_processor_impl.hpp index 48a4e545e..ec7d98f76 100644 --- a/include/mapnik/feature_style_processor_impl.hpp +++ b/include/mapnik/feature_style_processor_impl.hpp @@ -427,7 +427,7 @@ void feature_style_processor::apply_to_layer(layer const& lay, Proces featureset_ptr features = ds->features(q); if (features) { // Cache all features into the memory_datasource before rendering. - memory_datasource cache; + memory_datasource cache(ds->type(),false); feature_ptr feature, prev; while ((feature = features->next())) @@ -458,7 +458,7 @@ void feature_style_processor::apply_to_layer(layer const& lay, Proces } else if (cache_features) { - memory_datasource cache(ds->type()); + memory_datasource cache(ds->type(),false); featureset_ptr features = ds->features(q); if (features) { // Cache all features into the memory_datasource before rendering. diff --git a/include/mapnik/memory_datasource.hpp b/include/mapnik/memory_datasource.hpp index ef30d5f3d..8ebb8f281 100644 --- a/include/mapnik/memory_datasource.hpp +++ b/include/mapnik/memory_datasource.hpp @@ -36,7 +36,7 @@ class MAPNIK_DECL memory_datasource : public datasource { friend class memory_featureset; public: - memory_datasource(datasource::datasource_t type=datasource::Vector); + memory_datasource(datasource::datasource_t type=datasource::Vector, bool bbox_check=true); virtual ~memory_datasource(); void push(feature_ptr feature); datasource::datasource_t type() const; @@ -51,6 +51,7 @@ private: std::vector features_; mapnik::layer_descriptor desc_; datasource::datasource_t type_; + bool bbox_check_; }; } diff --git a/include/mapnik/memory_featureset.hpp b/include/mapnik/memory_featureset.hpp index 5bf5c452e..b84ec387b 100644 --- a/include/mapnik/memory_featureset.hpp +++ b/include/mapnik/memory_featureset.hpp @@ -34,18 +34,20 @@ namespace mapnik { class memory_featureset : public Featureset { public: - memory_featureset(box2d const& bbox, memory_datasource const& ds) + memory_featureset(box2d const& bbox, memory_datasource const& ds, bool bbox_check = true) : bbox_(bbox), pos_(ds.features_.begin()), end_(ds.features_.end()), - type_(ds.type()) + type_(ds.type()), + bbox_check_(bbox_check) {} - memory_featureset(box2d const& bbox, std::vector const& features) + memory_featureset(box2d const& bbox, std::vector const& features, bool bbox_check = true) : bbox_(bbox), pos_(features.begin()), end_(features.end()), - type_(datasource::Vector) + type_(datasource::Vector), + bbox_check_(bbox_check) {} virtual ~memory_featureset() {} @@ -54,22 +56,33 @@ public: { while (pos_ != end_) { - if (type_ == datasource::Raster) + if (bbox_check_) { return *pos_++; } else { - for (unsigned i=0; i<(*pos_)->num_geometries();++i) + if (type_ == datasource::Raster) { - geometry_type & geom = (*pos_)->get_geometry(i); - if (bbox_.intersects(geom.envelope())) + raster_ptr const& source = (*pos_)->get_raster(); + if (source && bbox_.intersects(source->ext_)) { return *pos_++; } } + else + { + for (unsigned i=0; i<(*pos_)->num_geometries();++i) + { + geometry_type & geom = (*pos_)->get_geometry(i); + if (bbox_.intersects(geom.envelope())) + { + return *pos_++; + } + } + } + ++pos_; } - ++pos_; } return feature_ptr(); } @@ -79,6 +92,7 @@ private: std::vector::const_iterator pos_; std::vector::const_iterator end_; datasource::datasource_t type_; + bool bbox_check_; }; } diff --git a/src/memory_datasource.cpp b/src/memory_datasource.cpp index 66cf83d46..b622729a2 100644 --- a/src/memory_datasource.cpp +++ b/src/memory_datasource.cpp @@ -62,10 +62,11 @@ struct accumulate_extent bool first_; }; -memory_datasource::memory_datasource(datasource::datasource_t type) +memory_datasource::memory_datasource(datasource::datasource_t type, bool bbox_check) : datasource(parameters()), desc_("in-memory datasource","utf-8"), - type_(type) {} + type_(type), + bbox_check_(bbox_check) {} memory_datasource::~memory_datasource() {} @@ -83,7 +84,7 @@ datasource::datasource_t memory_datasource::type() const featureset_ptr memory_datasource::features(const query& q) const { - return boost::make_shared(q.get_bbox(),*this); + return boost::make_shared(q.get_bbox(),*this,bbox_check_); } From 363fc2ddd0d0e7b98602a0baf6c62d1c028ed2ee Mon Sep 17 00:00:00 2001 From: Dane Springmeyer Date: Wed, 28 Nov 2012 21:18:17 -0800 Subject: [PATCH 15/15] fix logic error --- include/mapnik/memory_featureset.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/mapnik/memory_featureset.hpp b/include/mapnik/memory_featureset.hpp index b84ec387b..f52a9e514 100644 --- a/include/mapnik/memory_featureset.hpp +++ b/include/mapnik/memory_featureset.hpp @@ -56,7 +56,7 @@ public: { while (pos_ != end_) { - if (bbox_check_) + if (!bbox_check_) { return *pos_++; }