Compare commits

...

12 commits

15 changed files with 286 additions and 244 deletions

View file

@ -34,7 +34,8 @@
#include <mapnik/projection.hpp> #include <mapnik/projection.hpp>
#include <mapnik/ctrans.hpp> #include <mapnik/ctrans.hpp>
#include <mapnik/feature_type_style.hpp> #include <mapnik/feature_type_style.hpp>
//#include <mapnik/util/deepcopy.hpp> #include <mapnik/scale_denominator.hpp>
#include <mapnik/util/map_query.hpp>
#include "mapnik_enumeration.hpp" #include "mapnik_enumeration.hpp"
using mapnik::color; using mapnik::color;
@ -77,8 +78,7 @@ mapnik::featureset_ptr query_point(mapnik::Map const& m, int index, double x, do
PyErr_SetString(PyExc_IndexError, "Please provide a layer index >= 0"); PyErr_SetString(PyExc_IndexError, "Please provide a layer index >= 0");
boost::python::throw_error_already_set(); boost::python::throw_error_already_set();
} }
unsigned idx = index; return mapnik::util::query_point(m, static_cast<unsigned>(index), x, y);
return m.query_point(idx, x, y);
} }
mapnik::featureset_ptr query_map_point(mapnik::Map const& m, int index, double x, double y) mapnik::featureset_ptr query_map_point(mapnik::Map const& m, int index, double x, double y)
@ -87,8 +87,23 @@ mapnik::featureset_ptr query_map_point(mapnik::Map const& m, int index, double x
PyErr_SetString(PyExc_IndexError, "Please provide a layer index >= 0"); PyErr_SetString(PyExc_IndexError, "Please provide a layer index >= 0");
boost::python::throw_error_already_set(); boost::python::throw_error_already_set();
} }
unsigned idx = index; return mapnik::util::query_map_point(m, static_cast<unsigned>(index), x, y);
return m.query_map_point(idx, x, y); }
void zoom_all(mapnik::Map & m)
{
m.zoom_to_box(mapnik::util::get_extent(m));
}
mapnik::CoordTransform get_view_transform(mapnik::Map const& map)
{
return mapnik::CoordTransform(map.width(),map.height(),map.get_current_extent());
}
double get_scale_denominator(mapnik::Map const& map)
{
mapnik::projection map_proj(map.srs());
return mapnik::scale_denominator( map.scale(), map_proj.is_geographic());
} }
void set_maximum_extent(mapnik::Map & m, boost::optional<mapnik::box2d<double> > const& box) void set_maximum_extent(mapnik::Map & m, boost::optional<mapnik::box2d<double> > const& box)
@ -326,14 +341,14 @@ void export_map()
">>> m.scale()\n" ">>> m.scale()\n"
) )
.def("scale_denominator", &Map::scale_denominator, .def("scale_denominator", get_scale_denominator,
"Return the Map Scale Denominator.\n" "Return the Map Scale Denominator.\n"
"Usage:\n" "Usage:\n"
"\n" "\n"
">>> m.scale_denominator()\n" ">>> m.scale_denominator()\n"
) )
.def("view_transform",&Map::view_transform, .def("view_transform",get_view_transform,
"Return the map ViewTransform object\n" "Return the map ViewTransform object\n"
"which is used internally to convert between\n" "which is used internally to convert between\n"
"geographic coordinates and screen coordinates.\n" "geographic coordinates and screen coordinates.\n"
@ -353,7 +368,7 @@ void export_map()
">>> m.zoom(0.25)\n" ">>> m.zoom(0.25)\n"
) )
.def("zoom_all",&Map::zoom_all, .def("zoom_all",&zoom_all,
"Set the geographical extent of the map\n" "Set the geographical extent of the map\n"
"to the combined extents of all active layers.\n" "to the combined extents of all active layers.\n"
"\n" "\n"

View file

@ -130,8 +130,7 @@ void render(const mapnik::Map& map,
{ {
python_unblock_auto_block b; python_unblock_auto_block b;
mapnik::agg_renderer<mapnik::image_32> ren(map,image,scale_factor,offset_x, offset_y); mapnik::agg_renderer<mapnik::image_32> ren(map,image,scale_factor,offset_x, offset_y);
ren.apply(); ren.apply(map.layers(),map.styles());
} }
void render_with_detector( void render_with_detector(
@ -144,7 +143,7 @@ void render_with_detector(
{ {
python_unblock_auto_block b; python_unblock_auto_block b;
mapnik::agg_renderer<mapnik::image_32> ren(map,image,detector); mapnik::agg_renderer<mapnik::image_32> ren(map,image,detector);
ren.apply(); ren.apply(map.layers(),map.styles());
} }
void render_layer2(const mapnik::Map& map, void render_layer2(const mapnik::Map& map,
@ -164,7 +163,7 @@ void render_layer2(const mapnik::Map& map,
mapnik::layer const& layer = layers[layer_idx]; mapnik::layer const& layer = layers[layer_idx];
mapnik::agg_renderer<mapnik::image_32> ren(map,image,1.0,0,0); mapnik::agg_renderer<mapnik::image_32> ren(map,image,1.0,0,0);
std::set<std::string> names; std::set<std::string> names;
ren.apply(layer,names); ren.apply(layer,map.styles(),names);
} }
#if defined(HAVE_CAIRO) && defined(HAVE_PYCAIRO) #if defined(HAVE_CAIRO) && defined(HAVE_PYCAIRO)
@ -178,7 +177,7 @@ void render3(const mapnik::Map& map,
python_unblock_auto_block b; python_unblock_auto_block b;
mapnik::cairo_surface_ptr surface(cairo_surface_reference(py_surface->surface), mapnik::cairo_surface_closer()); mapnik::cairo_surface_ptr surface(cairo_surface_reference(py_surface->surface), mapnik::cairo_surface_closer());
mapnik::cairo_renderer<mapnik::cairo_surface_ptr> ren(map,surface,scale_factor,offset_x,offset_y); mapnik::cairo_renderer<mapnik::cairo_surface_ptr> ren(map,surface,scale_factor,offset_x,offset_y);
ren.apply(); ren.apply(map.layers(),map.styles());
} }
void render4(const mapnik::Map& map, PycairoSurface* py_surface) void render4(const mapnik::Map& map, PycairoSurface* py_surface)
@ -186,7 +185,7 @@ void render4(const mapnik::Map& map, PycairoSurface* py_surface)
python_unblock_auto_block b; python_unblock_auto_block b;
mapnik::cairo_surface_ptr surface(cairo_surface_reference(py_surface->surface), mapnik::cairo_surface_closer()); mapnik::cairo_surface_ptr surface(cairo_surface_reference(py_surface->surface), mapnik::cairo_surface_closer());
mapnik::cairo_renderer<mapnik::cairo_surface_ptr> ren(map,surface); mapnik::cairo_renderer<mapnik::cairo_surface_ptr> ren(map,surface);
ren.apply(); ren.apply(map.layers(),map.styles());
} }
void render5(const mapnik::Map& map, void render5(const mapnik::Map& map,
@ -198,7 +197,7 @@ void render5(const mapnik::Map& map,
python_unblock_auto_block b; python_unblock_auto_block b;
mapnik::cairo_ptr context(py_context->ctx, mapnik::cairo_closer()); mapnik::cairo_ptr context(py_context->ctx, mapnik::cairo_closer());
mapnik::cairo_renderer<mapnik::cairo_ptr> ren(map,context,scale_factor,offset_x, offset_y); mapnik::cairo_renderer<mapnik::cairo_ptr> ren(map,context,scale_factor,offset_x, offset_y);
ren.apply(); ren.apply(map.layers(),map.styles());
} }
void render6(const mapnik::Map& map, PycairoContext* py_context) void render6(const mapnik::Map& map, PycairoContext* py_context)
@ -206,7 +205,7 @@ void render6(const mapnik::Map& map, PycairoContext* py_context)
python_unblock_auto_block b; python_unblock_auto_block b;
mapnik::cairo_ptr context(py_context->ctx, mapnik::cairo_closer()); mapnik::cairo_ptr context(py_context->ctx, mapnik::cairo_closer());
mapnik::cairo_renderer<mapnik::cairo_ptr> ren(map,context); mapnik::cairo_renderer<mapnik::cairo_ptr> ren(map,context);
ren.apply(); ren.apply(map.layers(),map.styles());
} }
void render_with_detector2( void render_with_detector2(
@ -217,7 +216,7 @@ void render_with_detector2(
python_unblock_auto_block b; python_unblock_auto_block b;
mapnik::cairo_ptr context(py_context->ctx, mapnik::cairo_closer()); mapnik::cairo_ptr context(py_context->ctx, mapnik::cairo_closer());
mapnik::cairo_renderer<mapnik::cairo_ptr> ren(map,context,detector); mapnik::cairo_renderer<mapnik::cairo_ptr> ren(map,context,detector);
ren.apply(); ren.apply(map.layers(),map.styles());
} }
void render_with_detector3( void render_with_detector3(
@ -231,7 +230,7 @@ void render_with_detector3(
python_unblock_auto_block b; python_unblock_auto_block b;
mapnik::cairo_ptr context(py_context->ctx, mapnik::cairo_closer()); mapnik::cairo_ptr context(py_context->ctx, mapnik::cairo_closer());
mapnik::cairo_renderer<mapnik::cairo_ptr> ren(map,context,detector,scale_factor,offset_x,offset_y); mapnik::cairo_renderer<mapnik::cairo_ptr> ren(map,context,detector,scale_factor,offset_x,offset_y);
ren.apply(); ren.apply(map.layers(),map.styles());
} }
void render_with_detector4( void render_with_detector4(
@ -242,7 +241,7 @@ void render_with_detector4(
python_unblock_auto_block b; python_unblock_auto_block b;
mapnik::cairo_surface_ptr surface(cairo_surface_reference(py_surface->surface), mapnik::cairo_surface_closer()); mapnik::cairo_surface_ptr surface(cairo_surface_reference(py_surface->surface), mapnik::cairo_surface_closer());
mapnik::cairo_renderer<mapnik::cairo_surface_ptr> ren(map, surface, detector); mapnik::cairo_renderer<mapnik::cairo_surface_ptr> ren(map, surface, detector);
ren.apply(); ren.apply(map.layers(),map.styles());
} }
void render_with_detector5( void render_with_detector5(
@ -256,7 +255,7 @@ void render_with_detector5(
python_unblock_auto_block b; python_unblock_auto_block b;
mapnik::cairo_surface_ptr surface(cairo_surface_reference(py_surface->surface), mapnik::cairo_surface_closer()); mapnik::cairo_surface_ptr surface(cairo_surface_reference(py_surface->surface), mapnik::cairo_surface_closer());
mapnik::cairo_renderer<mapnik::cairo_surface_ptr> ren(map, surface, detector, scale_factor, offset_x, offset_y); mapnik::cairo_renderer<mapnik::cairo_surface_ptr> ren(map, surface, detector, scale_factor, offset_x, offset_y);
ren.apply(); ren.apply(map.layers(),map.styles());
} }
#endif #endif

View file

@ -394,7 +394,7 @@ void render_layer_for_grid(mapnik::Map const& map,
mapnik::grid_renderer<mapnik::grid> ren(map,grid,1.0,0,0); mapnik::grid_renderer<mapnik::grid> ren(map,grid,1.0,0,0);
mapnik::layer const& layer = layers[layer_idx]; mapnik::layer const& layer = layers[layer_idx];
ren.apply(layer,attributes); ren.apply(layer,map.styles(),attributes);
} }
/* old, original impl - to be removed after further testing /* old, original impl - to be removed after further testing
@ -457,7 +457,7 @@ boost::python::dict render_grid(mapnik::Map const& map,
{ {
mapnik::grid_renderer<mapnik::grid> ren(map,grid,1.0,0,0); mapnik::grid_renderer<mapnik::grid> ren(map,grid,1.0,0,0);
mapnik::layer const& layer = layers[layer_idx]; mapnik::layer const& layer = layers[layer_idx];
ren.apply(layer,attributes); ren.apply(layer,map.styles(),attributes);
} }
catch (...) catch (...)
{ {

View file

@ -262,7 +262,7 @@ int main ( int argc , char** argv)
image_32 buf(m.width(),m.height()); image_32 buf(m.width(),m.height());
agg_renderer<image_32> ren(m,buf); agg_renderer<image_32> ren(m,buf);
ren.apply(); ren.apply(m.layers(),m.styles());
save_to_file(buf,"demo.jpg","jpeg"); save_to_file(buf,"demo.jpg","jpeg");
save_to_file(buf,"demo.png","png"); save_to_file(buf,"demo.png","png");
@ -294,7 +294,7 @@ int main ( int argc , char** argv)
double scale_factor = 1.0; double scale_factor = 1.0;
cairo_ptr image_context = (create_context(image_surface)); cairo_ptr image_context = (create_context(image_surface));
mapnik::cairo_renderer<cairo_ptr> png_render(m,image_context,scale_factor); mapnik::cairo_renderer<cairo_ptr> png_render(m,image_context,scale_factor);
png_render.apply(); png_render.apply(m.layers(),m.styles());
// we can now write to png with cairo functionality // we can now write to png with cairo functionality
cairo_surface_write_to_png(&*image_surface, "cairo-demo.png"); cairo_surface_write_to_png(&*image_surface, "cairo-demo.png");
// but we can also benefit from quantization by converting // but we can also benefit from quantization by converting

View file

@ -19,7 +19,7 @@
// qt // qt
#include <QtWidgets/QApplication> #include <QApplication>
#include <QStringList> #include <QStringList>
#include <QSettings> #include <QSettings>
#include <mapnik/datasource_cache.hpp> #include <mapnik/datasource_cache.hpp>

View file

@ -34,6 +34,7 @@
#include <mapnik/feature_kv_iterator.hpp> #include <mapnik/feature_kv_iterator.hpp>
#include <mapnik/config_error.hpp> #include <mapnik/config_error.hpp>
#include <mapnik/image_util.hpp> #include <mapnik/image_util.hpp>
#include <mapnik/util/map_query.hpp>
#ifdef HAVE_CAIRO #ifdef HAVE_CAIRO
// cairo // cairo
@ -176,7 +177,7 @@ void MapWidget::mousePressEvent(QMouseEvent* e)
projection layer_proj(layer.srs()); projection layer_proj(layer.srs());
mapnik::proj_transform prj_trans(map_proj,layer_proj); mapnik::proj_transform prj_trans(map_proj,layer_proj);
//std::auto_ptr<mapnik::memory_datasource> data(new mapnik::memory_datasource); //std::auto_ptr<mapnik::memory_datasource> data(new mapnik::memory_datasource);
mapnik::featureset_ptr fs = map_->query_map_point(index,x,y); mapnik::featureset_ptr fs = mapnik::util::query_map_point(map,index,x,y);
if (fs) if (fs)
{ {
@ -483,7 +484,7 @@ void MapWidget::export_to_file(unsigned ,unsigned ,std::string const&,std::strin
{ {
//image_32 image(width,height); //image_32 image(width,height);
//agg_renderer renderer(map,image); //agg_renderer renderer(map,image);
//renderer.apply(); //renderer.apply(map.layers(),map.styles());
//image.saveToFile(filename,type); //image.saveToFile(filename,type);
std::cout << "Export to file .." << std::endl; std::cout << "Export to file .." << std::endl;
} }
@ -505,7 +506,7 @@ void render_agg(mapnik::Map const& map, double scaling_factor, QPixmap & pix)
{ {
{ {
boost::timer::auto_cpu_timer t; boost::timer::auto_cpu_timer t;
ren.apply(); ren.apply(map.layers(),map.styles());
} }
QImage image((uchar*)buf.raw_data(),width,height,QImage::Format_ARGB32); QImage image((uchar*)buf.raw_data(),width,height,QImage::Format_ARGB32);
pix = QPixmap::fromImage(image.rgbSwapped()); pix = QPixmap::fromImage(image.rgbSwapped());
@ -538,7 +539,7 @@ void render_cairo(mapnik::Map const& map, double scaling_factor, QPixmap & pix)
mapnik::cairo_surface_ptr image_surface(cairo_image_surface_create(CAIRO_FORMAT_ARGB32,map.width(),map.height()), mapnik::cairo_surface_ptr image_surface(cairo_image_surface_create(CAIRO_FORMAT_ARGB32,map.width(),map.height()),
mapnik::cairo_surface_closer()); mapnik::cairo_surface_closer());
mapnik::cairo_renderer<mapnik::cairo_surface_ptr> renderer(map, image_surface, scaling_factor); mapnik::cairo_renderer<mapnik::cairo_surface_ptr> renderer(map, image_surface, scaling_factor);
renderer.apply(); renderer.apply(map.layers(),map.styles());
image_32 buf(image_surface); image_32 buf(image_surface);
QImage image((uchar*)buf.raw_data(),buf.width(),buf.height(),QImage::Format_ARGB32); QImage image((uchar*)buf.raw_data(),buf.width(),buf.height(),QImage::Format_ARGB32);
pix = QPixmap::fromImage(image.rgbSwapped()); pix = QPixmap::fromImage(image.rgbSwapped());

View file

@ -24,11 +24,15 @@
#define MAPNIK_FEATURE_STYLE_PROCESSOR_HPP #define MAPNIK_FEATURE_STYLE_PROCESSOR_HPP
// mapnik // mapnik
#include <mapnik/datasource.hpp> // for featureset_ptr
#include <mapnik/config.hpp> #include <mapnik/config.hpp>
#include <mapnik/featureset.hpp>
// boost
#include <boost/optional.hpp>
// stl // stl
#include <set> #include <set>
#include <map>
#include <string> #include <string>
#include <vector> #include <vector>
@ -41,6 +45,7 @@ class projection;
class proj_transform; class proj_transform;
class feature_type_style; class feature_type_style;
class rule_cache; class rule_cache;
template <typename T> class box2d;
enum eAttributeCollectionPolicy enum eAttributeCollectionPolicy
{ {
@ -59,18 +64,22 @@ public:
/*! /*!
* \brief apply renderer to all map layers. * \brief apply renderer to all map layers.
*/ */
void apply(double scale_denom_override=0.0); void apply(std::vector<mapnik::layer> const& layers,
std::map<std::string,feature_type_style> const& styles,
double scale_denom_override=0.0);
/*! /*!
* \brief apply renderer to a single layer, providing pre-populated set of query attribute names. * \brief apply renderer to a single layer, providing pre-populated set of query attribute names.
*/ */
void apply(mapnik::layer const& lyr, void apply(mapnik::layer const& lyr,
std::map<std::string,feature_type_style> const& styles,
std::set<std::string>& names, std::set<std::string>& names,
double scale_denom_override=0.0); double scale_denom_override=0.0);
/*! /*!
* \brief render a layer given a projection and scale. * \brief render a layer given a projection and scale.
*/ */
void apply_to_layer(layer const& lay, void apply_to_layer(layer const& lay,
std::map<std::string,feature_type_style> const& styles,
Processor & p, Processor & p,
projection const& proj0, projection const& proj0,
double scale, double scale,
@ -79,7 +88,8 @@ public:
unsigned height, unsigned height,
box2d<double> const& extent, box2d<double> const& extent,
int buffer_size, int buffer_size,
std::set<std::string>& names); std::set<std::string>& names,
boost::optional<box2d<double> > const& maximum_extent);
private: private:
/*! /*!

View file

@ -138,7 +138,9 @@ feature_style_processor<Processor>::feature_style_processor(Map const& m, double
} }
template <typename Processor> template <typename Processor>
void feature_style_processor<Processor>::apply(double scale_denom) void feature_style_processor<Processor>::apply(std::vector<mapnik::layer> const& layers,
std::map<std::string,feature_type_style> const& styles,
double scale_denom)
{ {
Processor & p = static_cast<Processor&>(*this); Processor & p = static_cast<Processor&>(*this);
p.start_map_processing(m_); p.start_map_processing(m_);
@ -148,12 +150,13 @@ void feature_style_processor<Processor>::apply(double scale_denom)
scale_denom = mapnik::scale_denominator(m_.scale(),proj.is_geographic()); scale_denom = mapnik::scale_denominator(m_.scale(),proj.is_geographic());
scale_denom *= p.scale_factor(); scale_denom *= p.scale_factor();
BOOST_FOREACH ( layer const& lyr, m_.layers() ) BOOST_FOREACH ( layer const& lyr, layers )
{ {
if (lyr.visible(scale_denom)) if (lyr.visible(scale_denom))
{ {
std::set<std::string> names; std::set<std::string> names;
apply_to_layer(lyr, apply_to_layer(lyr,
styles,
p, p,
proj, proj,
m_.scale(), m_.scale(),
@ -162,17 +165,18 @@ void feature_style_processor<Processor>::apply(double scale_denom)
m_.height(), m_.height(),
m_.get_current_extent(), m_.get_current_extent(),
m_.buffer_size(), m_.buffer_size(),
names); names,
m_.maximum_extent());
} }
} }
p.end_map_processing(m_); p.end_map_processing(m_);
} }
template <typename Processor> template <typename Processor>
void feature_style_processor<Processor>::apply(mapnik::layer const& lyr, void feature_style_processor<Processor>::apply(mapnik::layer const& lyr,
std::map<std::string,feature_type_style> const& styles,
std::set<std::string>& names, std::set<std::string>& names,
double scale_denom) double scale_denom)
{ {
@ -186,6 +190,7 @@ void feature_style_processor<Processor>::apply(mapnik::layer const& lyr,
if (lyr.visible(scale_denom)) if (lyr.visible(scale_denom))
{ {
apply_to_layer(lyr, apply_to_layer(lyr,
styles,
p, p,
proj, proj,
m_.scale(), m_.scale(),
@ -194,13 +199,16 @@ void feature_style_processor<Processor>::apply(mapnik::layer const& lyr,
m_.height(), m_.height(),
m_.get_current_extent(), m_.get_current_extent(),
m_.buffer_size(), m_.buffer_size(),
names); names,
m_.maximum_extent());
} }
p.end_map_processing(m_); p.end_map_processing(m_);
} }
template <typename Processor> template <typename Processor>
void feature_style_processor<Processor>::apply_to_layer(layer const& lay, Processor & p, void feature_style_processor<Processor>::apply_to_layer(layer const& lay,
std::map<std::string,feature_type_style> const& styles,
Processor & p,
projection const& proj0, projection const& proj0,
double scale, double scale,
double scale_denom, double scale_denom,
@ -208,7 +216,8 @@ void feature_style_processor<Processor>::apply_to_layer(layer const& lay, Proces
unsigned height, unsigned height,
box2d<double> const& extent, box2d<double> const& extent,
int buffer_size, int buffer_size,
std::set<std::string>& names) std::set<std::string>& names,
boost::optional<box2d<double> > const& maximum_extent)
{ {
std::vector<std::string> const& style_names = lay.styles(); std::vector<std::string> const& style_names = lay.styles();
@ -248,7 +257,6 @@ void feature_style_processor<Processor>::apply_to_layer(layer const& lay, Proces
buffered_query_ext.height(query_ext.height() + buffer_padding); buffered_query_ext.height(query_ext.height() + buffer_padding);
// clip buffered extent by maximum extent, if supplied // clip buffered extent by maximum extent, if supplied
boost::optional<box2d<double> > const& maximum_extent = m_.maximum_extent();
if (maximum_extent) if (maximum_extent)
{ {
buffered_query_ext.clip(*maximum_extent); buffered_query_ext.clip(*maximum_extent);
@ -294,18 +302,20 @@ void feature_style_processor<Processor>::apply_to_layer(layer const& lay, Proces
// https://github.com/mapnik/mapnik/issues/1477 // https://github.com/mapnik/mapnik/issues/1477
BOOST_FOREACH(std::string const& style_name, style_names) BOOST_FOREACH(std::string const& style_name, style_names)
{ {
boost::optional<feature_type_style const&> style=m_.find_style(style_name); std::map<std::string,feature_type_style>::const_iterator itr = styles.find(style_name);
if (!style) if (itr == styles.end())
{ {
continue; continue;
} }
if (style->comp_op() || style->image_filters().size() > 0) feature_type_style const& style = itr->second;
if (style.comp_op() || style.image_filters().size() > 0)
{ {
if (style->active(scale_denom)) if (style.active(scale_denom))
{ {
// trigger any needed compositing ops // trigger any needed compositing ops
p.start_style_processing(*style); p.start_style_processing(style);
p.end_style_processing(*style); p.end_style_processing(style);
} }
} }
} }
@ -351,17 +361,16 @@ void feature_style_processor<Processor>::apply_to_layer(layer const& lay, Proces
// iterate through all named styles collecting active styles and attribute names // iterate through all named styles collecting active styles and attribute names
BOOST_FOREACH(std::string const& style_name, style_names) BOOST_FOREACH(std::string const& style_name, style_names)
{ {
boost::optional<feature_type_style const&> style=m_.find_style(style_name); std::map<std::string,feature_type_style>::const_iterator itr = styles.find(style_name);
if (!style) if (itr == styles.end())
{ {
MAPNIK_LOG_DEBUG(feature_style_processor) MAPNIK_LOG_DEBUG(feature_style_processor)
<< "feature_style_processor: Style=" << style_name << "feature_style_processor: Style=" << style_name
<< " required for layer=" << lay.name() << " does not exist."; << " required for layer=" << lay.name() << " does not exist.";
continue; continue;
} }
feature_type_style const& style = itr->second;
std::vector<rule> const& rules = style->get_rules(); std::vector<rule> const& rules = style.get_rules();
bool active_rules = false; bool active_rules = false;
std::auto_ptr<rule_cache> rc(new rule_cache); std::auto_ptr<rule_cache> rc(new rule_cache);
BOOST_FOREACH(rule const& r, rules) BOOST_FOREACH(rule const& r, rules)
@ -376,7 +385,7 @@ void feature_style_processor<Processor>::apply_to_layer(layer const& lay, Proces
if (active_rules) if (active_rules)
{ {
rule_caches.push_back(rc); rule_caches.push_back(rc);
active_styles.push_back(&(*style)); active_styles.push_back(&style);
} }
} }

View file

@ -0,0 +1,47 @@
/*****************************************************************************
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* 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
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*****************************************************************************/
#ifndef MAPNIK_FEATURESET_HPP
#define MAPNIK_FEATURESET_HPP
// mapnik
#include <mapnik/config.hpp>
#include <mapnik/noncopyable.hpp>
// boost
#include <boost/shared_ptr.hpp>
namespace mapnik {
class feature_impl;
struct MAPNIK_DECL Featureset : private mapnik::noncopyable
{
virtual boost::shared_ptr<feature_impl> next() = 0;
virtual ~Featureset() {}
};
typedef boost::shared_ptr<Featureset> featureset_ptr;
}
#endif // MAPNIK_FEATURESET_HPP

View file

@ -329,10 +329,6 @@ public:
*/ */
void zoom_to_box(box2d<double> const& box); void zoom_to_box(box2d<double> const& box);
/*! \brief Zoom the map to show all data.
*/
void zoom_all();
void pan(int x,int y); void pan(int x,int y);
void pan_and_zoom(int x,int y,double zoom); void pan_and_zoom(int x,int y,double zoom);
@ -352,36 +348,6 @@ public:
*/ */
double scale() const; double scale() const;
double scale_denominator() const;
CoordTransform view_transform() const;
/*!
* @brief Query a Map layer (by layer index) for features
*
* Intersecting the given x,y location in the coordinates
* of map projection.
*
* @param index The index of the layer to query from.
* @param x The x coordinate where to query.
* @param y The y coordinate where to query.
* @return A Mapnik Featureset if successful otherwise will return NULL.
*/
featureset_ptr query_point(unsigned index, double x, double y) const;
/*!
* @brief Query a Map layer (by layer index) for features
*
* Intersecting the given x,y location in the coordinates
* of the pixmap or map surface.
*
* @param index The index of the layer to query from.
* @param x The x coordinate where to query.
* @param y The y coordinate where to query.
* @return A Mapnik Featureset if successful otherwise will return NULL.
*/
featureset_ptr query_map_point(unsigned index, double x, double y) const;
~Map(); ~Map();
inline void set_aspect_fix_mode(aspect_fix_mode afm) { aspectFixMode_ = afm; } inline void set_aspect_fix_mode(aspect_fix_mode afm) { aspectFixMode_ = afm; }

View file

@ -0,0 +1,148 @@
/*****************************************************************************
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* 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
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*****************************************************************************/
#ifndef MAPNIK_UTIL_MAP_QUERY
#define MAPNIK_UTIL_MAP_QUERY
#include <mapnik/map.hpp>
#include <mapnik/box2d.hpp>
#include <mapnik/projection.hpp>
#include <mapnik/proj_transform.hpp>
#include <mapnik/datasource.hpp>
#include <mapnik/feature.hpp>
#include <mapnik/ctrans.hpp>
#include <mapnik/filter_featureset.hpp>
#include <mapnik/hit_test_filter.hpp>
#include <boost/make_shared.hpp>
#include <boost/foreach.hpp>
#include <sstream>
#include <stdexcept>
namespace mapnik { namespace util {
static mapnik::box2d<double> get_extent(mapnik::Map const& map)
{
std::vector<mapnik::layer> const& layers = map.layers();
if (layers.empty())
{
throw std::runtime_error("map has no layers so unable to get extent");
}
box2d<double> ext;
bool success = false;
projection proj0(map.srs());
bool first = true;
BOOST_FOREACH ( layer const& lay, map.layers() )
{
if (lay.active())
{
projection proj1(lay.srs());
proj_transform prj_trans(proj0,proj1);
box2d<double> layer_ext = lay.envelope();
if (prj_trans.backward(layer_ext, PROJ_ENVELOPE_POINTS))
{
success = true;
if (first)
{
ext = layer_ext;
first = false;
}
else
{
ext.expand_to_include(layer_ext);
}
}
}
}
if (!success)
{
throw std::runtime_error("could not zoom to combined layer extents");
}
return ext;
}
static featureset_ptr query_point(mapnik::Map const& map, unsigned index, double x, double y)
{
if (!map.get_current_extent().valid())
{
throw std::runtime_error("query_point: map extent is not intialized, you need to set a valid extent before querying");
}
if (!map.get_current_extent().intersects(x,y))
{
throw std::runtime_error("query_point: x,y coords do not intersect map extent");
}
std::vector<mapnik::layer> const& layers = map.layers();
if (index < layers.size())
{
mapnik::layer const& layer = layers[index];
mapnik::datasource_ptr ds = layer.datasource();
if (ds)
{
mapnik::projection dest(map.srs());
mapnik::projection source(layer.srs());
proj_transform prj_trans(source,dest);
double z = 0;
if (!prj_trans.equal() && !prj_trans.backward(x,y,z))
{
throw std::runtime_error("query_point: could not project x,y into layer srs");
}
// calculate default tolerance
mapnik::box2d<double> map_ex = map.get_current_extent();
if (!prj_trans.backward(map_ex,PROJ_ENVELOPE_POINTS))
{
std::ostringstream s;
s << "query_point: could not project map extent '" << map_ex
<< "' into layer srs for tolerance calculation";
throw std::runtime_error(s.str());
}
double tol = (map_ex.maxx() - map_ex.minx()) / map.width() * 3;
featureset_ptr fs = ds->features_at_point(mapnik::coord2d(x,y), tol);
if (fs)
{
return boost::make_shared<filter_featureset<hit_test_filter> >(fs,
hit_test_filter(x,y,tol));
}
}
}
else
{
std::ostringstream s;
s << "Invalid layer index passed to query_point: '" << index << "'";
if (!layers.empty()) s << " for map with " << layers.size() << " layers(s)";
else s << " (map has no layers)";
throw std::out_of_range(s.str());
}
return featureset_ptr();
}
static featureset_ptr query_map_point(mapnik::Map const& map, unsigned index, double x, double y)
{
CoordTransform tr(map.width(),map.height(),map.get_current_extent());
tr.backward(&x,&y);
return query_point(map,index,x,y);
}
}}
#endif // MAPNIK_UTIL_MAP_QUERY

View file

@ -559,7 +559,7 @@ void save_to_cairo_file(mapnik::Map const& map,
*/ */
mapnik::cairo_renderer<cairo_ptr> ren(map, create_context(surface), scale_factor); mapnik::cairo_renderer<cairo_ptr> ren(map, create_context(surface), scale_factor);
ren.apply(scale_denominator); ren.apply(map.layers(),map.styles(),scale_denominator);
if (type == "ARGB32" || type == "RGB24") if (type == "ARGB32" || type == "RGB24")
{ {

View file

@ -29,13 +29,8 @@
#include <mapnik/feature_type_style.hpp> #include <mapnik/feature_type_style.hpp>
#include <mapnik/debug.hpp> #include <mapnik/debug.hpp>
#include <mapnik/map.hpp> #include <mapnik/map.hpp>
#include <mapnik/datasource.hpp>
#include <mapnik/projection.hpp> #include <mapnik/projection.hpp>
#include <mapnik/proj_transform.hpp> #include <mapnik/proj_transform.hpp>
#include <mapnik/ctrans.hpp>
#include <mapnik/filter_featureset.hpp>
#include <mapnik/hit_test_filter.hpp>
#include <mapnik/scale_denominator.hpp>
#include <mapnik/config_error.hpp> #include <mapnik/config_error.hpp>
#include <mapnik/config.hpp> // for PROJ_ENVELOPE_POINTS #include <mapnik/config.hpp> // for PROJ_ENVELOPE_POINTS
@ -357,78 +352,6 @@ void Map::zoom(double factor)
fixAspectRatio(); fixAspectRatio();
} }
void Map::zoom_all()
{
try
{
if (layers_.empty())
{
return;
}
projection proj0(srs_);
box2d<double> ext;
bool success = false;
bool first = true;
std::vector<layer>::const_iterator itr = layers_.begin();
std::vector<layer>::const_iterator end = layers_.end();
while (itr != end)
{
if (itr->active())
{
std::string const& layer_srs = itr->srs();
projection proj1(layer_srs);
proj_transform prj_trans(proj0,proj1);
box2d<double> layer_ext = itr->envelope();
if (prj_trans.backward(layer_ext, PROJ_ENVELOPE_POINTS))
{
success = true;
MAPNIK_LOG_DEBUG(map) << "map: Layer " << itr->name() << " original ext=" << itr->envelope();
MAPNIK_LOG_DEBUG(map) << "map: Layer " << itr->name() << " transformed to map srs=" << layer_ext;
if (first)
{
ext = layer_ext;
first = false;
}
else
{
ext.expand_to_include(layer_ext);
}
}
}
++itr;
}
if (success)
{
if (maximum_extent_) {
ext.clip(*maximum_extent_);
}
zoom_to_box(ext);
}
else
{
if (maximum_extent_)
{
MAPNIK_LOG_ERROR(map) << "could not zoom to combined layer extents"
<< " so falling back to maximum-extent for zoom_all result";
zoom_to_box(*maximum_extent_);
}
else
{
std::ostringstream s;
s << "could not zoom to combined layer extents "
<< "using zoom_all because proj4 could not "
<< "back project any layer extents into the map srs "
<< "(set map 'maximum-extent' to override layer extents)";
throw std::runtime_error(s.str());
}
}
}
catch (proj_init_error const& ex)
{
throw mapnik::config_error(std::string("Projection error during map.zoom_all: ") + ex.what());
}
}
void Map::zoom_to_box(box2d<double> const& box) void Map::zoom_to_box(box2d<double> const& box)
{ {
current_extent_=box; current_extent_=box;
@ -530,83 +453,6 @@ double Map::scale() const
return current_extent_.width(); return current_extent_.width();
} }
double Map::scale_denominator() const
{
projection map_proj(srs_);
return mapnik::scale_denominator( scale(), map_proj.is_geographic());
}
CoordTransform Map::view_transform() const
{
return CoordTransform(width_,height_,current_extent_);
}
featureset_ptr Map::query_point(unsigned index, double x, double y) const
{
if (!current_extent_.valid())
{
throw std::runtime_error("query_point: map extent is not intialized, you need to set a valid extent before querying");
}
if (!current_extent_.intersects(x,y))
{
throw std::runtime_error("query_point: x,y coords do not intersect map extent");
}
if (index < layers_.size())
{
mapnik::layer const& layer = layers_[index];
mapnik::datasource_ptr ds = layer.datasource();
if (ds)
{
mapnik::projection dest(srs_);
mapnik::projection source(layer.srs());
proj_transform prj_trans(source,dest);
double z = 0;
if (!prj_trans.equal() && !prj_trans.backward(x,y,z))
{
throw std::runtime_error("query_point: could not project x,y into layer srs");
}
// calculate default tolerance
mapnik::box2d<double> map_ex = current_extent_;
if (maximum_extent_)
{
map_ex.clip(*maximum_extent_);
}
if (!prj_trans.backward(map_ex,PROJ_ENVELOPE_POINTS))
{
std::ostringstream s;
s << "query_point: could not project map extent '" << map_ex
<< "' into layer srs for tolerance calculation";
throw std::runtime_error(s.str());
}
double tol = (map_ex.maxx() - map_ex.minx()) / width_ * 3;
featureset_ptr fs = ds->features_at_point(mapnik::coord2d(x,y), tol);
MAPNIK_LOG_DEBUG(map) << "map: Query at point tol=" << tol << "(" << x << "," << y << ")";
if (fs)
{
return boost::make_shared<filter_featureset<hit_test_filter> >(fs,
hit_test_filter(x,y,tol));
}
}
}
else
{
std::ostringstream s;
s << "Invalid layer index passed to query_point: '" << index << "'";
if (!layers_.empty()) s << " for map with " << layers_.size() << " layers(s)";
else s << " (map has no layers)";
throw std::out_of_range(s.str());
}
return featureset_ptr();
}
featureset_ptr Map::query_map_point(unsigned index, double x, double y) const
{
CoordTransform tr = view_transform();
tr.backward(&x,&y);
return query_point(index,x,y);
}
parameters const& Map::get_extra_parameters() const parameters const& Map::get_extra_parameters() const
{ {
return extra_params_; return extra_params_;

View file

@ -21,6 +21,7 @@
#include <mapnik/util/fs.hpp> #include <mapnik/util/fs.hpp>
#include <vector> #include <vector>
#include <algorithm> #include <algorithm>
#include <mapnik/util/map_query.hpp>
#include "utils.hpp" #include "utils.hpp"
@ -64,13 +65,13 @@ int main(int argc, char** argv)
l.add_style("style"); l.add_style("style");
mapnik::Map m = map; mapnik::Map m = map;
m.addLayer(l); m.addLayer(l);
m.zoom_all(); m.zoom_to_box(mapnik::util::get_extent(m));
mapnik::image_32 im(m.width(),m.height()); mapnik::image_32 im(m.width(),m.height());
mapnik::agg_renderer<mapnik::image_32> ren(m,im); mapnik::agg_renderer<mapnik::image_32> ren(m,im);
//std::clog << mapnik::save_map_to_string(m) << "\n"; //std::clog << mapnik::save_map_to_string(m) << "\n";
BOOST_TEST(true); BOOST_TEST(true);
// should throw here with "CSV Plugin: no attribute 'foo'. Valid attributes are: x,y." // should throw here with "CSV Plugin: no attribute 'foo'. Valid attributes are: x,y."
ren.apply(); ren.apply(m.layers(),m.styles());
BOOST_TEST(false); BOOST_TEST(false);
} catch (...) { } catch (...) {
BOOST_TEST(true); BOOST_TEST(true);

View file

@ -67,7 +67,7 @@ int main(int argc, char** argv)
256,256)); 256,256));
mapnik::image_32 buf(m.width(),m.height()); mapnik::image_32 buf(m.width(),m.height());
mapnik::agg_renderer<mapnik::image_32> ren(m,buf); mapnik::agg_renderer<mapnik::image_32> ren(m,buf);
ren.apply(); ren.apply(m.layers(),m.styles());
} catch (std::exception const& ex) { } catch (std::exception const& ex) {
BOOST_TEST_EQ(std::string(ex.what()),std::string("No valid font face could be loaded for font set: 'fontset'")); BOOST_TEST_EQ(std::string(ex.what()),std::string("No valid font face could be loaded for font set: 'fontset'"));
} }