+ fix feature caching implementation - collect
attributes names from all active styles + use BOOST_FOREACH to improve readability TODO - move 'filter_factor' to raster_symbolizer
This commit is contained in:
parent
34d5fcf963
commit
1ecdba1965
1 changed files with 119 additions and 117 deletions
|
@ -40,11 +40,14 @@
|
||||||
#ifdef MAPNIK_DEBUG
|
#ifdef MAPNIK_DEBUG
|
||||||
//#include <mapnik/wall_clock_timer.hpp>
|
//#include <mapnik/wall_clock_timer.hpp>
|
||||||
#endif
|
#endif
|
||||||
|
// boost
|
||||||
|
#include <boost/foreach.hpp>
|
||||||
//stl
|
//stl
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
namespace mapnik
|
namespace mapnik
|
||||||
{
|
{
|
||||||
|
|
||||||
template <typename Processor>
|
template <typename Processor>
|
||||||
class feature_style_processor
|
class feature_style_processor
|
||||||
{
|
{
|
||||||
|
@ -87,7 +90,7 @@ public:
|
||||||
p.start_map_processing(m_);
|
p.start_map_processing(m_);
|
||||||
Map::const_metawriter_iterator metaItr = m_.begin_metawriters();
|
Map::const_metawriter_iterator metaItr = m_.begin_metawriters();
|
||||||
Map::const_metawriter_iterator metaItrEnd = m_.end_metawriters();
|
Map::const_metawriter_iterator metaItrEnd = m_.end_metawriters();
|
||||||
|
|
||||||
for (;metaItr!=metaItrEnd; ++metaItr)
|
for (;metaItr!=metaItrEnd; ++metaItr)
|
||||||
{
|
{
|
||||||
metaItr->second->start();
|
metaItr->second->start();
|
||||||
|
@ -101,16 +104,12 @@ public:
|
||||||
#ifdef MAPNIK_DEBUG
|
#ifdef MAPNIK_DEBUG
|
||||||
std::clog << "scale denominator = " << scale_denom << "\n";
|
std::clog << "scale denominator = " << scale_denom << "\n";
|
||||||
#endif
|
#endif
|
||||||
std::vector<layer>::const_iterator itr = m_.layers().begin();
|
BOOST_FOREACH ( layer const& lyr, m_.layers() )
|
||||||
std::vector<layer>::const_iterator end = m_.layers().end();
|
|
||||||
|
|
||||||
while (itr != end)
|
|
||||||
{
|
{
|
||||||
if (itr->isVisible(scale_denom))
|
if (lyr.isVisible(scale_denom))
|
||||||
{
|
{
|
||||||
apply_to_layer(*itr, p, proj, scale_denom);
|
apply_to_layer(lyr, p, proj, scale_denom);
|
||||||
}
|
}
|
||||||
++itr;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (proj_init_error& ex)
|
catch (proj_init_error& ex)
|
||||||
|
@ -123,7 +122,7 @@ public:
|
||||||
{
|
{
|
||||||
metaItr->second->stop();
|
metaItr->second->stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
p.end_map_processing(m_);
|
p.end_map_processing(m_);
|
||||||
}
|
}
|
||||||
private:
|
private:
|
||||||
|
@ -168,71 +167,93 @@ private:
|
||||||
ly0 = std::max(ext.miny(),ly0);
|
ly0 = std::max(ext.miny(),ly0);
|
||||||
lx1 = std::min(ext.maxx(),lx1);
|
lx1 = std::min(ext.maxx(),lx1);
|
||||||
ly1 = std::min(ext.maxy(),ly1);
|
ly1 = std::min(ext.maxy(),ly1);
|
||||||
|
|
||||||
prj_trans.forward(lx0,ly0,lz0);
|
prj_trans.forward(lx0,ly0,lz0);
|
||||||
prj_trans.forward(lx1,ly1,lz1);
|
prj_trans.forward(lx1,ly1,lz1);
|
||||||
box2d<double> bbox(lx0,ly0,lx1,ly1);
|
box2d<double> bbox(lx0,ly0,lx1,ly1);
|
||||||
|
|
||||||
query::resolution_type res(m_.width()/m_.get_current_extent().width(),m_.height()/m_.get_current_extent().height());
|
query::resolution_type res(m_.width()/m_.get_current_extent().width(),m_.height()/m_.get_current_extent().height());
|
||||||
query q(bbox,res,scale_denom); //BBOX query
|
query q(bbox,res,scale_denom); //BBOX query
|
||||||
|
|
||||||
std::vector<std::string> const& style_names = lay.styles();
|
std::vector<feature_type_style*> active_styles;
|
||||||
std::vector<std::string>::const_iterator stylesIter = style_names.begin();
|
std::set<std::string> names;
|
||||||
std::vector<std::string>::const_iterator stylesEnd = style_names.end();
|
attribute_collector collector(names);
|
||||||
|
|
||||||
|
std::vector<std::string> const& style_names = lay.styles();
|
||||||
|
// iterate through all named styles collecting active styles and attribute names
|
||||||
|
BOOST_FOREACH(std::string const& style_name, style_names)
|
||||||
|
{
|
||||||
|
boost::optional<feature_type_style const&> style=m_.find_style(style_name);
|
||||||
|
if (!style)
|
||||||
|
{
|
||||||
|
std::clog << "WARNING: style '" << style_name << "' required for layer '" << lay.name() << "' does not exist.\n";
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::vector<rule_type>& rules=(*style).get_rules();
|
||||||
|
bool active_rules=false;
|
||||||
|
|
||||||
|
BOOST_FOREACH(rule_type const& rule, rules)
|
||||||
|
{
|
||||||
|
if (rule.active(scale_denom))
|
||||||
|
{
|
||||||
|
active_rules = true;
|
||||||
|
if (ds->type() == datasource::Vector)
|
||||||
|
{
|
||||||
|
collector(rule);
|
||||||
|
}
|
||||||
|
// TODO - in the future rasters should be able to be filtered.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (active_rules)
|
||||||
|
{
|
||||||
|
active_styles.push_back(const_cast<feature_type_style*>(&(*style)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// push all property names
|
||||||
|
BOOST_FOREACH(std::string const& name, names)
|
||||||
|
{
|
||||||
|
q.add_property_name(name);
|
||||||
|
}
|
||||||
|
|
||||||
memory_datasource cache;
|
memory_datasource cache;
|
||||||
bool cache_features = style_names.size()>1?true:false;
|
bool cache_features = style_names.size()>1?true:false;
|
||||||
bool first = true;
|
bool first = true;
|
||||||
for (;stylesIter != stylesEnd; ++stylesIter)
|
|
||||||
|
BOOST_FOREACH (feature_type_style * style, active_styles)
|
||||||
{
|
{
|
||||||
std::set<std::string> names;
|
|
||||||
attribute_collector collector(names);
|
|
||||||
std::vector<rule_type*> if_rules;
|
std::vector<rule_type*> if_rules;
|
||||||
std::vector<rule_type*> else_rules;
|
std::vector<rule_type*> else_rules;
|
||||||
|
|
||||||
bool active_rules=false;
|
|
||||||
|
|
||||||
boost::optional<feature_type_style const&> style=m_.find_style(*stylesIter);
|
|
||||||
if (!style) {
|
|
||||||
std::clog << "WARNING: style '" << *stylesIter << "' required for layer '" << lay.name() << "' does not exist.\n";
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
const std::vector<rule_type>& rules=(*style).get_rules();
|
std::vector<rule_type> const& rules=style->get_rules();
|
||||||
std::vector<rule_type>::const_iterator ruleIter=rules.begin();
|
|
||||||
std::vector<rule_type>::const_iterator ruleEnd=rules.end();
|
BOOST_FOREACH(rule_type const& rule, rules)
|
||||||
|
|
||||||
for (;ruleIter!=ruleEnd;++ruleIter)
|
|
||||||
{
|
{
|
||||||
if (ruleIter->active(scale_denom))
|
if (rule.active(scale_denom))
|
||||||
{
|
{
|
||||||
active_rules=true;
|
if (rule.has_else_filter())
|
||||||
// collect unique attribute names
|
|
||||||
// TODO - in the future rasters should be able to be filtered...
|
|
||||||
if (ds->type() == datasource::Vector)
|
|
||||||
{
|
{
|
||||||
collector(*ruleIter);
|
else_rules.push_back(const_cast<rule_type*>(&rule));
|
||||||
}
|
|
||||||
if (ruleIter->has_else_filter())
|
|
||||||
{
|
|
||||||
else_rules.push_back(const_cast<rule_type*>(&(*ruleIter)));
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if_rules.push_back(const_cast<rule_type*>(&(*ruleIter)));
|
if_rules.push_back(const_cast<rule_type*>(&rule));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ds->type() == datasource::Raster)
|
if (ds->type() == datasource::Raster)
|
||||||
{
|
{
|
||||||
if (ds->params().get<double>("filter_factor",0.0) == 0.0)
|
if (ds->params().get<double>("filter_factor",0.0) == 0.0)
|
||||||
{
|
{
|
||||||
const rule_type::symbolizers& symbols = ruleIter->get_symbolizers();
|
rule_type::symbolizers const& symbols = rule.get_symbolizers();
|
||||||
rule_type::symbolizers::const_iterator symIter = symbols.begin();
|
rule_type::symbolizers::const_iterator symIter = symbols.begin();
|
||||||
rule_type::symbolizers::const_iterator symEnd = symbols.end();
|
rule_type::symbolizers::const_iterator symEnd = symbols.end();
|
||||||
for (;symIter != symEnd;++symIter)
|
for (;symIter != symEnd;++symIter)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
raster_symbolizer sym = boost::get<raster_symbolizer>(*symIter);
|
raster_symbolizer const& sym = boost::get<raster_symbolizer>(*symIter);
|
||||||
std::string scaling = sym.get_scaling();
|
std::string const& scaling = sym.get_scaling();
|
||||||
if (scaling == "bilinear" || scaling == "bilinear8" )
|
if (scaling == "bilinear" || scaling == "bilinear8" )
|
||||||
{
|
{
|
||||||
// todo - allow setting custom value in symbolizer property?
|
// todo - allow setting custom value in symbolizer property?
|
||||||
|
@ -246,89 +267,70 @@ private:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
std::set<std::string>::const_iterator namesIter=names.begin();
|
|
||||||
std::set<std::string>::const_iterator namesEnd =names.end();
|
// process features
|
||||||
|
featureset_ptr fs;
|
||||||
// push all property names
|
if (first)
|
||||||
for (;namesIter!=namesEnd;++namesIter)
|
|
||||||
{
|
{
|
||||||
q.add_property_name(*namesIter);
|
first = false;
|
||||||
|
fs = ds->features(q);
|
||||||
}
|
}
|
||||||
if (active_rules)
|
else
|
||||||
{
|
{
|
||||||
featureset_ptr fs;
|
fs = cache.features(q);
|
||||||
if (first)
|
}
|
||||||
{
|
|
||||||
first = false;
|
if (fs)
|
||||||
fs = ds->features(q);
|
{
|
||||||
}
|
feature_ptr feature;
|
||||||
else
|
while ((feature = fs->next()))
|
||||||
{
|
{
|
||||||
fs = cache.features(q);
|
bool do_else=true;
|
||||||
}
|
|
||||||
if (fs)
|
if (cache_features)
|
||||||
{
|
{
|
||||||
feature_ptr feature;
|
cache.push(feature);
|
||||||
while ((feature = fs->next()))
|
}
|
||||||
{
|
|
||||||
bool do_else=true;
|
BOOST_FOREACH(rule_type * rule, if_rules )
|
||||||
|
{
|
||||||
if (cache_features)
|
expression_ptr const& expr=rule->get_filter();
|
||||||
{
|
value_type result = boost::apply_visitor(evaluate<Feature,value_type>(*feature),*expr);
|
||||||
cache.push(feature);
|
if (result.to_bool())
|
||||||
}
|
{
|
||||||
|
do_else=false;
|
||||||
std::vector<rule_type*>::const_iterator itr=if_rules.begin();
|
rule_type::symbolizers const& symbols = rule->get_symbolizers();
|
||||||
std::vector<rule_type*>::const_iterator end=if_rules.end();
|
BOOST_FOREACH (symbolizer const& sym, symbols)
|
||||||
for (;itr != end;++itr)
|
|
||||||
{
|
|
||||||
expression_ptr const& expr=(*itr)->get_filter();
|
|
||||||
value_type result = boost::apply_visitor(evaluate<Feature,value_type>(*feature),*expr);
|
|
||||||
if (result.to_bool())
|
|
||||||
{
|
{
|
||||||
do_else=false;
|
boost::apply_visitor
|
||||||
const rule_type::symbolizers& symbols = (*itr)->get_symbolizers();
|
(symbol_dispatch(p,*feature,prj_trans),sym);
|
||||||
rule_type::symbolizers::const_iterator symIter=symbols.begin();
|
|
||||||
rule_type::symbolizers::const_iterator symEnd =symbols.end();
|
|
||||||
for (;symIter != symEnd;++symIter)
|
|
||||||
{
|
|
||||||
boost::apply_visitor
|
|
||||||
(symbol_dispatch(p,*feature,prj_trans),*symIter);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (do_else)
|
|
||||||
{
|
|
||||||
//else filter
|
|
||||||
std::vector<rule_type*>::const_iterator itr=
|
|
||||||
else_rules.begin();
|
|
||||||
std::vector<rule_type*>::const_iterator end=
|
|
||||||
else_rules.end();
|
|
||||||
for (;itr != end;++itr)
|
|
||||||
{
|
|
||||||
const rule_type::symbolizers& symbols = (*itr)->get_symbolizers();
|
|
||||||
rule_type::symbolizers::const_iterator symIter= symbols.begin();
|
|
||||||
rule_type::symbolizers::const_iterator symEnd = symbols.end();
|
|
||||||
|
|
||||||
for (;symIter!=symEnd;++symIter)
|
|
||||||
{
|
|
||||||
boost::apply_visitor
|
|
||||||
(symbol_dispatch(p,*feature,prj_trans),*symIter);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
cache_features = false;
|
if (do_else)
|
||||||
|
{
|
||||||
|
BOOST_FOREACH( rule_type * rule, else_rules )
|
||||||
|
{
|
||||||
|
rule_type::symbolizers const& symbols = rule->get_symbolizers();
|
||||||
|
BOOST_FOREACH (symbolizer const& sym, symbols)
|
||||||
|
{
|
||||||
|
boost::apply_visitor
|
||||||
|
(symbol_dispatch(p,*feature,prj_trans),sym);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
cache_features = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
p.end_layer_processing(lay);
|
p.end_layer_processing(lay);
|
||||||
}
|
}
|
||||||
|
|
||||||
Map const& m_;
|
Map const& m_;
|
||||||
double scale_factor_;
|
double scale_factor_;
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in a new issue