Compare commits
12 commits
master
...
future-ren
Author | SHA1 | Date | |
---|---|---|---|
|
1a5d0c8d27 | ||
|
569de8569b | ||
|
8acfc3dce6 | ||
|
5475255be9 | ||
|
f63474d255 | ||
|
f5a91ae7aa | ||
|
5415b551d7 | ||
|
b11290dfe1 | ||
|
dce3a73e0d | ||
|
2406c0e79d | ||
|
72d88cfd79 | ||
|
0c82ec6006 |
15 changed files with 286 additions and 244 deletions
|
@ -34,7 +34,8 @@
|
|||
#include <mapnik/projection.hpp>
|
||||
#include <mapnik/ctrans.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"
|
||||
|
||||
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");
|
||||
boost::python::throw_error_already_set();
|
||||
}
|
||||
unsigned idx = index;
|
||||
return m.query_point(idx, x, y);
|
||||
return mapnik::util::query_point(m, static_cast<unsigned>(index), x, 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");
|
||||
boost::python::throw_error_already_set();
|
||||
}
|
||||
unsigned idx = index;
|
||||
return m.query_map_point(idx, x, y);
|
||||
return mapnik::util::query_map_point(m, static_cast<unsigned>(index), 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)
|
||||
|
@ -326,14 +341,14 @@ void export_map()
|
|||
">>> m.scale()\n"
|
||||
)
|
||||
|
||||
.def("scale_denominator", &Map::scale_denominator,
|
||||
.def("scale_denominator", get_scale_denominator,
|
||||
"Return the Map Scale Denominator.\n"
|
||||
"Usage:\n"
|
||||
"\n"
|
||||
">>> m.scale_denominator()\n"
|
||||
)
|
||||
|
||||
.def("view_transform",&Map::view_transform,
|
||||
.def("view_transform",get_view_transform,
|
||||
"Return the map ViewTransform object\n"
|
||||
"which is used internally to convert between\n"
|
||||
"geographic coordinates and screen coordinates.\n"
|
||||
|
@ -353,7 +368,7 @@ void export_map()
|
|||
">>> m.zoom(0.25)\n"
|
||||
)
|
||||
|
||||
.def("zoom_all",&Map::zoom_all,
|
||||
.def("zoom_all",&zoom_all,
|
||||
"Set the geographical extent of the map\n"
|
||||
"to the combined extents of all active layers.\n"
|
||||
"\n"
|
||||
|
|
|
@ -130,8 +130,7 @@ void render(const mapnik::Map& map,
|
|||
{
|
||||
python_unblock_auto_block b;
|
||||
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(
|
||||
|
@ -144,7 +143,7 @@ void render_with_detector(
|
|||
{
|
||||
python_unblock_auto_block b;
|
||||
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,
|
||||
|
@ -164,7 +163,7 @@ void render_layer2(const mapnik::Map& map,
|
|||
mapnik::layer const& layer = layers[layer_idx];
|
||||
mapnik::agg_renderer<mapnik::image_32> ren(map,image,1.0,0,0);
|
||||
std::set<std::string> names;
|
||||
ren.apply(layer,names);
|
||||
ren.apply(layer,map.styles(),names);
|
||||
}
|
||||
|
||||
#if defined(HAVE_CAIRO) && defined(HAVE_PYCAIRO)
|
||||
|
@ -178,7 +177,7 @@ void render3(const mapnik::Map& map,
|
|||
python_unblock_auto_block b;
|
||||
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);
|
||||
ren.apply();
|
||||
ren.apply(map.layers(),map.styles());
|
||||
}
|
||||
|
||||
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;
|
||||
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);
|
||||
ren.apply();
|
||||
ren.apply(map.layers(),map.styles());
|
||||
}
|
||||
|
||||
void render5(const mapnik::Map& map,
|
||||
|
@ -198,7 +197,7 @@ void render5(const mapnik::Map& map,
|
|||
python_unblock_auto_block b;
|
||||
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);
|
||||
ren.apply();
|
||||
ren.apply(map.layers(),map.styles());
|
||||
}
|
||||
|
||||
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;
|
||||
mapnik::cairo_ptr context(py_context->ctx, mapnik::cairo_closer());
|
||||
mapnik::cairo_renderer<mapnik::cairo_ptr> ren(map,context);
|
||||
ren.apply();
|
||||
ren.apply(map.layers(),map.styles());
|
||||
}
|
||||
|
||||
void render_with_detector2(
|
||||
|
@ -217,7 +216,7 @@ void render_with_detector2(
|
|||
python_unblock_auto_block b;
|
||||
mapnik::cairo_ptr context(py_context->ctx, mapnik::cairo_closer());
|
||||
mapnik::cairo_renderer<mapnik::cairo_ptr> ren(map,context,detector);
|
||||
ren.apply();
|
||||
ren.apply(map.layers(),map.styles());
|
||||
}
|
||||
|
||||
void render_with_detector3(
|
||||
|
@ -231,7 +230,7 @@ void render_with_detector3(
|
|||
python_unblock_auto_block b;
|
||||
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);
|
||||
ren.apply();
|
||||
ren.apply(map.layers(),map.styles());
|
||||
}
|
||||
|
||||
void render_with_detector4(
|
||||
|
@ -242,7 +241,7 @@ void render_with_detector4(
|
|||
python_unblock_auto_block b;
|
||||
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);
|
||||
ren.apply();
|
||||
ren.apply(map.layers(),map.styles());
|
||||
}
|
||||
|
||||
void render_with_detector5(
|
||||
|
@ -256,7 +255,7 @@ void render_with_detector5(
|
|||
python_unblock_auto_block b;
|
||||
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);
|
||||
ren.apply();
|
||||
ren.apply(map.layers(),map.styles());
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -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::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
|
||||
|
@ -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::layer const& layer = layers[layer_idx];
|
||||
ren.apply(layer,attributes);
|
||||
ren.apply(layer,map.styles(),attributes);
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
|
|
|
@ -262,7 +262,7 @@ int main ( int argc , char** argv)
|
|||
|
||||
image_32 buf(m.width(),m.height());
|
||||
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.png","png");
|
||||
|
@ -294,7 +294,7 @@ int main ( int argc , char** argv)
|
|||
double scale_factor = 1.0;
|
||||
cairo_ptr image_context = (create_context(image_surface));
|
||||
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
|
||||
cairo_surface_write_to_png(&*image_surface, "cairo-demo.png");
|
||||
// but we can also benefit from quantization by converting
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
|
||||
|
||||
// qt
|
||||
#include <QtWidgets/QApplication>
|
||||
#include <QApplication>
|
||||
#include <QStringList>
|
||||
#include <QSettings>
|
||||
#include <mapnik/datasource_cache.hpp>
|
||||
|
|
|
@ -34,6 +34,7 @@
|
|||
#include <mapnik/feature_kv_iterator.hpp>
|
||||
#include <mapnik/config_error.hpp>
|
||||
#include <mapnik/image_util.hpp>
|
||||
#include <mapnik/util/map_query.hpp>
|
||||
|
||||
#ifdef HAVE_CAIRO
|
||||
// cairo
|
||||
|
@ -176,7 +177,7 @@ void MapWidget::mousePressEvent(QMouseEvent* e)
|
|||
projection layer_proj(layer.srs());
|
||||
mapnik::proj_transform prj_trans(map_proj,layer_proj);
|
||||
//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)
|
||||
{
|
||||
|
@ -483,7 +484,7 @@ void MapWidget::export_to_file(unsigned ,unsigned ,std::string const&,std::strin
|
|||
{
|
||||
//image_32 image(width,height);
|
||||
//agg_renderer renderer(map,image);
|
||||
//renderer.apply();
|
||||
//renderer.apply(map.layers(),map.styles());
|
||||
//image.saveToFile(filename,type);
|
||||
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;
|
||||
ren.apply();
|
||||
ren.apply(map.layers(),map.styles());
|
||||
}
|
||||
QImage image((uchar*)buf.raw_data(),width,height,QImage::Format_ARGB32);
|
||||
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_closer());
|
||||
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);
|
||||
QImage image((uchar*)buf.raw_data(),buf.width(),buf.height(),QImage::Format_ARGB32);
|
||||
pix = QPixmap::fromImage(image.rgbSwapped());
|
||||
|
|
|
@ -24,11 +24,15 @@
|
|||
#define MAPNIK_FEATURE_STYLE_PROCESSOR_HPP
|
||||
|
||||
// mapnik
|
||||
#include <mapnik/datasource.hpp> // for featureset_ptr
|
||||
#include <mapnik/config.hpp>
|
||||
#include <mapnik/featureset.hpp>
|
||||
|
||||
// boost
|
||||
#include <boost/optional.hpp>
|
||||
|
||||
// stl
|
||||
#include <set>
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
|
@ -41,6 +45,7 @@ class projection;
|
|||
class proj_transform;
|
||||
class feature_type_style;
|
||||
class rule_cache;
|
||||
template <typename T> class box2d;
|
||||
|
||||
enum eAttributeCollectionPolicy
|
||||
{
|
||||
|
@ -59,18 +64,22 @@ public:
|
|||
/*!
|
||||
* \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.
|
||||
*/
|
||||
void apply(mapnik::layer const& lyr,
|
||||
std::map<std::string,feature_type_style> const& styles,
|
||||
std::set<std::string>& names,
|
||||
double scale_denom_override=0.0);
|
||||
/*!
|
||||
* \brief render a layer given a projection and scale.
|
||||
*/
|
||||
void apply_to_layer(layer const& lay,
|
||||
std::map<std::string,feature_type_style> const& styles,
|
||||
Processor & p,
|
||||
projection const& proj0,
|
||||
double scale,
|
||||
|
@ -79,7 +88,8 @@ public:
|
|||
unsigned height,
|
||||
box2d<double> const& extent,
|
||||
int buffer_size,
|
||||
std::set<std::string>& names);
|
||||
std::set<std::string>& names,
|
||||
boost::optional<box2d<double> > const& maximum_extent);
|
||||
|
||||
private:
|
||||
/*!
|
||||
|
|
|
@ -138,7 +138,9 @@ feature_style_processor<Processor>::feature_style_processor(Map const& m, double
|
|||
}
|
||||
|
||||
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);
|
||||
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 *= p.scale_factor();
|
||||
|
||||
BOOST_FOREACH ( layer const& lyr, m_.layers() )
|
||||
BOOST_FOREACH ( layer const& lyr, layers )
|
||||
{
|
||||
if (lyr.visible(scale_denom))
|
||||
{
|
||||
std::set<std::string> names;
|
||||
apply_to_layer(lyr,
|
||||
styles,
|
||||
p,
|
||||
proj,
|
||||
m_.scale(),
|
||||
|
@ -162,17 +165,18 @@ void feature_style_processor<Processor>::apply(double scale_denom)
|
|||
m_.height(),
|
||||
m_.get_current_extent(),
|
||||
m_.buffer_size(),
|
||||
names);
|
||||
names,
|
||||
m_.maximum_extent());
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
p.end_map_processing(m_);
|
||||
|
||||
}
|
||||
|
||||
template <typename Processor>
|
||||
void feature_style_processor<Processor>::apply(mapnik::layer const& lyr,
|
||||
std::map<std::string,feature_type_style> const& styles,
|
||||
std::set<std::string>& names,
|
||||
double scale_denom)
|
||||
{
|
||||
|
@ -186,6 +190,7 @@ void feature_style_processor<Processor>::apply(mapnik::layer const& lyr,
|
|||
if (lyr.visible(scale_denom))
|
||||
{
|
||||
apply_to_layer(lyr,
|
||||
styles,
|
||||
p,
|
||||
proj,
|
||||
m_.scale(),
|
||||
|
@ -194,13 +199,16 @@ void feature_style_processor<Processor>::apply(mapnik::layer const& lyr,
|
|||
m_.height(),
|
||||
m_.get_current_extent(),
|
||||
m_.buffer_size(),
|
||||
names);
|
||||
names,
|
||||
m_.maximum_extent());
|
||||
}
|
||||
p.end_map_processing(m_);
|
||||
}
|
||||
|
||||
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,
|
||||
double scale,
|
||||
double scale_denom,
|
||||
|
@ -208,7 +216,8 @@ void feature_style_processor<Processor>::apply_to_layer(layer const& lay, Proces
|
|||
unsigned height,
|
||||
box2d<double> const& extent,
|
||||
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();
|
||||
|
||||
|
@ -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);
|
||||
|
||||
// clip buffered extent by maximum extent, if supplied
|
||||
boost::optional<box2d<double> > const& maximum_extent = m_.maximum_extent();
|
||||
if (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
|
||||
BOOST_FOREACH(std::string const& style_name, style_names)
|
||||
{
|
||||
boost::optional<feature_type_style const&> style=m_.find_style(style_name);
|
||||
if (!style)
|
||||
std::map<std::string,feature_type_style>::const_iterator itr = styles.find(style_name);
|
||||
if (itr == styles.end())
|
||||
{
|
||||
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
|
||||
p.start_style_processing(*style);
|
||||
p.end_style_processing(*style);
|
||||
p.start_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
|
||||
BOOST_FOREACH(std::string const& style_name, style_names)
|
||||
{
|
||||
boost::optional<feature_type_style const&> style=m_.find_style(style_name);
|
||||
if (!style)
|
||||
std::map<std::string,feature_type_style>::const_iterator itr = styles.find(style_name);
|
||||
if (itr == styles.end())
|
||||
{
|
||||
MAPNIK_LOG_DEBUG(feature_style_processor)
|
||||
<< "feature_style_processor: Style=" << style_name
|
||||
<< " required for layer=" << lay.name() << " does not exist.";
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
std::vector<rule> const& rules = style->get_rules();
|
||||
feature_type_style const& style = itr->second;
|
||||
std::vector<rule> const& rules = style.get_rules();
|
||||
bool active_rules = false;
|
||||
std::auto_ptr<rule_cache> rc(new rule_cache);
|
||||
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)
|
||||
{
|
||||
rule_caches.push_back(rc);
|
||||
active_styles.push_back(&(*style));
|
||||
active_styles.push_back(&style);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
47
include/mapnik/featureset.hpp
Normal file
47
include/mapnik/featureset.hpp
Normal 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
|
|
@ -329,10 +329,6 @@ public:
|
|||
*/
|
||||
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_and_zoom(int x,int y,double zoom);
|
||||
|
@ -352,36 +348,6 @@ public:
|
|||
*/
|
||||
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();
|
||||
|
||||
inline void set_aspect_fix_mode(aspect_fix_mode afm) { aspectFixMode_ = afm; }
|
||||
|
|
148
include/mapnik/util/map_query.hpp
Normal file
148
include/mapnik/util/map_query.hpp
Normal 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
|
|
@ -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);
|
||||
ren.apply(scale_denominator);
|
||||
ren.apply(map.layers(),map.styles(),scale_denominator);
|
||||
|
||||
if (type == "ARGB32" || type == "RGB24")
|
||||
{
|
||||
|
|
154
src/map.cpp
154
src/map.cpp
|
@ -29,13 +29,8 @@
|
|||
#include <mapnik/feature_type_style.hpp>
|
||||
#include <mapnik/debug.hpp>
|
||||
#include <mapnik/map.hpp>
|
||||
#include <mapnik/datasource.hpp>
|
||||
#include <mapnik/projection.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.hpp> // for PROJ_ENVELOPE_POINTS
|
||||
|
||||
|
@ -357,78 +352,6 @@ void Map::zoom(double factor)
|
|||
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)
|
||||
{
|
||||
current_extent_=box;
|
||||
|
@ -530,83 +453,6 @@ double Map::scale() const
|
|||
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
|
||||
{
|
||||
return extra_params_;
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
#include <mapnik/util/fs.hpp>
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
#include <mapnik/util/map_query.hpp>
|
||||
|
||||
#include "utils.hpp"
|
||||
|
||||
|
@ -64,13 +65,13 @@ int main(int argc, char** argv)
|
|||
l.add_style("style");
|
||||
mapnik::Map m = map;
|
||||
m.addLayer(l);
|
||||
m.zoom_all();
|
||||
m.zoom_to_box(mapnik::util::get_extent(m));
|
||||
mapnik::image_32 im(m.width(),m.height());
|
||||
mapnik::agg_renderer<mapnik::image_32> ren(m,im);
|
||||
//std::clog << mapnik::save_map_to_string(m) << "\n";
|
||||
BOOST_TEST(true);
|
||||
// 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);
|
||||
} catch (...) {
|
||||
BOOST_TEST(true);
|
||||
|
|
|
@ -67,7 +67,7 @@ int main(int argc, char** argv)
|
|||
256,256));
|
||||
mapnik::image_32 buf(m.width(),m.height());
|
||||
mapnik::agg_renderer<mapnik::image_32> ren(m,buf);
|
||||
ren.apply();
|
||||
ren.apply(m.layers(),m.styles());
|
||||
} 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'"));
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue