enable if/else type behavior in rules using style level keyword to control whether all rules will be evaluated or just the first that matches - closes #706 - thanks to original patch from kkaefer

This commit is contained in:
Dane Springmeyer 2011-02-01 22:55:50 +00:00
parent 1a2e1a7789
commit 7043c416fa
11 changed files with 138 additions and 22 deletions

View file

@ -37,6 +37,7 @@ Patches
- Beau Gunderson - Beau Gunderson
- John Hague - John Hague
- Aubrey Holland - Aubrey Holland
- Konstantin Käfer
- Mak Kolybabi - Mak Kolybabi
- Dennis Luxen - Dennis Luxen
- Tom MacWright - Tom MacWright

View file

@ -14,6 +14,8 @@ For a complete change history, see the SVN log.
Mapnik Trunk Mapnik Trunk
------------ ------------
- Added support for drawing only first matching rule using filter-mode="first" in Style (#706)
- Added support to PointSymbolizer ('ignore_placement') for skipping adding placed points to collision detector (#564) - Added support to PointSymbolizer ('ignore_placement') for skipping adding placed points to collision detector (#564)
- Added ability to register fonts within XML using Map level 'font_directory' parameter (#168) - Added ability to register fonts within XML using Map level 'font_directory' parameter (#168)

View file

@ -732,6 +732,7 @@ __all__ = [
'horizontal_alignment', 'horizontal_alignment',
'justify_alignment', 'justify_alignment',
'pattern_alignment', 'pattern_alignment',
'filter_mode',
# functions # functions
# datasources # datasources
'Datasource', 'Datasource',

View file

@ -24,6 +24,7 @@
#include <boost/python.hpp> #include <boost/python.hpp>
#include <boost/python/suite/indexing/vector_indexing_suite.hpp> #include <boost/python/suite/indexing/vector_indexing_suite.hpp>
#include "mapnik_enumeration.hpp"
#include <mapnik/feature_type_style.hpp> #include <mapnik/feature_type_style.hpp>
using mapnik::feature_type_style; using mapnik::feature_type_style;
@ -73,6 +74,11 @@ void export_style()
{ {
using namespace boost::python; using namespace boost::python;
mapnik::enumeration_<mapnik::filter_mode_e>("filter_mode")
.value("ALL",mapnik::FILTER_ALL)
.value("FIRST",mapnik::FILTER_FIRST)
;
class_<rules>("Rules",init<>("default ctor")) class_<rules>("Rules",init<>("default ctor"))
.def(vector_indexing_suite<rules>()) .def(vector_indexing_suite<rules>())
; ;
@ -92,6 +98,10 @@ void export_style()
"<mapnik2._mapnik2.Rule object at 0x100549910>\n" "<mapnik2._mapnik2.Rule object at 0x100549910>\n"
"<mapnik2._mapnik2.Rule object at 0x100549980>\n" "<mapnik2._mapnik2.Rule object at 0x100549980>\n"
) )
.add_property("filter_mode",
&feature_type_style::get_filter_mode,
&feature_type_style::set_filter_mode,
"Set/get the placement of the label")
; ;
} }

View file

@ -323,6 +323,11 @@ private:
boost::apply_visitor(symbol_dispatch(p,*feature,prj_trans),sym); boost::apply_visitor(symbol_dispatch(p,*feature,prj_trans),sym);
} }
} }
if (style->get_filter_mode() == FILTER_FIRST)
{
// Stop iterating over rules and proceed with next feature.
break;
}
} }
} }
if (do_else) if (do_else)

View file

