Merge remote-tracking branch 'origin/master'

This commit is contained in:
artemp 2012-10-04 12:17:07 +01:00
commit 3072b3f581
53 changed files with 332 additions and 126 deletions

13
.travis.yml Normal file
View file

@ -0,0 +1,13 @@
language: cpp
matrix:
include:
- compiler: clang
env: CXX_SCONS="-Qunused-arguments -fcolor-diagnostics" WARNING_CXXFLAGS="-Wno-unused-function -Wno-uninitialized -Wno-array-bounds -Wno-parentheses -Wno-char-subscripts -Wno-internal-linkage-in-inline"
before_install:
- echo 'yes' | sudo add-apt-repository ppa:mapnik/boost
- sudo apt-get update -qq
- sudo apt-get install -qq libboost-dev libboost-filesystem-dev libboost-program-options-dev libboost-python-dev libboost-regex-dev libboost-system-dev libboost-thread-dev python-nose libicu-dev libpng-dev libjpeg-dev libtiff-dev libz-dev libfreetype6-dev libxml2-dev libproj-dev libpq-dev libgdal-dev libcairomm-1.0-dev python-cairo-dev libsqlite3-dev
script: scons configure JOBS=2 FAST=True CXX="$CXX $CXX_SCONS" WARNING_CXXFLAGS=$WARNING_CXXFLAGS && sudo make install

View file

