Issue #1545 - override buffer-size parameter at layer level - revised

This commit is contained in:
Alexandre Bonnasseau 2012-10-29 10:50:37 +01:00 committed by mappyamon
parent 2d0bd726c3
commit efff5f0ef0
13 changed files with 136 additions and 35 deletions

View file

@ -103,6 +103,31 @@ void set_maximum_extent(mapnik::layer & l, boost::optional<mapnik::box2d<double>
}
}
void set_buffer_size(mapnik::layer & l, boost::optional<int> const& buffer_size)
{
if (buffer_size)
{
l.set_buffer_size(*buffer_size);
}
else
{
l.reset_buffer_size();
}
}
PyObject * get_buffer_size(mapnik::layer & l)
{
boost::optional<int> buffer_size = l.buffer_size();
if (buffer_size)
{
return PyInt_FromLong(*buffer_size);
}
else
{
Py_RETURN_NONE;
}
}
void export_layer()
{
using namespace boost::python;
@ -224,17 +249,18 @@ void export_layer()
)
.add_property("buffer_size",
&layer::buffer_size,
&layer::set_buffer_size,
&get_buffer_size,
&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"
">>> print(l.buffer_size)\n"
"None # None 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,

View file

@ -736,6 +736,7 @@ BOOST_PYTHON_MODULE(_mapnik)
python_optional<double>();
python_optional<float>();
python_optional<bool>();
python_optional<int>();
python_optional<mapnik::text_transform_e>();
register_ptr_to_python<mapnik::expression_ptr>();
register_ptr_to_python<mapnik::path_expression_ptr>();

View file

@ -239,7 +239,21 @@ void feature_style_processor<Processor>::apply_to_layer(layer const& lay, Proces
}
#endif
box2d<double> buffered_query_ext = m_.get_buffered_extent(); // buffered
box2d<double> query_ext = m_.get_current_extent(); // unbuffered
box2d<double> buffered_query_ext(query_ext); // buffered
boost::optional<int> layer_buffer_size = lay.buffer_size();
if (layer_buffer_size) // if layer overrides buffer size, use this value to compute buffered extent
{
double extra = 2.0 * m_.scale() * *layer_buffer_size;
buffered_query_ext.width(query_ext.width() + extra);
buffered_query_ext.height(query_ext.height() + extra);
}
else
{
buffered_query_ext = m_.get_buffered_extent();
}
// clip buffered extent by maximum extent, if supplied
boost::optional<box2d<double> > const& maximum_extent = m_.maximum_extent();
@ -310,7 +324,6 @@ 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)
{
query_ext.clip(*maximum_extent);

View file

@ -194,7 +194,8 @@ public:
boost::optional<box2d<double> > const& maximum_extent() const;
void reset_maximum_extent();
void set_buffer_size(int size);
int buffer_size() const;
boost::optional<int> const& buffer_size() const;
void reset_buffer_size();
~layer();
private:
void swap(const layer& other);
@ -211,7 +212,7 @@ private:
std::string group_by_;
std::vector<std::string> styles_;
datasource_ptr ds_;
int buffer_size_;
boost::optional<int> buffer_size_;
boost::optional<box2d<double> > maximum_extent_;
};
}

View file

@ -181,16 +181,6 @@ void agg_renderer<T>::start_layer_processing(layer const& lay, box2d<double> con
}
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)

View file

@ -104,16 +104,6 @@ void grid_renderer<T>::start_layer_processing(layer const& lay, box2d<double> co
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)

View file

