mirror of
https://github.com/mapnik/mapnik.git
synced 2025-12-08 20:13:09 +00:00
further refine the mapnik::request object which can be passed to custom agg_renderer
This commit is contained in:
parent
6a00f92517
commit
00a2f54346
@ -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);
|
||||
|
||||
@ -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_;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@ -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()))),
|
||||
|
||||
@ -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();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
132
tests/cpp_tests/map_request_test.cpp
Normal file
132
tests/cpp_tests/map_request_test.cpp
Normal 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 |
@ -1,4 +1,4 @@
|
||||
<Map>
|
||||
<Map srs="+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs">
|
||||
<Style name="ellipse">
|
||||
<Rule>
|
||||
<MarkersSymbolizer
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user