@ -8,6 +8,12 @@ For a complete change history, see the git log.
## Future
- Faster rendering of rasters by reducing memory allocation of temporary buffers (#1516)
- Added ability to pass a pre-created collision detector to the cairo renderer (#1444)
- Tolerance parameter is now supported for querying datasources at a given point (#503/#1499)
- Improved detection of newlines in CSV files - now more robust in the face of mixed newline types (#1497)
- Allow style level compositing operations to work outside of featureset extents across tiled requests (#1477)

View file

@ -1,12 +1,14 @@
```
_/ _/ _/ _/
_/_/ _/_/ _/_/_/ _/_/_/ _/_/_/ _/ _/
_/ _/ _/ _/ _/ _/ _/ _/ _/ _/ _/_/
_/ _/ _/ _/ _/ _/ _/ _/ _/ _/ _/
_/ _/ _/_/_/ _/_/_/ _/ _/ _/ _/ _/
_/
_/
```
_/ _/ _/ _/
_/_/ _/_/ _/_/_/ _/_/_/ _/_/_/ _/ _/
_/ _/ _/ _/ _/ _/ _/ _/ _/ _/ _/_/
_/ _/ _/ _/ _/ _/ _/ _/ _/ _/ _/
_/ _/ _/_/_/ _/_/_/ _/ _/ _/ _/ _/
_/
_/
```
[![Build Status](https://secure.travis-ci.org/mapnik/mapnik.png)](http://travis-ci.org/mapnik/mapnik)
# What is Mapnik?

View file

@ -172,7 +172,7 @@ void export_datasource()
.def("bind",&datasource::bind)
.def("fields",&fields)
.def("field_types",&field_types)
.def("features_at_point",&datasource::features_at_point)
.def("features_at_point",&datasource::features_at_point, (arg("coord"),arg("tolerance")=0))
.def("params",&datasource::params,return_value_policy<copy_const_reference>(),
"The configuration parameters of the data source. "
"These vary depending on the type of data source.")

View file

@ -199,6 +199,56 @@ void render6(const mapnik::Map& map, PycairoContext* context)
ren.apply();
}
void render_with_detector2(
const mapnik::Map& map,
PycairoContext* context,
boost::shared_ptr<mapnik::label_collision_detector4> detector)
{
python_unblock_auto_block b;
Cairo::RefPtr<Cairo::Context> c(new Cairo::Context(context->ctx));
mapnik::cairo_renderer<Cairo::Context> ren(map,c,detector);
ren.apply();
}
void render_with_detector3(
const mapnik::Map& map,
PycairoContext* context,
boost::shared_ptr<mapnik::label_collision_detector4> detector,
double scale_factor = 1.0,
unsigned offset_x = 0u,
unsigned offset_y = 0u)
{
python_unblock_auto_block b;
Cairo::RefPtr<Cairo::Context> c(new Cairo::Context(context->ctx));
mapnik::cairo_renderer<Cairo::Context> ren(map,c,detector,scale_factor,offset_x,offset_y);
ren.apply();
}
void render_with_detector4(
const mapnik::Map& map,
PycairoSurface* surface,
boost::shared_ptr<mapnik::label_collision_detector4> detector)
{
python_unblock_auto_block b;
Cairo::RefPtr<Cairo::Surface> s(new Cairo::Surface(surface->surface));
mapnik::cairo_renderer<Cairo::Surface> ren(map,s,detector);
ren.apply();
}
void render_with_detector5(
const mapnik::Map& map,
PycairoSurface* surface,
boost::shared_ptr<mapnik::label_collision_detector4> detector,
double scale_factor = 1.0,
unsigned offset_x = 0u,
unsigned offset_y = 0u)
{
python_unblock_auto_block b;
Cairo::RefPtr<Cairo::Surface> s(new Cairo::Surface(surface->surface));
mapnik::cairo_renderer<Cairo::Surface> ren(map,s,detector,scale_factor,offset_x,offset_y);
ren.apply();
}
#endif
@ -572,6 +622,65 @@ BOOST_PYTHON_MODULE(_mapnik)
">>> render(m,context)\n"
"\n"
);
def("render_with_detector", &render_with_detector2,
"\n"
"Render Map to Cairo Context using a pre-constructed detector.\n"
"\n"
"Usage:\n"
">>> from mapnik import Map, LabelCollisionDetector, render_with_detector, load_map\n"
">>> from cairo import SVGSurface, Context\n"
">>> surface = SVGSurface('image.svg', m.width, m.height)\n"
">>> ctx = Context(surface)\n"
">>> m = Map(256,256)\n"
">>> load_map(m,'mapfile.xml')\n"
">>> detector = LabelCollisionDetector(m)\n"
">>> render_with_detector(m, ctx, detector)\n"
);
def("render_with_detector", &render_with_detector3,
"\n"
"Render Map to Cairo Context using a pre-constructed detector, scale and offsets.\n"
"\n"
"Usage:\n"
">>> from mapnik import Map, LabelCollisionDetector, render_with_detector, load_map\n"
">>> from cairo import SVGSurface, Context\n"
">>> surface = SVGSurface('image.svg', m.width, m.height)\n"
">>> ctx = Context(surface)\n"
">>> m = Map(256,256)\n"
">>> load_map(m,'mapfile.xml')\n"
">>> detector = LabelCollisionDetector(m)\n"
">>> render_with_detector(m, ctx, detector, 1, 1, 1)\n"
);
def("render_with_detector", &render_with_detector4,
"\n"
"Render Map to Cairo Surface using a pre-constructed detector.\n"
"\n"
"Usage:\n"
">>> from mapnik import Map, LabelCollisionDetector, render_with_detector, load_map\n"
">>> from cairo import SVGSurface, Context\n"
">>> surface = SVGSurface('image.svg', m.width, m.height)\n"
">>> m = Map(256,256)\n"
">>> load_map(m,'mapfile.xml')\n"
">>> detector = LabelCollisionDetector(m)\n"
">>> render_with_detector(m, surface, detector)\n"
);
def("render_with_detector", &render_with_detector5,
"\n"
"Render Map to Cairo Surface using a pre-constructed detector, scale and offsets.\n"
"\n"
"Usage:\n"
">>> from mapnik import Map, LabelCollisionDetector, render_with_detector, load_map\n"
">>> from cairo import SVGSurface, Context\n"
">>> surface = SVGSurface('image.svg', m.width, m.height)\n"
">>> m = Map(256,256)\n"
">>> load_map(m,'mapfile.xml')\n"
">>> detector = LabelCollisionDetector(m)\n"
">>> render_with_detector(m, surface, detector, 1, 1, 1)\n"
);
#endif
def("scale_denominator", &scale_denominator,

View file

@ -142,7 +142,7 @@ private:
boost::shared_ptr<label_collision_detector4> detector_;
boost::scoped_ptr<rasterizer> ras_ptr;
box2d<double> query_extent_;
void setup(Map const &m);
void setup(Map const& m);
};
}

View file

@ -73,6 +73,7 @@ class MAPNIK_DECL cairo_renderer_base : private boost::noncopyable
{
protected:
cairo_renderer_base(Map const& m, Cairo::RefPtr<Cairo::Context> const& context, double scale_factor=1.0, unsigned offset_x=0, unsigned offset_y=0);
cairo_renderer_base(Map const& m, Cairo::RefPtr<Cairo::Context> const& context, boost::shared_ptr<label_collision_detector4> detector, double scale_factor=1.0, unsigned offset_x=0, unsigned offset_y=0);
public:
~cairo_renderer_base();
void start_map_processing(Map const& map);
@ -136,7 +137,7 @@ protected:
boost::shared_ptr<freetype_engine> font_engine_;
face_manager<freetype_engine> font_manager_;
cairo_face_manager face_manager_;
label_collision_detector4 detector_;
boost::shared_ptr<label_collision_detector4> detector_;
box2d<double> query_extent_;
};
@ -147,6 +148,7 @@ class MAPNIK_DECL cairo_renderer : public feature_style_processor<cairo_renderer
public:
typedef cairo_renderer_base processor_impl_type;
cairo_renderer(Map const& m, Cairo::RefPtr<T> const& surface, double scale_factor=1.0, unsigned offset_x=0, unsigned offset_y=0);
cairo_renderer(Map const& m, Cairo::RefPtr<T> const& surface, boost::shared_ptr<label_collision_detector4> detector, double scale_factor=1.0, unsigned offset_x=0, unsigned offset_y=0);
void end_map_processing(Map const& map);
};
}

View file

@ -115,7 +115,7 @@ public:
virtual void bind() const {}
virtual featureset_ptr features(query const& q) const = 0;
virtual featureset_ptr features_at_point(coord2d const& pt) const = 0;
virtual featureset_ptr features_at_point(coord2d const& pt, double tol = 0) const = 0;
virtual box2d<double> envelope() const = 0;
virtual boost::optional<geometry_t> get_geometry_type() const = 0;
virtual layer_descriptor get_descriptor() const = 0;

View file

@ -257,7 +257,7 @@ public:
return result;
}
const raster_ptr& get_raster() const
raster_ptr const& get_raster() const
{
return raster_;
}

View file

@ -41,7 +41,7 @@ public:
void push(feature_ptr feature);
datasource::datasource_t type() const;
featureset_ptr features(const query& q) const;
featureset_ptr features_at_point(coord2d const& pt) const;
featureset_ptr features_at_point(coord2d const& pt, double tol = 0) const;
box2d<double> envelope() const;
boost::optional<geometry_t> get_geometry_type() const;
layer_descriptor get_descriptor() const;

View file

@ -27,9 +27,13 @@
#include <mapnik/box2d.hpp>
#include <mapnik/image_data.hpp>
// boost
#include <boost/utility.hpp>
namespace mapnik {
struct raster
class raster : private boost::noncopyable
{
public:
box2d<double> ext_;
image_data_32 data_;
bool premultiplied_alpha_;
@ -38,12 +42,6 @@ struct raster
data_(width,height),
premultiplied_alpha_(premultiplied_alpha)
{}
raster(box2d<double> const& ext,image_data_32 const& data, bool premultiplied_alpha = false)
: ext_(ext),
data_(data),
premultiplied_alpha_(premultiplied_alpha)
{}
};
}

View file

@ -959,7 +959,7 @@ mapnik::featureset_ptr csv_datasource::features(mapnik::query const& q) const
return boost::make_shared<mapnik::memory_featureset>(q.get_bbox(),features_);
}
mapnik::featureset_ptr csv_datasource::features_at_point(mapnik::coord2d const& pt) const
mapnik::featureset_ptr csv_datasource::features_at_point(mapnik::coord2d const& pt, double tol) const
{
if (!is_bound_) bind();

View file

@ -47,7 +47,7 @@ public:
mapnik::datasource::datasource_t type() const;
static const char * name();
mapnik::featureset_ptr features(mapnik::query const& q) const;
mapnik::featureset_ptr features_at_point(mapnik::coord2d const& pt) const;
mapnik::featureset_ptr features_at_point(mapnik::coord2d const& pt, double tol = 0) const;
mapnik::box2d<double> envelope() const;
boost::optional<mapnik::datasource::geometry_t> get_geometry_type() const;
mapnik::layer_descriptor get_descriptor() const;

View file

@ -246,7 +246,7 @@ featureset_ptr gdal_datasource::features(query const& q) const
nodata_value_));
}
featureset_ptr gdal_datasource::features_at_point(coord2d const& pt) const
featureset_ptr gdal_datasource::features_at_point(coord2d const& pt, double tol) const
{
if (! is_bound_) bind();

View file

@ -50,7 +50,7 @@ public:
mapnik::datasource::datasource_t type() const;
static const char * name();
mapnik::featureset_ptr features(mapnik::query const& q) const;
mapnik::featureset_ptr features_at_point(mapnik::coord2d const& pt) const;
mapnik::featureset_ptr features_at_point(mapnik::coord2d const& pt, double tol = 0) const;
mapnik::box2d<double> envelope() const;
boost::optional<mapnik::datasource::geometry_t> get_geometry_type() const;
mapnik::layer_descriptor get_descriptor() const;

View file

@ -223,14 +223,14 @@ feature_ptr gdal_featureset::get_feature(mapnik::query const& q)
if (im_width > 0 && im_height > 0)
{
mapnik::image_data_32 image(im_width, im_height);
mapnik::raster_ptr raster = boost::make_shared<mapnik::raster>(intersect, im_width, im_height);
feature->set_raster(raster);
mapnik::image_data_32 & image = raster->data_;
image.set(0xffffffff);
MAPNIK_LOG_DEBUG(gdal) << "gdal_featureset: Image Size=(" << im_width << "," << im_height << ")";
MAPNIK_LOG_DEBUG(gdal) << "gdal_featureset: Reading band=" << band_;
typedef std::vector<int,int> pallete;
if (band_ > 0) // we are querying a single band
{
if (band_ > nbands_)
@ -255,7 +255,6 @@ feature_ptr gdal_featureset::get_feature(mapnik::query const& q)
imageData, image.width(), image.height(),
GDT_Float32, 0, 0);
feature->set_raster(boost::make_shared<mapnik::raster>(intersect,image));
if (hasNoData)
{
feature->put("NODATA",nodata);
@ -488,8 +487,6 @@ feature_ptr gdal_featureset::get_feature(mapnik::query const& q)
alpha->RasterIO(GF_Read, x_off, y_off, width, height, image.getBytes() + 3,
image.width(), image.height(), GDT_Byte, 4, 4 * image.width());
}
feature->set_raster(boost::make_shared<mapnik::raster>(intersect, image));
}
return feature;
}

View file

@ -217,7 +217,7 @@ mapnik::featureset_ptr geojson_datasource::features(mapnik::query const& q) cons
}
// FIXME
mapnik::featureset_ptr geojson_datasource::features_at_point(mapnik::coord2d const& pt) const
mapnik::featureset_ptr geojson_datasource::features_at_point(mapnik::coord2d const& pt, double tol) const
{
if (!is_bound_) bind();
throw mapnik::datasource_exception("GeoJSON Plugin: features_at_point is not supported yet");

View file

@ -60,7 +60,7 @@ public:
mapnik::datasource::datasource_t type() const;
static const char * name();
mapnik::featureset_ptr features(mapnik::query const& q) const;
mapnik::featureset_ptr features_at_point(mapnik::coord2d const& pt) const;
mapnik::featureset_ptr features_at_point(mapnik::coord2d const& pt, double tol = 0) const;
mapnik::box2d<double> envelope() const;
mapnik::layer_descriptor get_descriptor() const;
boost::optional<mapnik::datasource::geometry_t> get_geometry_type() const;

View file

@ -315,7 +315,7 @@ featureset_ptr geos_datasource::features(query const& q) const
desc_.get_encoding());
}
featureset_ptr geos_datasource::features_at_point(coord2d const& pt) const
featureset_ptr geos_datasource::features_at_point(coord2d const& pt, double tol) const
{
if (! is_bound_) bind();

View file

@ -50,7 +50,7 @@ public:
mapnik::datasource::datasource_t type() const;
static const char * name();
mapnik::featureset_ptr features(mapnik::query const& q) const;
mapnik::featureset_ptr features_at_point(mapnik::coord2d const& pt) const;
mapnik::featureset_ptr features_at_point(mapnik::coord2d const& pt, double tol = 0) const;
mapnik::box2d<double> envelope() const;
boost::optional<mapnik::datasource::geometry_t> get_geometry_type() const;
mapnik::layer_descriptor get_descriptor() const;

View file

@ -166,7 +166,7 @@ featureset_ptr kismet_datasource::features(query const& q) const
// return featureset_ptr();
}
featureset_ptr kismet_datasource::features_at_point(coord2d const& pt) const
featureset_ptr kismet_datasource::features_at_point(coord2d const& pt, double tol) const
{
if (! is_bound_) bind();

View file

@ -52,7 +52,7 @@ public:
datasource::datasource_t type() const;
static const char * name();
mapnik::featureset_ptr features(mapnik::query const& q) const;
mapnik::featureset_ptr features_at_point(mapnik::coord2d const& pt) const;
mapnik::featureset_ptr features_at_point(mapnik::coord2d const& pt, double tol = 0) const;
mapnik::box2d<double> envelope() const;
boost::optional<mapnik::datasource::geometry_t> get_geometry_type() const;
mapnik::layer_descriptor get_descriptor() const;

View file

@ -590,7 +590,7 @@ featureset_ptr occi_datasource::features(query const& q) const
row_prefetch_);
}
featureset_ptr occi_datasource::features_at_point(coord2d const& pt) const
featureset_ptr occi_datasource::features_at_point(coord2d const& pt, double tol) const
{
if (! is_bound_) bind();

View file

@ -51,7 +51,7 @@ public:
mapnik::datasource::datasource_t type() const;
static const char * name();
mapnik::featureset_ptr features(mapnik::query const& q) const;
mapnik::featureset_ptr features_at_point(mapnik::coord2d const& pt) const;
mapnik::featureset_ptr features_at_point(mapnik::coord2d const& pt, double tol = 0) const;
mapnik::box2d<double> envelope() const;
boost::optional<mapnik::datasource::geometry_t> get_geometry_type() const;
mapnik::layer_descriptor get_descriptor() const;

View file

@ -519,7 +519,7 @@ featureset_ptr ogr_datasource::features(query const& q) const
return featureset_ptr();
}
featureset_ptr ogr_datasource::features_at_point(coord2d const& pt) const
featureset_ptr ogr_datasource::features_at_point(coord2d const& pt, double tol) const
{
if (!is_bound_) bind();

View file

@ -52,7 +52,7 @@ public:
mapnik::datasource::datasource_t type() const;
static const char * name();
mapnik::featureset_ptr features(mapnik::query const& q) const;
mapnik::featureset_ptr features_at_point(mapnik::coord2d const& pt) const;
mapnik::featureset_ptr features_at_point(mapnik::coord2d const& pt, double tol = 0) const;
mapnik::box2d<double> envelope() const;
boost::optional<mapnik::datasource::geometry_t> get_geometry_type() const;
mapnik::layer_descriptor get_descriptor() const;

View file

@ -158,7 +158,7 @@ featureset_ptr osm_datasource::features(const query& q) const
desc_.get_encoding());
}
featureset_ptr osm_datasource::features_at_point(coord2d const& pt) const
featureset_ptr osm_datasource::features_at_point(coord2d const& pt, double tol) const
{
if (!is_bound_) bind();

View file

@ -58,7 +58,7 @@ public:
mapnik::datasource::datasource_t type() const;
static const char * name();
featureset_ptr features(const query& q) const;
featureset_ptr features_at_point(coord2d const& pt) const;
featureset_ptr features_at_point(coord2d const& pt, double tol = 0) const;
box2d<double> envelope() const;
boost::optional<mapnik::datasource::geometry_t> get_geometry_type() const;
layer_descriptor get_descriptor() const;

View file

@ -709,7 +709,7 @@ featureset_ptr postgis_datasource::features(const query& q) const
return featureset_ptr();
}
featureset_ptr postgis_datasource::features_at_point(coord2d const& pt) const
featureset_ptr postgis_datasource::features_at_point(coord2d const& pt, double tol) const
{
if (! is_bound_)
{
@ -778,7 +778,7 @@ featureset_ptr postgis_datasource::features_at_point(coord2d const& pt) const
}
}
box2d<double> box(pt.x, pt.y, pt.x, pt.y);
box2d<double> box(pt.x - tol, pt.y - tol, pt.x + tol, pt.y + tol);
std::string table_with_bbox = populate_tokens(table_, FMAX, box, 0, 0);
s << " FROM " << table_with_bbox;

View file

@ -63,7 +63,7 @@ public:
mapnik::datasource::datasource_t type() const;
static const char * name();
featureset_ptr features(const query& q) const;
featureset_ptr features_at_point(coord2d const& pt) const;
featureset_ptr features_at_point(coord2d const& pt, double tol = 0) const;
mapnik::box2d<double> envelope() const;
boost::optional<mapnik::datasource::geometry_t> get_geometry_type() const;
layer_descriptor get_descriptor() const;

View file

@ -189,7 +189,7 @@ mapnik::featureset_ptr python_datasource::features(mapnik::query const& q) const
return mapnik::featureset_ptr();
}
mapnik::featureset_ptr python_datasource::features_at_point(mapnik::coord2d const& pt) const
mapnik::featureset_ptr python_datasource::features_at_point(mapnik::coord2d const& pt, double tol) const
{
using namespace boost::python;

View file

@ -29,7 +29,7 @@ public:
// mandatory: function to query features by point (coord2d)
// not used by rendering, but available to calling applications
mapnik::featureset_ptr features_at_point(mapnik::coord2d const& pt) const;
mapnik::featureset_ptr features_at_point(mapnik::coord2d const& pt, double tol = 0) const;
// mandatory: return the box2d of the datasource
// called during rendering to determine if the layer should be processed

View file

@ -220,7 +220,7 @@ featureset_ptr raster_datasource::features(query const& q) const
}
}
featureset_ptr raster_datasource::features_at_point(coord2d const&) const
featureset_ptr raster_datasource::features_at_point(coord2d const&, double tol) const
{
MAPNIK_LOG_WARN(raster) << "raster_datasource: feature_at_point not supported";

View file

@ -49,7 +49,7 @@ public:
datasource::datasource_t type() const;
static const char * name();
mapnik::featureset_ptr features(const mapnik::query& q) const;
mapnik::featureset_ptr features_at_point(mapnik::coord2d const& pt) const;
mapnik::featureset_ptr features_at_point(mapnik::coord2d const& pt, double tol = 0) const;
mapnik::box2d<double> envelope() const;
boost::optional<mapnik::datasource::geometry_t> get_geometry_type() const;
mapnik::layer_descriptor get_descriptor() const;

View file

@ -111,9 +111,10 @@ feature_ptr raster_featureset<LookupPolicy>::next()
rem.maxy() + y_off + height);
intersect = t.backward(feature_raster_extent);
image_data_32 image(width,height);
reader->read(x_off, y_off, image);
feature->set_raster(boost::make_shared<raster>(intersect, image,reader->premultiplied_alpha()));
mapnik::raster_ptr raster = boost::make_shared<mapnik::raster>(intersect, width, height);
reader->read(x_off, y_off, raster->data_);
raster->premultiplied_alpha_ = reader->premultiplied_alpha();
feature->set_raster(raster);
}
}
}

View file

@ -201,7 +201,7 @@ featureset_ptr rasterlite_datasource::features(query const& q) const
return boost::make_shared<rasterlite_featureset>(open_dataset(), gq);
}
featureset_ptr rasterlite_datasource::features_at_point(coord2d const& pt) const
featureset_ptr rasterlite_datasource::features_at_point(coord2d const& pt, double tol) const
{
if (!is_bound_) bind();

View file

@ -50,7 +50,7 @@ public:
mapnik::datasource::datasource_t type() const;
static const char * name();
mapnik::featureset_ptr features(mapnik::query const& q) const;
mapnik::featureset_ptr features_at_point(mapnik::coord2d const& pt) const;
mapnik::featureset_ptr features_at_point(mapnik::coord2d const& pt, double tol = 0) const;
mapnik::box2d<double> envelope() const;
boost::optional<mapnik::datasource::geometry_t> get_geometry_type() const;
mapnik::layer_descriptor get_descriptor() const;

View file

@ -286,7 +286,7 @@ featureset_ptr shape_datasource::features(const query& q) const
}
}
featureset_ptr shape_datasource::features_at_point(coord2d const& pt) const
featureset_ptr shape_datasource::features_at_point(coord2d const& pt, double tol) const
{
if (!is_bound_) bind();

View file

@ -57,7 +57,7 @@ public:
datasource::datasource_t type() const;
static const char * name();
featureset_ptr features(const query& q) const;
featureset_ptr features_at_point(coord2d const& pt) const;
featureset_ptr features_at_point(coord2d const& pt, double tol = 0) const;
box2d<double> envelope() const;
boost::optional<mapnik::datasource::geometry_t> get_geometry_type() const;
layer_descriptor get_descriptor() const;

View file

@ -632,7 +632,7 @@ featureset_ptr sqlite_datasource::features(query const& q) const
return featureset_ptr();
}
featureset_ptr sqlite_datasource::features_at_point(coord2d const& pt) const
featureset_ptr sqlite_datasource::features_at_point(coord2d const& pt, double tol) const
{
if (! is_bound_) bind();

View file

@ -53,7 +53,7 @@ public:
datasource::datasource_t type() const;
static const char * name();
mapnik::featureset_ptr features(mapnik::query const& q) const;
mapnik::featureset_ptr features_at_point(mapnik::coord2d const& pt) const;
mapnik::featureset_ptr features_at_point(mapnik::coord2d const& pt, double tol = 0) const;
mapnik::box2d<double> envelope() const;
boost::optional<mapnik::datasource::geometry_t> get_geometry_type() const;
mapnik::layer_descriptor get_descriptor() const;

View file

@ -82,7 +82,7 @@ mapnik::featureset_ptr hello_datasource::features(mapnik::query const& q) const
return mapnik::featureset_ptr();
}
mapnik::featureset_ptr hello_datasource::features_at_point(mapnik::coord2d const& pt) const
mapnik::featureset_ptr hello_datasource::features_at_point(mapnik::coord2d const& pt, double tol) const
{
if (!is_bound_) bind();

View file

@ -39,7 +39,7 @@ public:
// mandatory: function to query features by point (coord2d)
// not used by rendering, but available to calling applications
mapnik::featureset_ptr features_at_point(mapnik::coord2d const& pt) const;
mapnik::featureset_ptr features_at_point(mapnik::coord2d const& pt, double tol = 0) const;
// mandatory: return the box2d of the datasource
// called during rendering to determine if the layer should be processed

View file

@ -62,32 +62,6 @@
namespace mapnik
{
class pattern_source : private boost::noncopyable
{
public:
pattern_source(image_data_32 const& pattern)
: pattern_(pattern) {}
unsigned int width() const
{
return pattern_.width();
}
unsigned int height() const
{
return pattern_.height();
}
agg::rgba8 pixel(int x, int y) const
{
unsigned c = pattern_(x,y);
return agg::rgba8(c & 0xff,
(c >> 8) & 0xff,
(c >> 16) & 0xff,
(c >> 24) & 0xff);
}
private:
image_data_32 const& pattern_;
};
template <typename T>
agg_renderer<T>::agg_renderer(Map const& m, T & pixmap, double scale_factor, unsigned offset_x, unsigned offset_y)
@ -300,6 +274,7 @@ void agg_renderer<T>::render_marker(pixel_position const& pos, marker const& mar
typedef agg::pixfmt_custom_blend_rgba<blender_type, agg::rendering_buffer> pixfmt_comp_type;
typedef agg::renderer_base<pixfmt_comp_type> renderer_base;
typedef agg::renderer_scanline_aa_solid<renderer_base> renderer_type;
typedef agg::pod_bvector<mapnik::svg::path_attributes> svg_attribute_type;
ras_ptr->reset();
ras_ptr->gamma(agg::gamma_power());
@ -324,9 +299,9 @@ void agg_renderer<T>::render_marker(pixel_position const& pos, marker const& mar
vertex_stl_adapter<svg_path_storage> stl_storage((*marker.get_vector_data())->source());
svg_path_adapter svg_path(stl_storage);
svg_renderer_agg<svg_path_adapter,
agg::pod_bvector<path_attributes>,
svg_attribute_type,
renderer_type,
agg::pixfmt_rgba32> svg_renderer(svg_path,
pixfmt_comp_type> svg_renderer(svg_path,
(*marker.get_vector_data())->attributes());
svg_renderer.render(*ras_ptr, sl, renb, mtx, opacity, bbox);

View file

@ -20,8 +20,6 @@
*
*****************************************************************************/
// boost
#include <boost/foreach.hpp>
// mapnik
#include <mapnik/debug.hpp>
#include <mapnik/graphics.hpp>
@ -33,6 +31,7 @@
#include <mapnik/marker_cache.hpp>
#include <mapnik/line_pattern_symbolizer.hpp>
#include <mapnik/vertex_converters.hpp>
// agg
#include "agg_basics.h"
#include "agg_rendering_buffer.h"
@ -47,6 +46,40 @@
#include "agg_renderer_outline_image.h"
#include "agg_conv_clip_polyline.h"
// boost
#include <boost/utility.hpp>
#include <boost/foreach.hpp>
namespace {
class pattern_source : private boost::noncopyable
{
public:
pattern_source(mapnik::image_data_32 const& pattern)
: pattern_(pattern) {}
unsigned int width() const
{
return pattern_.width();
}
unsigned int height() const
{
return pattern_.height();
}
agg::rgba8 pixel(int x, int y) const
{
unsigned c = pattern_(x,y);
return agg::rgba8(c & 0xff,
(c >> 8) & 0xff,
(c >> 16) & 0xff,
(c >> 24) & 0xff);
}
private:
mapnik::image_data_32 const& pattern_;
};
}
namespace mapnik {
template <typename T>

View file

@ -24,9 +24,6 @@
#include <mapnik/agg_renderer.hpp>
#include <mapnik/agg_rasterizer.hpp>
#include <mapnik/image_util.hpp>
#include <mapnik/svg/svg_converter.hpp>
#include <mapnik/svg/svg_renderer_agg.hpp>
#include <mapnik/svg/svg_path_adapter.hpp>
#include <mapnik/symbolizer_helpers.hpp>
// boost

View file

@ -777,7 +777,29 @@ cairo_renderer_base::cairo_renderer_base(Map const& m,
font_engine_(boost::make_shared<freetype_engine>()),
font_manager_(*font_engine_),
face_manager_(font_engine_),
detector_(box2d<double>(-m.buffer_size() ,-m.buffer_size() , m.width() + m.buffer_size() ,m.height() + m.buffer_size()))
detector_(boost::make_shared<label_collision_detector4>(
box2d<double>(-m.buffer_size(), -m.buffer_size(),
m.width() + m.buffer_size(), m.height() + m.buffer_size())))
{
MAPNIK_LOG_DEBUG(cairo_renderer) << "cairo_renderer_base: Scale=" << m.scale();
}
cairo_renderer_base::cairo_renderer_base(Map const& m,
Cairo::RefPtr<Cairo::Context> const& context,
boost::shared_ptr<label_collision_detector4> detector,
double scale_factor,
unsigned offset_x,
unsigned offset_y)
: m_(m),
context_(context),
width_(m.width()),
height_(m.height()),
scale_factor_(scale_factor),
t_(m.width(),m.height(),m.get_current_extent(),offset_x,offset_y),
font_engine_(boost::make_shared<freetype_engine>()),
font_manager_(*font_engine_),
face_manager_(font_engine_),
detector_(detector)
{
MAPNIK_LOG_DEBUG(cairo_renderer) << "cairo_renderer_base: Scale=" << m.scale();
}
@ -792,6 +814,16 @@ cairo_renderer<Cairo::Surface>::cairo_renderer(Map const& m, Cairo::RefPtr<Cairo
: feature_style_processor<cairo_renderer>(m,scale_factor),
cairo_renderer_base(m,Cairo::Context::create(surface),scale_factor,offset_x,offset_y) {}
template <>
cairo_renderer<Cairo::Context>::cairo_renderer(Map const& m, Cairo::RefPtr<Cairo::Context> const& context, boost::shared_ptr<label_collision_detector4> detector, double scale_factor, unsigned offset_x, unsigned offset_y)
: feature_style_processor<cairo_renderer>(m,scale_factor),
cairo_renderer_base(m,context,detector,scale_factor,offset_x,offset_y) {}
template <>
cairo_renderer<Cairo::Surface>::cairo_renderer(Map const& m, Cairo::RefPtr<Cairo::Surface> const& surface, boost::shared_ptr<label_collision_detector4> detector, double scale_factor, unsigned offset_x, unsigned offset_y)
: feature_style_processor<cairo_renderer>(m,scale_factor),
cairo_renderer_base(m,Cairo::Context::create(surface),detector,scale_factor,offset_x,offset_y) {}
cairo_renderer_base::~cairo_renderer_base() {}
void cairo_renderer_base::start_map_processing(Map const& map)
@ -837,7 +869,7 @@ void cairo_renderer_base::start_layer_processing(layer const& lay, box2d<double>
if (lay.clear_label_cache())
{
detector_.clear();
detector_->clear();
}
query_extent_ = query_extent;
}
@ -1229,12 +1261,12 @@ void cairo_renderer_base::process(point_symbolizer const& sym,
label_ext *= tr;
label_ext *= agg::trans_affine_translation(x,y);
if (sym.get_allow_overlap() ||
detector_.has_placement(label_ext))
detector_->has_placement(label_ext))
{
render_marker(pixel_position(x,y),**marker, tr, sym.get_opacity());
if (!sym.get_ignore_placement())
detector_.insert(label_ext);
detector_->insert(label_ext);
}
}
}
@ -1249,7 +1281,7 @@ void cairo_renderer_base::process(shield_symbolizer const& sym,
sym, feature, prj_trans,
width_, height_,
scale_factor_,
t_, font_manager_, detector_, query_extent_);
t_, font_manager_, *detector_, query_extent_);
cairo_context context(context_);
context.set_operator(sym.comp_op());
@ -1709,7 +1741,7 @@ void cairo_renderer_base::process(markers_symbolizer const& sym,
box2d<double> bbox = marker_ellipse.bounding_box();
dispatch_type dispatch(context, marker_ellipse, result?attributes:(*stock_vector_marker)->attributes(),
detector_, sym, bbox, marker_tr, scale_factor_);
*detector_, sym, bbox, marker_tr, scale_factor_);
vertex_converter<box2d<double>, dispatch_type, markers_symbolizer,
CoordTransform, proj_transform, agg::trans_affine, conv_types>
converter(query_extent_, dispatch, sym, t_, prj_trans, marker_tr, scale_factor_);
@ -1737,7 +1769,7 @@ void cairo_renderer_base::process(markers_symbolizer const& sym,
bool result = push_explicit_style( (*stock_vector_marker)->attributes(), attributes, sym);
dispatch_type dispatch(context, **stock_vector_marker, result?attributes:(*stock_vector_marker)->attributes(),
detector_, sym, bbox, tr, scale_factor_);
*detector_, sym, bbox, tr, scale_factor_);
vertex_converter<box2d<double>, dispatch_type, markers_symbolizer,
CoordTransform, proj_transform, agg::trans_affine, conv_types>
converter(query_extent_, dispatch, sym, t_, prj_trans, tr, scale_factor_);
@ -1769,7 +1801,7 @@ void cairo_renderer_base::process(markers_symbolizer const& sym,
if ( marker )
{
dispatch_type dispatch(context, *marker,
detector_, sym, bbox, tr, scale_factor_);
*detector_, sym, bbox, tr, scale_factor_);
vertex_converter<box2d<double>, dispatch_type, markers_symbolizer,
CoordTransform, proj_transform, agg::trans_affine, conv_types>
@ -1806,7 +1838,7 @@ void cairo_renderer_base::process(text_symbolizer const& sym,
sym, feature, prj_trans,
width_, height_,
scale_factor_,
t_, font_manager_, detector_, query_extent_);
t_, font_manager_, *detector_, query_extent_);
cairo_context context(context_);
context.set_operator(sym.comp_op());

View file

@ -27,9 +27,6 @@
#include <mapnik/grid/grid_pixel.hpp>
#include <mapnik/grid/grid.hpp>
#include <mapnik/symbolizer_helpers.hpp>
#include <mapnik/svg/svg_converter.hpp>
#include <mapnik/svg/svg_renderer_agg.hpp>
#include <mapnik/svg/svg_path_adapter.hpp>
// agg
#include "agg_trans_affine.h"

View file

@ -548,24 +548,24 @@ featureset_ptr Map::query_point(unsigned index, double x, double y) const
{
throw std::runtime_error("query_point: could not project x,y into layer srs");
}
// TODO - pass tolerance to features_at_point as well
featureset_ptr fs = ds->features_at_point(mapnik::coord2d(x,y));
// 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)
{
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;
MAPNIK_LOG_DEBUG(map) << "map: Query at point tol=" << tol << "(" << x << "," << y << ")";
return boost::make_shared<filter_featureset<hit_test_filter> >(fs,
hit_test_filter(x,y,tol));
}

View file

@ -86,7 +86,7 @@ featureset_ptr memory_datasource::features(const query& q) const
}
featureset_ptr memory_datasource::features_at_point(coord2d const& pt) const
featureset_ptr memory_datasource::features_at_point(coord2d const& pt, double tol) const
{
box2d<double> box = box2d<double>(pt.x, pt.y, pt.x, pt.y);

View file

@ -0,0 +1,43 @@
#!/usr/bin/env python
from nose.tools import *
from utilities import execution_path
import os, mapnik
def setup():
# All of the paths used are relative, if we run the tests
# from another directory we need to chdir()
os.chdir(execution_path('.'))
def test_query_tolerance():
srs = '+init=epsg:4326'
lyr = mapnik.Layer('test')
lyr.datasource = mapnik.Shapefile(file='../data/shp/arrows.shp')
lyr.srs = srs
_width = 256
_map = mapnik.Map(_width,_width, srs)
_map.layers.append(lyr)
# zoom determines tolerance
_map.zoom_all()
_map_env = _map.envelope()
tol = (_map_env.maxx - _map_env.minx) / _width * 3
# 0.046875 for arrows.shp and zoom_all
assert tol == 0.046875
# check point really exists
x, y = 2.0, 4.0
features = _map.query_point(0,x,y).features
assert len(features) == 1
# check inside tolerance limit
x = 2.0 + tol * 0.9
features = _map.query_point(0,x,y).features
assert len(features) == 1
# check outside tolerance limit
x = 2.0 + tol * 1.1
features = _map.query_point(0,x,y).features
assert len(features) == 0

View file

@ -151,7 +151,7 @@ def test_raster_with_alpha_blends_correctly_with_background():
mapnik.render(map, mim)
imdata = mim.tostring()
# All white is expected
eq_(contains_word('\xff\xff\xff\xff', imdata),True,'Image expected to contain true white, instead found %s' % get_unique_colors(mim))
eq_(get_unique_colors(mim),['rgba(254,254,254,255)'])
def test_raster_warping():
lyrSrs = "+init=epsg:32630"

View file

@ -142,7 +142,7 @@ int main (int argc,char** argv)
continue;
}
typedef agg::pixfmt_rgba32_plain pixfmt;
typedef agg::pixfmt_rgba32_pre pixfmt;
typedef agg::renderer_base<pixfmt> renderer_base;
typedef agg::renderer_scanline_aa_solid<renderer_base> renderer_solid;
agg::rasterizer_scanline_aa<> ras_ptr;
@ -173,12 +173,13 @@ int main (int argc,char** argv)
mapnik::svg::svg_renderer_agg<mapnik::svg::svg_path_adapter,
agg::pod_bvector<mapnik::svg::path_attributes>,
renderer_solid,
agg::pixfmt_rgba32_plain > svg_renderer_this(svg_path,
agg::pixfmt_rgba32_pre > svg_renderer_this(svg_path,
(*marker.get_vector_data())->attributes());
svg_renderer_this.render(ras_ptr, sl, renb, mtx, opacity, bbox);
boost::algorithm::ireplace_last(svg_name,".svg",".png");
im.demultiply();
mapnik::save_to_file<mapnik::image_data_32>(im.data(),svg_name,"png");
if (auto_open)
{