@ -42,8 +42,7 @@ layer::layer(std::string const& name, std::string const& srs)
clear_label_cache_(false),
cache_features_(false),
group_by_(""),
ds_(),
buffer_size_(0) {}
ds_() {}
layer::layer(const layer& rhs)
: name_(rhs.name_),
@ -198,14 +197,20 @@ void layer::reset_maximum_extent()
void layer::set_buffer_size(int size)
{
buffer_size_ = size;
buffer_size_.reset(size);
}
int layer::buffer_size() const
boost::optional<int> const& layer::buffer_size() const
{
return buffer_size_;
}
void layer::reset_buffer_size()
{
buffer_size_.reset();
}
box2d<double> layer::envelope() const
{
if (ds_) return ds_->envelope();

View file

@ -750,10 +750,10 @@ 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();
boost::optional<int> const& buffer_size = layer.buffer_size();
if ( buffer_size || explicit_defaults)
{
set_attr( layer_node, "buffer-size", buffer_size );
set_attr( layer_node, "buffer-size", *buffer_size );
}
optional<box2d<double> > const& maximum_extent = layer.maximum_extent();

View file

@ -0,0 +1,33 @@
<Map srs="+init=epsg:4326" background-color="lightsteelblue" >
<!--
XXX Difference entre rendu sous Debian et Ubuntu !!!!!!!!!!!!!!
<Style name="world_borders_style">
<Rule>
<PolygonSymbolizer fill="#f2eff9"/><LineSymbolizer stroke="rgb(50%,50%,50%)" stroke-width="0.1"/>
</Rule>
</Style>
<Layer name="world_borders2" srs="+init=epsg:4326">
<StyleName>world_borders_style</StyleName>
<Datasource>
<Parameter name="type">sqlite</Parameter>
<Parameter name="file">../sqlite/world.sqlite</Parameter>
<Parameter name="table">world_merc</Parameter>
</Datasource>
</Layer>
-->
<Style name="point_style">
<Rule>
<PointSymbolizer file="../svg/point_sm.svg"/>
<TextSymbolizer size="12" dy="-5" face-name="DejaVu Sans Book" halo-fill="rgba(255,255,255,.5)" halo-radius=".5">[name]</TextSymbolizer>
</Rule>
</Style>
<Layer name="point" srs="+init=epsg:4326" buffer-size="-150">
<StyleName>point_style</StyleName>
<Datasource>
<Parameter name="type">sqlite</Parameter>
<Parameter name="file">../sqlite/qgis_spatiallite.sqlite</Parameter>
<Parameter name="table">point</Parameter>
</Datasource>
</Layer>
</Map>

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

View file

@ -0,0 +1,42 @@
#coding=utf8
import os
import mapnik
import cairo
from utilities import execution_path
from nose.tools import *
def setup():
# All of the paths used are relative, if we run the tests
# from another directory we need to chdir()
os.chdir(execution_path('.'))
def test_layer_buffer_size_1():
m = mapnik.Map(512,512)
mapnik.load_map(m,'../data/good_maps/layer_buffer_size_reduction.xml')
m.zoom_all()
im = mapnik.Image(m.width,m.height)
mapnik.render(m,im)
actual = '/tmp/mapnik-layer-buffer-size.png'
expected = 'images/support/mapnik-layer-buffer-size.png'
im.save(actual)
expected_im = mapnik.Image.open(expected)
eq_(im.tostring(),expected_im.tostring(), 'failed comparing actual (%s) and expected (%s)' % (actual,'tests/python_tests/'+ expected))
def test_layer_buffer_size_2():
actual = '/tmp/mapnik-layer-buffer-size-cairo.png'
expected = 'images/support/mapnik-layer-buffer-size-cairo.png'
m = mapnik.Map(512,512)
mapnik.load_map(m,'../data/good_maps/layer_buffer_size_reduction.xml')
m.zoom_all()
surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, m.width, m.height)
mapnik.render(m, surface)
surface.write_to_png(actual)
surface.finish()
expected_im = mapnik.Image.open(expected)
actual_im = mapnik.Image.open(actual)
eq_(actual_im.tostring(),expected_im.tostring(), 'failed comparing actual (%s) and expected (%s)' % (actual,'tests/python_tests/'+ expected))
if __name__ == "__main__":
setup()
[eval(run)() for run in dir() if 'test_' in run]

View file

@ -20,7 +20,7 @@ def test_layer_init():
eq_(l.maxzoom > 1e+6,True)
eq_(l.group_by,"")
eq_(l.maximum_extent,None)
eq_(l.buffer_size,0.0)
eq_(l.buffer_size,None)
eq_(len(l.styles),0)
if __name__ == "__main__":