Merge commit 'cd064305fc8cf7fee1806e495d9016a5ce1e5d7f' into harfbuzz
Conflicts: src/cairo_renderer.cpp
This commit is contained in:
commit
0c62b481f6
48 changed files with 386 additions and 104 deletions
13
.travis.yml
Normal file
13
.travis.yml
Normal 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 && make test || echo "Overall Test Exit Code: $?"
|
|
@ -8,6 +8,10 @@ For a complete change history, see the git log.
|
|||
|
||||
## Future
|
||||
|
||||
- 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)
|
||||
|
|
18
README.md
18
README.md
|
@ -1,12 +1,14 @@
|
|||
```
|
||||
_/ _/ _/ _/
|
||||
_/_/ _/_/ _/_/_/ _/_/_/ _/_/_/ _/ _/
|
||||
_/ _/ _/ _/ _/ _/ _/ _/ _/ _/ _/_/
|
||||
_/ _/ _/ _/ _/ _/ _/ _/ _/ _/ _/
|
||||
_/ _/ _/_/_/ _/_/_/ _/ _/ _/ _/ _/
|
||||
_/
|
||||
_/
|
||||
```
|
||||
_/ _/ _/ _/
|
||||
_/_/ _/_/ _/_/_/ _/_/_/ _/_/_/ _/ _/
|
||||
_/ _/ _/ _/ _/ _/ _/ _/ _/ _/ _/_/
|
||||
_/ _/ _/ _/ _/ _/ _/ _/ _/ _/ _/
|
||||
_/ _/ _/_/_/ _/_/_/ _/ _/ _/ _/ _/
|
||||
_/
|
||||
_/
|
||||
```
|
||||
|
||||
[![Build Status](https://secure.travis-ci.org/mapnik/mapnik.png)](http://travis-ci.org/mapnik/mapnik)
|
||||
|
||||
# What is Mapnik?
|
||||
|
||||
|
|
|
@ -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.")
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -143,7 +143,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);
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -74,6 +74,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);
|
||||
|
@ -137,7 +138,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_;
|
||||
};
|
||||
|
||||
|
@ -148,6 +149,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);
|
||||
};
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -33,11 +33,17 @@ struct raster
|
|||
box2d<double> ext_;
|
||||
image_data_32 data_;
|
||||
bool premultiplied_alpha_;
|
||||
raster(box2d<double> const& ext, unsigned width, unsigned height, bool premultiplied_alpha = false)
|
||||
: ext_(ext),
|
||||
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)
|
||||
{}
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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";
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -38,6 +38,10 @@
|
|||
// stl
|
||||
#include <cmath>
|
||||
|
||||
// agg
|
||||
#include "agg_rendering_buffer.h"
|
||||
#include "agg_pixfmt_rgba.h"
|
||||
|
||||
|
||||
namespace mapnik {
|
||||
|
||||
|
@ -66,10 +70,22 @@ void agg_renderer<T>::process(raster_symbolizer const& sym,
|
|||
int raster_height = end_y - start_y;
|
||||
if (raster_width > 0 && raster_height > 0)
|
||||
{
|
||||
image_data_32 target_data(raster_width,raster_height);
|
||||
raster target(target_ext, target_data);
|
||||
raster target(target_ext, raster_width,raster_height);
|
||||
scaling_method_e scaling_method = sym.get_scaling_method();
|
||||
double filter_radius = sym.calculate_filter_factor();
|
||||
bool premultiply_source = !source->premultiplied_alpha_;
|
||||
boost::optional<bool> is_premultiplied = sym.premultiplied();
|
||||
if (is_premultiplied)
|
||||
{
|
||||
if (*is_premultiplied) premultiply_source = false;
|
||||
else premultiply_source = true;
|
||||
}
|
||||
if (premultiply_source)
|
||||
{
|
||||
agg::rendering_buffer buffer(source->data_.getBytes(),source->data_.width(),source->data_.height(),source->data_.width() * 4);
|
||||
agg::pixfmt_rgba32 pixf(buffer);
|
||||
pixf.premultiply();
|
||||
}
|
||||
if (!prj_trans.equal())
|
||||
{
|
||||
double offset_x = ext.minx() - start_x;
|
||||
|
@ -98,20 +114,9 @@ void agg_renderer<T>::process(raster_symbolizer const& sym,
|
|||
filter_radius);
|
||||
}
|
||||
}
|
||||
// handle whether to premultiply the source
|
||||
// data before compositing
|
||||
// first, default to what the data reports
|
||||
bool premultiply_source = !source->premultiplied_alpha_;
|
||||
// the, allow the user to override
|
||||
boost::optional<bool> is_premultiplied = sym.premultiplied();
|
||||
if (is_premultiplied)
|
||||
{
|
||||
if (*is_premultiplied) premultiply_source = false;
|
||||
else premultiply_source = true;
|
||||
}
|
||||
composite(current_buffer_->data(), target.data_,
|
||||
sym.comp_op(), sym.get_opacity(),
|
||||
start_x, start_y, premultiply_source);
|
||||
start_x, start_y, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -57,6 +57,8 @@
|
|||
#include "agg_conv_clip_polyline.h"
|
||||
#include "agg_conv_clip_polygon.h"
|
||||
#include "agg_conv_smooth_poly1.h"
|
||||
#include "agg_rendering_buffer.h"
|
||||
#include "agg_pixfmt_rgba.h"
|
||||
|
||||
// markers
|
||||
#include "agg_path_storage.h"
|
||||
|
@ -760,7 +762,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();
|
||||
}
|
||||
|
@ -775,6 +799,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)
|
||||
|
@ -820,7 +854,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;
|
||||
}
|
||||
|
@ -1212,12 +1246,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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1231,7 +1265,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());
|
||||
|
@ -1422,10 +1456,22 @@ void cairo_renderer_base::process(raster_symbolizer const& sym,
|
|||
int raster_height = end_y - start_y;
|
||||
if (raster_width > 0 && raster_height > 0)
|
||||
{
|
||||
image_data_32 target_data(raster_width,raster_height);
|
||||
raster target(target_ext, target_data);
|
||||
raster target(target_ext, raster_width,raster_height);
|
||||
scaling_method_e scaling_method = sym.get_scaling_method();
|
||||
double filter_radius = sym.calculate_filter_factor();
|
||||
bool premultiply_source = !source->premultiplied_alpha_;
|
||||
boost::optional<bool> is_premultiplied = sym.premultiplied();
|
||||
if (is_premultiplied)
|
||||
{
|
||||
if (*is_premultiplied) premultiply_source = false;
|
||||
else premultiply_source = true;
|
||||
}
|
||||
if (premultiply_source)
|
||||
{
|
||||
agg::rendering_buffer buffer(source->data_.getBytes(),source->data_.width(),source->data_.height(),source->data_.width() * 4);
|
||||
agg::pixfmt_rgba32 pixf(buffer);
|
||||
pixf.premultiply();
|
||||
}
|
||||
if (!prj_trans.equal())
|
||||
{
|
||||
double offset_x = ext.minx() - start_x;
|
||||
|
@ -1683,7 +1729,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_);
|
||||
|
@ -1711,7 +1757,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_);
|
||||
|
@ -1743,7 +1789,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>
|
||||
|
@ -1779,7 +1825,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());
|
||||
|
|
|
@ -263,12 +263,12 @@ void scale_image_agg(Image & target,
|
|||
double filter_radius,
|
||||
double ratio)
|
||||
{
|
||||
// TODO - should all types here be *_pre ?
|
||||
// "the image filters should work namely in the premultiplied color space"
|
||||
// http://old.nabble.com/Re:--AGG--Basic-image-transformations-p1110665.html
|
||||
typedef agg::pixfmt_rgba32 pixfmt;
|
||||
// "Yes, you need to use premultiplied images only. Only in this case the simple weighted averaging works correctly in the image fitering."
|
||||
// http://permalink.gmane.org/gmane.comp.graphics.agg/3443
|
||||
typedef agg::pixfmt_rgba32_pre pixfmt_pre;
|
||||
typedef agg::renderer_base<pixfmt_pre> renderer_base;
|
||||
typedef agg::renderer_base<pixfmt_pre> renderer_base_pre;
|
||||
|
||||
// define some stuff we'll use soon
|
||||
agg::rasterizer_scanline_aa<> ras;
|
||||
|
@ -278,15 +278,15 @@ void scale_image_agg(Image & target,
|
|||
|
||||
// initialize source AGG buffer
|
||||
agg::rendering_buffer rbuf_src((unsigned char*)source.getBytes(), source.width(), source.height(), source.width() * 4);
|
||||
pixfmt pixf_src(rbuf_src);
|
||||
typedef agg::image_accessor_clone<pixfmt> img_src_type;
|
||||
pixfmt_pre pixf_src(rbuf_src);
|
||||
typedef agg::image_accessor_clone<pixfmt_pre> img_src_type;
|
||||
img_src_type img_src(pixf_src);
|
||||
|
||||
// initialize destination AGG buffer (with transparency)
|
||||
agg::rendering_buffer rbuf_dst((unsigned char*)target.getBytes(), target.width(), target.height(), target.width() * 4);
|
||||
pixfmt_pre pixf_dst(rbuf_dst);
|
||||
renderer_base rb_dst(pixf_dst);
|
||||
rb_dst.clear(agg::rgba(0, 0, 0, 0));
|
||||
renderer_base_pre rb_dst_pre(pixf_dst);
|
||||
rb_dst_pre.clear(agg::rgba(0, 0, 0, 0));
|
||||
|
||||
// create a scaling matrix
|
||||
agg::trans_affine img_mtx;
|
||||
|
@ -311,7 +311,7 @@ void scale_image_agg(Image & target,
|
|||
{
|
||||
typedef agg::span_image_filter_rgba_nn<img_src_type, interpolator_type> span_gen_type;
|
||||
span_gen_type sg(img_src, interpolator);
|
||||
agg::render_scanlines_aa(ras, sl, rb_dst, sa, sg);
|
||||
agg::render_scanlines_aa(ras, sl, rb_dst_pre, sa, sg);
|
||||
return;
|
||||
}
|
||||
case SCALING_BILINEAR:
|
||||
|
@ -348,9 +348,21 @@ void scale_image_agg(Image & target,
|
|||
case SCALING_BLACKMAN:
|
||||
filter.calculate(agg::image_filter_blackman(filter_radius), true); break;
|
||||
}
|
||||
// details on various resampling considerations
|
||||
// http://old.nabble.com/Re%3A-Newbie---texture-p5057255.html
|
||||
|
||||
// high quality resampler
|
||||
//typedef agg::span_image_resample_rgba_affine<img_src_type> span_gen_type;
|
||||
|
||||
// faster, lower quality
|
||||
//typedef agg::span_image_filter_rgba<img_src_type,interpolator_type> span_gen_type;
|
||||
|
||||
// local, modified agg::span_image_resample_rgba_affine
|
||||
// not convinced we need this
|
||||
// https://github.com/mapnik/mapnik/issues/1489
|
||||
typedef mapnik::span_image_resample_rgba_affine<img_src_type> span_gen_type;
|
||||
span_gen_type sg(img_src, interpolator, filter);
|
||||
agg::render_scanlines_aa(ras, sl, rb_dst, sa, sg);
|
||||
agg::render_scanlines_aa(ras, sl, rb_dst_pre, sa, sg);
|
||||
}
|
||||
|
||||
template void scale_image_agg<image_data_32> (image_data_32& target,const image_data_32& source, scaling_method_e scaling_method, double scale_factor, double x_off_f, double y_off_f, double filter_radius, double ratio);
|
||||
|
|
32
src/map.cpp
32
src/map.cpp
|
@ -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));
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
43
tests/python_tests/query_tolerance_test.py
Normal file
43
tests/python_tests/query_tolerance_test.py
Normal 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
|
||||
|
|
@ -103,6 +103,22 @@ def test_load_save_map():
|
|||
if not 'Could not create datasource' in str(e):
|
||||
raise RuntimeError(str(e))
|
||||
|
||||
def pixel2rgba(pixel):
|
||||
alpha = (pixel >> 24) & 0xff
|
||||
red = pixel & 0xff
|
||||
green = (pixel >> 8) & 0xff
|
||||
blue = (pixel >> 16) & 0xff
|
||||
return 'rgba(%s,%s,%s,%s)' % (red,green,blue,alpha)
|
||||
|
||||
def get_unique_colors(im):
|
||||
pixels = []
|
||||
for x in range(im.width()):
|
||||
for y in range(im.height()):
|
||||
pixel = im.get_pixel(x,y)
|
||||
if pixel not in pixels:
|
||||
pixels.append(pixel)
|
||||
return map(pixel2rgba,pixels)
|
||||
|
||||
def test_raster_with_alpha_blends_correctly_with_background():
|
||||
WIDTH = 500
|
||||
HEIGHT = 500
|
||||
|
@ -135,7 +151,7 @@ def test_raster_with_alpha_blends_correctly_with_background():
|
|||
mapnik.render(map, mim)
|
||||
imdata = mim.tostring()
|
||||
# All white is expected
|
||||
assert contains_word('\xff\xff\xff\xff', imdata)
|
||||
eq_(contains_word('\xff\xff\xff\xff', imdata),True,'Image expected to contain true white, instead found %s' % get_unique_colors(mim))
|
||||
|
||||
def test_raster_warping():
|
||||
lyrSrs = "+init=epsg:32630"
|
||||
|
|
|
@ -8,6 +8,8 @@ import sys
|
|||
import os.path
|
||||
from compare import compare, summary, fail
|
||||
|
||||
visual_output_dir = "/tmp/mapnik-visual-images"
|
||||
|
||||
defaults = {
|
||||
'sizes': [(500, 100)]
|
||||
}
|
||||
|
@ -72,21 +74,25 @@ files = [
|
|||
]
|
||||
|
||||
def render(filename, width, height, bbox, quiet=False):
|
||||
if not quiet:
|
||||
print "\"%s\" with size %dx%d ..." % (filename, width, height),
|
||||
m = mapnik.Map(width, height)
|
||||
expected = os.path.join(dirname, "images", '%s-%d-reference.png' % (filename, width))
|
||||
actual = os.path.join("/tmp/mapnik-visual-images", '%s-%d-agg.png' % (filename, width))
|
||||
actual = '%s-%d' % (filename, width)
|
||||
try:
|
||||
mapnik.load_map(m, os.path.join(dirname, "styles", "%s.xml" % filename), False)
|
||||
if bbox is not None:
|
||||
m.zoom_to_box(bbox)
|
||||
else:
|
||||
m.zoom_all()
|
||||
if not os.path.exists('/tmp/mapnik-visual-images'):
|
||||
os.makedirs('/tmp/mapnik-visual-images')
|
||||
mapnik.render_to_file(m, actual)
|
||||
diff = compare(actual, expected)
|
||||
except Exception, e:
|
||||
sys.stderr.write(e.message + '\n')
|
||||
fail(actual,expected,str(e.message))
|
||||
return
|
||||
actual_agg = os.path.join(visual_output_dir, '%s-agg.png' % actual)
|
||||
if not quiet:
|
||||
print "\"%s\" with size %dx%d with agg..." % (filename, width, height),
|
||||
try:
|
||||
mapnik.render_to_file(m, actual_agg)
|
||||
diff = compare(actual_agg, expected)
|
||||
if not quiet:
|
||||
if diff > 0:
|
||||
print '\x1b[31m✘\x1b[0m (\x1b[34m%u different pixels\x1b[0m)' % diff
|
||||
|
@ -94,7 +100,22 @@ def render(filename, width, height, bbox, quiet=False):
|
|||
print '\x1b[32m✓\x1b[0m'
|
||||
except Exception, e:
|
||||
sys.stderr.write(e.message + '\n')
|
||||
fail(actual,expected,str(e.message))
|
||||
fail(actual_agg,expected,str(e.message))
|
||||
if 'tiff' in actual:
|
||||
actual_cairo = os.path.join(visual_output_dir, '%s-cairo.png' % actual)
|
||||
if not quiet:
|
||||
print "\"%s\" with size %dx%d with cairo..." % (filename, width, height),
|
||||
try:
|
||||
mapnik.render_to_file(m, actual_cairo,'ARGB32')
|
||||
diff = compare(actual_cairo, expected)
|
||||
if not quiet:
|
||||
if diff > 0:
|
||||
print '\x1b[31m✘\x1b[0m (\x1b[34m%u different pixels\x1b[0m)' % diff
|
||||
else:
|
||||
print '\x1b[32m✓\x1b[0m'
|
||||
except Exception, e:
|
||||
sys.stderr.write(e.message + '\n')
|
||||
fail(actual_cairo,expected,str(e.message))
|
||||
return m
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
@ -119,6 +140,9 @@ if __name__ == "__main__":
|
|||
for name in sys.argv[1:]:
|
||||
active.append({"name": name})
|
||||
|
||||
if not os.path.exists(visual_output_dir):
|
||||
os.makedirs(visual_output_dir)
|
||||
|
||||
if 'osm' in mapnik.DatasourceCache.plugin_names():
|
||||
for f in active:
|
||||
config = dict(defaults)
|
||||
|
|
Loading…
Add table
Reference in a new issue