c++11 optimizations for faster map loading

This commit is contained in:
Dane Springmeyer 2014-04-28 17:10:00 -07:00
parent 73517c9104
commit ef837eb92f
15 changed files with 140 additions and 76 deletions

View file

@ -47,6 +47,16 @@ std::vector<layer>& (Map::*layers_nonconst)() = &Map::layers;
std::vector<layer> const& (Map::*layers_const)() const = &Map::layers;
mapnik::parameters& (Map::*params_nonconst)() = &Map::get_extra_parameters;
void insert_style(mapnik::Map & m, std::string const& name, mapnik::feature_type_style const& style)
{
m.insert_style(name,style);
}
void insert_fontset(mapnik::Map & m, std::string const& name, mapnik::font_set const& fontset)
{
m.insert_fontset(name,fontset);
}
mapnik::feature_type_style find_style(mapnik::Map const& m, std::string const& name)
{
boost::optional<mapnik::feature_type_style const&> style = m.find_style(name);
@ -163,7 +173,7 @@ void export_map()
"'+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs'\n"
))
.def("append_style",&Map::insert_style,
.def("append_style",insert_style,
(arg("style_name"),arg("style_object")),
"Insert a Mapnik Style onto the map by appending it.\n"
"\n"
@ -176,7 +186,7 @@ void export_map()
"False # you can only append styles with unique names\n"
)
.def("append_fontset",&Map::insert_fontset,
.def("append_fontset",insert_fontset,
(arg("fontset")),
"Add a FontSet to the map."
)

View file

@ -32,6 +32,10 @@
#include <mapnik/expression.hpp>
#include <mapnik/color_factory.hpp>
#include <mapnik/image_util.hpp>
#include <mapnik/unicode.hpp>
#include <mapnik/expression.hpp>
#include <mapnik/expression_string.hpp>
#include <mapnik/expression_grammar.hpp>
#if defined(HAVE_CAIRO)
#include <mapnik/cairo_renderer.hpp>
@ -54,6 +58,9 @@ int main ( int argc , char** argv)
datasource_cache::instance().register_datasources("plugins/input/");
freetype_engine::register_font("fonts/dejavu-fonts-ttf-2.33/ttf/DejaVuSans.ttf");
mapnik::transcoder tr("utf-8");
mapnik::expression_grammar<std::string::const_iterator> expr_grammar(tr);
Map m(800,600);
m.set_background(parse_color("white"));
m.set_srs(srs_merc);
@ -63,25 +70,25 @@ int main ( int argc , char** argv)
feature_type_style provpoly_style;
{
rule r;
r.set_filter(parse_expression("[NAME_EN] = 'Ontario'"));
r.set_filter(parse_expression("[NAME_EN] = 'Ontario'", expr_grammar));
{
polygon_symbolizer poly_sym;
put(poly_sym, keys::fill, color(250, 190, 183));
r.append(std::move(poly_sym));
}
provpoly_style.add_rule(r);
provpoly_style.add_rule(std::move(r));
}
{
rule r;
r.set_filter(parse_expression("[NOM_FR] = 'Québec'"));
r.set_filter(parse_expression("[NOM_FR] = 'Québec'", expr_grammar));
{
polygon_symbolizer poly_sym;
put(poly_sym, keys::fill, color(217, 235, 203));
r.append(std::move(poly_sym));
}
provpoly_style.add_rule(r);
provpoly_style.add_rule(std::move(r));
}
m.insert_style("provinces",provpoly_style);
m.insert_style("provinces", std::move(provpoly_style));
// Provinces (polyline)
feature_type_style provlines_style;
@ -98,29 +105,29 @@ int main ( int argc , char** argv)
put(line_sym,keys::stroke_dasharray,dash);
r.append(std::move(line_sym));
}
provlines_style.add_rule(r);
provlines_style.add_rule(std::move(r));
}
m.insert_style("provlines",provlines_style);
m.insert_style("provlines", std::move(provlines_style));
// Drainage
feature_type_style qcdrain_style;
{
rule r;
r.set_filter(parse_expression("[HYC] = 8"));
r.set_filter(parse_expression("[HYC] = 8", expr_grammar));
{
polygon_symbolizer poly_sym;
put(poly_sym, keys::fill, color(153, 204, 255));
r.append(std::move(poly_sym));
}
qcdrain_style.add_rule(r);
qcdrain_style.add_rule(std::move(r));
}
m.insert_style("drainage",qcdrain_style);
m.insert_style("drainage", std::move(qcdrain_style));
// Roads 3 and 4 (The "grey" roads)
feature_type_style roads34_style;
{
rule r;
r.set_filter(parse_expression("[CLASS] = 3 or [CLASS] = 4"));
r.set_filter(parse_expression("[CLASS] = 3 or [CLASS] = 4", expr_grammar));
{
line_symbolizer line_sym;
put(line_sym,keys::stroke,color(171,158,137));
@ -129,15 +136,15 @@ int main ( int argc , char** argv)
put(line_sym,keys::stroke_linejoin,ROUND_JOIN);
r.append(std::move(line_sym));
}
roads34_style.add_rule(r);
roads34_style.add_rule(std::move(r));
}
m.insert_style("smallroads",roads34_style);
m.insert_style("smallroads", std::move(roads34_style));
// Roads 2 (The thin yellow ones)
feature_type_style roads2_style_1;
{
rule r;
r.set_filter(parse_expression("[CLASS] = 2"));
r.set_filter(parse_expression("[CLASS] = 2", expr_grammar));
{
line_symbolizer line_sym;
put(line_sym,keys::stroke,color(171,158,137));
@ -146,14 +153,14 @@ int main ( int argc , char** argv)
put(line_sym,keys::stroke_linejoin,ROUND_JOIN);
r.append(std::move(line_sym));
}
roads2_style_1.add_rule(r);
roads2_style_1.add_rule(std::move(r));
}
m.insert_style("road-border", roads2_style_1);
m.insert_style("road-border", std::move(roads2_style_1));
feature_type_style roads2_style_2;
{
rule r;
r.set_filter(parse_expression("[CLASS] = 2"));
r.set_filter(parse_expression("[CLASS] = 2", expr_grammar));
{
line_symbolizer line_sym;
put(line_sym,keys::stroke,color(255,250,115));
@ -162,15 +169,15 @@ int main ( int argc , char** argv)
put(line_sym,keys::stroke_linejoin,ROUND_JOIN);
r.append(std::move(line_sym));
}
roads2_style_2.add_rule(r);
roads2_style_2.add_rule(std::move(r));
}
m.insert_style("road-fill", roads2_style_2);
m.insert_style("road-fill", std::move(roads2_style_2));
// Roads 1 (The big orange ones, the highways)
feature_type_style roads1_style_1;
{
rule r;
r.set_filter(parse_expression("[CLASS] = 1"));
r.set_filter(parse_expression("[CLASS] = 1", expr_grammar));
{
line_symbolizer line_sym;
put(line_sym,keys::stroke,color(188,149,28));
@ -179,14 +186,14 @@ int main ( int argc , char** argv)
put(line_sym,keys::stroke_linejoin,ROUND_JOIN);
r.append(std::move(line_sym));
}
roads1_style_1.add_rule(r);
roads1_style_1.add_rule(std::move(r));
}
m.insert_style("highway-border", roads1_style_1);
m.insert_style("highway-border", std::move(roads1_style_1));
feature_type_style roads1_style_2;
{
rule r;
r.set_filter(parse_expression("[CLASS] = 1"));
r.set_filter(parse_expression("[CLASS] = 1", expr_grammar));
{
line_symbolizer line_sym;
put(line_sym,keys::stroke,color(242,191,36));
@ -195,9 +202,9 @@ int main ( int argc , char** argv)
put(line_sym,keys::stroke_linejoin,ROUND_JOIN);
r.append(std::move(line_sym));
}
roads1_style_2.add_rule(r);
roads1_style_2.add_rule(std::move(r));
}
m.insert_style("highway-fill", roads1_style_2);
m.insert_style("highway-fill", std::move(roads1_style_2));
// Populated Places
feature_type_style popplaces_style;
@ -211,14 +218,14 @@ int main ( int argc , char** argv)
placement_finder->defaults.format->fill = color(0,0,0);
placement_finder->defaults.format->halo_fill = color(255,255,200);
placement_finder->defaults.format->halo_radius = 1;
placement_finder->defaults.set_old_style_expression(parse_expression("[GEONAME]"));
placement_finder->defaults.set_old_style_expression(parse_expression("[GEONAME]", expr_grammar));
put<text_placements_ptr>(text_sym, keys::text_placements_, placement_finder);
r.append(std::move(text_sym));
}
popplaces_style.add_rule(r);
popplaces_style.add_rule(std::move(r));
}
m.insert_style("popplaces",popplaces_style );
m.insert_style("popplaces", std::move(popplaces_style));
// layers
// Provincial polygons

