Merge branch 'master' of github.com:mapnik/mapnik into geometry_cleanup
This commit is contained in:
commit
51bd04c448
10 changed files with 367 additions and 204 deletions
|
@ -23,8 +23,16 @@
|
||||||
#ifndef MAPNIK_FEATURE_STYLE_PROCESSOR_HPP
|
#ifndef MAPNIK_FEATURE_STYLE_PROCESSOR_HPP
|
||||||
#define MAPNIK_FEATURE_STYLE_PROCESSOR_HPP
|
#define MAPNIK_FEATURE_STYLE_PROCESSOR_HPP
|
||||||
|
|
||||||
|
// mapnik
|
||||||
|
#include <mapnik/map.hpp>
|
||||||
|
#include <mapnik/projection.hpp>
|
||||||
|
#include <mapnik/memory_datasource.hpp>
|
||||||
|
|
||||||
|
|
||||||
|
// stl
|
||||||
#include <set>
|
#include <set>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
namespace mapnik
|
namespace mapnik
|
||||||
{
|
{
|
||||||
|
@ -62,11 +70,23 @@ private:
|
||||||
/*!
|
/*!
|
||||||
* @return render a layer given a projection and scale.
|
* @return render a layer given a projection and scale.
|
||||||
*/
|
*/
|
||||||
void apply_to_layer(layer const& lay, Processor & p,
|
void apply_to_layer(layer const& lay,
|
||||||
|
Processor & p,
|
||||||
projection const& proj0,
|
projection const& proj0,
|
||||||
double scale_denom,
|
double scale_denom,
|
||||||
std::set<std::string>& names);
|
std::set<std::string>& names);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* @return renders a featureset with the given styles.
|
||||||
|
*/
|
||||||
|
void render_style(layer const& lay,
|
||||||
|
Processor & p,
|
||||||
|
feature_type_style* style,
|
||||||
|
std::string const& style_name,
|
||||||
|
featureset_ptr features,
|
||||||
|
proj_transform const& prj_trans,
|
||||||
|
double scale_denom);
|
||||||
|
|
||||||
Map const& m_;
|
Map const& m_;
|
||||||
double scale_factor_;
|
double scale_factor_;
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*****************************************************************************
|
/*****************************************************************************
|
||||||
*
|
*
|
||||||
* This file is part of Mapnik (c++ mapping toolkit)
|
* This file is part of Mapnik (c++ mapping toolkit)
|
||||||
*
|
*
|
||||||
* Copyright (C) 2011 Artem Pavlenko
|
* Copyright (C) 2011 Artem Pavlenko
|
||||||
|
@ -23,7 +23,7 @@
|
||||||
#ifndef MAPNIK_FEATURE_TYPE_STYLE_HPP
|
#ifndef MAPNIK_FEATURE_TYPE_STYLE_HPP
|
||||||
#define MAPNIK_FEATURE_TYPE_STYLE_HPP
|
#define MAPNIK_FEATURE_TYPE_STYLE_HPP
|
||||||
|
|
||||||
// mapnik
|
// mapnik
|
||||||
#include <mapnik/rule.hpp>
|
#include <mapnik/rule.hpp>
|
||||||
#include <mapnik/feature.hpp>
|
#include <mapnik/feature.hpp>
|
||||||
#include <mapnik/enumeration.hpp>
|
#include <mapnik/enumeration.hpp>
|
||||||
|
@ -43,29 +43,43 @@ enum filter_mode_enum {
|
||||||
DEFINE_ENUM( filter_mode_e, filter_mode_enum );
|
DEFINE_ENUM( filter_mode_e, filter_mode_enum );
|
||||||
|
|
||||||
typedef std::vector<rule> rules;
|
typedef std::vector<rule> rules;
|
||||||
|
typedef std::vector<rule*> rule_ptrs;
|
||||||
|
|
||||||
class MAPNIK_DECL feature_type_style
|
class MAPNIK_DECL feature_type_style
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
rules rules_;
|
rules rules_;
|
||||||
filter_mode_e filter_mode_;
|
filter_mode_e filter_mode_;
|
||||||
|
|
||||||
|
// The rule_ptrs vectors are only valid for the scale_denom_validity_.
|
||||||
|
double scale_denom_validity_;
|
||||||
|
rule_ptrs if_rules_;
|
||||||
|
rule_ptrs else_rules_;
|
||||||
|
rule_ptrs also_rules_;
|
||||||
public:
|
public:
|
||||||
feature_type_style();
|
feature_type_style();
|
||||||
|
|
||||||
feature_type_style(feature_type_style const& rhs, bool deep_copy = false);
|
feature_type_style(feature_type_style const& rhs, bool deep_copy = false);
|
||||||
|
|
||||||
feature_type_style& operator=(feature_type_style const& rhs);
|
feature_type_style& operator=(feature_type_style const& rhs);
|
||||||
|
|
||||||
void add_rule(rule const& rule);
|
void add_rule(rule const& rule);
|
||||||
|
|
||||||
rules const& get_rules() const;
|
rules const& get_rules() const;
|
||||||
|
rule_ptrs const& get_if_rules(double scale_denom);
|
||||||
|
rule_ptrs const& get_else_rules(double scale_denom);
|
||||||
|
rule_ptrs const& get_also_rules(double scale_denom);
|
||||||
|
|
||||||
rules &get_rules_nonconst();
|
rules &get_rules_nonconst();
|
||||||
|
|
||||||
void set_filter_mode(filter_mode_e mode);
|
void set_filter_mode(filter_mode_e mode);
|
||||||
|
|
||||||
filter_mode_e get_filter_mode() const;
|
filter_mode_e get_filter_mode() const;
|
||||||
|
|
||||||
~feature_type_style() {}
|
~feature_type_style() {}
|
||||||
|
|
||||||
|
private:
|
||||||
|
void update_rule_cache(double scale_denom);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -180,6 +180,16 @@ public:
|
||||||
*/
|
*/
|
||||||
bool cache_features() const;
|
bool cache_features() const;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* @param group_by Set the field rendering of this layer is grouped by.
|
||||||
|
*/
|
||||||
|
void set_group_by(std::string column);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* @return The field rendering of this layer is grouped by.
|
||||||
|
*/
|
||||||
|
std::string group_by() const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* @brief Attach a datasource for this layer.
|
* @brief Attach a datasource for this layer.
|
||||||
*
|
*
|
||||||
|
@ -212,6 +222,7 @@ private:
|
||||||
bool queryable_;
|
bool queryable_;
|
||||||
bool clear_label_cache_;
|
bool clear_label_cache_;
|
||||||
bool cache_features_;
|
bool cache_features_;
|
||||||
|
std::string group_by_;
|
||||||
std::vector<std::string> styles_;
|
std::vector<std::string> styles_;
|
||||||
datasource_ptr ds_;
|
datasource_ptr ds_;
|
||||||
};
|
};
|
||||||
|
|
|
@ -45,6 +45,7 @@ public:
|
||||||
box2d<double> envelope() const;
|
box2d<double> envelope() const;
|
||||||
layer_descriptor get_descriptor() const;
|
layer_descriptor get_descriptor() const;
|
||||||
size_t size() const;
|
size_t size() const;
|
||||||
|
void clear();
|
||||||
private:
|
private:
|
||||||
std::vector<feature_ptr> features_;
|
std::vector<feature_ptr> features_;
|
||||||
mapnik::layer_descriptor desc_;
|
mapnik::layer_descriptor desc_;
|
||||||
|
|
|
@ -25,13 +25,10 @@
|
||||||
#include <mapnik/box2d.hpp>
|
#include <mapnik/box2d.hpp>
|
||||||
#include <mapnik/datasource.hpp>
|
#include <mapnik/datasource.hpp>
|
||||||
#include <mapnik/layer.hpp>
|
#include <mapnik/layer.hpp>
|
||||||
#include <mapnik/map.hpp>
|
|
||||||
#include <mapnik/attribute_collector.hpp>
|
#include <mapnik/attribute_collector.hpp>
|
||||||
#include <mapnik/expression_evaluator.hpp>
|
#include <mapnik/expression_evaluator.hpp>
|
||||||
#include <mapnik/utils.hpp>
|
#include <mapnik/utils.hpp>
|
||||||
#include <mapnik/projection.hpp>
|
|
||||||
#include <mapnik/scale_denominator.hpp>
|
#include <mapnik/scale_denominator.hpp>
|
||||||
#include <mapnik/memory_datasource.hpp>
|
|
||||||
|
|
||||||
#include <mapnik/agg_renderer.hpp>
|
#include <mapnik/agg_renderer.hpp>
|
||||||
#include <mapnik/grid/grid_renderer.hpp>
|
#include <mapnik/grid/grid_renderer.hpp>
|
||||||
|
@ -308,65 +305,23 @@ void feature_style_processor<Processor>::apply_to_layer(layer const& lay, Proces
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// push all property names
|
// Don't even try to do more work if there are no active styles.
|
||||||
BOOST_FOREACH(std::string const& name, names)
|
if (active_styles.size() > 0)
|
||||||
{
|
{
|
||||||
q.add_property_name(name);
|
// push all property names
|
||||||
}
|
BOOST_FOREACH(std::string const& name, names)
|
||||||
|
|
||||||
memory_datasource cache;
|
|
||||||
bool cache_features = lay.cache_features() && num_styles>1?true:false;
|
|
||||||
bool first = true;
|
|
||||||
|
|
||||||
#if defined(RENDERING_STATS)
|
|
||||||
int style_index = 0;
|
|
||||||
if (!active_styles.size() > 0) {
|
|
||||||
layer_timer.discard();
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
BOOST_FOREACH (feature_type_style * style, active_styles)
|
|
||||||
{
|
|
||||||
#if defined(RENDERING_STATS)
|
|
||||||
std::string s_name = style_names[style_index];
|
|
||||||
std::ostringstream s1;
|
|
||||||
s1 << "rendering style #" << style_index+1
|
|
||||||
<< " for layer: '" << lay.name() << "' and style '" << s_name << "'";
|
|
||||||
mapnik::progress_timer style_timer(std::clog, s1.str());
|
|
||||||
if (!num_styles>1)
|
|
||||||
style_timer.discard();
|
|
||||||
style_index++;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
std::vector<rule*> if_rules;
|
|
||||||
std::vector<rule*> else_rules;
|
|
||||||
std::vector<rule*> also_rules;
|
|
||||||
|
|
||||||
std::vector<rule> const& rules=style->get_rules();
|
|
||||||
|
|
||||||
#if defined(RENDERING_STATS)
|
|
||||||
int feature_count = 0;
|
|
||||||
int feature_processed_count = 0;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
BOOST_FOREACH(rule const& r, rules)
|
|
||||||
{
|
{
|
||||||
if (r.active(scale_denom))
|
q.add_property_name(name);
|
||||||
{
|
}
|
||||||
if (r.has_else_filter())
|
|
||||||
{
|
|
||||||
else_rules.push_back(const_cast<rule*>(&r));
|
|
||||||
}
|
|
||||||
else if (r.has_also_filter())
|
|
||||||
{
|
|
||||||
also_rules.push_back(const_cast<rule*>(&r));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if_rules.push_back(const_cast<rule*>(&r));
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( (ds->type() == datasource::Raster) &&
|
// Update filter_factor for all enabled raster layers.
|
||||||
(ds->params().get<double>("filter_factor",0.0) == 0.0) )
|
BOOST_FOREACH (feature_type_style * style, active_styles)
|
||||||
|
{
|
||||||
|
BOOST_FOREACH(rule const& r, style->get_rules())
|
||||||
|
{
|
||||||
|
if (r.active(scale_denom) &&
|
||||||
|
ds->type() == datasource::Raster &&
|
||||||
|
ds->params().get<double>("filter_factor",0.0) == 0.0)
|
||||||
{
|
{
|
||||||
rule::symbolizers const& symbols = r.get_symbolizers();
|
rule::symbolizers const& symbols = r.get_symbolizers();
|
||||||
rule::symbolizers::const_iterator symIter = symbols.begin();
|
rule::symbolizers::const_iterator symIter = symbols.begin();
|
||||||
|
@ -382,163 +337,235 @@ void feature_style_processor<Processor>::apply_to_layer(layer const& lay, Proces
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// process features
|
// Also query the group by attribute
|
||||||
featureset_ptr fs;
|
std::string group_by = lay.group_by();
|
||||||
if (first)
|
if (group_by != "")
|
||||||
{
|
{
|
||||||
if (cache_features)
|
q.add_property_name(group_by);
|
||||||
first = false;
|
|
||||||
fs = ds->features(q);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
fs = cache.features(q);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fs)
|
bool cache_features = lay.cache_features() && active_styles.size() > 1;
|
||||||
|
|
||||||
|
// Render incrementally when the column that we group by
|
||||||
|
// changes value.
|
||||||
|
if (group_by != "")
|
||||||
{
|
{
|
||||||
feature_ptr feature;
|
featureset_ptr features = ds->features(q);
|
||||||
while ((feature = fs->next()))
|
if (features) {
|
||||||
{
|
// Cache all features into the memory_datasource before rendering.
|
||||||
|
memory_datasource cache;
|
||||||
|
feature_ptr feature, prev;
|
||||||
|
|
||||||
#if defined(RENDERING_STATS)
|
while ((feature = features->next()))
|
||||||
feature_count++;
|
{
|
||||||
bool feat_processed = false;
|
if (prev && prev->props()[group_by] != feature->props()[group_by])
|
||||||
#endif
|
{
|
||||||
|
// We're at a value boundary, so render what we have
|
||||||
|
// up to this point.
|
||||||
|
int i = 0;
|
||||||
|
BOOST_FOREACH (feature_type_style * style, active_styles)
|
||||||
|
{
|
||||||
|
render_style(lay, p, style, style_names[i++],
|
||||||
|
cache.features(q), prj_trans, scale_denom);
|
||||||
|
}
|
||||||
|
cache.clear();
|
||||||
|
}
|
||||||
|
cache.push(feature);
|
||||||
|
prev = feature;
|
||||||
|
}
|
||||||
|
|
||||||
bool do_else=true;
|
int i = 0;
|
||||||
bool do_also=false;
|
BOOST_FOREACH (feature_type_style * style, active_styles)
|
||||||
|
{
|
||||||
if (cache_features)
|
render_style(lay, p, style, style_names[i++],
|
||||||
|
cache.features(q), prj_trans, scale_denom);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (cache_features)
|
||||||
|
{
|
||||||
|
featureset_ptr features = ds->features(q);
|
||||||
|
if (features) {
|
||||||
|
// Cache all features into the memory_datasource before rendering.
|
||||||
|
memory_datasource cache;
|
||||||
|
feature_ptr feature;
|
||||||
|
while ((feature = features->next()))
|
||||||
{
|
{
|
||||||
cache.push(feature);
|
cache.push(feature);
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_FOREACH(rule * r, if_rules )
|
int i = 0;
|
||||||
|
BOOST_FOREACH (feature_type_style * style, active_styles)
|
||||||
{
|
{
|
||||||
expression_ptr const& expr=r->get_filter();
|
render_style(lay, p, style, style_names[i++],
|
||||||
value_type result = boost::apply_visitor(evaluate<Feature,value_type>(*feature),*expr);
|
cache.features(q), prj_trans, scale_denom);
|
||||||
if (result.to_bool())
|
|
||||||
{
|
|
||||||
#if defined(RENDERING_STATS)
|
|
||||||
feat_processed = true;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
p.painted(true);
|
|
||||||
|
|
||||||
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,
|
|
||||||
// process one by one.
|
|
||||||
#if defined(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 (style->get_filter_mode() == FILTER_FIRST)
|
|
||||||
{
|
|
||||||
// Stop iterating over rules and proceed with next feature.
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (do_else)
|
|
||||||
{
|
|
||||||
BOOST_FOREACH( rule * r, else_rules )
|
|
||||||
{
|
|
||||||
#if defined(RENDERING_STATS)
|
|
||||||
feat_processed = true;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
p.painted(true);
|
|
||||||
|
|
||||||
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.
|
|
||||||
#if defined(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 )
|
|
||||||
{
|
|
||||||
#if defined(RENDERING_STATS)
|
|
||||||
feat_processed = true;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
p.painted(true);
|
|
||||||
|
|
||||||
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.
|
|
||||||
#if defined(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 defined(RENDERING_STATS)
|
|
||||||
if (feat_processed)
|
|
||||||
feature_processed_count++;
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
#if defined(RENDERING_STATS)
|
// We only have a single style and no grouping.
|
||||||
style_timer.stop();
|
else
|
||||||
|
{
|
||||||
// done with style
|
int i = 0;
|
||||||
std::ostringstream s;
|
BOOST_FOREACH (feature_type_style * style, active_styles)
|
||||||
if (feature_count > 0) {
|
{
|
||||||
double perc_processed = ((double)feature_processed_count/(double)feature_count)*100.0;
|
featureset_ptr features = ds->features(q);
|
||||||
|
if (features) {
|
||||||
s << "percent rendered: " << perc_processed << "% - " << feature_processed_count
|
render_style(lay, p, style, style_names[i++],
|
||||||
<< " rendered for " << feature_count << " queried for ";
|
features, prj_trans, scale_denom);
|
||||||
s << std::setw(15 - (int)s.tellp()) << " layer '" << lay.name() << "' and style '" << s_name << "'\n";
|
}
|
||||||
|
|
||||||
} else {
|
|
||||||
s << "" << std::setw(15) << "- no features returned from query for layer '" << lay.name() << "' and style '" << s_name << "'\n";
|
|
||||||
}
|
}
|
||||||
std::clog << s.str();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
}
|
}
|
||||||
#if defined(RENDERING_STATS)
|
|
||||||
else {
|
|
||||||
style_timer.discard();
|
|
||||||
layer_timer.discard();
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
cache_features = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(RENDERING_STATS)
|
#if defined(RENDERING_STATS)
|
||||||
layer_timer.stop();
|
layer_timer.stop();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
p.end_layer_processing(lay);
|
p.end_layer_processing(lay);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template <typename Processor>
|
||||||
|
void feature_style_processor<Processor>::render_style(
|
||||||
|
layer const& lay,
|
||||||
|
Processor & p,
|
||||||
|
feature_type_style* style,
|
||||||
|
std::string const& style_name,
|
||||||
|
featureset_ptr features,
|
||||||
|
proj_transform const& prj_trans,
|
||||||
|
double scale_denom)
|
||||||
|
{
|
||||||
|
#if defined(RENDERING_STATS)
|
||||||
|
std::ostringstream s1;
|
||||||
|
s1 << "rendering style for layer: '" << lay.name()
|
||||||
|
<< "' and style '" << style_name << "'";
|
||||||
|
mapnik::progress_timer style_timer(std::clog, s1.str());
|
||||||
|
|
||||||
|
int feature_processed_count = 0;
|
||||||
|
int feature_count = 0;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
feature_ptr feature;
|
||||||
|
while ((feature = features->next()))
|
||||||
|
{
|
||||||
|
#if defined(RENDERING_STATS)
|
||||||
|
feature_count++;
|
||||||
|
bool feat_processed = false;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
bool do_else = true;
|
||||||
|
bool do_also = false;
|
||||||
|
|
||||||
|
BOOST_FOREACH(rule * r, style->get_if_rules(scale_denom) )
|
||||||
|
{
|
||||||
|
expression_ptr const& expr=r->get_filter();
|
||||||
|
value_type result = boost::apply_visitor(evaluate<Feature,value_type>(*feature),*expr);
|
||||||
|
if (result.to_bool())
|
||||||
|
{
|
||||||
|
#if defined(RENDERING_STATS)
|
||||||
|
feat_processed = true;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
p.painted(true);
|
||||||
|
|
||||||
|
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,
|
||||||
|
// process one by one.
|
||||||
|
#if defined(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 (style->get_filter_mode() == FILTER_FIRST)
|
||||||
|
{
|
||||||
|
// Stop iterating over rules and proceed with next feature.
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (do_else)
|
||||||
|
{
|
||||||
|
BOOST_FOREACH( rule * r, style->get_else_rules(scale_denom) )
|
||||||
|
{
|
||||||
|
#if defined(RENDERING_STATS)
|
||||||
|
feat_processed = true;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
p.painted(true);
|
||||||
|
|
||||||
|
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.
|
||||||
|
#if defined(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, style->get_also_rules(scale_denom) )
|
||||||
|
{
|
||||||
|
#if defined(RENDERING_STATS)
|
||||||
|
feat_processed = true;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
p.painted(true);
|
||||||
|
|
||||||
|
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.
|
||||||
|
#if defined(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 defined(RENDERING_STATS)
|
||||||
|
if (feat_processed)
|
||||||
|
feature_processed_count++;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(RENDERING_STATS)
|
||||||
|
style_timer.stop();
|
||||||
|
|
||||||
|
// done with style
|
||||||
|
std::ostringstream s;
|
||||||
|
if (feature_count > 0) {
|
||||||
|
double perc_processed = ((double)feature_processed_count/(double)feature_count)*100.0;
|
||||||
|
|
||||||
|
s << "percent rendered: " << perc_processed << "% - " << feature_processed_count
|
||||||
|
<< " rendered for " << feature_count << " queried for ";
|
||||||
|
s << std::setw(15 - (int)s.tellp()) << " layer '" << lay.name() << "' and style '" << s_name << "'\n";
|
||||||
|
|
||||||
|
} else {
|
||||||
|
s << "" << std::setw(15) << "- no features returned from query for layer '" << lay.name() << "' and style '" << s_name << "'\n";
|
||||||
|
}
|
||||||
|
std::clog << s.str();
|
||||||
|
style_timer.discard();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#if defined(HAVE_CAIRO)
|
#if defined(HAVE_CAIRO)
|
||||||
template class feature_style_processor<cairo_renderer<Cairo::Context> >;
|
template class feature_style_processor<cairo_renderer<Cairo::Context> >;
|
||||||
template class feature_style_processor<cairo_renderer<Cairo::Surface> >;
|
template class feature_style_processor<cairo_renderer<Cairo::Surface> >;
|
||||||
|
|
|
@ -35,10 +35,12 @@ IMPLEMENT_ENUM( filter_mode_e, filter_mode_strings )
|
||||||
|
|
||||||
|
|
||||||
feature_type_style::feature_type_style()
|
feature_type_style::feature_type_style()
|
||||||
: filter_mode_(FILTER_ALL) {}
|
: filter_mode_(FILTER_ALL),
|
||||||
|
scale_denom_validity_(-1) {}
|
||||||
|
|
||||||
feature_type_style::feature_type_style(feature_type_style const& rhs, bool deep_copy)
|
feature_type_style::feature_type_style(feature_type_style const& rhs, bool deep_copy)
|
||||||
: filter_mode_(rhs.filter_mode_)
|
: filter_mode_(rhs.filter_mode_),
|
||||||
|
scale_denom_validity_(-1)
|
||||||
{
|
{
|
||||||
if (!deep_copy) {
|
if (!deep_copy) {
|
||||||
rules_ = rhs.rules_;
|
rules_ = rhs.rules_;
|
||||||
|
@ -55,12 +57,14 @@ feature_type_style& feature_type_style::operator=(feature_type_style const& rhs)
|
||||||
{
|
{
|
||||||
if (this == &rhs) return *this;
|
if (this == &rhs) return *this;
|
||||||
rules_=rhs.rules_;
|
rules_=rhs.rules_;
|
||||||
|
scale_denom_validity_ = -1;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
void feature_type_style::add_rule(rule const& rule)
|
void feature_type_style::add_rule(rule const& rule)
|
||||||
{
|
{
|
||||||
rules_.push_back(rule);
|
rules_.push_back(rule);
|
||||||
|
scale_denom_validity_ = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
rules const& feature_type_style::get_rules() const
|
rules const& feature_type_style::get_rules() const
|
||||||
|
@ -83,4 +87,60 @@ filter_mode_e feature_type_style::get_filter_mode() const
|
||||||
return filter_mode_;
|
return filter_mode_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void feature_type_style::update_rule_cache(double scale_denom)
|
||||||
|
{
|
||||||
|
if_rules_.clear();
|
||||||
|
else_rules_.clear();
|
||||||
|
also_rules_.clear();
|
||||||
|
|
||||||
|
BOOST_FOREACH(rule const& r, rules_)
|
||||||
|
{
|
||||||
|
if (r.active(scale_denom))
|
||||||
|
{
|
||||||
|
if (r.has_else_filter())
|
||||||
|
{
|
||||||
|
else_rules_.push_back(const_cast<rule*>(&r));
|
||||||
|
}
|
||||||
|
else if (r.has_also_filter())
|
||||||
|
{
|
||||||
|
also_rules_.push_back(const_cast<rule*>(&r));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if_rules_.push_back(const_cast<rule*>(&r));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
scale_denom_validity_ = scale_denom;
|
||||||
|
}
|
||||||
|
|
||||||
|
rule_ptrs const& feature_type_style::get_if_rules(double scale_denom)
|
||||||
|
{
|
||||||
|
if (scale_denom_validity_ != scale_denom)
|
||||||
|
{
|
||||||
|
update_rule_cache(scale_denom);
|
||||||
|
}
|
||||||
|
return if_rules_;
|
||||||
|
}
|
||||||
|
|
||||||
|
rule_ptrs const& feature_type_style::get_else_rules(double scale_denom)
|
||||||
|
{
|
||||||
|
if (scale_denom_validity_ != scale_denom)
|
||||||
|
{
|
||||||
|
update_rule_cache(scale_denom);
|
||||||
|
}
|
||||||
|
return else_rules_;
|
||||||
|
}
|
||||||
|
|
||||||
|
rule_ptrs const& feature_type_style::get_also_rules(double scale_denom)
|
||||||
|
{
|
||||||
|
if (scale_denom_validity_ != scale_denom)
|
||||||
|
{
|
||||||
|
update_rule_cache(scale_denom);
|
||||||
|
}
|
||||||
|
return also_rules_;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -46,6 +46,7 @@ layer::layer(std::string const& name, std::string const& srs)
|
||||||
queryable_(false),
|
queryable_(false),
|
||||||
clear_label_cache_(false),
|
clear_label_cache_(false),
|
||||||
cache_features_(false),
|
cache_features_(false),
|
||||||
|
group_by_(""),
|
||||||
ds_() {}
|
ds_() {}
|
||||||
|
|
||||||
layer::layer(const layer& rhs)
|
layer::layer(const layer& rhs)
|
||||||
|
@ -59,6 +60,7 @@ layer::layer(const layer& rhs)
|
||||||
queryable_(rhs.queryable_),
|
queryable_(rhs.queryable_),
|
||||||
clear_label_cache_(rhs.clear_label_cache_),
|
clear_label_cache_(rhs.clear_label_cache_),
|
||||||
cache_features_(rhs.cache_features_),
|
cache_features_(rhs.cache_features_),
|
||||||
|
group_by_(rhs.group_by_),
|
||||||
styles_(rhs.styles_),
|
styles_(rhs.styles_),
|
||||||
ds_(rhs.ds_) {}
|
ds_(rhs.ds_) {}
|
||||||
|
|
||||||
|
@ -86,6 +88,7 @@ void layer::swap(const layer& rhs)
|
||||||
queryable_=rhs.queryable_;
|
queryable_=rhs.queryable_;
|
||||||
clear_label_cache_ = rhs.clear_label_cache_;
|
clear_label_cache_ = rhs.clear_label_cache_;
|
||||||
cache_features_ = rhs.cache_features_;
|
cache_features_ = rhs.cache_features_;
|
||||||
|
group_by_ = rhs.group_by_;
|
||||||
styles_=rhs.styles_;
|
styles_=rhs.styles_;
|
||||||
ds_=rhs.ds_;
|
ds_=rhs.ds_;
|
||||||
}
|
}
|
||||||
|
@ -228,4 +231,14 @@ bool layer::cache_features() const
|
||||||
return cache_features_;
|
return cache_features_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void layer::set_group_by(std::string column)
|
||||||
|
{
|
||||||
|
group_by_ = column;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string layer::group_by() const
|
||||||
|
{
|
||||||
|
return group_by_;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -583,7 +583,8 @@ void map_parser::parse_layer( Map & map, ptree const & lay )
|
||||||
<< "maxzoom,"
|
<< "maxzoom,"
|
||||||
<< "queryable,"
|
<< "queryable,"
|
||||||
<< "clear-label-cache,"
|
<< "clear-label-cache,"
|
||||||
<< "cache-features";
|
<< "cache-features,"
|
||||||
|
<< "group-by";
|
||||||
ensure_attrs(lay, "Layer", s.str());
|
ensure_attrs(lay, "Layer", s.str());
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
@ -644,6 +645,12 @@ void map_parser::parse_layer( Map & map, ptree const & lay )
|
||||||
lyr.set_cache_features( * cache_features );
|
lyr.set_cache_features( * cache_features );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
optional<std::string> group_by =
|
||||||
|
get_opt_attr<std::string>(lay, "group-by");
|
||||||
|
if (group_by)
|
||||||
|
{
|
||||||
|
lyr.set_group_by( * group_by );
|
||||||
|
}
|
||||||
|
|
||||||
ptree::const_iterator itr2 = lay.begin();
|
ptree::const_iterator itr2 = lay.begin();
|
||||||
ptree::const_iterator end2 = lay.end();
|
ptree::const_iterator end2 = lay.end();
|
||||||
|
|
|
@ -107,6 +107,11 @@ size_t memory_datasource::size() const
|
||||||
return features_.size();
|
return features_.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void memory_datasource::clear()
|
||||||
|
{
|
||||||
|
features_.clear();
|
||||||
|
}
|
||||||
|
|
||||||
// point_datasource
|
// point_datasource
|
||||||
|
|
||||||
void point_datasource::add_point(double x, double y, const char* key, const char* value)
|
void point_datasource::add_point(double x, double y, const char* key, const char* value)
|
||||||
|
|
|
@ -865,6 +865,11 @@ void serialize_layer( ptree & map_node, const layer & layer, bool explicit_defau
|
||||||
set_attr/*<bool>*/( layer_node, "cache-features", layer.cache_features() );
|
set_attr/*<bool>*/( layer_node, "cache-features", layer.cache_features() );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ( layer.group_by() != "" || explicit_defaults )
|
||||||
|
{
|
||||||
|
set_attr( layer_node, "group-by", layer.group_by() );
|
||||||
|
}
|
||||||
|
|
||||||
std::vector<std::string> const& style_names = layer.styles();
|
std::vector<std::string> const& style_names = layer.styles();
|
||||||
for (unsigned i = 0; i < style_names.size(); ++i)
|
for (unsigned i = 0; i < style_names.size(); ++i)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in a new issue