From fc6a22c014bd04b417eff13747d33be2a92502a2 Mon Sep 17 00:00:00 2001 From: artemp Date: Wed, 1 Aug 2012 11:07:45 +0100 Subject: [PATCH 1/2] + c++ style --- include/mapnik/attribute_collector.hpp | 6 ++--- src/feature_style_processor.cpp | 35 +++++++++++++------------- 2 files changed, 20 insertions(+), 21 deletions(-) diff --git a/include/mapnik/attribute_collector.hpp b/include/mapnik/attribute_collector.hpp index f814d1ac5..81cdad888 100644 --- a/include/mapnik/attribute_collector.hpp +++ b/include/mapnik/attribute_collector.hpp @@ -249,7 +249,7 @@ public: struct directive_collector : public boost::static_visitor<> { - directive_collector(double * filter_factor) + directive_collector(double & filter_factor) : filter_factor_(filter_factor) {} template @@ -257,10 +257,10 @@ struct directive_collector : public boost::static_visitor<> void operator () (raster_symbolizer const& sym) { - *filter_factor_ = sym.calculate_filter_factor(); + filter_factor_ = sym.calculate_filter_factor(); } private: - double * filter_factor_; + double & filter_factor_; }; } // namespace mapnik diff --git a/src/feature_style_processor.cpp b/src/feature_style_processor.cpp index a8e0fc8cd..7bc161f6a 100644 --- a/src/feature_style_processor.cpp +++ b/src/feature_style_processor.cpp @@ -101,35 +101,35 @@ struct feature_style_processor::symbol_dispatch : public boost::stati : output_(output), f_(f), prj_trans_(prj_trans) {} - + template void operator () (T const& sym) const { process_impl::value>::process(output_,sym,f_,prj_trans_); } - + Processor & output_; mapnik::feature_impl & f_; proj_transform const& prj_trans_; }; -typedef char (&no_tag)[1]; -typedef char (&yes_tag)[2]; +typedef char (&no_tag)[1]; +typedef char (&yes_tag)[2]; template -struct process_memfun_helper {}; - -template no_tag has_process_helper(...); +struct process_memfun_helper {}; + +template no_tag has_process_helper(...); template yes_tag has_process_helper(process_memfun_helper* p); - -template + +template struct has_process -{ +{ typedef typename T0::processor_impl_type processor_impl_type; - BOOST_STATIC_CONSTANT(bool - , value = sizeof(has_process_helper(0)) == sizeof(yes_tag) - ); -}; + BOOST_STATIC_CONSTANT(bool + , value = sizeof(has_process_helper(0)) == sizeof(yes_tag) + ); +}; template @@ -350,8 +350,8 @@ void feature_style_processor::apply_to_layer(layer const& lay, Proces query q(layer_ext,res,scale_denom,m_.get_current_extent()); std::vector active_styles; attribute_collector collector(names); - double filt_factor = 1; - directive_collector d_collector(&filt_factor); + double filt_factor = 1.0; + directive_collector d_collector(filt_factor); // iterate through all named styles collecting active styles and attribute names BOOST_FOREACH(std::string const& style_name, style_names) @@ -519,7 +519,7 @@ void feature_style_processor::render_style( { p.start_style_processing(*style); - + #if defined(RENDERING_STATS) std::ostringstream s1; s1 << "rendering style for layer: '" << lay.name() @@ -661,4 +661,3 @@ template class feature_style_processor >; template class feature_style_processor >; } - From 5541ea027138c4d8f6d469152df7c58d0146f100 Mon Sep 17 00:00:00 2001 From: artemp Date: Wed, 1 Aug 2012 15:44:36 +0100 Subject: [PATCH 2/2] + layer : minimum-extent and buffer-size + agg::process_xxx : remove ad-hoc query_extent modifiers + ctrans : simplify vertex skipping --- bindings/python/mapnik_layer.cpp | 33 +++++++++++ bindings/python/mapnik_map.cpp | 7 +-- include/mapnik/ctrans.hpp | 25 +++------ include/mapnik/layer.hpp | 13 ++++- include/mapnik/map.hpp | 6 +- src/agg/agg_renderer.cpp | 17 ++++++ src/agg/process_line_pattern_symbolizer.cpp | 20 +++---- src/agg/process_line_symbolizer.cpp | 2 +- src/agg/process_markers_symbolizer.cpp | 6 +- .../process_polygon_pattern_symbolizer.cpp | 3 +- src/agg/process_polygon_symbolizer.cpp | 6 +- src/feature_style_processor.cpp | 4 +- src/layer.cpp | 34 +++++++++++- src/load_map.cpp | 55 ++++++++++++++----- src/map.cpp | 6 +- src/save_map.cpp | 18 +++++- 16 files changed, 187 insertions(+), 68 deletions(-) diff --git a/bindings/python/mapnik_layer.cpp b/bindings/python/mapnik_layer.cpp index 0b2e8d63b..ae99e5971 100644 --- a/bindings/python/mapnik_layer.cpp +++ b/bindings/python/mapnik_layer.cpp @@ -91,6 +91,18 @@ struct layer_pickle_suite : boost::python::pickle_suite std::vector & (mapnik::layer::*_styles_)() = &mapnik::layer::styles; +void set_maximum_extent(mapnik::layer & l, boost::optional > const& box) +{ + if (box) + { + l.set_maximum_extent(*box); + } + else + { + l.reset_maximum_extent(); + } +} + void export_layer() { using namespace boost::python; @@ -196,6 +208,27 @@ void export_layer() "\n" ) + .add_property("buffer_size", + &layer::buffer_size, + &layer::set_buffer_size, + "Get/Set the size of buffer around layer in pixels.\n" + "\n" + "Usage:\n" + ">>> l.buffer_size\n" + "0 # zero by default\n" + ">>> l.buffer_size = 2\n" + ">>> l.buffer_size\n" + "2\n" + ) + .add_property("maximum_extent",make_function + (&layer::maximum_extent,return_value_policy()), + &set_maximum_extent, + "The maximum extent of the map.\n" + "\n" + "Usage:\n" + ">>> m.maximum_extent = Box2d(-180,-90,180,90)\n" + ) + .add_property("maxzoom", &layer::max_zoom, &layer::set_max_zoom, diff --git a/bindings/python/mapnik_map.cpp b/bindings/python/mapnik_map.cpp index 3bc1ca983..e2a21e674 100644 --- a/bindings/python/mapnik_map.cpp +++ b/bindings/python/mapnik_map.cpp @@ -117,7 +117,7 @@ struct map_pickle_suite : boost::python::pickle_suite std::vector& (Map::*layers_nonconst)() = &Map::layers; std::vector const& (Map::*layers_const)() const = &Map::layers; mapnik::parameters& (Map::*params_nonconst)() = &Map::get_extra_parameters; -boost::optional > const& (Map::*maximum_extent_const)() const = &Map::maximum_extent; +//boost::optional > const& (Map::*maximum_extent_const)() const = &Map::maximum_extent; mapnik::feature_type_style find_style(mapnik::Map const& m, std::string const& name) { @@ -192,7 +192,6 @@ mapnik::Map map_deepcopy(mapnik::Map & m, boost::python::dict memo) return result; } -// TODO - find a simplier way to set optional to uninitialized void set_maximum_extent(mapnik::Map & m, boost::optional > const& box) { if (box) @@ -201,7 +200,7 @@ void set_maximum_extent(mapnik::Map & m, boost::optional > } else { - m.maximum_extent().reset(); + m.reset_maximum_extent(); } } @@ -562,7 +561,7 @@ void export_map() ) .add_property("maximum_extent",make_function - (maximum_extent_const,return_value_policy()), + (&Map::maximum_extent,return_value_policy()), &set_maximum_extent, "The maximum extent of the map.\n" "\n" diff --git a/include/mapnik/ctrans.hpp b/include/mapnik/ctrans.hpp index a06872422..a56bc4bc4 100644 --- a/include/mapnik/ctrans.hpp +++ b/include/mapnik/ctrans.hpp @@ -52,34 +52,25 @@ struct MAPNIK_DECL coord_transform : t_(0), geom_(geom), prj_trans_(0) {} - + void set_proj_trans(proj_transform const& prj_trans) { prj_trans_ = &prj_trans; } - + void set_trans(Transform const& t) { t_ = &t; } - + unsigned vertex(double *x, double *y) const { - unsigned command = SEG_MOVETO; - bool ok = false; - bool skipped_points = false; - double z = 0; - while (!ok && command != SEG_END) + unsigned command = geom_.vertex(x, y); + if ( command != SEG_END) { - command = geom_.vertex(x, y); - ok = prj_trans_->backward(*x, *y, z); - if (!ok) { - skipped_points = true; - } - } - if (skipped_points && (command == SEG_LINETO)) - { - command = SEG_MOVETO; + double z = 0; + if (!prj_trans_->backward(*x, *y, z)) + return SEG_END; } t_->forward(x, y); return command; diff --git a/include/mapnik/layer.hpp b/include/mapnik/layer.hpp index ab0eb4a8e..1be1b23c0 100644 --- a/include/mapnik/layer.hpp +++ b/include/mapnik/layer.hpp @@ -43,7 +43,9 @@ namespace mapnik class MAPNIK_DECL layer { public: - explicit layer(std::string const& name, std::string const& srs="+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs"); + layer(std::string const& name, + std::string const& srs="+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs"); + layer(layer const& l); layer& operator=(layer const& l); bool operator==(layer const& other) const; @@ -57,7 +59,7 @@ public: * @return the name of the layer. */ - const std::string& name() const; + std::string const& name() const; /*! * @brief Set the SRS of the layer. @@ -188,6 +190,11 @@ public: */ box2d envelope() const; + void set_maximum_extent(box2d const& box); + boost::optional > const& maximum_extent() const; + void reset_maximum_extent(); + void set_buffer_size(int size); + int buffer_size() const; ~layer(); private: void swap(const layer& other); @@ -204,6 +211,8 @@ private: std::string group_by_; std::vector styles_; datasource_ptr ds_; + int buffer_size_; + boost::optional > maximum_extent_; }; } diff --git a/include/mapnik/map.hpp b/include/mapnik/map.hpp index bfbf87edd..400f081ac 100644 --- a/include/mapnik/map.hpp +++ b/include/mapnik/map.hpp @@ -331,15 +331,13 @@ public: /*! \brief Set the map maximum extent. * @param box The bounding box for the maximum extent. */ - void set_maximum_extent(box2dconst& box); + void set_maximum_extent(box2d const& box); /*! \brief Get the map maximum extent as box2d */ boost::optional > const& maximum_extent() const; - /*! \brief Get the non-const map maximum extent as box2d - */ - boost::optional > & maximum_extent(); + void reset_maximum_extent(); /*! \brief Get the map base path where paths should be relative to. */ diff --git a/src/agg/agg_renderer.cpp b/src/agg/agg_renderer.cpp index 92cda8973..77ae1e752 100644 --- a/src/agg/agg_renderer.cpp +++ b/src/agg/agg_renderer.cpp @@ -191,7 +191,24 @@ void agg_renderer::start_layer_processing(layer const& lay, box2d con { detector_->clear(); } + query_extent_ = query_extent; + int buffer_size = lay.buffer_size(); + if (buffer_size != 0 ) + { + double padding = buffer_size * (double)(query_extent.width()/pixmap_.width()); + double x0 = query_extent_.minx(); + double y0 = query_extent_.miny(); + double x1 = query_extent_.maxx(); + double y1 = query_extent_.maxy(); + query_extent_.init(x0 - padding, y0 - padding, x1 + padding , y1 + padding); + } + + boost::optional > const& maximum_extent = lay.maximum_extent(); + if (maximum_extent) + { + query_extent_.clip(*maximum_extent); + } } template diff --git a/src/agg/process_line_pattern_symbolizer.cpp b/src/agg/process_line_pattern_symbolizer.cpp index 5f79a7755..e8c50209b 100644 --- a/src/agg/process_line_pattern_symbolizer.cpp +++ b/src/agg/process_line_pattern_symbolizer.cpp @@ -56,7 +56,7 @@ void agg_renderer::process(line_pattern_symbolizer const& sym, { typedef agg::rgba8 color; typedef agg::order_rgba order; - typedef agg::pixel32_type pixel_type; + typedef agg::pixel32_type pixel_type; typedef agg::comp_op_adaptor_rgba_pre blender_type; typedef agg::pattern_filter_bilinear_rgba8 pattern_filter_type; typedef agg::line_image_pattern pattern_type; @@ -64,7 +64,7 @@ void agg_renderer::process(line_pattern_symbolizer const& sym, typedef agg::renderer_base renderer_base; typedef agg::renderer_outline_image renderer_type; typedef agg::rasterizer_outline_aa rasterizer_type; - + std::string filename = path_processor_type::evaluate( *sym.get_filename(), feature); boost::optional mark = marker_cache::instance()->find(filename,true); @@ -81,8 +81,6 @@ void agg_renderer::process(line_pattern_symbolizer const& sym, if (!pat) return; - box2d ext = query_extent_ * 1.0; - agg::rendering_buffer buf(current_buffer_->raw_data(),width_,height_, width_ * 4); pixfmt_type pixf(buf); pixf.comp_op(static_cast(sym.comp_op())); @@ -91,26 +89,26 @@ void agg_renderer::process(line_pattern_symbolizer const& sym, pattern_source source(*(*pat)); pattern_type pattern (filter,source); - renderer_type ren(ren_base, pattern); + renderer_type ren(ren_base, pattern); rasterizer_type ras(ren); - + agg::trans_affine tr; evaluate_transform(tr, feature, sym.get_transform()); typedef boost::mpl::vector conv_types; vertex_converter, rasterizer_type, line_pattern_symbolizer, CoordTransform, proj_transform, agg::trans_affine, conv_types> - converter(ext,ras,sym,t_,prj_trans,tr,scale_factor_); - + converter(query_extent_,ras,sym,t_,prj_trans,tr,scale_factor_); + if (sym.clip()) converter.set(); //optional clip (default: true) - converter.set(); //always transform + converter.set(); //always transform if (sym.smooth() > 0.0) converter.set(); // optional smooth converter - + BOOST_FOREACH(geometry_type & geom, feature.paths()) { if (geom.size() > 1) { - converter.apply(geom); + converter.apply(geom); } } } diff --git a/src/agg/process_line_symbolizer.cpp b/src/agg/process_line_symbolizer.cpp index ec75035b4..bc02c8739 100644 --- a/src/agg/process_line_symbolizer.cpp +++ b/src/agg/process_line_symbolizer.cpp @@ -80,7 +80,7 @@ void agg_renderer::process(line_symbolizer const& sym, agg::trans_affine tr; evaluate_transform(tr, feature, sym.get_transform()); - box2d ext = query_extent_ * 1.1; + box2d ext = query_extent_ * 1.0; if (sym.get_rasterizer() == RASTERIZER_FAST) { diff --git a/src/agg/process_markers_symbolizer.cpp b/src/agg/process_markers_symbolizer.cpp index 451323f5b..9a32f0424 100644 --- a/src/agg/process_markers_symbolizer.cpp +++ b/src/agg/process_markers_symbolizer.cpp @@ -363,7 +363,7 @@ void agg_renderer::process(markers_symbolizer const& sym, bbox, marker_trans, sym, *detector_, scale_factor_); vertex_converter, dispatch_type, markers_symbolizer, CoordTransform, proj_transform, agg::trans_affine, conv_types> - converter(query_extent_* 1.1,rasterizer_dispatch, sym,t_,prj_trans,tr,scale_factor_); + converter(query_extent_, rasterizer_dispatch, sym,t_,prj_trans,tr,scale_factor_); if (sym.clip() && feature.paths().size() > 0) // optional clip (default: true) { eGeomType type = feature.paths()[0].type(); @@ -396,7 +396,7 @@ void agg_renderer::process(markers_symbolizer const& sym, bbox, marker_trans, sym, *detector_, scale_factor_); vertex_converter, dispatch_type, markers_symbolizer, CoordTransform, proj_transform, agg::trans_affine, conv_types> - converter(query_extent_* 1.1,rasterizer_dispatch, sym,t_,prj_trans,tr,scale_factor_); + converter(query_extent_, rasterizer_dispatch, sym,t_,prj_trans,tr,scale_factor_); if (sym.clip() && feature.paths().size() > 0) // optional clip (default: true) { eGeomType type = feature.paths()[0].type(); @@ -427,7 +427,7 @@ void agg_renderer::process(markers_symbolizer const& sym, marker_trans, sym, *detector_, scale_factor_); vertex_converter, dispatch_type, markers_symbolizer, CoordTransform, proj_transform, agg::trans_affine, conv_types> - converter(query_extent_* 1.1, rasterizer_dispatch, sym,t_,prj_trans,tr,scale_factor_); + converter(query_extent_, rasterizer_dispatch, sym,t_,prj_trans,tr,scale_factor_); if (sym.clip() && feature.paths().size() > 0) // optional clip (default: true) { diff --git a/src/agg/process_polygon_pattern_symbolizer.cpp b/src/agg/process_polygon_pattern_symbolizer.cpp index 2a5ec53d3..a8b5a7c9f 100644 --- a/src/agg/process_polygon_pattern_symbolizer.cpp +++ b/src/agg/process_polygon_pattern_symbolizer.cpp @@ -139,11 +139,10 @@ void agg_renderer::process(polygon_pattern_symbolizer const& sym, agg::trans_affine tr; evaluate_transform(tr, feature, sym.get_transform()); - box2d inflated_extent = query_extent_ * 1.0; typedef boost::mpl::vector conv_types; vertex_converter, rasterizer, polygon_pattern_symbolizer, CoordTransform, proj_transform, agg::trans_affine, conv_types> - converter(inflated_extent,*ras_ptr,sym,t_,prj_trans,tr,scale_factor_); + converter(query_extent_,*ras_ptr,sym,t_,prj_trans,tr,scale_factor_); if (sym.clip()) converter.set(); //optional clip (default: true) converter.set(); //always transform diff --git a/src/agg/process_polygon_symbolizer.cpp b/src/agg/process_polygon_symbolizer.cpp index 2b1266659..323f987ef 100644 --- a/src/agg/process_polygon_symbolizer.cpp +++ b/src/agg/process_polygon_symbolizer.cpp @@ -48,15 +48,13 @@ void agg_renderer::process(polygon_symbolizer const& sym, ras_ptr->reset(); set_gamma_method(sym,ras_ptr); - box2d inflated_extent = query_extent_ * 1.0; - agg::trans_affine tr; evaluate_transform(tr, feature, sym.get_transform()); typedef boost::mpl::vector conv_types; vertex_converter, rasterizer, polygon_symbolizer, CoordTransform, proj_transform, agg::trans_affine, conv_types> - converter(inflated_extent,*ras_ptr,sym,t_,prj_trans,tr,scale_factor_); + converter(query_extent_,*ras_ptr,sym,t_,prj_trans,tr,scale_factor_); if (sym.clip()) converter.set(); //optional clip (default: true) converter.set(); //always transform @@ -72,7 +70,7 @@ void agg_renderer::process(polygon_symbolizer const& sym, } agg::rendering_buffer buf(current_buffer_->raw_data(),width_,height_, width_ * 4); - + color const& fill = sym.get_fill(); unsigned r=fill.red(); unsigned g=fill.green(); diff --git a/src/feature_style_processor.cpp b/src/feature_style_processor.cpp index 7bc161f6a..d22d8caf1 100644 --- a/src/feature_style_processor.cpp +++ b/src/feature_style_processor.cpp @@ -320,9 +320,11 @@ void feature_style_processor::apply_to_layer(layer const& lay, Proces // if we've got this far, now prepare the unbuffered extent // which is used as a bbox for clipping geometries box2d query_ext = m_.get_current_extent(); // unbuffered - if (maximum_extent) { + if (maximum_extent) + { query_ext.clip(*maximum_extent); } + box2d layer_ext2 = lay.envelope(); if (fw_success) { diff --git a/src/layer.cpp b/src/layer.cpp index 985eb5bad..09fbb0eb6 100644 --- a/src/layer.cpp +++ b/src/layer.cpp @@ -42,7 +42,8 @@ layer::layer(std::string const& name, std::string const& srs) clear_label_cache_(false), cache_features_(false), group_by_(""), - ds_() {} + ds_(), + buffer_size_(0) {} layer::layer(const layer& rhs) : name_(rhs.name_), @@ -55,7 +56,9 @@ layer::layer(const layer& rhs) cache_features_(rhs.cache_features_), group_by_(rhs.group_by_), styles_(rhs.styles_), - ds_(rhs.ds_) {} + ds_(rhs.ds_), + buffer_size_(rhs.buffer_size_), + maximum_extent_(rhs.maximum_extent_) {} layer& layer::operator=(const layer& rhs) { @@ -82,6 +85,8 @@ void layer::swap(const layer& rhs) group_by_ = rhs.group_by_; styles_=rhs.styles_; ds_=rhs.ds_; + buffer_size_ = rhs.buffer_size_; + maximum_extent_ = rhs.maximum_extent_; } layer::~layer() {} @@ -176,6 +181,31 @@ void layer::set_datasource(datasource_ptr const& ds) ds_ = ds; } +void layer::set_maximum_extent(box2d const& box) +{ + maximum_extent_.reset(box); +} + +boost::optional > const& layer::maximum_extent() const +{ + return maximum_extent_; +} + +void layer::reset_maximum_extent() +{ + maximum_extent_.reset(); +} + +void layer::set_buffer_size(int size) +{ + buffer_size_ = size; +} + +int layer::buffer_size() const +{ + return buffer_size_; +} + box2d layer::envelope() const { if (ds_) return ds_->envelope(); diff --git a/src/load_map.cpp b/src/load_map.cpp index f834e8202..9c0cebd93 100644 --- a/src/load_map.cpp +++ b/src/load_map.cpp @@ -574,66 +574,95 @@ bool map_parser::parse_font(font_set &fset, xml_node const& f) return false; } -void map_parser::parse_layer(Map & map, xml_node const& lay) +void map_parser::parse_layer(Map & map, xml_node const& node) { std::string name; try { - name = lay.get_attr("name", std::string("Unnamed")); + name = node.get_attr("name", std::string("Unnamed")); // XXX if no projection is given inherit from map? [DS] - std::string srs = lay.get_attr("srs", map.srs()); + std::string srs = node.get_attr("srs", map.srs()); layer lyr(name, srs); - optional status = lay.get_opt_attr("status"); + optional status = node.get_opt_attr("status"); if (status) { lyr.set_active(* status); } - optional min_zoom = lay.get_opt_attr("minzoom"); + optional min_zoom = node.get_opt_attr("minzoom"); if (min_zoom) { lyr.set_min_zoom(* min_zoom); } - optional max_zoom = lay.get_opt_attr("maxzoom"); + optional max_zoom = node.get_opt_attr("maxzoom"); if (max_zoom) { lyr.set_max_zoom(* max_zoom); } - optional queryable = lay.get_opt_attr("queryable"); + optional queryable = node.get_opt_attr("queryable"); if (queryable) { lyr.set_queryable(* queryable); } optional clear_cache = - lay.get_opt_attr("clear-label-cache"); + node.get_opt_attr("clear-label-cache"); if (clear_cache) { lyr.set_clear_label_cache(* clear_cache); } optional cache_features = - lay.get_opt_attr("cache-features"); + node.get_opt_attr("cache-features"); if (cache_features) { lyr.set_cache_features(* cache_features); } optional group_by = - lay.get_opt_attr("group-by"); + node.get_opt_attr("group-by"); if (group_by) { lyr.set_group_by(* group_by); } - xml_node::const_iterator child = lay.begin(); - xml_node::const_iterator end = lay.end(); + optional buffer_size = node.get_opt_attr("buffer-size"); + if (buffer_size) + { + lyr.set_buffer_size(*buffer_size); + } + + optional maximum_extent = node.get_opt_attr("maximum-extent"); + if (maximum_extent) + { + box2d box; + if (box.from_string(*maximum_extent)) + { + lyr.set_maximum_extent(box); + } + else + { + std::ostringstream s_err; + s_err << "failed to parse 'maximum-extent' in layer " << name; + if (strict_) + { + throw config_error(s_err.str()); + } + else + { + MAPNIK_LOG_WARN(load_map) << "map_parser: " << s_err.str(); + } + } + } + + xml_node::const_iterator child = node.begin(); + xml_node::const_iterator end = node.end(); for(; child != end; ++child) { @@ -718,7 +747,7 @@ void map_parser::parse_layer(Map & map, xml_node const& lay) { if (!name.empty()) { - ex.append_context(std::string(" encountered during parsing of layer '") + name + "'", lay); + ex.append_context(std::string(" encountered during parsing of layer '") + name + "'", node); } throw; } diff --git a/src/map.cpp b/src/map.cpp index 7a9d1f14b..c94509df7 100644 --- a/src/map.cpp +++ b/src/map.cpp @@ -352,7 +352,7 @@ void Map::set_background_image(std::string const& image_filename) void Map::set_maximum_extent(box2d const& box) { - maximum_extent_ = box; + maximum_extent_.reset(box); } boost::optional > const& Map::maximum_extent() const @@ -360,9 +360,9 @@ boost::optional > const& Map::maximum_extent() const return maximum_extent_; } -boost::optional > & Map::maximum_extent() +void Map::reset_maximum_extent() { - return maximum_extent_; + maximum_extent_.reset(); } std::string const& Map::base_path() const diff --git a/src/save_map.cpp b/src/save_map.cpp index 52d0482ec..fef378e79 100644 --- a/src/save_map.cpp +++ b/src/save_map.cpp @@ -741,6 +741,22 @@ void serialize_layer( ptree & map_node, const layer & layer, bool explicit_defau set_attr( layer_node, "group-by", layer.group_by() ); } + int buffer_size = layer.buffer_size(); + if ( buffer_size || explicit_defaults) + { + set_attr( layer_node, "buffer-size", buffer_size ); + } + + optional > const& maximum_extent = layer.maximum_extent(); + if ( maximum_extent) + { + std::ostringstream s; + s << std::setprecision(16) + << maximum_extent->minx() << "," << maximum_extent->miny() << "," + << maximum_extent->maxx() << "," << maximum_extent->maxy(); + set_attr( layer_node, "maximum-extent", s.str() ); + } + std::vector const& style_names = layer.styles(); for (unsigned i = 0; i < style_names.size(); ++i) { @@ -788,7 +804,7 @@ void serialize_map(ptree & pt, Map const & map, bool explicit_defaults) set_attr( map_node, "background-image", *image_filename ); } - unsigned buffer_size = map.buffer_size(); + int buffer_size = map.buffer_size(); if ( buffer_size || explicit_defaults) { set_attr( map_node, "buffer-size", buffer_size );