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
- John Hague
- Aubrey Holland
- Konstantin Käfer
- Mak Kolybabi
- Dennis Luxen
- Tom MacWright

View file

@ -14,6 +14,8 @@ For a complete change history, see the SVN log.
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 ability to register fonts within XML using Map level 'font_directory' parameter (#168)

View file

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

View file

@ -24,6 +24,7 @@
#include <boost/python.hpp>
#include <boost/python/suite/indexing/vector_indexing_suite.hpp>
#include "mapnik_enumeration.hpp"
#include <mapnik/feature_type_style.hpp>
using mapnik::feature_type_style;
@ -73,6 +74,11 @@ void export_style()
{
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"))
.def(vector_indexing_suite<rules>())
;
@ -92,6 +98,10 @@ void export_style()
"<mapnik2._mapnik2.Rule object at 0x100549910>\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);
}
}
if (style->get_filter_mode() == FILTER_FIRST)
{
// Stop iterating over rules and proceed with next feature.
break;
}
}
}
if (do_else)

View file

@ -27,44 +27,44 @@
// mapnik
#include <mapnik/rule.hpp>
#include <mapnik/feature.hpp>
#include <mapnik/enumeration.hpp>
// stl
#include <vector>
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;
class feature_type_style
{
private:
rules rules_;
filter_mode_e filter_mode_;
public:
feature_type_style() {}
feature_type_style();
feature_type_style(feature_type_style const& rhs)
: rules_(rhs.rules_) {}
feature_type_style(feature_type_style const& rhs);
feature_type_style& operator=(feature_type_style const& rhs)
{
if (this == &rhs) return *this;
rules_=rhs.rules_;
return *this;
}
feature_type_style& operator=(feature_type_style const& rhs);
void add_rule(rule const& rule)
{
rules_.push_back(rule);
}
void add_rule(rule const& rule);
rules const& get_rules() const
{
return rules_;
}
rules const& get_rules() const;
rules &get_rules_nonconst()
{
return rules_;
}
rules &get_rules_nonconst();
void set_filter_mode(filter_mode_e mode);
filter_mode_e get_filter_mode() const;
~feature_type_style() {}
};
}

View file

@ -102,6 +102,7 @@ source = Split(
expression_node.cpp
expression_string.cpp
filter_factory.cpp
feature_type_style.cpp
font_engine_freetype.cpp
font_set.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");
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 endRule = sty.end();

View file

@ -632,11 +632,18 @@ void serialize_style( ptree & map_node, Map::const_style_iterator style_it, bool
{
const feature_type_style & style = style_it->second;
const std::string & name = style_it->first;
filter_mode_e filter_mode = style.get_filter_mode();
ptree & style_node = map_node.push_back(
ptree::value_type("Style", ptree()))->second;
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 end = style.get_rules().end();

View file

@ -42,6 +42,12 @@ map_ = '''<Map>
</Rule>
</Style>
<Style name="s2" filter-mode="first">
<Rule>
</Rule>
<Rule>
</Rule>
</Style>
</Map>'''
def test_filter_init():
@ -80,4 +86,8 @@ def test_filter_init():
first = filters[0]
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)