@ -27,43 +27,43 @@
// mapnik // mapnik
#include <mapnik/rule.hpp> #include <mapnik/rule.hpp>
#include <mapnik/feature.hpp> #include <mapnik/feature.hpp>
#include <mapnik/enumeration.hpp>
// stl // stl
#include <vector> #include <vector>
namespace mapnik namespace mapnik
{ {
enum filter_mode_enum {
FILTER_ALL,
FILTER_FIRST,
filter_mode_enum_MAX
};
DEFINE_ENUM( filter_mode_e, filter_mode_enum );
typedef std::vector<rule> rules; typedef std::vector<rule> rules;
class feature_type_style class feature_type_style
{ {
private: private:
rules rules_; rules rules_;
filter_mode_e filter_mode_;
public: public:
feature_type_style() {} feature_type_style();
feature_type_style(feature_type_style const& rhs) feature_type_style(feature_type_style const& rhs);
: rules_(rhs.rules_) {}
feature_type_style& operator=(feature_type_style const& rhs) feature_type_style& operator=(feature_type_style const& rhs);
{
if (this == &rhs) return *this;
rules_=rhs.rules_;
return *this;
}
void add_rule(rule const& rule) void add_rule(rule const& rule);
{
rules_.push_back(rule);
}
rules const& get_rules() const rules const& get_rules() const;
{
return rules_;
}
rules &get_rules_nonconst() rules &get_rules_nonconst();
{
return rules_; void set_filter_mode(filter_mode_e mode);
}
filter_mode_e get_filter_mode() const;
~feature_type_style() {} ~feature_type_style() {}
}; };

View file

@ -102,6 +102,7 @@ source = Split(
expression_node.cpp expression_node.cpp
expression_string.cpp expression_string.cpp
filter_factory.cpp filter_factory.cpp
feature_type_style.cpp
font_engine_freetype.cpp font_engine_freetype.cpp
font_set.cpp font_set.cpp
gradient.cpp gradient.cpp

View file

@ -0,0 +1,76 @@
/*****************************************************************************
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2010 Artem Pavlenko
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*****************************************************************************/
#include <mapnik/feature_type_style.hpp>
namespace mapnik
{
static const char * filter_mode_strings[] = {
"all",
"first",
""
};
IMPLEMENT_ENUM( filter_mode_e, filter_mode_strings );
feature_type_style::feature_type_style()
: filter_mode_(FILTER_ALL) {}
feature_type_style::feature_type_style(feature_type_style const& rhs)
: rules_(rhs.rules_),
filter_mode_(rhs.filter_mode_) {}
feature_type_style& feature_type_style::operator=(feature_type_style const& rhs)
{
if (this == &rhs) return *this;
rules_=rhs.rules_;
return *this;
}
void feature_type_style::add_rule(rule const& rule)
{
rules_.push_back(rule);
}
rules const& feature_type_style::get_rules() const
{
return rules_;
}
rules &feature_type_style::get_rules_nonconst()
{
return rules_;
}
void feature_type_style::set_filter_mode(filter_mode_e mode)
{
filter_mode_ = mode;
}
filter_mode_e feature_type_style::get_filter_mode() const
{
return filter_mode_;
}
}

View file

@ -347,6 +347,9 @@ void map_parser::parse_style( Map & map, ptree const & sty )
name = get_attr<string>(sty, "name"); name = get_attr<string>(sty, "name");
feature_type_style style; feature_type_style style;
filter_mode_e filter_mode = get_attr<filter_mode_e>(sty, "filter-mode", FILTER_ALL);
style.set_filter_mode(filter_mode);
ptree::const_iterator ruleIter = sty.begin(); ptree::const_iterator ruleIter = sty.begin();
ptree::const_iterator endRule = sty.end(); ptree::const_iterator endRule = sty.end();

View file

@ -632,12 +632,19 @@ void serialize_style( ptree & map_node, Map::const_style_iterator style_it, bool
{ {
const feature_type_style & style = style_it->second; const feature_type_style & style = style_it->second;
const std::string & name = style_it->first; const std::string & name = style_it->first;
filter_mode_e filter_mode = style.get_filter_mode();
ptree & style_node = map_node.push_back( ptree & style_node = map_node.push_back(
ptree::value_type("Style", ptree()))->second; ptree::value_type("Style", ptree()))->second;
set_attr(style_node, "name", name); set_attr(style_node, "name", name);
feature_type_style dfl;
if (filter_mode != dfl.get_filter_mode() || explicit_defaults)
{
set_attr(style_node, "filter-mode", filter_mode);
}
rules::const_iterator it = style.get_rules().begin(); rules::const_iterator it = style.get_rules().begin();
rules::const_iterator end = style.get_rules().end(); rules::const_iterator end = style.get_rules().end();
for (; it != end; ++it) for (; it != end; ++it)

View file

@ -42,6 +42,12 @@ map_ = '''<Map>
</Rule> </Rule>
</Style> </Style>
<Style name="s2" filter-mode="first">
<Rule>
</Rule>
<Rule>
</Rule>
</Style>
</Map>''' </Map>'''
def test_filter_init(): def test_filter_init():
@ -81,3 +87,7 @@ def test_filter_init():
first = filters[0] first = filters[0]
for f in filters: for f in filters:
eq_(str(first),str(f)) eq_(str(first),str(f))
s = m.find_style('s2')
eq_(s.filter_mode,mapnik2.filter_mode.FIRST)