further refine the mapnik::request object which can be passed to custom agg_renderer

This commit is contained in:
Dane Springmeyer 2013-02-25 19:33:08 -05:00
parent 6a00f92517
commit 00a2f54346
7 changed files with 161 additions and 144 deletions

View File

@ -70,8 +70,8 @@ public:
// create with external placement detector, possibly non-empty
agg_renderer(Map const &m, T & pixmap, boost::shared_ptr<label_collision_detector4> detector,
double scale_factor=1.0, unsigned offset_x=0, unsigned offset_y=0);
// create with mapnik.request object that holds request-specific stuff
agg_renderer(Map const& m, request const& req, T & pixmap, double scale_factor=1.0);
// pass in mapnik::request object to provide the mutable things per render
agg_renderer(Map const& m, request const& req, T & pixmap, double scale_factor=1.0, unsigned offset_x=0, unsigned offset_y=0);
~agg_renderer();
void start_map_processing(Map const& map);
void end_map_processing(Map const& map);

View File

@ -24,7 +24,6 @@
#define MAPNIK_REQUEST_HPP
// mapnik
//#include <mapnik/well_known_srs.hpp>
#include <mapnik/config.hpp>
#include <mapnik/box2d.hpp>
@ -36,91 +35,24 @@ namespace mapnik
class MAPNIK_DECL request
{
private:
static const unsigned MIN_MAPSIZE=16;
static const unsigned MAX_MAPSIZE=MIN_MAPSIZE<<10;
unsigned width_;
unsigned height_;
int buffer_size_;
box2d<double> current_extent_;
boost::optional<box2d<double> > maximum_extent_;
public:
/*! \brief Constructor
* @param width Initial map width.
* @param height Initial map height.
* @param srs Initial map projection.
*/
request(int width, int height);
/*! \brief Get map width.
*/
request(unsigned width,
unsigned height,
box2d<double> const& extent);
unsigned width() const;
/*! \brief Get map height.
*/
unsigned height() const;
/*! \brief Set map width.
*/
void set_width(unsigned width);
/*! \brief Set map height.
*/
void set_height(unsigned height);
/*! \brief Resize the map.
*/
void resize(unsigned width,unsigned height);
/*! \brief Set buffer size
* @param buffer_size Buffer size in pixels.
*/
void set_buffer_size(int buffer_size);
/*! \brief Get the map buffer size
* @return Buffer size as int
*/
int buffer_size() const;
/*! \brief Set the map maximum extent.
* @param box The bounding box for the maximum extent.
*/
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;
void reset_maximum_extent();
/*! \brief Zoom the map to a bounding box.
*
* Aspect is handled automatic if not fitting to width/height.
* @param box The bounding box where to zoom.
*/
void zoom_to_box(const box2d<double>& box);
/*! \brief Get current bounding box.
* @return The current bounding box.
*/
const box2d<double>& get_current_extent() const;
/*! \brief Get current buffered bounding box.
* @return The current buffered bounding box.
*/
box2d<double> const& extent() const;
void set_extent(box2d<double> const& box);
box2d<double> get_buffered_extent() const;
/*!
* @return The Map Scale.
*/
double scale() const;
~request();
private:
unsigned width_;
unsigned height_;
box2d<double> extent_;
int buffer_size_;
};
}

View File

