Skip to content
Browse files

+ layer : minimum-extent and buffer-size

+ agg::process_xxx : remove ad-hoc query_extent modifiers
+ ctrans : simplify vertex skipping
  • Loading branch information...
1 parent 2dcf940 commit 5541ea027138c4d8f6d469152df7c58d0146f100 @artemp artemp committed Aug 1, 2012
View
33 bindings/python/mapnik_layer.cpp
@@ -91,6 +91,18 @@ struct layer_pickle_suite : boost::python::pickle_suite
std::vector<std::string> & (mapnik::layer::*_styles_)() = &mapnik::layer::styles;
+void set_maximum_extent(mapnik::layer & l, boost::optional<mapnik::box2d<double> > 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()
"<mapnik.Datasource object at 0x65470>\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<copy_const_reference>()),
+ &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,
View
7 bindings/python/mapnik_map.cpp
@@ -117,7 +117,7 @@ struct map_pickle_suite : boost::python::pickle_suite
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;
-boost::optional<mapnik::box2d<double> > const& (Map::*maximum_extent_const)() const = &Map::maximum_extent;
+//boost::optional<mapnik::box2d<double> > 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<mapnik::box2d<double> > const& box)
{
if (box)
@@ -201,7 +200,7 @@ void set_maximum_extent(mapnik::Map & m, boost::optional<mapnik::box2d<double> >
}
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<copy_const_reference>()),
+ (&Map::maximum_extent,return_value_policy<copy_const_reference>()),
&set_maximum_extent,
"The maximum extent of the map.\n"
"\n"
View
25 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)
- {
- command = geom_.vertex(x, y);
- ok = prj_trans_->backward(*x, *y, z);
- if (!ok) {
- skipped_points = true;
- }
- }
- if (skipped_points && (command == SEG_LINETO))
+ unsigned command = geom_.vertex(x, y);
+ if ( command != SEG_END)
{
- command = SEG_MOVETO;
+ double z = 0;
+ if (!prj_trans_->backward(*x, *y, z))
+ return SEG_END;
}
t_->forward(x, y);
return command;
View
13 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 @@ class MAPNIK_DECL layer
* @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 @@ class MAPNIK_DECL layer
*/
box2d<double> envelope() const;
+ void set_maximum_extent(box2d<double> const& box);
+ boost::optional<box2d<double> > 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 @@ class MAPNIK_DECL layer
std::string group_by_;
std::vector<std::string> styles_;
datasource_ptr ds_;
+ int buffer_size_;
+ boost::optional<box2d<double> > maximum_extent_;
};
}
View
6 include/mapnik/map.hpp
@@ -331,15 +331,13 @@ class MAPNIK_DECL Map
/*! \brief Set the map maximum extent.
* @param box The bounding box for the maximum extent.
*/
- void set_maximum_extent(box2d<double>const& box);
+ void set_maximum_extent(box2d<double> const& box);
/*! \brief Get the map maximum extent as box2d<double>
*/
boost::optional<box2d<double> > const& maximum_extent() const;
- /*! \brief Get the non-const map maximum extent as box2d<double>
- */
- boost::optional<box2d<double> > & maximum_extent();
+ void reset_maximum_extent();
/*! \brief Get the map base path where paths should be relative to.
*/
View
17 src/agg/agg_renderer.cpp
@@ -191,7 +191,24 @@ void agg_renderer<T>::start_layer_processing(layer const& lay, box2d<double> 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<box2d<double> > const& maximum_extent = lay.maximum_extent();
+ if (maximum_extent)
+ {
+ query_extent_.clip(*maximum_extent);
+ }
}
template <typename T>
View
20 src/agg/process_line_pattern_symbolizer.cpp
@@ -56,15 +56,15 @@ void agg_renderer<T>::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<color, order> blender_type;
typedef agg::pattern_filter_bilinear_rgba8 pattern_filter_type;
typedef agg::line_image_pattern<pattern_filter_type> pattern_type;
typedef agg::pixfmt_custom_blend_rgba<blender_type, agg::rendering_buffer> pixfmt_type;
typedef agg::renderer_base<pixfmt_type> renderer_base;
typedef agg::renderer_outline_image<renderer_base, pattern_type> renderer_type;
typedef agg::rasterizer_outline_aa<renderer_type> rasterizer_type;
-
+
std::string filename = path_processor_type::evaluate( *sym.get_filename(), feature);
boost::optional<marker_ptr> mark = marker_cache::instance()->find(filename,true);
@@ -81,8 +81,6 @@ void agg_renderer<T>::process(line_pattern_symbolizer const& sym,
if (!pat) return;
- box2d<double> 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<agg::comp_op_e>(sym.comp_op()));
@@ -91,26 +89,26 @@ void agg_renderer<T>::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<clip_line_tag,transform_tag,smooth_tag> conv_types;
vertex_converter<box2d<double>, 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<clip_line_tag>(); //optional clip (default: true)
- converter.set<transform_tag>(); //always transform
+ converter.set<transform_tag>(); //always transform
if (sym.smooth() > 0.0) converter.set<smooth_tag>(); // optional smooth converter
-
+
BOOST_FOREACH(geometry_type & geom, feature.paths())
{
if (geom.size() > 1)
{
- converter.apply(geom);
+ converter.apply(geom);
}
}
}
View
2 src/agg/process_line_symbolizer.cpp
@@ -80,7 +80,7 @@ void agg_renderer<T>::process(line_symbolizer const& sym,
agg::trans_affine tr;
evaluate_transform(tr, feature, sym.get_transform());
- box2d<double> ext = query_extent_ * 1.1;
+ box2d<double> ext = query_extent_ * 1.0;
@springmeyer
Mapnik member
springmeyer added a note Aug 1, 2012

this will regress #1215, right, unless layer-buffer is set which it will not be by default?

@artemp
Mapnik member
artemp added a note Aug 1, 2012

@springmeyer - yes, but this is better than multiplying query_extent by 1.1 and also gives a user better control over padding size:

<Layer buffer-size="10"  ..>

@springmeyer
Mapnik member
springmeyer added a note Aug 1, 2012

okay my concern is that in the case of TileMill the user has no ability to set layer properties currently so this will immediately introduce line rendering artifacts that can not be turned off without turning off clipping.

@springmeyer
Mapnik member
springmeyer added a note Aug 1, 2012

perhaps tilemill should default to setting a layer buffer-size? or default to not clipping lines?

@artemp
Mapnik member
artemp added a note Aug 1, 2012

I think it's ok to set buffer-size to something sensible for lines as it's no different logically to ext*1.1 but will be more robust - consistent padding in pixels

@springmeyer
Mapnik member
springmeyer added a note Aug 1, 2012

K. Should this buffer default be in Mapnik or Tilemill? Not positive how best to detect line type layers.

@artemp
Mapnik member
artemp added a note Aug 1, 2012

@springmeyer - TileMill I reckon. One way would be to check if there's an active LineSymbolizer ?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
if (sym.get_rasterizer() == RASTERIZER_FAST)
{
View
6 src/agg/process_markers_symbolizer.cpp
@@ -363,7 +363,7 @@ void agg_renderer<T>::process(markers_symbolizer const& sym,
bbox, marker_trans, sym, *detector_, scale_factor_);
vertex_converter<box2d<double>, 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<T>::process(markers_symbolizer const& sym,
bbox, marker_trans, sym, *detector_, scale_factor_);
vertex_converter<box2d<double>, 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<T>::process(markers_symbolizer const& sym,
marker_trans, sym, *detector_, scale_factor_);
vertex_converter<box2d<double>, 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)
{
View
3 src/agg/process_polygon_pattern_symbolizer.cpp
@@ -139,11 +139,10 @@ void agg_renderer<T>::process(polygon_pattern_symbolizer const& sym,
agg::trans_affine tr;
evaluate_transform(tr, feature, sym.get_transform());
- box2d<double> inflated_extent = query_extent_ * 1.0;
typedef boost::mpl::vector<clip_poly_tag,transform_tag,smooth_tag> conv_types;
vertex_converter<box2d<double>, 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<clip_poly_tag>(); //optional clip (default: true)
converter.set<transform_tag>(); //always transform
View
6 src/agg/process_polygon_symbolizer.cpp
@@ -48,15 +48,13 @@ void agg_renderer<T>::process(polygon_symbolizer const& sym,
ras_ptr->reset();
set_gamma_method(sym,ras_ptr);
- box2d<double> inflated_extent = query_extent_ * 1.0;
-
agg::trans_affine tr;
evaluate_transform(tr, feature, sym.get_transform());
typedef boost::mpl::vector<clip_poly_tag,transform_tag,affine_transform_tag,smooth_tag> conv_types;
vertex_converter<box2d<double>, 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<clip_poly_tag>(); //optional clip (default: true)
converter.set<transform_tag>(); //always transform
@@ -72,7 +70,7 @@ void agg_renderer<T>::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();
View
4 src/feature_style_processor.cpp
@@ -320,9 +320,11 @@ void feature_style_processor<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<double> query_ext = m_.get_current_extent(); // unbuffered
- if (maximum_extent) {
+ if (maximum_extent)
+ {
query_ext.clip(*maximum_extent);
}
+
box2d<double> layer_ext2 = lay.envelope();
if (fw_success)
{
View
34 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<double> const& box)
+{
+ maximum_extent_.reset(box);
+}
+
+boost::optional<box2d<double> > 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<double> layer::envelope() const
{
if (ds_) return ds_->envelope();
View
55 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<boolean> status = lay.get_opt_attr<boolean>("status");
+ optional<boolean> status = node.get_opt_attr<boolean>("status");
if (status)
{
lyr.set_active(* status);
}
- optional<double> min_zoom = lay.get_opt_attr<double>("minzoom");
+ optional<double> min_zoom = node.get_opt_attr<double>("minzoom");
if (min_zoom)
{
lyr.set_min_zoom(* min_zoom);
}
- optional<double> max_zoom = lay.get_opt_attr<double>("maxzoom");
+ optional<double> max_zoom = node.get_opt_attr<double>("maxzoom");
if (max_zoom)
{
lyr.set_max_zoom(* max_zoom);
}
- optional<boolean> queryable = lay.get_opt_attr<boolean>("queryable");
+ optional<boolean> queryable = node.get_opt_attr<boolean>("queryable");
if (queryable)
{
lyr.set_queryable(* queryable);
}
optional<boolean> clear_cache =
- lay.get_opt_attr<boolean>("clear-label-cache");
+ node.get_opt_attr<boolean>("clear-label-cache");
if (clear_cache)
{
lyr.set_clear_label_cache(* clear_cache);
}
optional<boolean> cache_features =
- lay.get_opt_attr<boolean>("cache-features");
+ node.get_opt_attr<boolean>("cache-features");
if (cache_features)
{
lyr.set_cache_features(* cache_features);
}
optional<std::string> group_by =
- lay.get_opt_attr<std::string>("group-by");
+ node.get_opt_attr<std::string>("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<unsigned> buffer_size = node.get_opt_attr<unsigned>("buffer-size");
+ if (buffer_size)
+ {
+ lyr.set_buffer_size(*buffer_size);
+ }
+
+ optional<std::string> maximum_extent = node.get_opt_attr<std::string>("maximum-extent");
+ if (maximum_extent)
+ {
+ box2d<double> 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;
}
View
6 src/map.cpp
@@ -352,17 +352,17 @@ void Map::set_background_image(std::string const& image_filename)
void Map::set_maximum_extent(box2d<double> const& box)
{
- maximum_extent_ = box;
+ maximum_extent_.reset(box);
}
boost::optional<box2d<double> > const& Map::maximum_extent() const
{
return maximum_extent_;
}
-boost::optional<box2d<double> > & Map::maximum_extent()
+void Map::reset_maximum_extent()
{
- return maximum_extent_;
+ maximum_extent_.reset();
}
std::string const& Map::base_path() const
View
18 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<box2d<double> > 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<std::string> 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 );

0 comments on commit 5541ea0

Please sign in to comment.
Something went wrong with that request. Please try again.