From 9e87c9f91467e596db9191a95239d87cb754ddf5 Mon Sep 17 00:00:00 2001 From: Dane Springmeyer Date: Tue, 30 Aug 2011 17:38:27 +0000 Subject: [PATCH] =?UTF-8?q?apply=20patch=20from=20Peter=20K=C3=B6rner=20ad?= =?UTF-8?q?ding=20AlsoFilter=20functionality=20-=20closes=20#820?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- AUTHORS | 3 ++- CHANGELOG | 2 ++ bindings/python/mapnik_rule.cpp | 11 ++++++++-- include/mapnik/feature_style_processor.hpp | 25 ++++++++++++++++++++++ include/mapnik/rule.hpp | 21 +++++++++++++++--- src/load_map.cpp | 8 +++++++ src/save_map.cpp | 5 +++++ tests/python_tests/object_test.py | 22 +++++++++++++++++++ 8 files changed, 91 insertions(+), 6 deletions(-) diff --git a/AUTHORS b/AUTHORS index 5b1a4638b..3dd813cb9 100644 --- a/AUTHORS +++ b/AUTHORS @@ -39,6 +39,7 @@ Patches - Aubrey Holland - Konstantin Käfer - Mak Kolybabi + - Peter Körner - Stella Laurenzo - Dennis Luxen - Tom MacWright @@ -67,4 +68,4 @@ Patches Community Wiki ============== - - http://trac.mapnik.org/stractistics \ No newline at end of file + - http://trac.mapnik.org/stractistics diff --git a/CHANGELOG b/CHANGELOG index 4ba14c540..e663998be 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -14,6 +14,8 @@ For a complete change history, see the SVN log. Mapnik Trunk ------------ +- Add AlsoFilter functionality - http://trac.mapnik.org/wiki/AlsoFilter + - SQLite Plugin: optimize io using shared cache and no mutexes (#797) - Directly link input plugins to libmapnik to avoid having to set dlopen flags from binding languages (#790) diff --git a/bindings/python/mapnik_rule.cpp b/bindings/python/mapnik_rule.cpp index bdbc713c2..67912f1c3 100644 --- a/bindings/python/mapnik_rule.cpp +++ b/bindings/python/mapnik_rule.cpp @@ -102,7 +102,7 @@ struct rule_pickle_suite : boost::python::pickle_suite // We serialize filter expressions AST as strings std::string filter_expr = to_expression_string(*r.get_filter()); - return boost::python::make_tuple(r.get_abstract(),filter_expr,r.has_else_filter(),syms); + return boost::python::make_tuple(r.get_abstract(),filter_expr,r.has_else_filter(),r.has_also_filter(),syms); } static void @@ -138,8 +138,13 @@ struct rule_pickle_suite : boost::python::pickle_suite { r.set_else(true); } + + if (state[3]) + { + r.set_also(true); + } - boost::python::list syms=extract(state[3]); + boost::python::list syms=extract(state[4]); extract_symbolizer serializer( r ); for (int i=0;i())) diff --git a/include/mapnik/feature_style_processor.hpp b/include/mapnik/feature_style_processor.hpp index d7d3e9fb6..6cc311cc5 100644 --- a/include/mapnik/feature_style_processor.hpp +++ b/include/mapnik/feature_style_processor.hpp @@ -310,6 +310,7 @@ private: { std::vector if_rules; std::vector else_rules; + std::vector also_rules; std::vector const& rules=style->get_rules(); @@ -321,6 +322,10 @@ private: { else_rules.push_back(const_cast(&r)); } + else if (r.has_also_filter()) + { + also_rules.push_back(const_cast(&r)); + } else { if_rules.push_back(const_cast(&r)); @@ -362,6 +367,7 @@ private: while ((feature = fs->next())) { bool do_else=true; + bool do_also=false; if (cache_features) { @@ -375,6 +381,7 @@ private: if (result.to_bool()) { do_else=false; + do_also=true; rule::symbolizers const& symbols = r->get_symbolizers(); // if the underlying renderer is not able to process the complete set of symbolizers, @@ -405,6 +412,24 @@ private: // process one by one. #ifdef SVG_RENDERER if(!p.process(symbols,*feature,prj_trans)) +#endif + { + BOOST_FOREACH (symbolizer const& sym, symbols) + { + boost::apply_visitor(symbol_dispatch(p,*feature,prj_trans),sym); + } + } + } + } + if (do_also) + { + BOOST_FOREACH( rule * r, also_rules ) + { + rule::symbolizers const& symbols = r->get_symbolizers(); + // if the underlying renderer is not able to process the complete set of symbolizers, + // process one by one. +#ifdef SVG_RENDERER + if(!p.process(symbols,*feature,prj_trans)) #endif { BOOST_FOREACH (symbolizer const& sym, symbols) diff --git a/include/mapnik/rule.hpp b/include/mapnik/rule.hpp index 6632ed820..a5f111a4d 100644 --- a/include/mapnik/rule.hpp +++ b/include/mapnik/rule.hpp @@ -138,6 +138,7 @@ private: symbolizers syms_; expression_ptr filter_; bool else_filter_; + bool also_filter_; public: rule() : name_(), @@ -147,7 +148,8 @@ public: max_scale_(std::numeric_limits::infinity()), syms_(), filter_(boost::make_shared(true)), - else_filter_(false) {} + else_filter_(false), + also_filter_(false) {} rule(const std::string& name, const std::string& title="", @@ -159,7 +161,8 @@ public: max_scale_(max_scale_denominator), syms_(), filter_(boost::make_shared(true)), - else_filter_(false) {} + else_filter_(false), + also_filter_(false) {} rule(const rule& rhs) : name_(rhs.name_), @@ -169,7 +172,8 @@ public: max_scale_(rhs.max_scale_), syms_(rhs.syms_), filter_(rhs.filter_), - else_filter_(rhs.else_filter_) {} + else_filter_(rhs.else_filter_), + also_filter_(rhs.also_filter_) {} rule& operator=(rule const& rhs) { @@ -290,6 +294,16 @@ public: return else_filter_; } + void set_also(bool also_filter) + { + also_filter_=also_filter; + } + + bool has_also_filter() const + { + return also_filter_; + } + bool active(double scale) const { return ( scale >= min_scale_ - 1e-6 && scale < max_scale_ + 1e-6); @@ -307,6 +321,7 @@ private: syms_=rhs.syms_; filter_=rhs.filter_; else_filter_=rhs.else_filter_; + also_filter_=rhs.also_filter_; } }; diff --git a/src/load_map.cpp b/src/load_map.cpp index 873c95faf..3b67dee7a 100644 --- a/src/load_map.cpp +++ b/src/load_map.cpp @@ -733,6 +733,13 @@ void map_parser::parse_rule( feature_type_style & style, ptree const & r ) rule.set_else(true); } + optional also_filter = + get_opt_child(r, "AlsoFilter"); + if (also_filter) + { + rule.set_also(true); + } + optional min_scale = get_opt_child(r, "MinScaleDenominator"); if (min_scale) @@ -803,6 +810,7 @@ void map_parser::parse_rule( feature_type_style & style, ptree const & r ) sym.first != "MaxScaleDenominator" && sym.first != "Filter" && sym.first != "ElseFilter" && + sym.first != "AlsoFilter" && sym.first != "" && sym.first != "" ) { diff --git a/src/save_map.cpp b/src/save_map.cpp index 0534fd2a0..17d2cfd05 100644 --- a/src/save_map.cpp +++ b/src/save_map.cpp @@ -639,6 +639,11 @@ void serialize_rule( ptree & style_node, const rule & r, bool explicit_defaults) rule_node.push_back( ptree::value_type( "ElseFilter", ptree())); } + else if ( r.has_also_filter() ) + { + rule_node.push_back( ptree::value_type( + "AlsoFilter", ptree())); + } else { // filters were not comparable, perhaps should now compare expressions? diff --git a/tests/python_tests/object_test.py b/tests/python_tests/object_test.py index 4c1c29236..7bf95ba54 100644 --- a/tests/python_tests/object_test.py +++ b/tests/python_tests/object_test.py @@ -539,6 +539,20 @@ def test_rule_init(): eq_(r.title, '') eq_(r.min_scale, 0) eq_(r.max_scale, float('inf')) + eq_(r.has_else(), False) + eq_(r.has_also(), False) + + r = mapnik2.Rule() + + r.set_else(True) + eq_(r.has_else(), True) + eq_(r.has_also(), False) + + r = mapnik2.Rule() + + r.set_also(True) + eq_(r.has_else(), False) + eq_(r.has_also(), True) r = mapnik2.Rule("Name") @@ -546,6 +560,8 @@ def test_rule_init(): eq_(r.title, '') eq_(r.min_scale, 0) eq_(r.max_scale, float('inf')) + eq_(r.has_else(), False) + eq_(r.has_also(), False) r = mapnik2.Rule("Name", "Title") @@ -553,6 +569,8 @@ def test_rule_init(): eq_(r.title, 'Title') eq_(r.min_scale, 0) eq_(r.max_scale, float('inf')) + eq_(r.has_else(), False) + eq_(r.has_also(), False) r = mapnik2.Rule("Name", "Title", min_scale) @@ -560,6 +578,8 @@ def test_rule_init(): eq_(r.title, 'Title') eq_(r.min_scale, min_scale) eq_(r.max_scale, float('inf')) + eq_(r.has_else(), False) + eq_(r.has_also(), False) r = mapnik2.Rule("Name", "Title", min_scale, max_scale) @@ -567,6 +587,8 @@ def test_rule_init(): eq_(r.title, 'Title') eq_(r.min_scale, min_scale) eq_(r.max_scale, max_scale) + eq_(r.has_else(), False) + eq_(r.has_also(), False) # Coordinate initialization def test_coord_init():