@ -85,7 +85,7 @@ agg_renderer<T>::agg_renderer(Map const& m, T & pixmap, double scale_factor, uns
}
template <typename T>
agg_renderer<T>::agg_renderer(Map const& m, request const& req, T & pixmap, double scale_factor)
agg_renderer<T>::agg_renderer(Map const& m, request const& req, T & pixmap, double scale_factor, unsigned offset_x, unsigned offset_y)
: feature_style_processor<agg_renderer>(m, scale_factor),
pixmap_(pixmap),
internal_buffer_(),
@ -94,7 +94,7 @@ agg_renderer<T>::agg_renderer(Map const& m, request const& req, T & pixmap, doub
width_(pixmap_.width()),
height_(pixmap_.height()),
scale_factor_(scale_factor),
t_(req.width(),req.height(),req.get_current_extent(),0.0,0.0),
t_(req.width(),req.height(),req.extent(),offset_x,offset_y),
font_engine_(),
font_manager_(font_engine_),
detector_(boost::make_shared<label_collision_detector4>(box2d<double>(-req.buffer_size(), -req.buffer_size(), req.width() + req.buffer_size() ,req.height() + req.buffer_size()))),

View File

@ -2,7 +2,7 @@
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2011 Artem Pavlenko
* Copyright (C) 2013 Artem Pavlenko
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@ -26,10 +26,12 @@
namespace mapnik
{
request::request(int width,int height)
request::request(unsigned width,
unsigned height,
box2d<double> const& extent)
: width_(width),
height_(height),
extent_(extent),
buffer_size_(0) {}
request::~request() {}
@ -44,41 +46,7 @@ unsigned request::height() const
return height_;
}
void request::set_width(unsigned width)
{
if (width != width_ &&
width >= MIN_MAPSIZE &&
width <= MAX_MAPSIZE)
{
width_=width;
}
}
void request::set_height(unsigned height)
{
if (height != height_ &&
height >= MIN_MAPSIZE &&
height <= MAX_MAPSIZE)
{
height_=height;
}
}
void request::resize(unsigned width,unsigned height)
{
if (width != width_ &&
height != height_ &&
width >= MIN_MAPSIZE &&
width <= MAX_MAPSIZE &&
height >= MIN_MAPSIZE &&
height <= MAX_MAPSIZE)
{
width_=width;
height_=height;
}
}
void request::set_buffer_size( int buffer_size)
void request::set_buffer_size(int buffer_size)
{
buffer_size_ = buffer_size;
}
@ -88,45 +56,30 @@ int request::buffer_size() const
return buffer_size_;
}
void request::set_maximum_extent(box2d<double> const& box)
void request::set_extent(box2d<double> const& box)
{
maximum_extent_.reset(box);
extent_ = box;
}
boost::optional<box2d<double> > const& request::maximum_extent() const
box2d<double> const& request::extent() const
{
return maximum_extent_;
}
void request::reset_maximum_extent()
{
maximum_extent_.reset();
}
void request::zoom_to_box(const box2d<double> &box)
{
current_extent_=box;
}
const box2d<double>& request::get_current_extent() const
{
return current_extent_;
return extent_;
}
box2d<double> request::get_buffered_extent() const
{
double extra = 2.0 * scale() * buffer_size_;
box2d<double> ext(current_extent_);
ext.width(current_extent_.width() + extra);
ext.height(current_extent_.height() + extra);
box2d<double> ext(extent_);
ext.width(extent_.width() + extra);
ext.height(extent_.height() + extra);
return ext;
}
double request::scale() const
{
if (width_>0)
return current_extent_.width()/width_;
return current_extent_.width();
return extent_.width()/width_;
return extent_.width();
}
}

View File