View file

@ -68,7 +68,7 @@ public:
feature_type_style(feature_type_style const& rhs);
feature_type_style& operator=(feature_type_style rhs);
void add_rule(rule const& rule);
void add_rule(rule && rule);
rules const& get_rules() const;
rules& get_rules_nonconst();
@ -89,6 +89,10 @@ public:
float get_opacity() const;
void set_image_filters_inflate(bool inflate);
bool image_filters_inflate() const;
inline void reserve(std::size_t size)
{
rules_.reserve(size);
}
~feature_type_style() {}

View file

@ -162,6 +162,7 @@ public:
* false If no success.
*/
bool insert_style(std::string const& name,feature_type_style const& style);
bool insert_style(std::string const& name,feature_type_style && style);
/*! \brief Remove a style from the map.
* @param name The name of the style.
@ -181,6 +182,7 @@ public:
* false If failure.
*/
bool insert_fontset(std::string const& name, font_set const& fontset);
bool insert_fontset(std::string const& name, font_set && fontset);
/*! \brief Find a fontset.
* @param name The name of the fontset.

View file

@ -82,6 +82,10 @@ public:
{
return ( scale >= min_scale_ - 1e-6 && scale < max_scale_ + 1e-6 && !syms_.empty());
}
inline void reserve(std::size_t size)
{
syms_.reserve(size);
}
private:

View file

@ -43,7 +43,7 @@ class xml_tree;
class xml_attribute
{
public:
xml_attribute(std::string const& value);
xml_attribute(const char * value_);
std::string value;
mutable bool processed;
};
@ -84,7 +84,7 @@ class xml_node
public:
typedef std::list<xml_node>::const_iterator const_iterator;
typedef std::map<std::string, xml_attribute> attribute_map;
xml_node(xml_tree &tree, std::string const& name, unsigned line=0, bool is_text = false);
xml_node(xml_tree &tree, std::string && name, unsigned line=0, bool is_text = false);
std::string const& name() const;
std::string const& text() const;
@ -92,8 +92,8 @@ public:
bool is_text() const;
bool is(std::string const& name) const;
xml_node &add_child(std::string const& name, unsigned line=0, bool is_text = false);
void add_attribute(std::string const& name, std::string const& value);
xml_node & add_child(std::string && name, unsigned line=0, bool is_text = false);
void add_attribute(const char * name, const char * value);
attribute_map const& get_attributes() const;
bool processed() const;
@ -102,6 +102,7 @@ public:
unsigned line() const;
std::string line_to_string() const;
std::size_t size() const;
const_iterator begin() const;
const_iterator end() const;

View file

@ -25,6 +25,7 @@
// mapnik
#include <mapnik/xml_node.hpp>
#include <mapnik/expression.hpp>
#include <mapnik/expression_grammar.hpp>
#include <mapnik/path_expression_grammar.hpp>
#include <mapnik/transform_expression_grammar.hpp>
@ -52,6 +53,8 @@ private:
std::string file_;
transcoder tr_;
public:
mutable std::map<std::string,mapnik::color> color_cache_;
mutable std::map<std::string,mapnik::expression_ptr> expr_cache_;
mapnik::css_color_grammar<std::string::const_iterator> color_grammar;
mapnik::expression_grammar<std::string::const_iterator> expr_grammar;
path_expression_grammar<std::string::const_iterator> path_expr_grammar;

View file

@ -46,7 +46,7 @@ color parse_color(std::string const& str,
c);
if (result && (first == last))
{
return c;
return std::move(c);
}
else
{

View file

@ -66,9 +66,9 @@ feature_type_style& feature_type_style::operator=(feature_type_style rhs)
return *this;
}
void feature_type_style::add_rule(rule const& rule)
void feature_type_style::add_rule(rule && rule)
{
rules_.push_back(rule);
rules_.push_back(std::move(rule));
}
rules const& feature_type_style::get_rules() const

View file

@ -150,15 +150,15 @@ public:
}
private:
void append_attributes(xmlAttr *attributes, xml_node &node)
void inline append_attributes(xmlAttr *attributes, xml_node & node)
{
for (; attributes; attributes = attributes->next )
{
node.add_attribute((const char *)attributes->name, (const char *)attributes->children->content);
node.add_attribute((const char *)attributes->name,(const char *)attributes->children->content);
}
}
void populate_tree(xmlNode *cur_node, xml_node &node)
void inline populate_tree(xmlNode *cur_node, xml_node &node)
{
for (; cur_node; cur_node = cur_node->next )
{
@ -166,8 +166,8 @@ private:
{
case XML_ELEMENT_NODE:
{
xml_node &new_node = node.add_child((const char *)cur_node->name, cur_node->line, false);
std::string name((const char *)cur_node->name);
xml_node &new_node = node.add_child(std::move(name), cur_node->line, false);
append_attributes(cur_node->properties, new_node);
populate_tree(cur_node->children, new_node);
}
@ -177,7 +177,7 @@ private:
std::string trimmed((const char*)cur_node->content);
mapnik::util::trim(trimmed);
if (trimmed.empty()) break; //Don't add empty text nodes
node.add_child(trimmed, cur_node->line, true);
node.add_child(std::move(trimmed), cur_node->line, true);
}
break;
case XML_COMMENT_NODE:

View file

@ -235,7 +235,7 @@ void map_parser::parse_map(Map & map, xml_node const& pt, std::string const& bas
try
{
// create throwaway projection object here to ensure it is valid
projection proj(srs);
projection proj(srs,true);
}
catch (std::exception const& ex)
{
@ -366,7 +366,7 @@ void map_parser::parse_map_include(Map & map, xml_node const& include)
{
std::string name = itr->get_attr<std::string>("name");
std::string value = itr->get_text();
file_sources_[name] = value;
file_sources_[std::move(name)] = std::move(value);
}
else if (itr->is("Datasource"))
{
@ -380,10 +380,10 @@ void map_parser::parse_map_include(Map & map, xml_node const& include)
{
std::string param_name = paramIter->get_attr<std::string>("name");
std::string value = paramIter->get_text();
params[param_name] = value;
params[std::move(param_name)] = std::move(value);
}
}
datasource_templates_[name] = params;
datasource_templates_[name] = std::move(params);
}
else if (itr->is("Parameters"))
{
@ -403,20 +403,20 @@ void map_parser::parse_map_include(Map & map, xml_node const& include)
{
is_string = false;
mapnik::value_integer value = paramIter->get_value<mapnik::value_integer>();
params[name] = value;
params[std::move(name)] = std::move(value);
}
else if (*type == "float")
{
is_string = false;
double value = paramIter->get_value<mapnik::value_double>();
params[name] = value;
params[std::move(name)] = std::move(value);
}
}
if (is_string)
{
std::string value = paramIter->get_text();
params[name] = value;
params[std::move(name)] = std::move(value);
}
}
}
@ -467,12 +467,18 @@ void map_parser::parse_style(Map & map, xml_node const& sty)
optional<std::string> filters = sty.get_opt_attr<std::string>("image-filters");
if (filters)
{
std::string filter_str = *filters;
bool result = filter::parse_image_filters(filter_str, style.image_filters());
if (!result)
std::string::const_iterator itr = filters->begin();
std::string::const_iterator end = filters->end();
boost::spirit::qi::ascii::space_type space;
bool result = boost::spirit::qi::phrase_parse(itr,end,
sty.get_tree().image_filters_grammar,
space,
style.image_filters());
if (!result || itr!=end)
{
throw config_error("failed to parse image-filters: '" + filter_str + "'");
throw config_error("failed to parse image-filters: '" + std::string(itr,end) + "'");
}
}
// direct image filters (applied directly on main image buffer
@ -482,9 +488,8 @@ void map_parser::parse_style(Map & map, xml_node const& sty)
optional<std::string> direct_filters = sty.get_opt_attr<std::string>("direct-image-filters");
if (direct_filters)
{
std::string filter_str = *direct_filters;
std::string::const_iterator itr = filter_str.begin();
std::string::const_iterator end = filter_str.end();
std::string::const_iterator itr = direct_filters->begin();
std::string::const_iterator end = direct_filters->end();
boost::spirit::qi::ascii::space_type space;
bool result = boost::spirit::qi::phrase_parse(itr,end,
sty.get_tree().image_filters_grammar,
@ -496,6 +501,7 @@ void map_parser::parse_style(Map & map, xml_node const& sty)
}
}
style.reserve(sty.size());
// rules
for (auto const& rule_ : sty)
{
@ -504,7 +510,7 @@ void map_parser::parse_style(Map & map, xml_node const& sty)
parse_rule(style, rule_);
}
}
map.insert_style(name, style);
map.insert_style(name, std::move(style));
}
catch (config_error const& ex)
{
@ -541,11 +547,11 @@ void map_parser::parse_fontset(Map & map, xml_node const& fset)
throw mapnik::config_error("no valid fonts could be loaded");
}
map.insert_fontset(name, fontset);
map.insert_fontset(name, std::move(fontset));
// XXX Hack because map object isn't accessible by text_symbolizer
// when it's parsed
fontsets_.insert(std::pair<std::string, font_set>(name, fontset));
fontsets_.insert(std::move(std::make_pair(name, fontset)));
}
catch (config_error const& ex)
{
@ -590,7 +596,7 @@ void map_parser::parse_layer(Map & map, xml_node const& node)
try
{
// create throwaway projection object here to ensure it is valid
projection proj(srs);
projection proj(srs,true);
}
catch (std::exception const& ex)
{
@ -807,7 +813,7 @@ void map_parser::parse_rule(feature_type_style & style, xml_node const& node)
}
parse_symbolizers(rule, node);
style.add_rule(rule);
style.add_rule(std::move(rule));
}
catch (config_error const& ex)
@ -822,6 +828,7 @@ void map_parser::parse_rule(feature_type_style & style, xml_node const& node)
void map_parser::parse_symbolizers(rule & rule, xml_node const & node)
{
rule.reserve(node.size());
for (auto const& sym_node : node)
{
switch (name2int(sym_node.name().c_str()))
@ -1378,14 +1385,18 @@ void map_parser::parse_stroke(symbolizer_base & symbol, xml_node const & sym)
{
size_t size = buf.size();
if (size % 2 == 1)
{
buf.insert(buf.end(),buf.begin(),buf.end());
}
dash_array dash;
std::vector<double>::const_iterator pos = buf.begin();
while (pos != buf.end())
{
if (*pos > 0.0 || *(pos+1) > 0.0) // avoid both dash and gap eq 0.0
{
dash.emplace_back(*pos,*(pos + 1));
}
pos +=2;
}
if (dash.size() > 0)

View file

@ -137,9 +137,15 @@ Map::const_style_iterator Map::end_styles() const
return styles_.end();
}
// TODO(dane) - only kept for python bindings, can we avoid needing?
bool Map::insert_style(std::string const& name,feature_type_style const& style)
{
return styles_.insert(make_pair(name,style)).second;
return styles_.insert(std::move(make_pair(name,style))).second;
}
bool Map::insert_style(std::string const& name,feature_type_style && style)
{
return styles_.insert(std::move(make_pair(name,std::move(style)))).second;
}
void Map::remove_style(std::string const& name)
@ -162,7 +168,16 @@ bool Map::insert_fontset(std::string const& name, font_set const& fontset)
{
throw mapnik::config_error("Fontset name must match the name used to reference it on the map");
}
return fontsets_.insert(make_pair(name, fontset)).second;
return fontsets_.insert(std::move(make_pair(name, fontset))).second;
}
bool Map::insert_fontset(std::string const& name, font_set && fontset)
{
if (fontset.get_name() != name)
{
throw mapnik::config_error("Fontset name must match the name used to reference it on the map");
}
return fontsets_.insert(std::move(make_pair(name, std::move(fontset)))).second;
}
boost::optional<font_set const&> Map::find_fontset(std::string const& name) const

View file

@ -126,8 +126,9 @@ const xml_node &xml_tree::root() const
return node_;
}
xml_attribute::xml_attribute(std::string const& value_)
: value(value_), processed(false)
xml_attribute::xml_attribute(const char * value_)
: value(value_),
processed(false)
{
}
@ -167,9 +168,9 @@ const char* more_than_one_child::what() const throw()
more_than_one_child::~more_than_one_child() throw() {}
xml_node::xml_node(xml_tree &tree, std::string const& name, unsigned line, bool is_text)
xml_node::xml_node(xml_tree &tree, std::string && name, unsigned line, bool is_text)
: tree_(tree),
name_(name),
name_(std::move(name)),
is_text_(is_text),
line_(line),
processed_(false) {}
@ -221,15 +222,15 @@ bool xml_node::is(std::string const& name) const
return false;
}
xml_node &xml_node::add_child(std::string const& name, unsigned line, bool is_text)
xml_node &xml_node::add_child(std::string && name, unsigned line, bool is_text)
{
children_.push_back(xml_node(tree_, name, line, is_text));
children_.emplace_back(tree_, std::move(name), line, is_text);
return children_.back();
}
void xml_node::add_attribute(std::string const& name, std::string const& value)
void xml_node::add_attribute(const char * name, const char * value)
{
attributes_.insert(std::make_pair(name,xml_attribute(value)));
attributes_.insert(std::move(std::make_pair(name,std::move(xml_attribute(value)))));
}
xml_node::attribute_map const& xml_node::get_attributes() const
@ -247,6 +248,11 @@ bool xml_node::processed() const
return processed_;
}
std::size_t xml_node::size() const
{
return children_.size();
}
xml_node::const_iterator xml_node::begin() const
{
return children_.begin();
@ -302,6 +308,7 @@ bool xml_node::has_child(std::string const& name) const
template <typename T>
boost::optional<T> xml_node::get_opt_attr(std::string const& name) const
{
if (attributes_.empty()) return boost::optional<T>();
std::map<std::string, xml_attribute>::const_iterator itr = attributes_.find(name);
if (itr == attributes_.end()) return boost::optional<T>();
itr->second.processed = true;
@ -333,7 +340,7 @@ T xml_node::get_attr(std::string const& name) const
std::string xml_node::get_text() const
{
if (children_.size() == 0)
if (children_.empty())
{
if (is_text_)
{

View file

@ -56,7 +56,7 @@ int main(int argc, char** argv)
r.set_filter(mapnik::parse_expression("[foo]='bar'"));
r.append(std::move(mapnik::markers_symbolizer()));
mapnik::feature_type_style style;
style.add_rule(r);
style.add_rule(std::move(r));
map.insert_style("style",style);
std::string csv_plugin("./plugins/input/csv.input");

View file

@ -69,7 +69,7 @@ int main(int argc, char** argv)
placement_finder->defaults.set_old_style_expression(mapnik::parse_expression("[name]"));
mapnik::put<mapnik::text_placements_ptr>(text_sym, mapnik::keys::text_placements_, placement_finder);
r.append(std::move(text_sym));
the_style.add_rule(r);
the_style.add_rule(std::move(r));
m.insert_style("style",the_style );
m.zoom_to_box(mapnik::box2d<double>(-256,-256,
256,256));