@ -0,0 +1,132 @@
#include <boost/version.hpp>
#include <boost/detail/lightweight_test.hpp>
#include <iostream>
#include <mapnik/map.hpp>
#include <mapnik/load_map.hpp>
#include <mapnik/agg_renderer.hpp>
#include <mapnik/graphics.hpp>
#include <mapnik/image_util.hpp>
#include <mapnik/datasource_cache.hpp>
#include <mapnik/font_engine_freetype.hpp>
#include <mapnik/image_data.hpp>
#include <mapnik/image_reader.hpp>
#include <mapnik/scale_denominator.hpp>
#include <mapnik/feature_style_processor.hpp>
#include <boost/foreach.hpp>
bool compare_images(std::string const& src_fn,std::string const& dest_fn)
{
using namespace mapnik;
std::auto_ptr<mapnik::image_reader> reader1(mapnik::get_image_reader(dest_fn,"png"));
if (!reader1.get())
{
throw mapnik::image_reader_exception("Failed to load: " + dest_fn);
}
boost::shared_ptr<image_32> image_ptr1 = boost::make_shared<image_32>(reader1->width(),reader1->height());
reader1->read(0,0,image_ptr1->data());
std::auto_ptr<mapnik::image_reader> reader2(mapnik::get_image_reader(src_fn,"png"));
if (!reader2.get())
{
throw mapnik::image_reader_exception("Failed to load: " + src_fn);
}
boost::shared_ptr<image_32> image_ptr2 = boost::make_shared<image_32>(reader2->width(),reader2->height());
reader2->read(0,0,image_ptr2->data());
image_data_32 const& dest = image_ptr1->data();
image_data_32 const& src = image_ptr2->data();
unsigned int width = src.width();
unsigned int height = src.height();
if ((width != dest.width()) || height != dest.height()) return false;
for (unsigned int y = 0; y < height; ++y)
{
const unsigned int* row_from = src.getRow(y);
const unsigned int* row_to = dest.getRow(y);
for (unsigned int x = 0; x < width; ++x)
{
if (row_from[x] != row_to[x]) return false;
}
}
return true;
}
int main( int, char*[] )
{
try {
mapnik::datasource_cache::instance().register_datasources("./plugins/input/");
mapnik::freetype_engine::register_fonts("./fonts", true );
mapnik::Map m(256,256);
mapnik::load_map(m,"./tests/data/good_maps/marker-text-line.xml",false);
m.zoom_all();
mapnik::image_32 im(m.width(),m.height());
double scale_factor = 1.2;
std::string expected("./tests/cpp_tests/support/map-request-marker-text-line-expected.png");
// render normally with apply() and just map and image
mapnik::agg_renderer<mapnik::image_32> renderer1(m,im,scale_factor);
renderer1.apply();
std::string actual1("/tmp/map-request-marker-text-line-actual1.png");
//mapnik::save_to_file(im,expected);
mapnik::save_to_file(im,actual1);
BOOST_TEST(compare_images(actual1,expected));
// reset image
im.clear();
// set up a mapnik::request object
mapnik::request req(m.width(),m.height(),m.get_current_extent());
req.set_buffer_size(m.buffer_size());
// render using apply() and mapnik::request
mapnik::agg_renderer<mapnik::image_32> renderer2(m,req,im,scale_factor);
renderer2.apply();
std::string actual2("/tmp/map-request-marker-text-line-actual2.png");
mapnik::save_to_file(im,actual2);
BOOST_TEST(compare_images(actual2,expected));
// reset image
im.clear();
// render with apply_to_layer api and mapnik::request params passed to apply_to_layer
mapnik::agg_renderer<mapnik::image_32> renderer3(m,req,im,scale_factor);
renderer3.start_map_processing(m);
mapnik::projection map_proj(m.srs(),true);
double scale_denom = mapnik::scale_denominator(req.scale(),map_proj.is_geographic());
scale_denom *= scale_factor;
BOOST_FOREACH ( mapnik::layer const& lyr, m.layers() )
{
if (lyr.visible(scale_denom))
{
std::set<std::string> names;
renderer3.apply_to_layer(lyr,
renderer3,
map_proj,
req.scale(),
scale_denom,
req.width(),
req.height(),
req.extent(),
req.buffer_size(),
names);
}
}
renderer3.end_map_processing(m);
std::string actual3("/tmp/map-request-marker-text-line-actual3.png");
mapnik::save_to_file(im,actual3);
BOOST_TEST(compare_images(actual3,expected));
} catch (std::exception const& ex) {
std::clog << ex.what() << "\n";
}
if (!::boost::detail::test_errors()) {
std::clog << "C++ Map Request rendering hook: \x1b[1;32m✓ \x1b[0m\n";
#if BOOST_VERSION >= 104600
::boost::detail::report_errors_remind().called_report_errors_function = true;
#endif
} else {
return ::boost::report_errors();
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

View File

@ -1,4 +1,4 @@
<Map>
<Map srs="+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs">
<Style name="ellipse">
<Rule>
<MarkersSymbolizer