Merge branch 'master' of github.com:mapnik/mapnik

This commit is contained in:
Robert Coup 2011-10-21 23:51:27 -07:00
commit eb81e72522
51 changed files with 2216 additions and 1328 deletions

View file

@ -410,6 +410,13 @@ def Raster(**keywords):
Optional keyword arguments:
base -- path prefix (default None)
multi -- whether the image is in tiles on disk (default False)
Multi-tiled keyword arguments:
x_width -- virtual image number of tiles in X direction (required)
y_width -- virtual image number of tiles in Y direction (required)
tile_size -- if an image is in tiles, how large are the tiles (default 256)
tile_stride -- if an image is in tiles, what's the increment between rows/cols (default 1)
>>> from mapnik import Raster, Layer
>>> raster = Raster(base='/home/mapnik/data',file='elevation.tif',lox=-122.8,loy=48.5,hix=-122.7,hiy=48.6)

View file

@ -78,7 +78,6 @@ void export_geometry()
.def("envelope",&geometry_type::envelope)
// .def("__str__",&geometry_type::to_string)
.def("type",&geometry_type::type)
.def("area",&geometry_type::area)
// TODO add other geometry_type methods
;

View file

@ -0,0 +1,123 @@
/*****************************************************************************
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2011 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
*
*****************************************************************************/
#include <boost/python.hpp>
#include <boost/python/module.hpp>
#include <boost/python/def.hpp>
#include <boost/make_shared.hpp>
#include <mapnik/label_collision_detector.hpp>
#include <mapnik/map.hpp>
#include <list>
using mapnik::label_collision_detector4;
using mapnik::box2d;
using mapnik::Map;
using boost::make_shared;
namespace
{
boost::shared_ptr<label_collision_detector4>
create_label_collision_detector_from_extent(box2d<double> const &extent)
{
return make_shared<label_collision_detector4>(extent);
}
boost::shared_ptr<label_collision_detector4>
create_label_collision_detector_from_map(Map const &m)
{
double buffer = m.buffer_size();
box2d<double> extent(-buffer, -buffer, m.width() + buffer, m.height() + buffer);
return make_shared<label_collision_detector4>(extent);
}
boost::python::list
make_label_boxes(boost::shared_ptr<label_collision_detector4> det)
{
boost::python::list boxes;
for (label_collision_detector4::query_iterator jtr = det->begin();
jtr != det->end(); ++jtr)
{
boxes.append<box2d<double> >(jtr->box);
}
return boxes;
}
}
void export_label_collision_detector()
{
using namespace boost::python;
// for overload resolution
void (label_collision_detector4::*insert_box)(box2d<double> const &) = &label_collision_detector4::insert;
class_<label_collision_detector4, boost::shared_ptr<label_collision_detector4>, boost::noncopyable>
("LabelCollisionDetector",
"Object to detect collisions between labels, used in the rendering process.",
no_init)
.def("__init__", make_constructor(create_label_collision_detector_from_extent),
"Creates an empty collision detection object with a given extent. Note "
"that the constructor from Map objects is a sensible default and usually "
"what you want to do.\n"
"\n"
"Example:\n"
">>> m = Map(size_x, size_y)\n"
">>> buf_sz = m.buffer_size\n"
">>> extent = mapnik.Box2d(-buf_sz, -buf_sz, m.width + buf_sz, m.height + buf_sz)\n"
">>> detector = mapnik.LabelCollisionDetector(extent)")
.def("__init__", make_constructor(create_label_collision_detector_from_map),
"Creates an empty collision detection object matching the given Map object. "
"The created detector will have the same size, including the buffer, as the "
"map object. This is usually what you want to do.\n"
"\n"
"Example:\n"
">>> m = Map(size_x, size_y)\n"
">>> detector = mapnik.LabelCollisionDetector(m)")
.def("extent", &label_collision_detector4::extent, return_value_policy<copy_const_reference>(),
"Returns the total extent (bounding box) of all labels inside the detector.\n"
"\n"
"Example:\n"
">>> detector.extent()\n"
"Box2d(573.252589209,494.789179821,584.261023823,496.83610261)")
.def("boxes", &make_label_boxes,
"Returns a list of all the label boxes inside the detector.")
.def("insert", insert_box,
"Insert a 2d box into the collision detector. This can be used to ensure that "
"some space is left clear on the map for later overdrawing, for example by "
"non-Mapnik processes.\n"
"\n"
"Example:\n"
">>> m = Map(size_x, size_y)\n"
">>> detector = mapnik.LabelCollisionDetector(m)"
">>> detector.insert(mapnik.Box2d(196, 254, 291, 389))")
;
}

View file

@ -66,6 +66,7 @@ void export_view_transform();
void export_raster_colorizer();
void export_glyph_symbolizer();
void export_inmem_metawriter();
void export_label_collision_detector();
#include <mapnik/version.hpp>
#include <mapnik/value_error.hpp>
@ -120,6 +121,28 @@ void render(const mapnik::Map& map,
Py_END_ALLOW_THREADS
}
void render_with_detector(
const mapnik::Map &map,
mapnik::image_32 &image,
boost::shared_ptr<mapnik::label_collision_detector4> detector,
double scale_factor = 1.0,
unsigned offset_x = 0u,
unsigned offset_y = 0u)
{
Py_BEGIN_ALLOW_THREADS
try
{
mapnik::agg_renderer<mapnik::image_32> ren(map,image,detector);
ren.apply();
}
catch (...)
{
Py_BLOCK_THREADS
throw;
}
Py_END_ALLOW_THREADS
}
void render_layer2(const mapnik::Map& map,
mapnik::image_32& image,
unsigned layer_idx)
@ -374,6 +397,7 @@ BOOST_PYTHON_FUNCTION_OVERLOADS(load_map_string_overloads, load_map_string, 2, 4
BOOST_PYTHON_FUNCTION_OVERLOADS(save_map_overloads, save_map, 2, 3)
BOOST_PYTHON_FUNCTION_OVERLOADS(save_map_to_string_overloads, save_map_to_string, 1, 2)
BOOST_PYTHON_FUNCTION_OVERLOADS(render_overloads, render, 2, 5)
BOOST_PYTHON_FUNCTION_OVERLOADS(render_with_detector_overloads, render_with_detector, 3, 6)
BOOST_PYTHON_MODULE(_mapnik2)
{
@ -427,6 +451,7 @@ BOOST_PYTHON_MODULE(_mapnik2)
export_raster_colorizer();
export_glyph_symbolizer();
export_inmem_metawriter();
export_label_collision_detector();
def("render_grid",&render_grid,
( arg("map"),
@ -503,6 +528,19 @@ BOOST_PYTHON_MODULE(_mapnik2)
"\n"
));
def("render_with_detector", &render_with_detector, render_with_detector_overloads(
"\n"
"Render Map to an AGG image_32 using a pre-constructed detector.\n"
"\n"
"Usage:\n"
">>> from mapnik import Map, Image, LabelCollisionDetector, render_with_detector, load_map\n"
">>> m = Map(256,256)\n"
">>> load_map(m,'mapfile.xml')\n"
">>> im = Image(m.width,m.height)\n"
">>> detector = LabelCollisionDetector(m)\n"
">>> render_with_detector(m, im, detector)\n"
));
def("render_layer", &render_layer2,
(arg("map"),arg("image"),args("layer"))
);

View file

@ -40,6 +40,7 @@
// boost
#include <boost/utility.hpp>
#include <boost/scoped_ptr.hpp>
#include <boost/shared_ptr.hpp>
// FIXME
// forward declare so that
@ -61,7 +62,11 @@ class MAPNIK_DECL agg_renderer : public feature_style_processor<agg_renderer<T>
{
public:
// create with default, empty placement detector
agg_renderer(Map const& m, T & pixmap, double scale_factor=1.0, unsigned offset_x=0, unsigned offset_y=0);
// create with external placement detector, possibly non-empty
agg_renderer(Map const &m, T & pixmap, boost::shared_ptr<label_collision_detector4> detector,
double scale_factor=1.0, unsigned offset_x=0, unsigned offset_y=0);
~agg_renderer();
void start_map_processing(Map const& map);
void end_map_processing(Map const& map);
@ -122,8 +127,10 @@ private:
CoordTransform t_;
freetype_engine font_engine_;
face_manager<freetype_engine> font_manager_;
label_collision_detector4 detector_;
boost::shared_ptr<label_collision_detector4> detector_;
boost::scoped_ptr<rasterizer> ras_ptr;
void setup(Map const &m);
};
}

View file

@ -1,5 +1,5 @@
/*****************************************************************************
*
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2006 Artem Pavlenko
@ -19,91 +19,92 @@
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*****************************************************************************/
//$Id: ctrans.hpp 39 2005-04-10 20:39:53Z pavlenko $
//$Id$
#ifndef CTRANS_HPP
#define CTRANS_HPP
#include <algorithm>
// mapnik
#include <mapnik/box2d.hpp>
#include <mapnik/vertex.hpp>
#include <mapnik/coord_array.hpp>
#include <mapnik/proj_transform.hpp>
namespace mapnik {
// boost
#include <boost/math/constants/constants.hpp>
// stl
#include <algorithm>
const double pi = boost::math::constants::pi<double>();
const double pi_by_2 = pi/2.0;
namespace mapnik
{
typedef coord_array<coord2d> CoordinateArray;
template <typename Transform,typename Geometry>
template <typename Transform, typename Geometry>
struct MAPNIK_DECL coord_transform
{
coord_transform(Transform const& t, Geometry& geom)
: t_(t), geom_(geom) {}
unsigned vertex(double *x , double *y) const
unsigned vertex(double *x, double *y) const
{
unsigned command = geom_.vertex(x,y);
t_.forward(x,y);
unsigned command = geom_.vertex(x, y);
t_.forward(x, y);
return command;
}
void rewind (unsigned pos)
void rewind(unsigned pos)
{
geom_.rewind(pos);
}
private:
Transform const& t_;
Geometry& geom_;
};
template <typename Transform,typename Geometry>
template <typename Transform, typename Geometry>
struct MAPNIK_DECL coord_transform2
{
typedef std::size_t size_type;
typedef typename Geometry::value_type value_type;
coord_transform2(Transform const& t,
Geometry const& geom,
coord_transform2(Transform const& t,
Geometry const& geom,
proj_transform const& prj_trans)
: t_(t),
geom_(geom),
: t_(t),
geom_(geom),
prj_trans_(prj_trans) {}
unsigned vertex(double * x , double * y) const
unsigned vertex(double *x, double *y) const
{
unsigned command(SEG_MOVETO);
unsigned command = SEG_MOVETO;
bool ok = false;
bool skipped_points = false;
while (!ok)
double z = 0;
while (!ok && command != SEG_END)
{
command = geom_.vertex(x,y);
double z=0;
ok = prj_trans_.backward(*x,*y,z);
command = geom_.vertex(x, y);
ok = prj_trans_.backward(*x, *y, z);
if (!ok) {
skipped_points = true;
}
ok = ok || (command == SEG_END);
}
if (skipped_points && (command == SEG_LINETO))
{
command = SEG_MOVETO;
}
t_.forward(x,y);
t_.forward(x, y);
return command;
}
/*unsigned vertex(double * x , double * y) const
{
unsigned command = geom_.vertex(x,y);
double z=0;
prj_trans_.backward(*x,*y,z);
t_.forward(x,y);
return command;
}*/
void rewind (unsigned pos)
void rewind(unsigned pos)
{
geom_.rewind(pos);
}
@ -112,42 +113,42 @@ struct MAPNIK_DECL coord_transform2
{
return geom_;
}
private:
Transform const& t_;
Geometry const& geom_;
proj_transform const& prj_trans_;
};
template <typename Transform,typename Geometry>
template <typename Transform, typename Geometry>
struct MAPNIK_DECL coord_transform3
{
coord_transform3(Transform const& t,
Geometry const& geom,
coord_transform3(Transform const& t,
Geometry const& geom,
proj_transform const& prj_trans,
int dx, int dy)
: t_(t),
geom_(geom),
: t_(t),
geom_(geom),
prj_trans_(prj_trans),
dx_(dx), dy_(dy) {}
unsigned vertex(double * x , double * y) const
unsigned vertex(double *x, double *y) const
{
unsigned command = geom_.vertex(x,y);
double z=0;
prj_trans_.backward(*x,*y,z);
t_.forward(x,y);
*x+=dx_;
*y+=dy_;
unsigned command = geom_.vertex(x, y);
double z = 0;
prj_trans_.backward(*x, *y, z);
t_.forward(x, y);
*x += dx_;
*y += dy_;
return command;
}
void rewind (unsigned pos)
void rewind(unsigned pos)
{
geom_.rewind(pos);
}
private:
Transform const& t_;
Geometry const& geom_;
@ -155,7 +156,226 @@ private:
int dx_;
int dy_;
};
// TODO - expose this and make chainable
template <typename Transform,typename Geometry>
struct MAPNIK_DECL coord_transform_parallel
{
typedef std::size_t size_type;
typedef typename Geometry::value_type value_type;
coord_transform_parallel(Transform const& t,
Geometry const& geom,
proj_transform const& prj_trans )
: t_(t),
geom_(geom),
prj_trans_(prj_trans),
offset_(0.0),
threshold_(10),
m_status(initial) {}
enum status
{
initial,
start,
first,
process,
last_vertex,
angle_joint,
end
};
double get_offset() const
{
return offset_;
}
void set_offset(double offset)
{
offset_ = offset;
}
unsigned int get_threshold() const
{
return threshold_;
}
void set_threshold(unsigned int t)
{
threshold_ = t;
}
unsigned vertex(double * x , double * y)
{
double z=0;
if (offset_==0.0)
{
unsigned command = geom_.vertex(x,y);
prj_trans_.backward(*x,*y,z);
t_.forward(x,y);
return command;
}
else
{
while(true){
switch(m_status)
{
case end:
return SEG_END;
break;
case initial:
m_pre_cmd = geom_.vertex(x,y);
prj_trans_.backward(*x,*y,z);
t_.forward(x,y);
m_pre_x = *x;
m_pre_y = *y;
//m_status = (m_pre_cmd!=SEG_END)?start:end; //
case start:
m_cur_cmd = geom_.vertex(&m_cur_x, &m_cur_y);
prj_trans_.backward(m_cur_x,m_cur_y,z);
t_.forward(&m_cur_x,&m_cur_y);
case first:
angle_a = atan2((m_pre_y-m_cur_y),(m_pre_x-m_cur_x));
dx_pre = cos(angle_a + pi_by_2);
dy_pre = sin(angle_a + pi_by_2);
#ifdef MAPNIK_DEBUG
std::clog << "offsetting line by: " << offset_ << "\n";
std::clog << "initial dx=" << (dx_pre * offset_) << " dy=" << (dy_pre * offset_) << "\n";
#endif
*x = m_pre_x + (dx_pre * offset_);
*y = m_pre_y + (dy_pre * offset_);
m_status = process;
return SEG_MOVETO;
case process:
switch(m_cur_cmd)
{
case SEG_LINETO:
m_next_cmd = geom_.vertex(&m_next_x, &m_next_y);
prj_trans_.backward(m_next_x,m_next_y,z);
t_.forward(&m_next_x,&m_next_y);
switch(m_next_cmd)
{
case SEG_LINETO:
m_status = angle_joint;
break;
default:
m_status = last_vertex;
break;
}
break;
case SEG_END:
m_status = end;
return SEG_END;
}
break;
case last_vertex:
dx_curr = cos(angle_a + pi_by_2);
dy_curr = sin(angle_a + pi_by_2);
*x = m_cur_x + (dx_curr * offset_);
*y = m_cur_y + (dy_curr * offset_);
m_status = end;
return m_cur_cmd;
case angle_joint:
angle_b = atan2((m_cur_y-m_next_y),(m_cur_x-m_next_x));
h = tan((angle_b - angle_a)/2.0);
if (fabs(h) < threshold_)
{
dx_curr = cos(angle_a + pi_by_2);
dy_curr = sin(angle_a + pi_by_2);
*x = m_cur_x + (dx_curr * offset_) - h * (dy_curr * offset_);
*y = m_cur_y + (dy_curr * offset_) + h * (dx_curr * offset_);
}
else // skip sharp spikes
{
#ifdef MAPNIK_DEBUG
dx_curr = cos(angle_a + pi_by_2);
dy_curr = sin(angle_a + pi_by_2);
sin_curve = dx_curr*dy_pre-dy_curr*dx_pre;
std::clog << "angle a: " << angle_a << "\n";
std::clog << "angle b: " << angle_b << "\n";
std::clog << "h: " << h << "\n";
std::clog << "sin_curve: " << sin_curve << "\n";
#endif
m_status = process;
break;
}
// alternate sharp spike fix, but suboptimal...
/*
sin_curve = dx_curr*dy_pre-dy_curr*dx_pre;
cos_curve = -dx_pre*dx_curr-dy_pre*dy_curr;
#ifdef MAPNIK_DEBUG
std::clog << "sin_curve value: " << sin_curve << "\n";
#endif
if(sin_curve > -0.3 && sin_curve < 0.3) {
angle_b = atan2((m_cur_y-m_next_y),(m_cur_x-m_next_x));
h = tan((angle_b - angle_a)/2.0);
*x = m_cur_x + (dx_curr * offset_) - h * (dy_curr * offset_);
*y = m_cur_y + (dy_curr * offset_) + h * (dx_curr * offset_);
} else {
if (angle_b - angle_a > 0)
h = -1.0*(1.0+cos_curve)/sin_curve;
else
h = (1.0+cos_curve)/sin_curve;
*x = m_cur_x + (dx_curr + base_shift*dy_curr)*offset_;
*y = m_cur_y + (dy_curr - base_shift*dx_curr)*offset_;
}
*/
m_pre_x = *x;
m_pre_x = *y;
m_cur_x = m_next_x;
m_cur_y = m_next_y;
angle_a = angle_b;
m_pre_cmd = m_cur_cmd;
m_cur_cmd = m_next_cmd;
m_status = process;
return m_pre_cmd;
}
}
}
}
void rewind (unsigned pos)
{
geom_.rewind(pos);
m_status = initial;
}
private:
Transform const& t_;
Geometry const& geom_;
proj_transform const& prj_trans_;
int offset_;
unsigned int threshold_;
status m_status;
double dx_pre;
double dy_pre;
double dx_curr;
double dy_curr;
double sin_curve;
double cos_curve;
double angle_a;
double angle_b;
double h;
unsigned m_pre_cmd;
double m_pre_x;
double m_pre_y;
unsigned m_cur_cmd;
double m_cur_x;
double m_cur_y;
unsigned m_next_cmd;
double m_next_x;
double m_next_y;
};
class CoordTransform
{
private:
@ -166,71 +386,74 @@ private:
box2d<double> extent_;
double offset_x_;
double offset_y_;
public:
CoordTransform(int width,int height,const box2d<double>& extent,
CoordTransform(int width, int height, const box2d<double>& extent,
double offset_x = 0, double offset_y = 0)
:width_(width),height_(height),extent_(extent),offset_x_(offset_x),offset_y_(offset_y)
: width_(width), height_(height), extent_(extent),
offset_x_(offset_x), offset_y_(offset_y)
{
sx_ = (double(width_))/extent_.width();
sy_ = (double(height_))/extent_.height();
sx_ = static_cast<double>(width_) / extent_.width();
sy_ = static_cast<double>(height_) / extent_.height();
}
inline int width() const
{
return width_;
}
inline int height() const
{
return height_;
}
inline double scale_x() const
{
return sx_;
}
inline double scale_y() const
{
return sy_;
}
inline void forward(double * x, double * y) const
inline void forward(double *x, double *y) const
{
*x = (*x - extent_.minx()) * sx_ - offset_x_;
*y = (extent_.maxy() - *y) * sy_ - offset_y_;
}
inline void backward(double * x, double * y) const
inline void backward(double *x, double *y) const
{
*x = extent_.minx() + (*x + offset_x_)/sx_;
*y = extent_.maxy() - (*y + offset_y_)/sy_;
*x = extent_.minx() + (*x + offset_x_) / sx_;
*y = extent_.maxy() - (*y + offset_y_) / sy_;
}
inline coord2d& forward(coord2d& c) const
{
forward(&c.x,&c.y);
return c;
}
inline coord2d& backward(coord2d& c) const
{
backward(&c.x,&c.y);
forward(&c.x, &c.y);
return c;
}
inline box2d<double> forward(const box2d<double>& e,proj_transform const& prj_trans) const
inline coord2d& backward(coord2d& c) const
{
backward(&c.x, &c.y);
return c;
}
inline box2d<double> forward(const box2d<double>& e,
proj_transform const& prj_trans) const
{
double x0 = e.minx();
double y0 = e.miny();
double x1 = e.maxx();
double y1 = e.maxy();
double z = 0.0;
prj_trans.backward(x0,y0,z);
forward(&x0,&y0);
prj_trans.backward(x1,y1,z);
forward(&x1,&y1);
return box2d<double>(x0,y0,x1,y1);
prj_trans.backward(x0, y0, z);
forward(&x0, &y0);
prj_trans.backward(x1, y1, z);
forward(&x1, &y1);
return box2d<double>(x0, y0, x1, y1);
}
inline box2d<double> forward(const box2d<double>& e) const
@ -239,23 +462,24 @@ public:
double y0 = e.miny();
double x1 = e.maxx();
double y1 = e.maxy();
forward(&x0,&y0);
forward(&x1,&y1);
return box2d<double>(x0,y0,x1,y1);
forward(&x0, &y0);
forward(&x1, &y1);
return box2d<double>(x0, y0, x1, y1);
}
inline box2d<double> backward(const box2d<double>& e,proj_transform const& prj_trans) const
inline box2d<double> backward(const box2d<double>& e,
proj_transform const& prj_trans) const
{
double x0 = e.minx();
double y0 = e.miny();
double x1 = e.maxx();
double y1 = e.maxy();
double z = 0.0;
backward(&x0,&y0);
prj_trans.forward(x0,y0,z);
backward(&x1,&y1);
prj_trans.forward(x1,y1,z);
return box2d<double>(x0,y0,x1,y1);
backward(&x0, &y0);
prj_trans.forward(x0, y0, z);
backward(&x1, &y1);
prj_trans.forward(x1, y1, z);
return box2d<double>(x0, y0, x1, y1);
}
inline box2d<double> backward(const box2d<double>& e) const
@ -264,28 +488,29 @@ public:
double y0 = e.miny();
double x1 = e.maxx();
double y1 = e.maxy();
backward(&x0,&y0);
backward(&x1,&y1);
return box2d<double>(x0,y0,x1,y1);
backward(&x0, &y0);
backward(&x1, &y1);
return box2d<double>(x0, y0, x1, y1);
}
inline CoordinateArray& forward(CoordinateArray& coords) const
{
for (unsigned i=0;i<coords.size();++i)
for (unsigned i = 0; i < coords.size(); ++i)
{
forward(coords[i]);
}
return coords;
}
inline CoordinateArray& backward(CoordinateArray& coords) const
{
for (unsigned i=0;i<coords.size();++i)
for (unsigned i = 0; i < coords.size(); ++i)
{
backward(coords[i]);
}
return coords;
}
inline box2d<double> const& extent() const
{
return extent_;

View file

@ -68,27 +68,7 @@ public:
{
return type_;
}
double area() const
{
double sum = 0.0;
double x(0);
double y(0);
rewind(0);
double xs = x;
double ys = y;
for (unsigned i=0;i<num_points();++i)
{
double x0(0);
double y0(0);
vertex(&x0,&y0);
sum += x * y0 - y * x0;
x = x0;
y = y0;
}
return (sum + x * ys - y * xs) * 0.5;
}
box2d<double> envelope() const
{
box2d<double> result;

View file

@ -69,7 +69,7 @@ class label_collision_detector2 : boost::noncopyable
typedef quad_tree<box2d<double> > tree_t;
tree_t tree_;
public:
explicit label_collision_detector2(box2d<double> const& extent)
: tree_(extent) {}
@ -138,6 +138,7 @@ public:
//quad tree based label collission detector so labels dont appear within a given distance
class label_collision_detector4 : boost::noncopyable
{
public:
struct label
{
label(box2d<double> const& b) : box(b) {}
@ -146,11 +147,13 @@ class label_collision_detector4 : boost::noncopyable
box2d<double> box;
UnicodeString text;
};
private:
typedef quad_tree< label > tree_t;
tree_t tree_;
public:
typedef tree_t::query_iterator query_iterator;
explicit label_collision_detector4(box2d<double> const& extent)
: tree_(extent) {}
@ -224,6 +227,9 @@ public:
{
return tree_.extent();
}
query_iterator begin() { return tree_.query_in_box(extent()); }
query_iterator end() { return tree_.query_end(); }
};
}

View file

@ -2,7 +2,7 @@
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2007 Artem Pavlenko
* Copyright (C) 2011 Artem Pavlenko
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@ -45,7 +45,7 @@ using mapnik::datasource_exception;
* Opens a GDALDataset and returns a pointer to it.
* Caller is responsible for calling GDALClose on it
*/
inline GDALDataset *gdal_datasource::open_dataset() const
inline GDALDataset* gdal_datasource::open_dataset() const
{
#ifdef MAPNIK_DEBUG
@ -55,21 +55,28 @@ inline GDALDataset *gdal_datasource::open_dataset() const
GDALDataset *dataset;
#if GDAL_VERSION_NUM >= 1600
if (shared_dataset_)
dataset = reinterpret_cast<GDALDataset*>(GDALOpenShared((dataset_name_).c_str(),GA_ReadOnly));
{
dataset = reinterpret_cast<GDALDataset*>(GDALOpenShared((dataset_name_).c_str(), GA_ReadOnly));
}
else
#endif
dataset = reinterpret_cast<GDALDataset*>(GDALOpen((dataset_name_).c_str(),GA_ReadOnly));
{
dataset = reinterpret_cast<GDALDataset*>(GDALOpen((dataset_name_).c_str(), GA_ReadOnly));
}
if (! dataset)
{
throw datasource_exception(CPLGetLastErrorMsg());
}
if (! dataset) throw datasource_exception(CPLGetLastErrorMsg());
return dataset;
}
gdal_datasource::gdal_datasource(parameters const& params, bool bind)
: datasource(params),
desc_(*params.get<std::string>("type"),"utf-8"),
filter_factor_(*params_.get<double>("filter_factor",0.0))
: datasource(params),
desc_(*params.get<std::string>("type"), "utf-8"),
filter_factor_(*params_.get<double>("filter_factor", 0.0))
{
#ifdef MAPNIK_DEBUG
std::clog << "GDAL Plugin: Initializing..." << std::endl;
@ -78,13 +85,17 @@ gdal_datasource::gdal_datasource(parameters const& params, bool bind)
GDALAllRegister();
boost::optional<std::string> file = params.get<std::string>("file");
if (!file) throw datasource_exception("missing <file> parameter");
if (! file) throw datasource_exception("missing <file> parameter");
boost::optional<std::string> base = params_.get<std::string>("base");
if (base)
{
dataset_name_ = *base + "/" + *file;
}
else
{
dataset_name_ = *file;
}
if (bind)
{
@ -96,7 +107,7 @@ void gdal_datasource::bind() const
{
if (is_bound_) return;
shared_dataset_ = *params_.get<mapnik::boolean>("shared",false);
shared_dataset_ = *params_.get<mapnik::boolean>("shared", false);
band_ = *params_.get<int>("band", -1);
GDALDataset *dataset = open_dataset();
@ -105,7 +116,6 @@ void gdal_datasource::bind() const
width_ = dataset->GetRasterXSize();
height_ = dataset->GetRasterYSize();
double tr[6];
bool bbox_override = false;
boost::optional<std::string> bbox_s = params_.get<std::string>("bbox");
@ -114,8 +124,9 @@ void gdal_datasource::bind() const
#ifdef MAPNIK_DEBUG
std::clog << "GDAL Plugin: bbox parameter=" << *bbox_s << std::endl;
#endif
bbox_override = extent_.from_string(*bbox_s);
if (!bbox_override)
if (! bbox_override)
{
throw datasource_exception("GDAL Plugin: bbox parameter '" + *bbox_s + "' invalid");
}
@ -141,7 +152,7 @@ void gdal_datasource::bind() const
<< tr[4] << "," << tr[5] << std::endl;
#endif
if (tr[2] !=0 || tr[4] != 0)
if (tr[2] != 0 || tr[4] != 0)
{
throw datasource_exception("GDAL Plugin: only 'north up' images are supported");
}
@ -149,7 +160,7 @@ void gdal_datasource::bind() const
dx_ = tr[1];
dy_ = tr[5];
if (!bbox_override)
if (! bbox_override)
{
double x0 = tr[0];
double y0 = tr[3];
@ -164,8 +175,9 @@ void gdal_datasource::bind() const
double y1 = tr[3] + (width_) * tr[4]; // maxy
*/
extent_.init(x0,y0,x1,y1);
extent_.init(x0, y0, x1, y1);
}
GDALClose(dataset);
#ifdef MAPNIK_DEBUG
@ -192,7 +204,7 @@ std::string gdal_datasource::name()
box2d<double> gdal_datasource::envelope() const
{
if (!is_bound_) bind();
if (! is_bound_) bind();
return extent_;
}
@ -204,18 +216,38 @@ layer_descriptor gdal_datasource::get_descriptor() const
featureset_ptr gdal_datasource::features(query const& q) const
{
if (!is_bound_) bind();
if (! is_bound_) bind();
gdal_query gq = q;
// TODO - move to boost::make_shared, but must reduce # of args to <= 9
return featureset_ptr(new gdal_featureset(*open_dataset(), band_, gq, extent_, width_, height_, nbands_, dx_, dy_, filter_factor_));
return featureset_ptr(new gdal_featureset(*open_dataset(),
band_,
gq,
extent_,
width_,
height_,
nbands_,
dx_,
dy_,
filter_factor_));
}
featureset_ptr gdal_datasource::features_at_point(coord2d const& pt) const
{
if (!is_bound_) bind();
if (! is_bound_) bind();
gdal_query gq = pt;
return featureset_ptr(new gdal_featureset(*open_dataset(), band_, gq, extent_, width_, height_, nbands_, dx_, dy_, filter_factor_));
}
// TODO - move to boost::make_shared, but must reduce # of args to <= 9
return featureset_ptr(new gdal_featureset(*open_dataset(),
band_,
gq,
extent_,
width_,
height_,
nbands_,
dx_,
dy_,
filter_factor_));
}

View file

@ -2,7 +2,7 @@
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2007 Artem Pavlenko
* Copyright (C) 2011 Artem Pavlenko
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@ -35,29 +35,29 @@
class gdal_datasource : public mapnik::datasource
{
public:
gdal_datasource(mapnik::parameters const& params, bool bind=true);
virtual ~gdal_datasource ();
int type() const;
static std::string name();
mapnik::featureset_ptr features( mapnik::query const& q) const;
mapnik::featureset_ptr features_at_point(mapnik::coord2d const& pt) const;
mapnik::box2d<double> envelope() const;
mapnik::layer_descriptor get_descriptor() const;
void bind() const;
private:
mutable mapnik::box2d<double> extent_;
std::string dataset_name_;
mutable int band_;
mapnik::layer_descriptor desc_;
mutable unsigned width_;
mutable unsigned height_;
mutable double dx_;
mutable double dy_;
mutable int nbands_;
mutable bool shared_dataset_;
double filter_factor_;
inline GDALDataset *open_dataset() const;
public:
gdal_datasource(mapnik::parameters const& params, bool bind = true);
virtual ~gdal_datasource();
int type() const;
static std::string name();
mapnik::featureset_ptr features(mapnik::query const& q) const;
mapnik::featureset_ptr features_at_point(mapnik::coord2d const& pt) const;
mapnik::box2d<double> envelope() const;
mapnik::layer_descriptor get_descriptor() const;
void bind() const;
private:
mutable mapnik::box2d<double> extent_;
std::string dataset_name_;
mutable int band_;
mapnik::layer_descriptor desc_;
mutable unsigned width_;
mutable unsigned height_;
mutable double dx_;
mutable double dy_;
mutable int nbands_;
mutable bool shared_dataset_;
double filter_factor_;
inline GDALDataset* open_dataset() const;
};

View file

@ -2,7 +2,7 @@
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2007 Artem Pavlenko
* Copyright (C) 2011 Artem Pavlenko
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@ -41,20 +41,27 @@ using mapnik::datasource_exception;
using mapnik::feature_factory;
gdal_featureset::gdal_featureset(GDALDataset & dataset, int band, gdal_query q,
mapnik::box2d<double> extent, double width, double height, int nbands,
double dx, double dy, double filter_factor)
: dataset_(dataset),
band_(band),
gquery_(q),
raster_extent_(extent),
raster_width_(width),
raster_height_(height),
dx_(dx),
dy_(dy),
nbands_(nbands),
filter_factor_(filter_factor),
first_(true)
gdal_featureset::gdal_featureset(GDALDataset& dataset,
int band,
gdal_query q,
mapnik::box2d<double> extent,
double width,
double height,
int nbands,
double dx,
double dy,
double filter_factor)
: dataset_(dataset),
band_(band),
gquery_(q),
raster_extent_(extent),
raster_width_(width),
raster_height_(height),
dx_(dx),
dy_(dy),
nbands_(nbands),
filter_factor_(filter_factor),
first_(true)
{
}
@ -63,6 +70,7 @@ gdal_featureset::~gdal_featureset()
#ifdef MAPNIK_DEBUG
std::clog << "GDAL Plugin: closing dataset = " << &dataset_ << std::endl;
#endif
GDALClose(&dataset_);
}
@ -76,11 +84,15 @@ feature_ptr gdal_featureset::next()
#endif
query *q = boost::get<query>(&gquery_);
if(q) {
if (q)
{
return get_feature(*q);
} else {
}
else
{
coord2d *p = boost::get<coord2d>(&gquery_);
if(p) {
if (p)
{
return get_feature_at_point(*p);
}
}
@ -108,40 +120,60 @@ feature_ptr gdal_featureset::get_feature(mapnik::query const& q)
std::clog << "dx_: " << dx_ << " dx: " << dx << " dy_: " << dy_ << "dy: " << dy << "\n";
*/
CoordTransform t(raster_width_,raster_height_,raster_extent_,0,0);
CoordTransform t(raster_width_, raster_height_, raster_extent_, 0, 0);
box2d<double> intersect = raster_extent_.intersect(q.get_bbox());
box2d<double> box = t.forward(intersect);
//size of resized output pixel in source image domain
double margin_x = 1.0/(fabs(dx_)*boost::get<0>(q.resolution()));
double margin_y = 1.0/(fabs(dy_)*boost::get<1>(q.resolution()));
double margin_x = 1.0 / (fabs(dx_) * boost::get<0>(q.resolution()));
double margin_y = 1.0 / (fabs(dy_) * boost::get<1>(q.resolution()));
if (margin_x < 1)
{
margin_x = 1.0;
}
if (margin_y < 1)
{
margin_y = 1.0;
}
//select minimum raster containing whole box
int x_off = rint(box.minx() - margin_x);
int y_off = rint(box.miny() - margin_y);
int end_x = rint(box.maxx() + margin_x);
int end_y = rint(box.maxy() + margin_y);
//clip to available data
if (x_off < 0)
{
x_off = 0;
}
if (y_off < 0)
{
y_off = 0;
}
if (end_x > (int)raster_width_)
{
end_x = raster_width_;
}
if (end_y > (int)raster_height_)
{
end_y = raster_height_;
}
int width = end_x - x_off;
int height = end_y - y_off;
// don't process almost invisible data
if (box.width() < 0.5)
{
width = 0;
}
if (box.height() < 0.5)
{
height = 0;
}
//calculate actual box2d of returned raster
box2d<double> feature_raster_extent(x_off, y_off, x_off+width, y_off+height);
box2d<double> feature_raster_extent(x_off, y_off, x_off + width, y_off + height);
intersect = t.backward(feature_raster_extent);
#ifdef MAPNIK_DEBUG
@ -197,9 +229,11 @@ feature_ptr gdal_featureset::get_feature(mapnik::query const& q)
if (band_ > 0) // we are querying a single band
{
if (band_ > nbands_)
{
throw datasource_exception((boost::format("GDAL Plugin: '%d' is an invalid band, dataset only has '%d' bands\n") % band_ % nbands_).str());
}
float *imageData = (float*)image.getBytes();
float* imageData = (float*)image.getBytes();
GDALRasterBand * band = dataset_.GetRasterBand(band_);
int hasNoData;
double nodata = band->GetNoDataValue(&hasNoData);
@ -209,17 +243,18 @@ feature_ptr gdal_featureset::get_feature(mapnik::query const& q)
feature->set_raster(mapnik::raster_ptr(boost::make_shared<mapnik::raster>(intersect,image)));
if (hasNoData)
feature->props()["NODATA"]=nodata;
{
feature->props()["NODATA"] = nodata;
}
}
else // working with all bands
{
for (int i = 0; i < nbands_; ++i)
{
GDALRasterBand * band = dataset_.GetRasterBand(i+1);
GDALRasterBand * band = dataset_.GetRasterBand(i + 1);
#ifdef MAPNIK_DEBUG
get_overview_meta(band);
get_overview_meta(band);
#endif
GDALColorInterp color_interp = band->GetColorInterpretation();
@ -263,7 +298,7 @@ feature_ptr gdal_featureset::get_feature(mapnik::query const& q)
#endif
GDALColorTable *color_table = band->GetColorTable();
if ( color_table)
if (color_table)
{
int count = color_table->GetColorEntryCount();
#ifdef MAPNIK_DEBUG
@ -303,33 +338,36 @@ feature_ptr gdal_featureset::get_feature(mapnik::query const& q)
float nodata = red->GetNoDataValue(&hasNoData);
GDALColorTable *color_table = red->GetColorTable();
if (!alpha && hasNoData && !color_table)
if (! alpha && hasNoData && ! color_table)
{
// first read the data in and create an alpha channel from the nodata values
float *imageData = (float*)image.getBytes();
float* imageData = (float*)image.getBytes();
red->RasterIO(GF_Read, x_off, y_off, width, height,
imageData, image.width(), image.height(),
GDT_Float32, 0, 0);
imageData, image.width(), image.height(),
GDT_Float32, 0, 0);
int len = image.width() * image.height();
for (int i=0; i<len; ++i)
for (int i = 0; i < len; ++i)
{
if (nodata == imageData[i])
*reinterpret_cast<unsigned *> (&imageData[i]) = 0;
{
*reinterpret_cast<unsigned *>(&imageData[i]) = 0;
}
else
*reinterpret_cast<unsigned *> (&imageData[i]) = 0xFFFFFFFF;
{
*reinterpret_cast<unsigned *>(&imageData[i]) = 0xFFFFFFFF;
}
}
}
red->RasterIO(GF_Read,x_off,y_off,width,height,image.getBytes() + 0,
image.width(),image.height(),GDT_Byte,4,4*image.width());
green->RasterIO(GF_Read,x_off,y_off,width,height,image.getBytes() + 1,
image.width(),image.height(),GDT_Byte,4,4*image.width());
blue->RasterIO(GF_Read,x_off,y_off,width,height,image.getBytes() + 2,
image.width(),image.height(),GDT_Byte,4,4*image.width());
red->RasterIO(GF_Read, x_off, y_off, width, height, image.getBytes() + 0,
image.width(), image.height(), GDT_Byte, 4, 4 * image.width());
green->RasterIO(GF_Read, x_off, y_off, width, height, image.getBytes() + 1,
image.width(), image.height(), GDT_Byte, 4, 4 * image.width());
blue->RasterIO(GF_Read, x_off, y_off, width, height, image.getBytes() + 2,
image.width(), image.height(), GDT_Byte, 4, 4 * image.width());
}
else if (grey)
{
@ -338,36 +376,40 @@ feature_ptr gdal_featureset::get_feature(mapnik::query const& q)
#endif
int hasNoData;
float nodata = grey->GetNoDataValue(&hasNoData);
GDALColorTable *color_table = grey->GetColorTable();
GDALColorTable* color_table = grey->GetColorTable();
if (hasNoData && !color_table)
if (hasNoData && ! color_table)
{
#ifdef MAPNIK_DEBUG
std::clog << "\tno data value for layer: " << nodata << std::endl;
#endif
// first read the data in and create an alpha channel from the nodata values
float *imageData = (float*)image.getBytes();
float* imageData = (float*)image.getBytes();
grey->RasterIO(GF_Read, x_off, y_off, width, height,
imageData, image.width(), image.height(),
GDT_Float32, 0, 0);
imageData, image.width(), image.height(),
GDT_Float32, 0, 0);
int len = image.width() * image.height();
for (int i=0; i<len; ++i)
for (int i = 0; i < len; ++i)
{
if (nodata == imageData[i])
*reinterpret_cast<unsigned *> (&imageData[i]) = 0;
{
*reinterpret_cast<unsigned *>(&imageData[i]) = 0;
}
else
{
*reinterpret_cast<unsigned *> (&imageData[i]) = 0xFFFFFFFF;
}
}
}
grey->RasterIO(GF_Read,x_off,y_off,width,height,image.getBytes() + 0,
image.width(),image.height(),GDT_Byte, 4, 4 * image.width());
grey->RasterIO(GF_Read,x_off,y_off,width,height,image.getBytes() + 1,
image.width(),image.height(),GDT_Byte, 4, 4 * image.width());
grey->RasterIO(GF_Read,x_off,y_off,width,height,image.getBytes() + 2,
image.width(),image.height(),GDT_Byte, 4, 4 * image.width());
grey->RasterIO(GF_Read, x_off, y_off, width, height, image.getBytes() + 0,
image.width(), image.height(), GDT_Byte, 4, 4 * image.width());
grey->RasterIO(GF_Read,x_off, y_off, width, height, image.getBytes() + 1,
image.width(), image.height(), GDT_Byte, 4, 4 * image.width());
grey->RasterIO(GF_Read,x_off, y_off, width, height, image.getBytes() + 2,
image.width(), image.height(), GDT_Byte, 4, 4 * image.width());
if (color_table)
{
@ -380,8 +422,9 @@ feature_ptr gdal_featureset::get_feature(mapnik::query const& q)
for (unsigned x = 0; x < image.width(); ++x)
{
unsigned value = row[x] & 0xff;
const GDALColorEntry *ce = color_table->GetColorEntry ( value );
if (ce ){
const GDALColorEntry *ce = color_table->GetColorEntry(value);
if (ce )
{
// TODO - big endian support
row[x] = (ce->c4 << 24)| (ce->c3 << 16) | (ce->c2 << 8) | (ce->c1) ;
}
@ -395,11 +438,11 @@ feature_ptr gdal_featureset::get_feature(mapnik::query const& q)
#ifdef MAPNIK_DEBUG
std::clog << "GDAL Plugin: processing alpha band..." << std::endl;
#endif
alpha->RasterIO(GF_Read,x_off,y_off,width,height,image.getBytes() + 3,
image.width(),image.height(),GDT_Byte,4,4*image.width());
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(mapnik::raster_ptr(new mapnik::raster(intersect,image)));
feature->set_raster(mapnik::raster_ptr(new mapnik::raster(intersect, image)));
}
return feature;
}
@ -418,7 +461,7 @@ feature_ptr gdal_featureset::get_feature_at_point(mapnik::coord2d const& pt)
double gt[6];
dataset_.GetGeoTransform(gt);
double det = gt[1]*gt[5] - gt[2]*gt[4];
double det = gt[1] * gt[5] - gt[2] * gt[4];
// subtract half a pixel width & height because gdal coord reference
// is the top-left corner of a pixel, not the center.
double X = pt.x - gt[0] - gt[1]/2;
@ -433,7 +476,7 @@ feature_ptr gdal_featureset::get_feature_at_point(mapnik::coord2d const& pt)
std::clog << boost::format("GDAL Plugin: pt.x=%f pt.y=%f") % pt.x % pt.y << std::endl;
std::clog << boost::format("GDAL Plugin: x=%f y=%f") % x % y << std::endl;
#endif
GDALRasterBand * band = dataset_.GetRasterBand(band_);
GDALRasterBand* band = dataset_.GetRasterBand(band_);
int hasNoData;
double nodata = band->GetNoDataValue(&hasNoData);
double value;
@ -455,7 +498,7 @@ feature_ptr gdal_featureset::get_feature_at_point(mapnik::coord2d const& pt)
}
#ifdef MAPNIK_DEBUG
void gdal_featureset::get_overview_meta(GDALRasterBand * band)
void gdal_featureset::get_overview_meta(GDALRasterBand* band)
{
int band_overviews = band->GetOverviewCount();
if (band_overviews > 0)
@ -464,7 +507,7 @@ void gdal_featureset::get_overview_meta(GDALRasterBand * band)
for (int b = 0; b < band_overviews; b++)
{
GDALRasterBand * overview = band->GetOverview (b);
GDALRasterBand * overview = band->GetOverview(b);
std::clog << boost::format("GDAL Plugin: Overview=%d Width=%d Height=%d")
% b % overview->GetXSize() % overview->GetYSize() << std::endl;
}
@ -476,7 +519,7 @@ void gdal_featureset::get_overview_meta(GDALRasterBand * band)
int bsx,bsy;
double scale;
band->GetBlockSize(&bsx,&bsy);
band->GetBlockSize(&bsx, &bsy);
scale = band->GetScale();
std::clog << boost::format("GDAL Plugin: Block=%dx%d Scale=%f Type=%s Color=%s") % bsx % bsy % scale
@ -484,4 +527,3 @@ void gdal_featureset::get_overview_meta(GDALRasterBand * band)
% GDALGetColorInterpretationName(band->GetColorInterpretation()) << std::endl;
}
#endif

View file

@ -2,7 +2,7 @@
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2007 Artem Pavlenko
* Copyright (C) 2011 Artem Pavlenko
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@ -33,33 +33,40 @@
class GDALDataset;
class GDALRasterBand;
typedef boost::variant<mapnik::query,mapnik::coord2d> gdal_query;
typedef boost::variant<mapnik::query, mapnik::coord2d> gdal_query;
class gdal_featureset : public mapnik::Featureset
{
public:
gdal_featureset(GDALDataset & dataset, int band, gdal_query q,
mapnik::box2d<double> extent, double width, double height, int nbands,
double dx, double dy, double filter_factor);
virtual ~gdal_featureset();
mapnik::feature_ptr next();
private:
mapnik::feature_ptr get_feature(mapnik::query const& q);
mapnik::feature_ptr get_feature_at_point(mapnik::coord2d const& p);
public:
gdal_featureset(GDALDataset& dataset,
int band,
gdal_query q,
mapnik::box2d<double> extent,
double width,
double height,
int nbands,
double dx,
double dy,
double filter_factor);
virtual ~gdal_featureset();
mapnik::feature_ptr next();
private:
mapnik::feature_ptr get_feature(mapnik::query const& q);
mapnik::feature_ptr get_feature_at_point(mapnik::coord2d const& p);
#ifdef MAPNIK_DEBUG
void get_overview_meta(GDALRasterBand * band);
void get_overview_meta(GDALRasterBand * band);
#endif
GDALDataset & dataset_;
int band_;
gdal_query gquery_;
mapnik::box2d<double> raster_extent_;
unsigned raster_width_;
unsigned raster_height_;
double dx_;
double dy_;
int nbands_;
double filter_factor_;
bool first_;
GDALDataset & dataset_;
int band_;
gdal_query gquery_;
mapnik::box2d<double> raster_extent_;
unsigned raster_width_;
unsigned raster_height_;
double dx_;
double dy_;
int nbands_;
double filter_factor_;
bool first_;
};
#endif // GDAL_FEATURESET_HPP

View file

@ -2,7 +2,7 @@
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2007 Artem Pavlenko
* Copyright (C) 2011 Artem Pavlenko
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@ -22,15 +22,15 @@
// $Id$
// network
#include <netdb.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
// mapnik
#include <mapnik/ptree_helpers.hpp>
@ -72,26 +72,42 @@ std::list<kismet_network_data> knd_list;
const unsigned int queue_size = 20;
kismet_datasource::kismet_datasource(parameters const& params, bool bind)
: datasource(params),
extent_(),
extent_initialized_(false),
type_(datasource::Vector),
desc_(*params.get<std::string>("type"), *params.get<std::string>("encoding","utf-8"))
: datasource(params),
extent_(),
extent_initialized_(false),
type_(datasource::Vector),
srs_("+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs"),
desc_(*params.get<std::string>("type"), *params.get<std::string>("encoding","utf-8"))
{
boost::optional<std::string> host = params_.get<std::string>("host");
if (host) {
if (host)
{
host_ = *host;
} else {
}
else
{
throw datasource_exception("Kismet Plugin: missing <host> parameter");
}
boost::optional<unsigned int> port = params_.get<unsigned int>("port", 2501);
if (port) port_ = *port;
if (port)
{
port_ = *port;
}
boost::optional<std::string> srs = params_.get<std::string>("srs");
if (srs)
{
srs_ = *srs;
}
boost::optional<std::string> ext = params_.get<std::string>("extent");
if (ext) extent_initialized_ = extent_.from_string(*ext);
if (ext)
{
extent_initialized_ = extent_.from_string(*ext);
}
kismet_thread.reset (new boost::thread (boost::bind (&kismet_datasource::run, this, host_, port_)));
kismet_thread.reset(new boost::thread(boost::bind(&kismet_datasource::run, this, host_, port_)));
if (bind)
{
@ -122,7 +138,7 @@ int kismet_datasource::type() const
box2d<double> kismet_datasource::envelope() const
{
if (!is_bound_) bind();
if (! is_bound_) bind();
return extent_;
}
@ -133,15 +149,17 @@ layer_descriptor kismet_datasource::get_descriptor() const
featureset_ptr kismet_datasource::features(query const& q) const
{
if (!is_bound_) bind();
if (! is_bound_) bind();
//cout << "kismet_datasource::features()" << endl;
// std::clog << "kismet_datasource::features()" << endl;
// TODO: use box2d to filter bbox before adding to featureset_ptr
//mapnik::box2d<double> const& e = q.get_bbox();
// mapnik::box2d<double> const& e = q.get_bbox();
boost::mutex::scoped_lock lock(knd_list_mutex);
return boost::make_shared<kismet_featureset>(knd_list, desc_.get_encoding());
return boost::make_shared<kismet_featureset>(knd_list,
srs_,
desc_.get_encoding());
// TODO: if illegal:
// return featureset_ptr();
@ -149,14 +167,14 @@ featureset_ptr kismet_datasource::features(query const& q) const
featureset_ptr kismet_datasource::features_at_point(coord2d const& pt) const
{
if (!is_bound_) bind();
if (! is_bound_) bind();
//cout << "kismet_datasource::features_at_point()" << endl;
// std::clog << "kismet_datasource::features_at_point()" << endl;
return featureset_ptr();
}
void kismet_datasource::run (const std::string &ip_host, const unsigned int port)
void kismet_datasource::run(const std::string& ip_host, const unsigned int port)
{
#ifdef MAPNIK_DEBUG
std::clog << "Kismet Plugin: enter run" << std::endl;
@ -169,18 +187,18 @@ void kismet_datasource::run (const std::string &ip_host, const unsigned int port
char buffer[MAX_TCP_BUFFER]; // TCP data send from kismet_server
std::string command;
if (inet_aton(ip_host.c_str (), &inadr))
if (inet_aton(ip_host.c_str(), &inadr))
{
host = gethostbyaddr((char *) &inadr, sizeof(inadr), AF_INET);
host = gethostbyaddr((char*)&inadr, sizeof(inadr), AF_INET);
}
else
{
host = gethostbyname(ip_host.c_str ());
host = gethostbyname(ip_host.c_str());
}
if (host == NULL)
{
herror ("Kismet Plugin: Error while searching host");
std::cerr << "Kismet Plugin: error while searching host" << std::endl;
return;
}
@ -188,13 +206,13 @@ void kismet_datasource::run (const std::string &ip_host, const unsigned int port
sock_addr.sin_port = htons(port);
memcpy(&sock_addr.sin_addr, host->h_addr_list[0], sizeof(sock_addr.sin_addr));
if ( (sockfd = socket(PF_INET, SOCK_STREAM, 0)) < 0)
if ((sockfd = socket(PF_INET, SOCK_STREAM, 0)) < 0)
{
std::cerr << "Kismet Plugin: error while creating socket" << std::endl;
return;
}
if (connect(sockfd, (struct sockaddr *) &sock_addr, sizeof(sock_addr)))
if (connect(sockfd, (struct sockaddr*) &sock_addr, sizeof(sock_addr)))
{
std::cerr << "KISMET Plugin: Error while connecting" << std::endl;
return;
@ -202,9 +220,10 @@ void kismet_datasource::run (const std::string &ip_host, const unsigned int port
command = "!1 ENABLE NETWORK ssid,bssid,wep,bestlat,bestlon\n";
if (write(sockfd, command.c_str (), command.length ()) != (signed) command.length ())
if (write(sockfd, command.c_str(), command.length()) != (signed)command.length())
{
std::cerr << "KISMET Plugin: Error sending command to " << ip_host << std::endl;
close(sockfd);
return;
}
@ -219,10 +238,10 @@ void kismet_datasource::run (const std::string &ip_host, const unsigned int port
// assert is called. Needs to be analyzed!
while ((n = read(sockfd, buffer, sizeof(buffer))) > 0)
{
assert (n < MAX_TCP_BUFFER);
assert(n < MAX_TCP_BUFFER);
buffer[n] = '\0';
std::string bufferObj (buffer); // TCP data send from kismet_server as STL string
std::string bufferObj(buffer); // TCP data send from kismet_server as STL string
#ifdef MAPNIK_DEBUG
std::clog << "Kismet Plugin: buffer_obj=" << bufferObj << "[END]" << std::endl;
@ -233,10 +252,10 @@ void kismet_datasource::run (const std::string &ip_host, const unsigned int port
std::string kismet_line; // contains a line from kismet_server
do
{
found = bufferObj.find ('\n', search_start);
found = bufferObj.find('\n', search_start);
if (found != std::string::npos)
{
kismet_line.assign (bufferObj, search_start, found - search_start);
kismet_line.assign(bufferObj, search_start, found - search_start);
#ifdef MAPNIK_DEBUG
std::clog << "Kismet Plugin: line=" << kismet_line << " [ENDL]" << std::endl;
@ -245,7 +264,7 @@ void kismet_datasource::run (const std::string &ip_host, const unsigned int port
int param_number = 5; // the number of parameters to parse
// Attention: string length specified to the constant!
if (sscanf (kismet_line.c_str (),
if (sscanf (kismet_line.c_str(),
KISMET_COMMAND,
ssid,
bssid,
@ -255,20 +274,20 @@ void kismet_datasource::run (const std::string &ip_host, const unsigned int port
{
#ifdef MAPNIK_DEBUG
std::clog << "Kismet Plugin: ssid=" << ssid << ", bssid=" << bssid
<< ", crypt=" << crypt << ", bestlat=" << bestlat << ", bestlon=" << bestlon << std::endl;
<< ", crypt=" << crypt << ", bestlat=" << bestlat << ", bestlon=" << bestlon << std::endl;
#endif
kismet_network_data knd (ssid, bssid, bestlat, bestlon, crypt);
kismet_network_data knd(ssid, bssid, bestlat, bestlon, crypt);
boost::mutex::scoped_lock lock(knd_list_mutex);
// the queue only grows to a max size
if (knd_list.size () >= queue_size)
{
knd_list.pop_front ();
knd_list.pop_front();
}
knd_list.push_back (knd);
knd_list.push_back(knd);
}
else
{

View file

@ -2,7 +2,7 @@
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2007 Artem Pavlenko
* Copyright (C) 2011 Artem Pavlenko
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@ -43,27 +43,28 @@
class kismet_datasource : public mapnik::datasource
{
public:
kismet_datasource(mapnik::parameters const& params, bool bind=true);
virtual ~kismet_datasource ();
int type() const;
static std::string name();
mapnik::featureset_ptr features(mapnik::query const& q) const;
mapnik::featureset_ptr features_at_point(mapnik::coord2d const& pt) const;
mapnik::box2d<double> envelope() const;
mapnik::layer_descriptor get_descriptor() const;
void bind() const;
private:
void run (const std::string &host, const unsigned int port);
public:
kismet_datasource(mapnik::parameters const& params, bool bind = true);
virtual ~kismet_datasource ();
int type() const;
static std::string name();
mapnik::featureset_ptr features(mapnik::query const& q) const;
mapnik::featureset_ptr features_at_point(mapnik::coord2d const& pt) const;
mapnik::box2d<double> envelope() const;
mapnik::layer_descriptor get_descriptor() const;
void bind() const;
mapnik::box2d<double> extent_;
bool extent_initialized_;
std::string host_;
unsigned int port_;
int type_;
mapnik::layer_descriptor desc_;
boost::shared_ptr<boost::thread> kismet_thread;
private:
void run (const std::string& host, const unsigned int port);
mapnik::box2d<double> extent_;
bool extent_initialized_;
std::string host_;
unsigned int port_;
int type_;
std::string srs_;
mapnik::layer_descriptor desc_;
boost::shared_ptr<boost::thread> kismet_thread;
};
#endif // KISMET_DATASOURCE_HPP

View file

@ -2,7 +2,7 @@
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2007 Artem Pavlenko
* Copyright (C) 2011 Artem Pavlenko
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@ -41,13 +41,14 @@ using mapnik::geometry_utils;
using mapnik::transcoder;
using mapnik::feature_factory;
kismet_featureset::kismet_featureset(const std::list<kismet_network_data> &knd_list,
kismet_featureset::kismet_featureset(const std::list<kismet_network_data>& knd_list,
std::string const& srs,
std::string const& encoding)
: knd_list_(knd_list),
tr_(new transcoder(encoding)),
feature_id_(1),
knd_list_it(knd_list_.begin ()),
source_("+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs")
knd_list_it(knd_list_.begin()),
source_(srs)
{
}
@ -63,11 +64,11 @@ feature_ptr kismet_featureset::next()
const std::string key = "internet_access";
std::string value;
if (knd.crypt_ == crypt_none)
if (knd.crypt() == crypt_none)
{
value = "wlan_uncrypted";
}
else if (knd.crypt_ == crypt_wep)
else if (knd.crypt() == crypt_wep)
{
value = "wlan_wep";
}
@ -80,7 +81,7 @@ feature_ptr kismet_featureset::next()
++feature_id_;
geometry_type* pt = new geometry_type(mapnik::Point);
pt->move_to(knd.bestlon_, knd.bestlat_);
pt->move_to(knd.bestlon(), knd.bestlat());
feature->add_geometry(pt);
boost::put(*feature, key, tr_->transcode(value.c_str()));
@ -92,4 +93,3 @@ feature_ptr kismet_featureset::next()
return feature_ptr();
}

View file

@ -2,7 +2,7 @@
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2007 Artem Pavlenko
* Copyright (C) 2011 Artem Pavlenko
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@ -40,20 +40,21 @@
class kismet_featureset : public mapnik::Featureset
{
public:
kismet_featureset(const std::list<kismet_network_data> &knd_list,
std::string const& encoding);
virtual ~kismet_featureset();
mapnik::feature_ptr next();
private:
const std::list<kismet_network_data> &knd_list_;
boost::scoped_ptr<mapnik::transcoder> tr_;
mapnik::wkbFormat format_;
bool multiple_geometries_;
int feature_id_;
std::list<kismet_network_data>::const_iterator knd_list_it;
mapnik::projection source_;
public:
kismet_featureset(const std::list<kismet_network_data>& knd_list,
std::string const& srs,
std::string const& encoding);
virtual ~kismet_featureset();
mapnik::feature_ptr next();
private:
const std::list<kismet_network_data>& knd_list_;
boost::scoped_ptr<mapnik::transcoder> tr_;
mapnik::wkbFormat format_;
bool multiple_geometries_;
int feature_id_;
std::list<kismet_network_data>::const_iterator knd_list_it;
mapnik::projection source_;
};
#endif // KISMET_FEATURESET_HPP

View file

@ -2,7 +2,7 @@
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2007 Artem Pavlenko
* Copyright (C) 2011 Artem Pavlenko
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@ -57,21 +57,56 @@ enum crypt_type
class kismet_network_data
{
public:
kismet_network_data() : bestlat_(0), bestlon_(0), crypt_ (crypt_none) {}
kismet_network_data(std::string ssid, std::string bssid,
double bestlat, double bestlon, int crypt) :
ssid_(ssid), bssid_(bssid),
bestlat_(bestlat), bestlon_(bestlon),
crypt_ (crypt)
{}
std::string ssid_;
std::string bssid_;
double bestlat_;
double bestlon_;
int crypt_;
public:
kismet_network_data()
: bestlat_(0), bestlon_(0), crypt_(crypt_none)
{
}
kismet_network_data(std::string ssid,
std::string bssid,
double bestlat,
double bestlon,
int crypt)
: ssid_(ssid),
bssid_(bssid),
bestlat_(bestlat),
bestlon_(bestlon),
crypt_(crypt)
{
}
const std::string& ssid() const
{
return ssid_;
}
const std::string& bssid() const
{
return bssid_;
}
double bestlat() const
{
return bestlat_;
}
double bestlon() const
{
return bestlon_;
}
int crypt() const
{
return crypt_;
}
protected:
std::string ssid_;
std::string bssid_;
double bestlat_;
double bestlon_;
int crypt_;
};
#endif //KISMET_TYPES_HPP
#endif // KISMET_TYPES_HPP

View file

@ -2,7 +2,7 @@
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2007 Artem Pavlenko
* Copyright (C) 2011 Artem Pavlenko
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@ -63,30 +63,29 @@ using oracle::occi::SQLException;
using oracle::occi::Type;
using oracle::occi::StatelessConnectionPool;
const std::string occi_datasource::METADATA_TABLE="USER_SDO_GEOM_METADATA";
const std::string occi_datasource::METADATA_TABLE = "USER_SDO_GEOM_METADATA";
DATASOURCE_PLUGIN(occi_datasource)
occi_datasource::occi_datasource(parameters const& params, bool bind)
: datasource (params),
type_(datasource::Vector),
fields_(*params_.get<std::string>("fields","*")),
geometry_field_(*params_.get<std::string>("geometry_field","")),
srid_initialized_(false),
extent_initialized_(false),
desc_(*params_.get<std::string>("type"), *params_.get<std::string>("encoding","utf-8")),
row_limit_(*params_.get<int>("row_limit",0)),
row_prefetch_(*params_.get<int>("row_prefetch",100)),
pool_(0),
conn_(0)
: datasource (params),
type_(datasource::Vector),
fields_(*params_.get<std::string>("fields", "*")),
geometry_field_(*params_.get<std::string>("geometry_field", "")),
srid_initialized_(false),
extent_initialized_(false),
desc_(*params_.get<std::string>("type"), *params_.get<std::string>("encoding", "utf-8")),
row_limit_(*params_.get<int>("row_limit", 0)),
row_prefetch_(*params_.get<int>("row_prefetch", 100)),
pool_(0),
conn_(0)
{
if (! params_.get<std::string>("user")) throw datasource_exception("OCCI Plugin: no <user> specified");
if (! params_.get<std::string>("password")) throw datasource_exception("OCCI Plugin: no <password> specified");
if (! params_.get<std::string>("host")) throw datasource_exception("OCCI Plugin: no <host> string specified");
boost::optional<std::string> table = params_.get<std::string>("table");
if (!table)
if (! table)
{
throw datasource_exception("OCCI Plugin: no <table> parameter specified");
}
@ -124,12 +123,16 @@ occi_datasource::~occi_datasource()
if (use_connection_pool_)
{
if (pool_ != 0)
env->terminateStatelessConnectionPool (pool_, StatelessConnectionPool::SPD_FORCE);
{
env->terminateStatelessConnectionPool(pool_, StatelessConnectionPool::SPD_FORCE);
}
}
else
{
if (conn_ != 0)
{
env->terminateConnection(conn_);
}
}
}
}
@ -149,12 +152,12 @@ void occi_datasource::bind() const
*params_.get<std::string>("user"),
*params_.get<std::string>("password"),
*params_.get<std::string>("host"),
*params_.get<int>("max_size",10),
*params_.get<int>("initial_size",1),
*params_.get<int>("max_size", 10),
*params_.get<int>("initial_size", 1),
1,
StatelessConnectionPool::HOMOGENEOUS);
}
catch (SQLException &ex)
catch (SQLException& ex)
{
throw datasource_exception("OCCI Plugin: " + ex.getMessage());
}
@ -170,7 +173,7 @@ void occi_datasource::bind() const
*params_.get<std::string>("password"),
*params_.get<std::string>("host"));
}
catch (SQLException &ex)
catch (SQLException& ex)
{
throw datasource_exception("OCCI Plugin: " + ex.getMessage());
}
@ -186,7 +189,9 @@ void occi_datasource::bind() const
s << " LOWER(table_name) = LOWER('" << table_name << "')";
if (geometry_field_ != "")
{
s << " AND LOWER(column_name) = LOWER('" << geometry_field_ << "')";
}
#ifdef MAPNIK_DEBUG
std::clog << "OCCI Plugin: " << s.str() << std::endl;
@ -198,7 +203,7 @@ void occi_datasource::bind() const
if (use_connection_pool_) conn.set_pool(pool_);
else conn.set_connection(conn_, false);
ResultSet* rs = conn.execute_query (s.str());
ResultSet* rs = conn.execute_query(s.str());
if (rs && rs->next ())
{
if (! srid_initialized_)
@ -213,7 +218,7 @@ void occi_datasource::bind() const
}
}
}
catch (SQLException &ex)
catch (SQLException& ex)
{
throw datasource_exception("OCCI Plugin: " + ex.getMessage());
}
@ -234,7 +239,7 @@ void occi_datasource::bind() const
if (use_connection_pool_) conn.set_pool(pool_);
else conn.set_connection(conn_, false);
ResultSet* rs = conn.execute_query (s.str());
ResultSet* rs = conn.execute_query(s.str());
if (rs)
{
std::vector<MetaData> listOfColumns = rs->getColumnListMetaData();
@ -317,20 +322,22 @@ void occi_datasource::bind() const
case oracle::occi::OCCI_SQLT_BLOB:
case oracle::occi::OCCI_SQLT_RSET:
#ifdef MAPNIK_DEBUG
std::clog << "OCCI Plugin: unsupported datatype " << occi_enums::resolve_datatype(type_oid)
<< " (type_oid=" << type_oid << ")" << std::endl;
std::clog << "OCCI Plugin: unsupported datatype "
<< occi_enums::resolve_datatype(type_oid)
<< " (type_oid=" << type_oid << ")" << std::endl;
#endif
break;
default:
#ifdef MAPNIK_DEBUG
std::clog << "OCCI Plugin: unknown datatype (type_oid=" << type_oid << ")" << std::endl;
std::clog << "OCCI Plugin: unknown datatype "
<< "(type_oid=" << type_oid << ")" << std::endl;
#endif
break;
}
}
}
}
catch (SQLException &ex)
catch (SQLException& ex)
{
throw datasource_exception(ex.getMessage());
}
@ -352,11 +359,12 @@ int occi_datasource::type() const
box2d<double> occi_datasource::envelope() const
{
if (extent_initialized_) return extent_;
if (!is_bound_) bind();
if (! is_bound_) bind();
double lox = 0.0, loy = 0.0, hix = 0.0, hiy = 0.0;
boost::optional<mapnik::boolean> estimate_extent = params_.get<mapnik::boolean>("estimate_extent",false);
boost::optional<mapnik::boolean> estimate_extent =
params_.get<mapnik::boolean>("estimate_extent",false);
if (estimate_extent && *estimate_extent)
{
@ -375,8 +383,8 @@ box2d<double> occi_datasource::envelope() const
if (use_connection_pool_) conn.set_pool(pool_);
else conn.set_connection(conn_, false);
ResultSet* rs = conn.execute_query (s.str());
if (rs && rs->next ())
ResultSet* rs = conn.execute_query(s.str());
if (rs && rs->next())
{
try
{
@ -384,16 +392,16 @@ box2d<double> occi_datasource::envelope() const
loy = lexical_cast<double>(rs->getDouble(2));
hix = lexical_cast<double>(rs->getDouble(3));
hiy = lexical_cast<double>(rs->getDouble(4));
extent_.init (lox,loy,hix,hiy);
extent_.init(lox, loy, hix, hiy);
extent_initialized_ = true;
}
catch (bad_lexical_cast &ex)
catch (bad_lexical_cast& ex)
{
std::clog << "OCCI Plugin: " << ex.what() << std::endl;
}
}
}
catch (SQLException &ex)
catch (SQLException& ex)
{
throw datasource_exception("OCCI Plugin: " + ex.getMessage());
}
@ -421,63 +429,65 @@ box2d<double> occi_datasource::envelope() const
if (use_connection_pool_) conn.set_pool(pool_);
else conn.set_connection(conn_, false);
ResultSet* rs = conn.execute_query (s.str());
ResultSet* rs = conn.execute_query(s.str());
if (rs)
{
if (rs->next ())
if (rs->next())
{
try
{
lox = lexical_cast<double>(rs->getDouble(1));
hix = lexical_cast<double>(rs->getDouble(2));
}
catch (bad_lexical_cast &ex)
catch (bad_lexical_cast& ex)
{
std::clog << "OCCI Plugin: " << ex.what() << std::endl;
}
}
if (rs->next ())
if (rs->next())
{
try
{
loy = lexical_cast<double>(rs->getDouble(1));
hiy = lexical_cast<double>(rs->getDouble(2));
}
catch (bad_lexical_cast &ex)
catch (bad_lexical_cast& ex)
{
std::clog << "OCCI Plugin: " << ex.what() << std::endl;
}
}
extent_.init (lox,loy,hix,hiy);
extent_.init(lox, loy, hix, hiy);
extent_initialized_ = true;
}
}
catch (SQLException &ex)
catch (SQLException& ex)
{
throw datasource_exception("OCCI Plugin: " + ex.getMessage());
}
}
if (! extent_initialized_)
{
throw datasource_exception("OCCI Plugin: unable to determine the extent of a <occi> table");
}
return extent_;
}
layer_descriptor occi_datasource::get_descriptor() const
{
if (!is_bound_) bind();
if (! is_bound_) bind();
return desc_;
}
featureset_ptr occi_datasource::features(query const& q) const
{
if (!is_bound_) bind();
if (! is_bound_) bind();
box2d<double> const& box=q.get_bbox();
box2d<double> const& box = q.get_bbox();
std::ostringstream s;
s << "SELECT " << geometry_field_;
@ -492,7 +502,7 @@ featureset_ptr occi_datasource::features(query const& q) const
s << " FROM ";
std::string query (table_);
std::string query(table_);
std::string table_name = mapnik::table_from_sql(query);
if (use_spatial_index_)
@ -549,24 +559,24 @@ featureset_ptr occi_datasource::features(query const& q) const
#endif
return boost::make_shared<occi_featureset>(pool_,
conn_,
s.str(),
desc_.get_encoding(),
multiple_geometries_,
use_connection_pool_,
row_prefetch_,
props.size());
conn_,
s.str(),
desc_.get_encoding(),
multiple_geometries_,
use_connection_pool_,
row_prefetch_,
props.size());
}
featureset_ptr occi_datasource::features_at_point(coord2d const& pt) const
{
if (!is_bound_) bind();
if (! is_bound_) bind();
std::ostringstream s;
s << "SELECT " << geometry_field_;
std::vector<attribute_descriptor>::const_iterator itr = desc_.get_descriptors().begin();
std::vector<attribute_descriptor>::const_iterator end = desc_.get_descriptors().end();
unsigned size=0;
unsigned size = 0;
while (itr != end)
{
s << ", " << itr->get_name();
@ -576,7 +586,7 @@ featureset_ptr occi_datasource::features_at_point(coord2d const& pt) const
s << " FROM ";
std::string query (table_);
std::string query(table_);
std::string table_name = mapnik::table_from_sql(query);
if (use_spatial_index_)
@ -593,7 +603,7 @@ featureset_ptr occi_datasource::features_at_point(coord2d const& pt) const
{
boost::algorithm::ireplace_first(query, "WHERE", spatial_sql.str() + " AND ");
}
else if (boost::algorithm::ifind_first(query,table_name))
else if (boost::algorithm::ifind_first(query, table_name))
{
boost::algorithm::ireplace_first(query, table_name, table_name + " " + spatial_sql.str());
}
@ -632,12 +642,11 @@ featureset_ptr occi_datasource::features_at_point(coord2d const& pt) const
#endif
return boost::make_shared<occi_featureset>(pool_,
conn_,
s.str(),
desc_.get_encoding(),
multiple_geometries_,
use_connection_pool_,
row_prefetch_,
size);
conn_,
s.str(),
desc_.get_encoding(),
multiple_geometries_,
use_connection_pool_,
row_prefetch_,
size);
}

View file

@ -2,7 +2,7 @@
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2007 Artem Pavlenko
* Copyright (C) 2011 Artem Pavlenko
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@ -38,35 +38,35 @@
class occi_datasource : public mapnik::datasource
{
public:
occi_datasource(mapnik::parameters const& params, bool bind=true);
virtual ~occi_datasource ();
int type() const;
static std::string name();
mapnik::featureset_ptr features(mapnik::query const& q) const;
mapnik::featureset_ptr features_at_point(mapnik::coord2d const& pt) const;
mapnik::box2d<double> envelope() const;
mapnik::layer_descriptor get_descriptor() const;
void bind() const;
private:
int type_;
mutable std::string table_;
mutable std::string fields_;
mutable std::string geometry_field_;
mutable int srid_;
mutable bool srid_initialized_;
mutable bool extent_initialized_;
mutable mapnik::box2d<double> extent_;
mutable mapnik::layer_descriptor desc_;
int row_limit_;
int row_prefetch_;
mutable oracle::occi::StatelessConnectionPool* pool_;
mutable oracle::occi::Connection* conn_;
bool use_connection_pool_;
bool multiple_geometries_;
bool use_spatial_index_;
static const std::string METADATA_TABLE;
public:
occi_datasource(mapnik::parameters const& params, bool bind = true);
virtual ~occi_datasource ();
int type() const;
static std::string name();
mapnik::featureset_ptr features(mapnik::query const& q) const;
mapnik::featureset_ptr features_at_point(mapnik::coord2d const& pt) const;
mapnik::box2d<double> envelope() const;
mapnik::layer_descriptor get_descriptor() const;
void bind() const;
private:
int type_;
mutable std::string table_;
mutable std::string fields_;
mutable std::string geometry_field_;
mutable int srid_;
mutable bool srid_initialized_;
mutable bool extent_initialized_;
mutable mapnik::box2d<double> extent_;
mutable mapnik::layer_descriptor desc_;
int row_limit_;
int row_prefetch_;
mutable oracle::occi::StatelessConnectionPool* pool_;
mutable oracle::occi::Connection* conn_;
bool use_connection_pool_;
bool multiple_geometries_;
bool use_spatial_index_;
static const std::string METADATA_TABLE;
};
#endif // OCCI_DATASOURCE_HPP

View file

@ -2,7 +2,7 @@
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2007 Artem Pavlenko
* Copyright (C) 2011 Artem Pavlenko
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@ -64,19 +64,23 @@ occi_featureset::occi_featureset(StatelessConnectionPool* pool,
bool use_connection_pool,
unsigned prefetch_rows,
unsigned num_attrs)
: tr_(new transcoder(encoding)),
multiple_geometries_(multiple_geometries),
num_attrs_(num_attrs),
feature_id_(1)
: tr_(new transcoder(encoding)),
multiple_geometries_(multiple_geometries),
num_attrs_(num_attrs),
feature_id_(1)
{
if (use_connection_pool)
{
conn_.set_pool(pool);
}
else
{
conn_.set_connection(conn, false);
}
try
{
rs_ = conn_.execute_query (sqlstring, prefetch_rows);
rs_ = conn_.execute_query(sqlstring, prefetch_rows);
}
catch (SQLException &ex)
{
@ -95,10 +99,10 @@ feature_ptr occi_featureset::next()
feature_ptr feature(feature_factory::create(feature_id_));
++feature_id_;
boost::scoped_ptr<SDOGeometry> geom (dynamic_cast<SDOGeometry*> (rs_->getObject(1)));
boost::scoped_ptr<SDOGeometry> geom(dynamic_cast<SDOGeometry*>(rs_->getObject(1)));
if (geom.get())
{
convert_geometry (geom.get(), feature, multiple_geometries_);
convert_geometry(geom.get(), feature, multiple_geometries_);
}
std::vector<MetaData> listOfColumns = rs_->getColumnListMetaData();
@ -120,75 +124,77 @@ feature_ptr occi_featureset::next()
switch (type_oid)
{
case oracle::occi::OCCIBOOL:
case oracle::occi::OCCIINT:
case oracle::occi::OCCIUNSIGNED_INT:
case oracle::occi::OCCIROWID:
boost::put(*feature,fld_name,rs_->getInt (i + 1));
break;
case oracle::occi::OCCIFLOAT:
case oracle::occi::OCCIBFLOAT:
case oracle::occi::OCCIDOUBLE:
case oracle::occi::OCCIBDOUBLE:
case oracle::occi::OCCINUMBER:
case oracle::occi::OCCI_SQLT_NUM:
boost::put(*feature,fld_name,rs_->getDouble (i + 1));
break;
case oracle::occi::OCCICHAR:
case oracle::occi::OCCISTRING:
case oracle::occi::OCCI_SQLT_AFC:
case oracle::occi::OCCI_SQLT_AVC:
case oracle::occi::OCCI_SQLT_CHR:
case oracle::occi::OCCI_SQLT_LVC:
case oracle::occi::OCCI_SQLT_RDD:
case oracle::occi::OCCI_SQLT_STR:
case oracle::occi::OCCI_SQLT_VCS:
case oracle::occi::OCCI_SQLT_VNU:
case oracle::occi::OCCI_SQLT_VBI:
case oracle::occi::OCCI_SQLT_VST:
boost::put(*feature,fld_name,(UnicodeString) tr_->transcode (rs_->getString (i + 1).c_str()));
break;
case oracle::occi::OCCIDATE:
case oracle::occi::OCCITIMESTAMP:
case oracle::occi::OCCIINTERVALDS:
case oracle::occi::OCCIINTERVALYM:
case oracle::occi::OCCI_SQLT_DAT:
case oracle::occi::OCCI_SQLT_DATE:
case oracle::occi::OCCI_SQLT_TIME:
case oracle::occi::OCCI_SQLT_TIME_TZ:
case oracle::occi::OCCI_SQLT_TIMESTAMP:
case oracle::occi::OCCI_SQLT_TIMESTAMP_LTZ:
case oracle::occi::OCCI_SQLT_TIMESTAMP_TZ:
case oracle::occi::OCCI_SQLT_INTERVAL_YM:
case oracle::occi::OCCI_SQLT_INTERVAL_DS:
case oracle::occi::OCCIANYDATA:
case oracle::occi::OCCIBLOB:
case oracle::occi::OCCIBFILE:
case oracle::occi::OCCIBYTES:
case oracle::occi::OCCICLOB:
case oracle::occi::OCCIVECTOR:
case oracle::occi::OCCIMETADATA:
case oracle::occi::OCCIPOBJECT:
case oracle::occi::OCCIREF:
case oracle::occi::OCCIREFANY:
case oracle::occi::OCCISTREAM:
case oracle::occi::OCCICURSOR:
case oracle::occi::OCCI_SQLT_FILE:
case oracle::occi::OCCI_SQLT_CFILE:
case oracle::occi::OCCI_SQLT_REF:
case oracle::occi::OCCI_SQLT_CLOB:
case oracle::occi::OCCI_SQLT_BLOB:
case oracle::occi::OCCI_SQLT_RSET:
case oracle::occi::OCCIBOOL:
case oracle::occi::OCCIINT:
case oracle::occi::OCCIUNSIGNED_INT:
case oracle::occi::OCCIROWID:
boost::put(*feature,fld_name,rs_->getInt (i + 1));
break;
case oracle::occi::OCCIFLOAT:
case oracle::occi::OCCIBFLOAT:
case oracle::occi::OCCIDOUBLE:
case oracle::occi::OCCIBDOUBLE:
case oracle::occi::OCCINUMBER:
case oracle::occi::OCCI_SQLT_NUM:
boost::put(*feature,fld_name,rs_->getDouble (i + 1));
break;
case oracle::occi::OCCICHAR:
case oracle::occi::OCCISTRING:
case oracle::occi::OCCI_SQLT_AFC:
case oracle::occi::OCCI_SQLT_AVC:
case oracle::occi::OCCI_SQLT_CHR:
case oracle::occi::OCCI_SQLT_LVC:
case oracle::occi::OCCI_SQLT_RDD:
case oracle::occi::OCCI_SQLT_STR:
case oracle::occi::OCCI_SQLT_VCS:
case oracle::occi::OCCI_SQLT_VNU:
case oracle::occi::OCCI_SQLT_VBI:
case oracle::occi::OCCI_SQLT_VST:
boost::put(*feature,fld_name,(UnicodeString) tr_->transcode (rs_->getString (i + 1).c_str()));
break;
case oracle::occi::OCCIDATE:
case oracle::occi::OCCITIMESTAMP:
case oracle::occi::OCCIINTERVALDS:
case oracle::occi::OCCIINTERVALYM:
case oracle::occi::OCCI_SQLT_DAT:
case oracle::occi::OCCI_SQLT_DATE:
case oracle::occi::OCCI_SQLT_TIME:
case oracle::occi::OCCI_SQLT_TIME_TZ:
case oracle::occi::OCCI_SQLT_TIMESTAMP:
case oracle::occi::OCCI_SQLT_TIMESTAMP_LTZ:
case oracle::occi::OCCI_SQLT_TIMESTAMP_TZ:
case oracle::occi::OCCI_SQLT_INTERVAL_YM:
case oracle::occi::OCCI_SQLT_INTERVAL_DS:
case oracle::occi::OCCIANYDATA:
case oracle::occi::OCCIBLOB:
case oracle::occi::OCCIBFILE:
case oracle::occi::OCCIBYTES:
case oracle::occi::OCCICLOB:
case oracle::occi::OCCIVECTOR:
case oracle::occi::OCCIMETADATA:
case oracle::occi::OCCIPOBJECT:
case oracle::occi::OCCIREF:
case oracle::occi::OCCIREFANY:
case oracle::occi::OCCISTREAM:
case oracle::occi::OCCICURSOR:
case oracle::occi::OCCI_SQLT_FILE:
case oracle::occi::OCCI_SQLT_CFILE:
case oracle::occi::OCCI_SQLT_REF:
case oracle::occi::OCCI_SQLT_CLOB:
case oracle::occi::OCCI_SQLT_BLOB:
case oracle::occi::OCCI_SQLT_RSET:
#ifdef MAPNIK_DEBUG
std::clog << "OCCI Plugin: unsupported datatype " << occi_enums::resolve_datatype(type_oid)
<< " (type_oid=" << type_oid << ")" << std::endl;
std::clog << "OCCI Plugin: unsupported datatype "
<< occi_enums::resolve_datatype(type_oid)
<< " (type_oid=" << type_oid << ")" << std::endl;
#endif
break;
default: // shouldn't get here
break;
default: // shouldn't get here
#ifdef MAPNIK_DEBUG
std::clog << "OCCI Plugin: unknown datatype (type_oid=" << type_oid << ")" << std::endl;
std::clog << "OCCI Plugin: unknown datatype "
<< "(type_oid=" << type_oid << ")" << std::endl;
#endif
break;
break;
}
}
@ -199,30 +205,30 @@ feature_ptr occi_featureset::next()
}
void occi_featureset::convert_geometry (SDOGeometry* geom, feature_ptr feature, bool multiple_geometries)
void occi_featureset::convert_geometry(SDOGeometry* geom, feature_ptr feature, bool multiple_geometries)
{
int gtype = (int) geom->getSdo_gtype();
int gtype = (int)geom->getSdo_gtype();
int dimensions = gtype / 1000;
int lrsvalue = (gtype - dimensions * 1000) / 100;
int geomtype = (gtype - dimensions * 1000 - lrsvalue * 100);
#if 0
clog << "-----------Geometry Object ------------" << endl;
clog << "SDO GTYPE = " << gtype << endl;
clog << "SDO DIMENSIONS = " << dimensions << endl;
clog << "SDO LRS = " << lrsvalue << endl;
clog << "SDO GEOMETRY TYPE = " << geomtype << endl;
std::clog << "-----------Geometry Object ------------" << std::endl;
std::clog << "SDO GTYPE = " << gtype << std::endl;
std::clog << "SDO DIMENSIONS = " << dimensions << std::endl;
std::clog << "SDO LRS = " << lrsvalue << std::endl;
std::clog << "SDO GEOMETRY TYPE = " << geomtype << std::endl;
Number sdo_srid = geom->getSdo_srid();
if (sdo_srid.isNull())
clog << "SDO SRID = " << "Null" << endl;
std::clog << "SDO SRID = " << "Null" << std::endl;
else
clog << "SDO SRID = " << (int) sdo_srid << endl;
std::clog << "SDO SRID = " << (int)sdo_srid << std::endl;
#endif
const std::vector<Number>& elem_info = geom->getSdo_elem_info();
const std::vector<Number>& ordinates = geom->getSdo_ordinates();
const int ordinates_size = (int) ordinates.size();
const int ordinates_size = (int)ordinates.size();
switch (geomtype)
{
@ -232,8 +238,8 @@ void occi_featureset::convert_geometry (SDOGeometry* geom, feature_ptr feature,
if (sdopoint && ! sdopoint->isNull())
{
geometry_type* point = new geometry_type(mapnik::Point);
point->move_to (sdopoint->getX(), sdopoint->getY());
feature->add_geometry (point);
point->move_to(sdopoint->getX(), sdopoint->getY());
feature->add_geometry(point);
}
}
break;
@ -245,14 +251,14 @@ void occi_featureset::convert_geometry (SDOGeometry* geom, feature_ptr feature,
const bool is_point_type = false;
const bool multiple_geoms = false;
convert_ordinates (feature,
mapnik::LineString,
elem_info,
ordinates,
dimensions,
is_single_geom,
is_point_type,
multiple_geoms);
convert_ordinates(feature,
mapnik::LineString,
elem_info,
ordinates,
dimensions,
is_single_geom,
is_point_type,
multiple_geoms);
}
}
break;
@ -264,14 +270,14 @@ void occi_featureset::convert_geometry (SDOGeometry* geom, feature_ptr feature,
const bool is_point_type = false;
const bool multiple_geoms = false;
convert_ordinates (feature,
mapnik::Polygon,
elem_info,
ordinates,
dimensions,
is_single_geom,
is_point_type,
multiple_geoms);
convert_ordinates(feature,
mapnik::Polygon,
elem_info,
ordinates,
dimensions,
is_single_geom,
is_point_type,
multiple_geoms);
}
}
break;
@ -286,14 +292,14 @@ void occi_featureset::convert_geometry (SDOGeometry* geom, feature_ptr feature,
// Todo - force using true as multiple_geometries until we have proper multipoint handling
// http://trac.mapnik.org/ticket/458
convert_ordinates (feature,
mapnik::Point,
elem_info,
ordinates,
dimensions,
is_single_geom,
is_point_type,
multiple_geoms);
convert_ordinates(feature,
mapnik::Point,
elem_info,
ordinates,
dimensions,
is_single_geom,
is_point_type,
multiple_geoms);
}
}
break;
@ -304,16 +310,15 @@ void occi_featureset::convert_geometry (SDOGeometry* geom, feature_ptr feature,
const bool is_single_geom = false;
const bool is_point_type = false;
convert_ordinates (feature,
mapnik::LineString,
elem_info,
ordinates,
dimensions,
is_single_geom,
is_point_type,
multiple_geometries);
convert_ordinates(feature,
mapnik::LineString,
elem_info,
ordinates,
dimensions,
is_single_geom,
is_point_type,
multiple_geometries);
}
}
break;
case SDO_GTYPE_MULTIPOLYGON:
@ -323,14 +328,14 @@ void occi_featureset::convert_geometry (SDOGeometry* geom, feature_ptr feature,
const bool is_single_geom = false;
const bool is_point_type = false;
convert_ordinates (feature,
mapnik::Polygon,
elem_info,
ordinates,
dimensions,
is_single_geom,
is_point_type,
multiple_geometries);
convert_ordinates(feature,
mapnik::Polygon,
elem_info,
ordinates,
dimensions,
is_single_geom,
is_point_type,
multiple_geometries);
}
}
@ -342,55 +347,56 @@ void occi_featureset::convert_geometry (SDOGeometry* geom, feature_ptr feature,
const bool is_single_geom = false;
const bool is_point_type = false;
convert_ordinates (feature,
mapnik::Polygon,
elem_info,
ordinates,
dimensions,
is_single_geom,
is_point_type,
multiple_geometries);
convert_ordinates(feature,
mapnik::Polygon,
elem_info,
ordinates,
dimensions,
is_single_geom,
is_point_type,
multiple_geometries);
}
}
break;
case SDO_GTYPE_UNKNOWN:
default:
#ifdef MAPNIK_DEBUG
std::clog << "OCCI Plugin: unknown <occi> " << occi_enums::resolve_gtype(geomtype)
<< "(gtype=" << gtype << ")" << std::endl;
std::clog << "OCCI Plugin: unknown <occi> "
<< occi_enums::resolve_gtype(geomtype)
<< "(gtype=" << gtype << ")" << std::endl;
#endif
break;
}
}
void occi_featureset::convert_ordinates (mapnik::feature_ptr feature,
const mapnik::eGeomType& geom_type,
const std::vector<Number>& elem_info,
const std::vector<Number>& ordinates,
const int dimensions,
const bool is_single_geom,
const bool is_point_geom,
const bool multiple_geometries)
void occi_featureset::convert_ordinates(mapnik::feature_ptr feature,
const mapnik::eGeomType& geom_type,
const std::vector<Number>& elem_info,
const std::vector<Number>& ordinates,
const int dimensions,
const bool is_single_geom,
const bool is_point_geom,
const bool multiple_geometries)
{
const int elem_size = elem_info.size();
const int ord_size = ordinates.size();
if (elem_size >= 0)
{
int offset = elem_info [0];
int etype = elem_info [1];
int interp = elem_info [2];
int offset = elem_info[0];
int etype = elem_info[1];
int interp = elem_info[2];
if (! is_single_geom && elem_size > SDO_ELEM_INFO_SIZE)
{
geometry_type* geom = multiple_geometries ? 0 : new geometry_type(geom_type);
if (geom) geom->set_capacity (ord_size);
if (geom) geom->set_capacity(ord_size);
for (int i = SDO_ELEM_INFO_SIZE; i < elem_size; i+=3)
{
int next_offset = elem_info [i];
int next_etype = elem_info [i + 1];
int next_interp = elem_info [i + 2];
int next_offset = elem_info[i];
int next_etype = elem_info[i + 1];
int next_interp = elem_info[i + 2];
bool is_linear_element = true;
bool is_unknown_etype = false;
mapnik::eGeomType gtype = mapnik::Point;
@ -398,14 +404,14 @@ void occi_featureset::convert_ordinates (mapnik::feature_ptr feature,
switch (etype)
{
case SDO_ETYPE_POINT:
if (interp == SDO_INTERPRETATION_POINT) {}
if (interp > SDO_INTERPRETATION_POINT) {}
if (interp == SDO_INTERPRETATION_POINT) {}
if (interp > SDO_INTERPRETATION_POINT) {}
gtype = mapnik::Point;
break;
case SDO_ETYPE_LINESTRING:
if (interp == SDO_INTERPRETATION_STRAIGHT) {}
if (interp == SDO_INTERPRETATION_CIRCULAR) {}
if (interp == SDO_INTERPRETATION_STRAIGHT) {}
if (interp == SDO_INTERPRETATION_CIRCULAR) {}
gtype = mapnik::LineString;
break;
@ -433,25 +439,29 @@ void occi_featureset::convert_ordinates (mapnik::feature_ptr feature,
}
if (is_unknown_etype)
{
break;
}
if (is_linear_element)
{
if (multiple_geometries)
{
if (geom)
feature->add_geometry (geom);
{
feature->add_geometry(geom);
}
geom = new geometry_type(gtype);
geom->set_capacity ((next_offset - 1) - (offset - 1 - dimensions));
geom->set_capacity((next_offset - 1) - (offset - 1 - dimensions));
}
fill_geometry_type (geom,
offset - 1,
next_offset - 1,
ordinates,
dimensions,
is_point_geom);
fill_geometry_type(geom,
offset - 1,
next_offset - 1,
ordinates,
dimensions,
is_point_geom);
}
offset = next_offset;
@ -461,45 +471,48 @@ void occi_featureset::convert_ordinates (mapnik::feature_ptr feature,
if (geom)
{
feature->add_geometry (geom);
feature->add_geometry(geom);
geom = 0;
}
}
else
{
geometry_type * geom = new geometry_type(geom_type);
geom->set_capacity (ord_size);
geom->set_capacity(ord_size);
fill_geometry_type (geom,
offset - 1,
ord_size,
ordinates,
dimensions,
is_point_geom);
fill_geometry_type(geom,
offset - 1,
ord_size,
ordinates,
dimensions,
is_point_geom);
feature->add_geometry (geom);
feature->add_geometry(geom);
}
}
}
void occi_featureset::fill_geometry_type (geometry_type * geom,
const int real_offset,
const int next_offset,
const std::vector<Number>& ordinates,
const int dimensions,
const bool is_point_geom)
void occi_featureset::fill_geometry_type(geometry_type* geom,
const int real_offset,
const int next_offset,
const std::vector<Number>& ordinates,
const int dimensions,
const bool is_point_geom)
{
geom->move_to ((double) ordinates[real_offset], (double) ordinates[real_offset + 1]);
geom->move_to((double) ordinates[real_offset], (double) ordinates[real_offset + 1]);
if (is_point_geom)
{
for (int p = real_offset + dimensions; p < next_offset; p += dimensions)
geom->move_to ((double) ordinates[p], (double) ordinates[p + 1]);
{
geom->move_to((double) ordinates[p], (double) ordinates[p + 1]);
}
}
else
{
for (int p = real_offset + dimensions; p < next_offset; p += dimensions)
geom->line_to ((double) ordinates[p], (double) ordinates[p + 1]);
{
geom->line_to((double) ordinates[p], (double) ordinates[p + 1]);
}
}
}

View file

@ -2,7 +2,7 @@
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2007 Artem Pavlenko
* Copyright (C) 2011 Artem Pavlenko
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@ -38,40 +38,42 @@
class occi_featureset : public mapnik::Featureset
{
public:
occi_featureset(oracle::occi::StatelessConnectionPool* pool,
oracle::occi::Connection* conn,
std::string const& sqlstring,
std::string const& encoding,
bool multiple_geometries,
bool use_connection_pool,
unsigned prefetch_rows,
unsigned num_attrs);
virtual ~occi_featureset();
mapnik::feature_ptr next();
private:
void convert_geometry (SDOGeometry* geom, mapnik::feature_ptr feature, bool multiple_geometries);
void convert_ordinates (mapnik::feature_ptr feature,
const mapnik::eGeomType& geom_type,
const std::vector<oracle::occi::Number>& elem_info,
const std::vector<oracle::occi::Number>& ordinates,
const int dimensions,
const bool is_single_geom,
const bool is_point_geom,
const bool multiple_geometries);
void fill_geometry_type (mapnik::geometry_type * geom,
const int real_offset,
const int next_offset,
const std::vector<oracle::occi::Number>& ordinates,
const int dimensions,
const bool is_point_geom);
occi_connection_ptr conn_;
oracle::occi::ResultSet* rs_;
boost::scoped_ptr<mapnik::transcoder> tr_;
const char* fidcolumn_;
bool multiple_geometries_;
unsigned num_attrs_;
mutable int feature_id_;
public:
occi_featureset(oracle::occi::StatelessConnectionPool* pool,
oracle::occi::Connection* conn,
std::string const& sqlstring,
std::string const& encoding,
bool multiple_geometries,
bool use_connection_pool,
unsigned prefetch_rows,
unsigned num_attrs);
virtual ~occi_featureset();
mapnik::feature_ptr next();
private:
void convert_geometry (SDOGeometry* geom, mapnik::feature_ptr feature, bool multiple_geometries);
void convert_ordinates (mapnik::feature_ptr feature,
const mapnik::eGeomType& geom_type,
const std::vector<oracle::occi::Number>& elem_info,
const std::vector<oracle::occi::Number>& ordinates,
const int dimensions,
const bool is_single_geom,
const bool is_point_geom,
const bool multiple_geometries);
void fill_geometry_type (mapnik::geometry_type* geom,
const int real_offset,
const int next_offset,
const std::vector<oracle::occi::Number>& ordinates,
const int dimensions,
const bool is_point_geom);
occi_connection_ptr conn_;
oracle::occi::ResultSet* rs_;
boost::scoped_ptr<mapnik::transcoder> tr_;
const char* fidcolumn_;
bool multiple_geometries_;
unsigned num_attrs_;
mutable int feature_id_;
};
#endif // OCCI_FEATURESET_HPP

View file

@ -2,7 +2,7 @@
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2007 Artem Pavlenko
* Copyright (C) 2011 Artem Pavlenko
*
* This library is free software, you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@ -25,71 +25,69 @@
oracle::occi::Environment* occi_environment::env_ = 0;
std::string occi_enums::resolve_gtype(int gtype)
{
switch(gtype)
switch (gtype)
{
case SDO_GTYPE_UNKNOWN: return "SDO_GTYPE_UNKNOWN";
case SDO_GTYPE_POINT: return "SDO_GTYPE_POINT";
case SDO_GTYPE_LINE: return "SDO_GTYPE_LINE";
case SDO_GTYPE_POLYGON: return "SDO_GTYPE_POLYGON";
case SDO_GTYPE_MULTIPOINT: return "SDO_GTYPE_MULTIPOINT";
case SDO_GTYPE_MULTILINE: return "SDO_GTYPE_MULTILINE";
case SDO_GTYPE_MULTIPOLYGON: return "SDO_GTYPE_MULTIPOLYGON";
case SDO_GTYPE_COLLECTION: return "SDO_GTYPE_COLLECTION";
default: return "<unknown SDO_GTYPE>";
case SDO_GTYPE_UNKNOWN: return "SDO_GTYPE_UNKNOWN";
case SDO_GTYPE_POINT: return "SDO_GTYPE_POINT";
case SDO_GTYPE_LINE: return "SDO_GTYPE_LINE";
case SDO_GTYPE_POLYGON: return "SDO_GTYPE_POLYGON";
case SDO_GTYPE_MULTIPOINT: return "SDO_GTYPE_MULTIPOINT";
case SDO_GTYPE_MULTILINE: return "SDO_GTYPE_MULTILINE";
case SDO_GTYPE_MULTIPOLYGON: return "SDO_GTYPE_MULTIPOLYGON";
case SDO_GTYPE_COLLECTION: return "SDO_GTYPE_COLLECTION";
default: return "<unknown SDO_GTYPE>";
}
}
std::string occi_enums::resolve_etype(int etype)
{
switch(etype)
switch (etype)
{
case SDO_ETYPE_UNKNOWN: return "SDO_ETYPE_UNKNOWN";
case SDO_ETYPE_POINT: return "SDO_ETYPE_POINT";
case SDO_ETYPE_LINESTRING: return "SDO_ETYPE_LINESTRING";
case SDO_ETYPE_POLYGON: return "SDO_ETYPE_POLYGON";
case SDO_ETYPE_POLYGON_INTERIOR: return "SDO_ETYPE_POLYGON_INTERIOR";
case SDO_ETYPE_COMPOUND_LINESTRING: return "SDO_ETYPE_COMPOUND_LINESTRING";
case SDO_ETYPE_COMPOUND_POLYGON: return "SDO_ETYPE_COMPOUND_POLYGON";
case SDO_ETYPE_COMPOUND_POLYGON_INTERIOR: return "SDO_ETYPE_COMPOUND_POLYGON_INTERIOR";
default: return "<unknown SDO_ETYPE>";
case SDO_ETYPE_UNKNOWN: return "SDO_ETYPE_UNKNOWN";
case SDO_ETYPE_POINT: return "SDO_ETYPE_POINT";
case SDO_ETYPE_LINESTRING: return "SDO_ETYPE_LINESTRING";
case SDO_ETYPE_POLYGON: return "SDO_ETYPE_POLYGON";
case SDO_ETYPE_POLYGON_INTERIOR: return "SDO_ETYPE_POLYGON_INTERIOR";
case SDO_ETYPE_COMPOUND_LINESTRING: return "SDO_ETYPE_COMPOUND_LINESTRING";
case SDO_ETYPE_COMPOUND_POLYGON: return "SDO_ETYPE_COMPOUND_POLYGON";
case SDO_ETYPE_COMPOUND_POLYGON_INTERIOR: return "SDO_ETYPE_COMPOUND_POLYGON_INTERIOR";
default: return "<unknown SDO_ETYPE>";
}
}
std::string occi_enums::resolve_datatype(int type_id)
{
switch(type_id)
switch (type_id)
{
case oracle::occi::OCCIINT: return "OCCIINT";
case oracle::occi::OCCIUNSIGNED_INT: return "OCCIUNSIGNED_INT";
case oracle::occi::OCCIFLOAT: return "OCCIFLOAT";
case oracle::occi::OCCIBFLOAT: return "OCCIBFLOAT";
case oracle::occi::OCCIDOUBLE: return "OCCIDOUBLE";
case oracle::occi::OCCIBDOUBLE: return "OCCIBDOUBLE";
case oracle::occi::OCCINUMBER: return "OCCINUMBER";
case oracle::occi::OCCI_SQLT_NUM: return "OCCI_SQLT_NUM";
case oracle::occi::OCCICHAR: return "OCCICHAR";
case oracle::occi::OCCISTRING: return "OCCISTRING";
case oracle::occi::OCCI_SQLT_AFC: return "OCCI_SQLT_AFC";
case oracle::occi::OCCI_SQLT_AVC: return "OCCI_SQLT_AVC";
case oracle::occi::OCCI_SQLT_CHR: return "OCCI_SQLT_CHR";
case oracle::occi::OCCI_SQLT_LVC: return "OCCI_SQLT_LVC";
case oracle::occi::OCCI_SQLT_STR: return "OCCI_SQLT_STR";
case oracle::occi::OCCI_SQLT_VCS: return "OCCI_SQLT_VCS";
case oracle::occi::OCCI_SQLT_VNU: return "OCCI_SQLT_VNU";
case oracle::occi::OCCI_SQLT_VBI: return "OCCI_SQLT_VBI";
case oracle::occi::OCCI_SQLT_VST: return "OCCI_SQLT_VST";
case oracle::occi::OCCI_SQLT_RDD: return "OCCI_SQLT_RDD";
case oracle::occi::OCCIDATE: return "OCCIDATE";
case oracle::occi::OCCITIMESTAMP: return "OCCITIMESTAMP";
case oracle::occi::OCCI_SQLT_DAT: return "OCCI_SQLT_DAT";
case oracle::occi::OCCI_SQLT_TIMESTAMP: return "OCCI_SQLT_TIMESTAMP";
case oracle::occi::OCCI_SQLT_TIMESTAMP_LTZ: return "OCCI_SQLT_TIMESTAMP_LTZ";
case oracle::occi::OCCI_SQLT_TIMESTAMP_TZ: return "OCCI_SQLT_TIMESTAMP_TZ";
case oracle::occi::OCCIPOBJECT: return "OCCIPOBJECT";
default: return "<unknown ATTR_DATA_TYPE>";
case oracle::occi::OCCIINT: return "OCCIINT";
case oracle::occi::OCCIUNSIGNED_INT: return "OCCIUNSIGNED_INT";
case oracle::occi::OCCIFLOAT: return "OCCIFLOAT";
case oracle::occi::OCCIBFLOAT: return "OCCIBFLOAT";
case oracle::occi::OCCIDOUBLE: return "OCCIDOUBLE";
case oracle::occi::OCCIBDOUBLE: return "OCCIBDOUBLE";
case oracle::occi::OCCINUMBER: return "OCCINUMBER";
case oracle::occi::OCCI_SQLT_NUM: return "OCCI_SQLT_NUM";
case oracle::occi::OCCICHAR: return "OCCICHAR";
case oracle::occi::OCCISTRING: return "OCCISTRING";
case oracle::occi::OCCI_SQLT_AFC: return "OCCI_SQLT_AFC";
case oracle::occi::OCCI_SQLT_AVC: return "OCCI_SQLT_AVC";
case oracle::occi::OCCI_SQLT_CHR: return "OCCI_SQLT_CHR";
case oracle::occi::OCCI_SQLT_LVC: return "OCCI_SQLT_LVC";
case oracle::occi::OCCI_SQLT_STR: return "OCCI_SQLT_STR";
case oracle::occi::OCCI_SQLT_VCS: return "OCCI_SQLT_VCS";
case oracle::occi::OCCI_SQLT_VNU: return "OCCI_SQLT_VNU";
case oracle::occi::OCCI_SQLT_VBI: return "OCCI_SQLT_VBI";
case oracle::occi::OCCI_SQLT_VST: return "OCCI_SQLT_VST";
case oracle::occi::OCCI_SQLT_RDD: return "OCCI_SQLT_RDD";
case oracle::occi::OCCIDATE: return "OCCIDATE";
case oracle::occi::OCCITIMESTAMP: return "OCCITIMESTAMP";
case oracle::occi::OCCI_SQLT_DAT: return "OCCI_SQLT_DAT";
case oracle::occi::OCCI_SQLT_TIMESTAMP: return "OCCI_SQLT_TIMESTAMP";
case oracle::occi::OCCI_SQLT_TIMESTAMP_LTZ: return "OCCI_SQLT_TIMESTAMP_LTZ";
case oracle::occi::OCCI_SQLT_TIMESTAMP_TZ: return "OCCI_SQLT_TIMESTAMP_TZ";
case oracle::occi::OCCIPOBJECT: return "OCCIPOBJECT";
default: return "<unknown ATTR_DATA_TYPE>";
}
}

View file

@ -2,7 +2,7 @@
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2007 Artem Pavlenko
* Copyright (C) 2011 Artem Pavlenko
*
* This library is free software, you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@ -41,7 +41,6 @@
#error Only ORACLE 10g >= 10.2.0.X is supported !
#endif
// geometry types definitions
enum
{
@ -79,14 +78,13 @@ enum
SDO_INTERPRETATION_CIRCULAR = 2
};
class occi_environment : public mapnik::singleton<occi_environment,mapnik::CreateStatic>
class occi_environment : public mapnik::singleton<occi_environment, mapnik::CreateStatic>
{
friend class mapnik::CreateStatic<occi_environment>;
public:
static oracle::occi::Environment* get_environment ()
static oracle::occi::Environment* get_environment()
{
if (env_ == 0)
{
@ -94,11 +92,11 @@ public:
std::clog << "OCCI Plugin: occi_environment constructor" << std::endl;
#endif
int mode = oracle::occi::Environment::OBJECT
| oracle::occi::Environment::THREADED_MUTEXED;
const int mode = oracle::occi::Environment::OBJECT
| oracle::occi::Environment::THREADED_MUTEXED;
env_ = oracle::occi::Environment::createEnvironment ((oracle::occi::Environment::Mode) mode);
RegisterClasses (env_);
env_ = oracle::occi::Environment::createEnvironment((oracle::occi::Environment::Mode) mode);
RegisterClasses(env_);
}
return env_;
@ -118,7 +116,7 @@ private:
std::clog << "OCCI Plugin: occi_environment destructor" << std::endl;
#endif
oracle::occi::Environment::terminateEnvironment (env_);
oracle::occi::Environment::terminateEnvironment(env_);
env_ = 0;
}
}
@ -126,28 +124,27 @@ private:
static oracle::occi::Environment* env_;
};
class occi_connection_ptr
{
public:
explicit occi_connection_ptr ()
: env_ (occi_environment::get_environment()),
pool_ (0),
conn_ (0),
stmt_ (0),
rs_ (0),
owns_connection_ (false)
explicit occi_connection_ptr()
: env_(occi_environment::get_environment()),
pool_(0),
conn_(0),
stmt_(0),
rs_(0),
owns_connection_(false)
{
}
~occi_connection_ptr ()
~occi_connection_ptr()
{
close_query (true);
close_query(true);
}
void set_pool(oracle::occi::StatelessConnectionPool* pool)
{
close_query (true);
close_query(true);
pool_ = pool;
conn_ = pool_->getConnection();
@ -156,26 +153,26 @@ public:
void set_connection(oracle::occi::Connection* conn, bool owns_connection)
{
close_query (true);
close_query(true);
pool_ = 0;
conn_ = conn;
owns_connection_ = owns_connection;
}
oracle::occi::ResultSet* execute_query (const std::string& s, const unsigned prefetch = 0)
oracle::occi::ResultSet* execute_query(const std::string& s, const unsigned prefetch = 0)
{
close_query (false);
close_query(false);
stmt_ = conn_->createStatement (s);
stmt_ = conn_->createStatement(s);
if (prefetch > 0)
{
stmt_->setPrefetchMemorySize (0);
stmt_->setPrefetchRowCount (prefetch);
stmt_->setPrefetchMemorySize(0);
stmt_->setPrefetchRowCount(prefetch);
}
rs_ = stmt_->executeQuery ();
rs_ = stmt_->executeQuery();
return rs_;
}
@ -186,8 +183,7 @@ public:
}
private:
void close_query (const bool release_connection)
void close_query(const bool release_connection)
{
if (conn_)
{
@ -195,11 +191,11 @@ private:
{
if (rs_)
{
stmt_->closeResultSet (rs_);
stmt_->closeResultSet(rs_);
rs_ = 0;
}
conn_->terminateStatement (stmt_);
conn_->terminateStatement(stmt_);
stmt_ = 0;
}
@ -207,7 +203,7 @@ private:
{
if (pool_)
{
pool_->releaseConnection (conn_);
pool_->releaseConnection(conn_);
}
else
{
@ -230,7 +226,6 @@ private:
bool owns_connection_;
};
class occi_enums
{
public:
@ -240,5 +235,4 @@ public:
static std::string resolve_datatype(int type_id);
};
#endif // OCCI_TYPES_HPP

View file

@ -2,7 +2,7 @@
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2007 Artem Pavlenko
* Copyright (C) 2011 Artem Pavlenko
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@ -36,235 +36,246 @@ using mapnik::feature_ptr;
using mapnik::geometry_utils;
using mapnik::geometry_type;
void ogr_converter::convert_geometry (OGRGeometry* geom, feature_ptr feature, bool multiple_geometries)
void ogr_converter::convert_geometry(OGRGeometry* geom, feature_ptr feature, bool multiple_geometries)
{
switch (wkbFlatten (geom->getGeometryType()))
{
case wkbPoint:
convert_point (static_cast<OGRPoint*>(geom), feature);
break;
case wkbLineString:
convert_linestring (static_cast<OGRLineString*>(geom), feature);
break;
case wkbPolygon:
convert_polygon (static_cast<OGRPolygon*>(geom), feature);
break;
case wkbMultiPoint:
if (multiple_geometries)
convert_multipoint_2 (static_cast<OGRMultiPoint*>(geom), feature);
else
// Todo - using convert_multipoint_2 until we have proper multipoint handling in convert_multipoint
// http://trac.mapnik.org/ticket/458
//convert_multipoint (static_cast<OGRMultiPoint*>(geom), feature);
convert_multipoint_2 (static_cast<OGRMultiPoint*>(geom), feature);
break;
case wkbMultiLineString:
if (multiple_geometries)
convert_multilinestring_2 (static_cast<OGRMultiLineString*>(geom), feature);
else
convert_multilinestring (static_cast<OGRMultiLineString*>(geom), feature);
break;
case wkbMultiPolygon:
if (multiple_geometries)
convert_multipolygon_2 (static_cast<OGRMultiPolygon*>(geom), feature);
else
convert_multipolygon (static_cast<OGRMultiPolygon*>(geom), feature);
break;
case wkbGeometryCollection:
convert_collection (static_cast<OGRGeometryCollection*>(geom), feature, multiple_geometries);
break;
case wkbLinearRing:
convert_linestring (static_cast<OGRLinearRing*>(geom), feature);
break;
case wkbNone:
case wkbUnknown:
default:
switch (wkbFlatten(geom->getGeometryType()))
{
case wkbPoint:
convert_point(static_cast<OGRPoint*>(geom), feature);
break;
case wkbLineString:
convert_linestring(static_cast<OGRLineString*>(geom), feature);
break;
case wkbPolygon:
convert_polygon(static_cast<OGRPolygon*>(geom), feature);
break;
case wkbMultiPoint:
if (multiple_geometries)
{
convert_multipoint_2(static_cast<OGRMultiPoint*>(geom), feature);
}
else
{
// Todo - using convert_multipoint_2 until we have proper multipoint handling in convert_multipoint
// http://trac.mapnik.org/ticket/458
//convert_multipoint(static_cast<OGRMultiPoint*>(geom), feature);
convert_multipoint_2(static_cast<OGRMultiPoint*>(geom), feature);
}
break;
case wkbMultiLineString:
if (multiple_geometries)
{
convert_multilinestring_2(static_cast<OGRMultiLineString*>(geom), feature);
}
else
{
convert_multilinestring(static_cast<OGRMultiLineString*>(geom), feature);
}
break;
case wkbMultiPolygon:
if (multiple_geometries)
{
convert_multipolygon_2(static_cast<OGRMultiPolygon*>(geom), feature);
}
else
{
convert_multipolygon(static_cast<OGRMultiPolygon*>(geom), feature);
}
break;
case wkbGeometryCollection:
convert_collection(static_cast<OGRGeometryCollection*>(geom), feature, multiple_geometries);
break;
case wkbLinearRing:
convert_linestring(static_cast<OGRLinearRing*>(geom), feature);
break;
case wkbNone:
case wkbUnknown:
default:
#ifdef MAPNIK_DEBUG
std::clog << "OGR Plugin: unknown <ogr> geometry_type=" << wkbFlatten (geom->getGeometryType()) << std::endl;
std::clog << "OGR Plugin: unknown <ogr> geometry_type="
<< wkbFlatten(geom->getGeometryType()) << std::endl;
#endif
break;
}
break;
}
}
void ogr_converter::convert_point (OGRPoint* geom, feature_ptr feature)
void ogr_converter::convert_point(OGRPoint* geom, feature_ptr feature)
{
geometry_type * point = new geometry_type(mapnik::Point);
point->move_to (geom->getX(), geom->getY());
feature->add_geometry (point);
point->move_to(geom->getX(), geom->getY());
feature->add_geometry(point);
}
void ogr_converter::convert_linestring (OGRLineString* geom, feature_ptr feature)
void ogr_converter::convert_linestring(OGRLineString* geom, feature_ptr feature)
{
int num_points = geom->getNumPoints ();
geometry_type * line = new geometry_type(mapnik::LineString);
line->set_capacity (num_points);
line->move_to (geom->getX (0), geom->getY (0));
for (int i=1;i<num_points;++i)
int num_points = geom->getNumPoints();
geometry_type* line = new geometry_type(mapnik::LineString);
line->set_capacity(num_points);
line->move_to(geom->getX(0), geom->getY(0));
for (int i = 1; i < num_points; ++i)
{
line->line_to (geom->getX (i), geom->getY (i));
line->line_to (geom->getX(i), geom->getY(i));
}
feature->add_geometry (line);
feature->add_geometry(line);
}
void ogr_converter::convert_polygon (OGRPolygon* geom, feature_ptr feature)
void ogr_converter::convert_polygon(OGRPolygon* geom, feature_ptr feature)
{
OGRLinearRing* exterior = geom->getExteriorRing ();
int num_points = exterior->getNumPoints ();
int num_interior = geom->getNumInteriorRings ();
OGRLinearRing* exterior = geom->getExteriorRing();
int num_points = exterior->getNumPoints();
int num_interior = geom->getNumInteriorRings();
int capacity = 0;
for (int r=0;r<num_interior;r++)
for (int r = 0; r < num_interior; r++)
{
OGRLinearRing* interior = geom->getInteriorRing (r);
capacity += interior->getNumPoints ();
OGRLinearRing* interior = geom->getInteriorRing(r);
capacity += interior->getNumPoints();
}
geometry_type * poly = new geometry_type(mapnik::Polygon);
poly->set_capacity (num_points + capacity);
poly->move_to (exterior->getX (0), exterior->getY (0));
for (int i=1;i<num_points;++i)
geometry_type* poly = new geometry_type(mapnik::Polygon);
poly->set_capacity(num_points + capacity);
poly->move_to(exterior->getX(0), exterior->getY(0));
for (int i = 1; i < num_points; ++i)
{
poly->line_to (exterior->getX (i), exterior->getY (i));
poly->line_to(exterior->getX(i), exterior->getY(i));
}
for (int r=0;r<num_interior;r++)
for (int r = 0; r < num_interior; r++)
{
OGRLinearRing* interior = geom->getInteriorRing (r);
num_points = interior->getNumPoints ();
poly->move_to(interior->getX (0), interior->getY (0));
for (int i=1;i<num_points;++i)
OGRLinearRing* interior = geom->getInteriorRing(r);
num_points = interior->getNumPoints();
poly->move_to(interior->getX(0), interior->getY(0));
for (int i = 1; i < num_points; ++i)
{
poly->line_to(interior->getX (i), interior->getY (i));
poly->line_to(interior->getX(i), interior->getY(i));
}
}
feature->add_geometry (poly);
feature->add_geometry(poly);
}
void ogr_converter::convert_multipoint (OGRMultiPoint* geom, feature_ptr feature)
void ogr_converter::convert_multipoint(OGRMultiPoint* geom, feature_ptr feature)
{
int num_geometries = geom->getNumGeometries ();
geometry_type * point = new geometry_type(mapnik::Point);
int num_geometries = geom->getNumGeometries();
geometry_type* point = new geometry_type(mapnik::Point);
for (int i=0;i<num_geometries;i++)
for (int i = 0; i < num_geometries; i++)
{
OGRPoint* ogrpoint = static_cast<OGRPoint*>(geom->getGeometryRef (i));
point->move_to (ogrpoint->getX(), ogrpoint->getY());
OGRPoint* ogrpoint = static_cast<OGRPoint*>(geom->getGeometryRef(i));
point->move_to(ogrpoint->getX(), ogrpoint->getY());
//Todo - need to accept multiple points per mapnik::Point
}
// Todo - this only gets last point
feature->add_geometry (point);
feature->add_geometry(point);
}
void ogr_converter::convert_multipoint_2 (OGRMultiPoint* geom, feature_ptr feature)
void ogr_converter::convert_multipoint_2(OGRMultiPoint* geom, feature_ptr feature)
{
int num_geometries = geom->getNumGeometries ();
for (int i=0;i<num_geometries;i++)
int num_geometries = geom->getNumGeometries();
for (int i = 0; i < num_geometries; i++)
{
convert_point (static_cast<OGRPoint*>(geom->getGeometryRef (i)), feature);
convert_point(static_cast<OGRPoint*>(geom->getGeometryRef(i)), feature);
}
}
void ogr_converter::convert_multilinestring (OGRMultiLineString* geom, feature_ptr feature)
void ogr_converter::convert_multilinestring(OGRMultiLineString* geom, feature_ptr feature)
{
int num_geometries = geom->getNumGeometries ();
int num_geometries = geom->getNumGeometries();
int num_points = 0;
for (int i=0;i<num_geometries;i++)
for (int i = 0; i < num_geometries; i++)
{
OGRLineString* ls = static_cast<OGRLineString*>(geom->getGeometryRef (i));
num_points += ls->getNumPoints ();
OGRLineString* ls = static_cast<OGRLineString*>(geom->getGeometryRef(i));
num_points += ls->getNumPoints();
}
geometry_type * line = new geometry_type(mapnik::LineString);
line->set_capacity (num_points);
geometry_type* line = new geometry_type(mapnik::LineString);
line->set_capacity(num_points);
for (int i=0;i<num_geometries;i++)
for (int i = 0; i < num_geometries; i++)
{
OGRLineString* ls = static_cast<OGRLineString*>(geom->getGeometryRef (i));
num_points = ls->getNumPoints ();
line->move_to (ls->getX (0), ls->getY (0));
for (int i=1;i<num_points;++i)
OGRLineString* ls = static_cast<OGRLineString*>(geom->getGeometryRef(i));
num_points = ls->getNumPoints();
line->move_to(ls->getX(0), ls->getY(0));
for (int i = 1; i < num_points; ++i)
{
line->line_to (ls->getX (i), ls->getY (i));
line->line_to(ls->getX(i), ls->getY(i));
}
}
feature->add_geometry (line);
feature->add_geometry(line);
}
void ogr_converter::convert_multilinestring_2 (OGRMultiLineString* geom, feature_ptr feature)
void ogr_converter::convert_multilinestring_2(OGRMultiLineString* geom, feature_ptr feature)
{
int num_geometries = geom->getNumGeometries ();
for (int i=0;i<num_geometries;i++)
int num_geometries = geom->getNumGeometries();
for (int i = 0; i < num_geometries; i++)
{
convert_linestring (static_cast<OGRLineString*>(geom->getGeometryRef (i)), feature);
convert_linestring(static_cast<OGRLineString*>(geom->getGeometryRef(i)), feature);
}
}
void ogr_converter::convert_multipolygon (OGRMultiPolygon* geom, feature_ptr feature)
void ogr_converter::convert_multipolygon(OGRMultiPolygon* geom, feature_ptr feature)
{
int num_geometries = geom->getNumGeometries ();
int num_geometries = geom->getNumGeometries();
int capacity = 0;
for (int i=0;i<num_geometries;i++)
for (int i = 0; i < num_geometries; i++)
{
OGRPolygon* p = static_cast<OGRPolygon*>(geom->getGeometryRef (i));
OGRLinearRing* exterior = p->getExteriorRing ();
capacity += exterior->getNumPoints ();
for (int r=0;r<p->getNumInteriorRings ();r++)
OGRPolygon* p = static_cast<OGRPolygon*>(geom->getGeometryRef(i));
OGRLinearRing* exterior = p->getExteriorRing();
capacity += exterior->getNumPoints();
for (int r = 0; r < p->getNumInteriorRings(); r++)
{
OGRLinearRing* interior = p->getInteriorRing (r);
capacity += interior->getNumPoints ();
OGRLinearRing* interior = p->getInteriorRing(r);
capacity += interior->getNumPoints();
}
}
geometry_type * poly = new geometry_type(mapnik::Polygon);
poly->set_capacity (capacity);
geometry_type* poly = new geometry_type(mapnik::Polygon);
poly->set_capacity(capacity);
for (int i=0;i<num_geometries;i++)
for (int i = 0; i < num_geometries; i++)
{
OGRPolygon* p = static_cast<OGRPolygon*>(geom->getGeometryRef (i));
OGRLinearRing* exterior = p->getExteriorRing ();
int num_points = exterior->getNumPoints ();
int num_interior = p->getNumInteriorRings ();
poly->move_to (exterior->getX (0), exterior->getY (0));
for (int i=1;i<num_points;++i)
OGRPolygon* p = static_cast<OGRPolygon*>(geom->getGeometryRef(i));
OGRLinearRing* exterior = p->getExteriorRing();
int num_points = exterior->getNumPoints();
int num_interior = p->getNumInteriorRings();
poly->move_to(exterior->getX(0), exterior->getY(0));
for (int i = 1; i < num_points; ++i)
{
poly->line_to (exterior->getX (i), exterior->getY (i));
poly->line_to(exterior->getX(i), exterior->getY(i));
}
for (int r=0;r<num_interior;r++)
for (int r = 0; r < num_interior; r++)
{
OGRLinearRing* interior = p->getInteriorRing (r);
num_points = interior->getNumPoints ();
poly->move_to(interior->getX (0), interior->getY (0));
for (int i=1;i<num_points;++i)
OGRLinearRing* interior = p->getInteriorRing(r);
num_points = interior->getNumPoints();
poly->move_to(interior->getX(0), interior->getY(0));
for (int i = 1; i < num_points; ++i)
{
poly->line_to(interior->getX (i), interior->getY (i));
poly->line_to(interior->getX(i), interior->getY(i));
}
}
}
feature->add_geometry (poly);
feature->add_geometry(poly);
}
void ogr_converter::convert_multipolygon_2 (OGRMultiPolygon* geom, feature_ptr feature)
void ogr_converter::convert_multipolygon_2(OGRMultiPolygon* geom, feature_ptr feature)
{
int num_geometries = geom->getNumGeometries ();
for (int i=0;i<num_geometries;i++)
int num_geometries = geom->getNumGeometries();
for (int i = 0; i < num_geometries; i++)
{
convert_polygon (static_cast<OGRPolygon*>(geom->getGeometryRef (i)), feature);
convert_polygon(static_cast<OGRPolygon*>(geom->getGeometryRef(i)), feature);
}
}
void ogr_converter::convert_collection (OGRGeometryCollection* geom, feature_ptr feature, bool multiple_geometries)
void ogr_converter::convert_collection(OGRGeometryCollection* geom, feature_ptr feature, bool multiple_geometries)
{
int num_geometries = geom->getNumGeometries ();
for (int i=0;i<num_geometries;i++)
int num_geometries = geom->getNumGeometries();
for (int i = 0; i < num_geometries; i++)
{
OGRGeometry* g = geom->getGeometryRef (i);
OGRGeometry* g = geom->getGeometryRef(i);
if (g != NULL)
{
convert_geometry (g, feature, multiple_geometries);
convert_geometry(g, feature, multiple_geometries);
}
}
}

View file

@ -2,7 +2,7 @@
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2007 Artem Pavlenko
* Copyright (C) 2011 Artem Pavlenko
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@ -32,19 +32,19 @@
class ogr_converter
{
public:
public:
static void convert_geometry (OGRGeometry* geom, mapnik::feature_ptr feature, bool multiple_geometries);
static void convert_collection (OGRGeometryCollection* geom, mapnik::feature_ptr feature, bool multiple_geometries);
static void convert_point (OGRPoint* geom, mapnik::feature_ptr feature);
static void convert_linestring (OGRLineString* geom, mapnik::feature_ptr feature);
static void convert_polygon (OGRPolygon* geom, mapnik::feature_ptr feature);
static void convert_multipoint (OGRMultiPoint* geom, mapnik::feature_ptr feature);
static void convert_multipoint_2 (OGRMultiPoint* geom, mapnik::feature_ptr feature);
static void convert_multilinestring (OGRMultiLineString* geom, mapnik::feature_ptr feature);
static void convert_multilinestring_2 (OGRMultiLineString* geom, mapnik::feature_ptr feature);
static void convert_multipolygon (OGRMultiPolygon* geom, mapnik::feature_ptr feature);
static void convert_multipolygon_2 (OGRMultiPolygon* geom, mapnik::feature_ptr feature);
static void convert_geometry (OGRGeometry* geom, mapnik::feature_ptr feature, bool multiple_geometries);
static void convert_collection (OGRGeometryCollection* geom, mapnik::feature_ptr feature, bool multiple_geometries);
static void convert_point (OGRPoint* geom, mapnik::feature_ptr feature);
static void convert_linestring (OGRLineString* geom, mapnik::feature_ptr feature);
static void convert_polygon (OGRPolygon* geom, mapnik::feature_ptr feature);
static void convert_multipoint (OGRMultiPoint* geom, mapnik::feature_ptr feature);
static void convert_multipoint_2 (OGRMultiPoint* geom, mapnik::feature_ptr feature);
static void convert_multilinestring (OGRMultiLineString* geom, mapnik::feature_ptr feature);
static void convert_multilinestring_2 (OGRMultiLineString* geom, mapnik::feature_ptr feature);
static void convert_multipolygon (OGRMultiPolygon* geom, mapnik::feature_ptr feature);
static void convert_multipolygon_2 (OGRMultiPolygon* geom, mapnik::feature_ptr feature);
};
#endif // OGR_FEATURESET_HPP
#endif // OGR_CONVERTER_HPP

View file

@ -2,7 +2,7 @@
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2007 Artem Pavlenko
* Copyright (C) 2011 Artem Pavlenko
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@ -53,35 +53,42 @@ using mapnik::filter_at_point;
ogr_datasource::ogr_datasource(parameters const& params, bool bind)
: datasource(params),
extent_(),
type_(datasource::Vector),
desc_(*params.get<std::string>("type"), *params.get<std::string>("encoding","utf-8")),
indexed_(false)
: datasource(params),
extent_(),
type_(datasource::Vector),
desc_(*params.get<std::string>("type"), *params.get<std::string>("encoding","utf-8")),
indexed_(false)
{
boost::optional<std::string> file = params.get<std::string>("file");
boost::optional<std::string> string = params.get<std::string>("string");
if (!file && !string) throw datasource_exception("missing <file> or <string> parameter");
boost::optional<std::string> file = params.get<std::string>("file");
boost::optional<std::string> string = params.get<std::string>("string");
if (! file && ! string)
{
throw datasource_exception("missing <file> or <string> parameter");
}
multiple_geometries_ = *params.get<mapnik::boolean>("multiple_geometries",false);
multiple_geometries_ = *params.get<mapnik::boolean>("multiple_geometries",false);
if (string)
{
if (string)
{
dataset_name_ = *string;
}
else
{
boost::optional<std::string> base = params.get<std::string>("base");
if (base)
dataset_name_ = *base + "/" + *file;
else
dataset_name_ = *file;
}
if (bind)
{
this->bind();
}
}
else
{
boost::optional<std::string> base = params.get<std::string>("base");
if (base)
{
dataset_name_ = *base + "/" + *file;
}
else
{
dataset_name_ = *file;
}
}
if (bind)
{
this->bind();
}
}
ogr_datasource::~ogr_datasource()
@ -94,236 +101,265 @@ ogr_datasource::~ogr_datasource()
void ogr_datasource::bind() const
{
if (is_bound_) return;
if (is_bound_) return;
// initialize ogr formats
OGRRegisterAll();
// open ogr driver
dataset_ = OGRSFDriverRegistrar::Open ((dataset_name_).c_str(), FALSE);
if (!dataset_)
{
std::string err = CPLGetLastErrorMsg();
if( err.size() == 0 ) {
throw datasource_exception("OGR Plugin: connection failed: " + dataset_name_ + " was not found or is not a supported format");
} else {
throw datasource_exception("OGR Plugin: " + err);
}
}
// initialize ogr formats
OGRRegisterAll();
// initialize layer
boost::optional<std::string> layer_by_name = params_.get<std::string>("layer");
boost::optional<unsigned> layer_by_index = params_.get<unsigned>("layer_by_index");
if (layer_by_name && layer_by_index)
throw datasource_exception("OGR Plugin: you can only select an ogr layer by name ('layer' parameter) or by number ('layer_by_index' parameter), do not supply both parameters" );
// open ogr driver
dataset_ = OGRSFDriverRegistrar::Open((dataset_name_).c_str(), FALSE);
if (! dataset_)
{
const std::string err = CPLGetLastErrorMsg();
if (err.size() == 0)
{
throw datasource_exception("OGR Plugin: connection failed: " + dataset_name_ + " was not found or is not a supported format");
}
else
{
throw datasource_exception("OGR Plugin: " + err);
}
}
if (layer_by_name)
{
layerName_ = *layer_by_name;
layer_ = dataset_->GetLayerByName (layerName_.c_str());
}
else if (layer_by_index)
{
unsigned num_layers = dataset_->GetLayerCount();
if (*layer_by_index >= num_layers)
{
std::ostringstream s;
s << "OGR Plugin: only ";
s << num_layers;
s << " layer(s) exist, cannot find layer by index '" << *layer_by_index << "'";
throw datasource_exception(s.str());
}
OGRLayer *ogr_layer = dataset_->GetLayer(*layer_by_index);
if (ogr_layer)
{
OGRFeatureDefn* def = ogr_layer->GetLayerDefn();
if (def != 0) {
layerName_ = def->GetName();
layer_ = ogr_layer;
}
}
}
else
{
std::ostringstream s;
s << "OGR Plugin: missing <layer> or <layer_by_index> parameter, available layers are: ";
unsigned num_layers = dataset_->GetLayerCount();
bool found = false;
for (unsigned i = 0; i < num_layers; ++i )
{
OGRLayer *ogr_layer = dataset_->GetLayer(i);
OGRFeatureDefn* def = ogr_layer->GetLayerDefn();
if (def != 0) {
found = true;
s << " '" << def->GetName() << "' ";
}
}
if (!found) {
s << "None (no layers were found in dataset)";
}
throw datasource_exception(s.str());
}
// initialize layer
if (!layer_)
{
std::string s("OGR Plugin: ");
if (layer_by_name) s += "cannot find layer by name '" + *layer_by_name;
else if (layer_by_index) s += "cannot find layer by index number '" + *layer_by_index;
s += "' in dataset '" + dataset_name_ + "'";
throw datasource_exception(s);
}
// initialize envelope
OGREnvelope envelope;
layer_->GetExtent (&envelope);
extent_.init (envelope.MinX, envelope.MinY, envelope.MaxX, envelope.MaxY);
boost::optional<std::string> layer_by_name = params_.get<std::string>("layer");
boost::optional<unsigned> layer_by_index = params_.get<unsigned>("layer_by_index");
// scan for index file
// TODO - layer names don't match dataset name, so this will break for
// any layer types of ogr than shapefiles, etc
// fix here and in ogrindex
size_t breakpoint = dataset_name_.find_last_of (".");
if (breakpoint == std::string::npos) breakpoint = dataset_name_.length();
index_name_ = dataset_name_.substr(0, breakpoint) + ".ogrindex";
std::ifstream index_file (index_name_.c_str(), std::ios::in | std::ios::binary);
if (index_file)
{
indexed_=true;
index_file.close();
}
// enable this warning once the ogrindex tool is a bit more stable/mature
//else
/*{
std::clog << "### Notice: no ogrindex file found for " + dataset_name_ + ", use the 'ogrindex' program to build an index for faster rendering\n";
}*/
if (layer_by_name && layer_by_index)
{
throw datasource_exception("OGR Plugin: you can only select an ogr layer by name ('layer' parameter) or by number ('layer_by_index' parameter), do not supply both parameters" );
}
// deal with attributes descriptions
OGRFeatureDefn* def = layer_->GetLayerDefn ();
if (def != 0)
{
int fld_count = def->GetFieldCount ();
for (int i = 0; i < fld_count; i++)
{
OGRFieldDefn* fld = def->GetFieldDefn (i);
if (layer_by_name)
{
layerName_ = *layer_by_name;
layer_ = dataset_->GetLayerByName(layerName_.c_str());
}
else if (layer_by_index)
{
const unsigned num_layers = dataset_->GetLayerCount();
if (*layer_by_index >= num_layers)
{
std::ostringstream s;
s << "OGR Plugin: only ";
s << num_layers;
s << " layer(s) exist, cannot find layer by index '" << *layer_by_index << "'";
std::string fld_name = fld->GetNameRef ();
OGRFieldType type_oid = fld->GetType ();
throw datasource_exception(s.str());
}
switch (type_oid)
{
case OFTInteger:
desc_.add_descriptor(attribute_descriptor(fld_name,mapnik::Integer));
break;
OGRLayer* ogr_layer = dataset_->GetLayer(*layer_by_index);
if (ogr_layer)
{
OGRFeatureDefn* def = ogr_layer->GetLayerDefn();
if (def != 0)
{
layerName_ = def->GetName();
layer_ = ogr_layer;
}
}
}
else
{
std::ostringstream s;
s << "OGR Plugin: missing <layer> or <layer_by_index> parameter, available layers are: ";
case OFTReal:
desc_.add_descriptor(attribute_descriptor(fld_name,mapnik::Double));
break;
case OFTString:
case OFTWideString: // deprecated
desc_.add_descriptor(attribute_descriptor(fld_name,mapnik::String));
break;
case OFTBinary:
desc_.add_descriptor(attribute_descriptor(fld_name,mapnik::Object));
break;
unsigned num_layers = dataset_->GetLayerCount();
bool layer_found = false;
for (unsigned i = 0; i < num_layers; ++i )
{
OGRLayer* ogr_layer = dataset_->GetLayer(i);
OGRFeatureDefn* ogr_layer_def = ogr_layer->GetLayerDefn();
if (ogr_layer_def != 0)
{
layer_found = true;
s << " '" << ogr_layer_def->GetName() << "' ";
}
}
case OFTIntegerList:
case OFTRealList:
case OFTStringList:
case OFTWideStringList: // deprecated !
#ifdef MAPNIK_DEBUG
std::clog << "OGR Plugin: unhandled type_oid=" << type_oid << std::endl;
if (! layer_found)
{
s << "None (no layers were found in dataset)";
}
throw datasource_exception(s.str());
}
if (! layer_)
{
std::string s("OGR Plugin: ");
if (layer_by_name)
{
s += "cannot find layer by name '" + *layer_by_name;
}
else if (layer_by_index)
{
s += "cannot find layer by index number '" + *layer_by_index;
}
s += "' in dataset '" + dataset_name_ + "'";
throw datasource_exception(s);
}
// initialize envelope
OGREnvelope envelope;
layer_->GetExtent(&envelope);
extent_.init(envelope.MinX, envelope.MinY, envelope.MaxX, envelope.MaxY);
// scan for index file
// TODO - layer names don't match dataset name, so this will break for
// any layer types of ogr than shapefiles, etc
// fix here and in ogrindex
size_t breakpoint = dataset_name_.find_last_of(".");
if (breakpoint == std::string::npos)
{
breakpoint = dataset_name_.length();
}
index_name_ = dataset_name_.substr(0, breakpoint) + ".ogrindex";
std::ifstream index_file (index_name_.c_str(), std::ios::in | std::ios::binary);
if (index_file)
{
indexed_ = true;
index_file.close();
}
#if 0
// TODO - enable this warning once the ogrindex tool is a bit more stable/mature
else
{
std::clog << "### Notice: no ogrindex file found for " << dataset_name_
<< ", use the 'ogrindex' program to build an index for faster rendering"
<< std::endl;
}
#endif
break;
case OFTDate:
case OFTTime:
case OFTDateTime: // unhandled !
#ifdef MAPNIK_DEBUG
std::clog << "OGR Plugin: unhandled type_oid=" << type_oid << std::endl;
#endif
desc_.add_descriptor(attribute_descriptor(fld_name,mapnik::Object));
break;
// deal with attributes descriptions
OGRFeatureDefn* def = layer_->GetLayerDefn();
if (def != 0)
{
const int fld_count = def->GetFieldCount();
for (int i = 0; i < fld_count; i++)
{
OGRFieldDefn* fld = def->GetFieldDefn(i);
default: // unknown
const std::string fld_name = fld->GetNameRef();
const OGRFieldType type_oid = fld->GetType();
switch (type_oid)
{
case OFTInteger:
desc_.add_descriptor(attribute_descriptor(fld_name, mapnik::Integer));
break;
case OFTReal:
desc_.add_descriptor(attribute_descriptor(fld_name, mapnik::Double));
break;
case OFTString:
case OFTWideString: // deprecated
desc_.add_descriptor(attribute_descriptor(fld_name, mapnik::String));
break;
case OFTBinary:
desc_.add_descriptor(attribute_descriptor(fld_name, mapnik::Object));
break;
case OFTIntegerList:
case OFTRealList:
case OFTStringList:
case OFTWideStringList: // deprecated !
#ifdef MAPNIK_DEBUG
std::clog << "OGR Plugin: unknown type_oid=" << type_oid << std::endl;
std::clog << "OGR Plugin: unhandled type_oid=" << type_oid << std::endl;
#endif
break;
}
}
}
is_bound_ = true;
break;
case OFTDate:
case OFTTime:
case OFTDateTime: // unhandled !
#ifdef MAPNIK_DEBUG
std::clog << "OGR Plugin: unhandled type_oid=" << type_oid << std::endl;
#endif
desc_.add_descriptor(attribute_descriptor(fld_name, mapnik::Object));
break;
default: // unknown
#ifdef MAPNIK_DEBUG
std::clog << "OGR Plugin: unknown type_oid=" << type_oid << std::endl;
#endif
break;
}
}
}
is_bound_ = true;
}
std::string ogr_datasource::name()
{
return "ogr";
return "ogr";
}
int ogr_datasource::type() const
{
return type_;
return type_;
}
box2d<double> ogr_datasource::envelope() const
{
if (!is_bound_) bind();
return extent_;
if (! is_bound_) bind();
return extent_;
}
layer_descriptor ogr_datasource::get_descriptor() const
{
if (!is_bound_) bind();
return desc_;
if (! is_bound_) bind();
return desc_;
}
featureset_ptr ogr_datasource::features(query const& q) const
{
if (!is_bound_) bind();
if (! is_bound_) bind();
if (dataset_ && layer_)
{
if (dataset_ && layer_)
{
#if 0
// TODO - actually filter fields!
// http://trac.osgeo.org/gdal/wiki/rfc29_desired_fields
// http://trac.osgeo.org/gdal/wiki/rfc28_sqlfunc
#if 0
std::ostringstream s;
s << "select ";
std::set<std::string> const& props=q.property_names();
std::set<std::string>::const_iterator pos=props.begin();
std::set<std::string>::const_iterator end=props.end();
std::set<std::string> const& props = q.property_names();
std::set<std::string>::const_iterator pos = props.begin();
std::set<std::string>::const_iterator end = props.end();
while (pos != end)
{
s <<",\""<<*pos<<"\"";
s << ",\"" << *pos << "\"";
++pos;
}
s << " from " << layerName_ ;
// execute existing SQL
OGRLayer* layer = dataset_->ExecuteSQL (s.str(), poly);
OGRLayer* layer = dataset_->ExecuteSQL(s.str(), poly);
// layer must be freed
dataset_->ReleaseResultSet (layer);
dataset_->ReleaseResultSet(layer);
#endif
if (indexed_)
{
filter_in_box filter(q.get_bbox());
return featureset_ptr(new ogr_index_featureset<filter_in_box> (*dataset_,
*layer_,
filter,
index_name_,
desc_.get_encoding(),
multiple_geometries_));
return featureset_ptr(new ogr_index_featureset<filter_in_box>(*dataset_,
*layer_,
filter,
index_name_,
desc_.get_encoding(),
multiple_geometries_));
}
else
{
@ -333,16 +369,16 @@ featureset_ptr ogr_datasource::features(query const& q) const
desc_.get_encoding(),
multiple_geometries_));
}
}
return featureset_ptr();
}
return featureset_ptr();
}
featureset_ptr ogr_datasource::features_at_point(coord2d const& pt) const
{
if (!is_bound_) bind();
if (!is_bound_) bind();
if (dataset_ && layer_)
{
if (dataset_ && layer_)
{
if (indexed_)
{
filter_at_point filter(pt);
@ -366,7 +402,6 @@ featureset_ptr ogr_datasource::features_at_point(coord2d const& pt) const
desc_.get_encoding(),
multiple_geometries_));
}
}
return featureset_ptr();
}
return featureset_ptr();
}

View file

@ -2,7 +2,7 @@
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2007 Artem Pavlenko
* Copyright (C) 2011 Artem Pavlenko
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@ -37,28 +37,29 @@
class ogr_datasource : public mapnik::datasource
{
public:
ogr_datasource(mapnik::parameters const& params, bool bind=true);
virtual ~ogr_datasource ();
int type() const;
static std::string name();
mapnik::featureset_ptr features(mapnik::query const& q) const;
mapnik::featureset_ptr features_at_point(mapnik::coord2d const& pt) const;
mapnik::box2d<double> envelope() const;
mapnik::layer_descriptor get_descriptor() const;
void bind() const;
private:
mutable mapnik::box2d<double> extent_;
int type_;
std::string dataset_name_;
mutable std::string index_name_;
mutable OGRDataSource* dataset_;
mutable OGRLayer* layer_;
mutable std::string layerName_;
mutable mapnik::layer_descriptor desc_;
bool multiple_geometries_;
mutable bool indexed_;
public:
ogr_datasource(mapnik::parameters const& params, bool bind=true);
virtual ~ogr_datasource ();
int type() const;
static std::string name();
mapnik::featureset_ptr features(mapnik::query const& q) const;
mapnik::featureset_ptr features_at_point(mapnik::coord2d const& pt) const;
mapnik::box2d<double> envelope() const;
mapnik::layer_descriptor get_descriptor() const;
void bind() const;
private:
mutable mapnik::box2d<double> extent_;
int type_;
std::string dataset_name_;
mutable std::string index_name_;
mutable OGRDataSource* dataset_;
mutable OGRLayer* layer_;
mutable std::string layerName_;
mutable mapnik::layer_descriptor desc_;
bool multiple_geometries_;
mutable bool indexed_;
};
#endif // OGR_DATASOURCE_HPP

View file

@ -2,7 +2,7 @@
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2007 Artem Pavlenko
* Copyright (C) 2011 Artem Pavlenko
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@ -51,4 +51,3 @@ private:
};
#endif // OGR_FEATURE_PTR_HPP

View file

@ -2,7 +2,7 @@
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2007 Artem Pavlenko
* Copyright (C) 2011 Artem Pavlenko
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@ -51,13 +51,13 @@ ogr_featureset::ogr_featureset(OGRDataSource & dataset,
OGRGeometry & extent,
const std::string& encoding,
const bool multiple_geometries)
: dataset_(dataset),
layer_(layer),
layerdef_(layer.GetLayerDefn()),
tr_(new transcoder(encoding)),
fidcolumn_(layer_.GetFIDColumn ()),
multiple_geometries_(multiple_geometries),
count_(0)
: dataset_(dataset),
layer_(layer),
layerdef_(layer.GetLayerDefn()),
tr_(new transcoder(encoding)),
fidcolumn_(layer_.GetFIDColumn ()),
multiple_geometries_(multiple_geometries),
count_(0)
{
layer_.SetSpatialFilter (&extent);
}
@ -67,13 +67,13 @@ ogr_featureset::ogr_featureset(OGRDataSource & dataset,
const mapnik::box2d<double> & extent,
const std::string& encoding,
const bool multiple_geometries)
: dataset_(dataset),
layer_(layer),
layerdef_(layer.GetLayerDefn()),
tr_(new transcoder(encoding)),
fidcolumn_(layer_.GetFIDColumn()),
multiple_geometries_(multiple_geometries),
count_(0)
: dataset_(dataset),
layer_(layer),
layerdef_(layer.GetLayerDefn()),
tr_(new transcoder(encoding)),
fidcolumn_(layer_.GetFIDColumn()),
multiple_geometries_(multiple_geometries),
count_(0)
{
layer_.SetSpatialFilterRect (extent.minx(),
extent.miny(),
@ -81,27 +81,31 @@ ogr_featureset::ogr_featureset(OGRDataSource & dataset,
extent.maxy());
}
ogr_featureset::~ogr_featureset() {}
ogr_featureset::~ogr_featureset()
{
}
feature_ptr ogr_featureset::next()
{
ogr_feature_ptr feat (layer_.GetNextFeature());
if ((*feat) != NULL)
{
// ogr feature ids start at 0, so add one to stay
// consistent with other mapnik datasources that start at 1
int feature_id = ((*feat)->GetFID() + 1);
const int feature_id = ((*feat)->GetFID() + 1);
feature_ptr feature(feature_factory::create(feature_id));
OGRGeometry* geom=(*feat)->GetGeometryRef();
if (geom && !geom->IsEmpty())
OGRGeometry* geom = (*feat)->GetGeometryRef();
if (geom && ! geom->IsEmpty())
{
ogr_converter::convert_geometry (geom, feature, multiple_geometries_);
ogr_converter::convert_geometry(geom, feature, multiple_geometries_);
}
#ifdef MAPNIK_DEBUG
else
{
std::clog << "### Warning: feature with null geometry: " << (*feat)->GetFID() << "\n";
std::clog << "OGR Plugin: feature with null geometry: "
<< (*feat)->GetFID() << std::endl;
}
#endif
++count_;
@ -109,30 +113,30 @@ feature_ptr ogr_featureset::next()
int fld_count = layerdef_->GetFieldCount();
for (int i = 0; i < fld_count; i++)
{
OGRFieldDefn* fld = layerdef_->GetFieldDefn (i);
OGRFieldType type_oid = fld->GetType ();
std::string fld_name = fld->GetNameRef ();
OGRFieldDefn* fld = layerdef_->GetFieldDefn(i);
const OGRFieldType type_oid = fld->GetType();
const std::string fld_name = fld->GetNameRef();
switch (type_oid)
{
case OFTInteger:
{
boost::put(*feature,fld_name,(*feat)->GetFieldAsInteger (i));
break;
boost::put(*feature, fld_name, (*feat)->GetFieldAsInteger(i));
break;
}
case OFTReal:
{
boost::put(*feature,fld_name,(*feat)->GetFieldAsDouble (i));
break;
boost::put(*feature, fld_name, (*feat)->GetFieldAsDouble(i));
break;
}
case OFTString:
case OFTWideString: // deprecated !
{
UnicodeString ustr = tr_->transcode((*feat)->GetFieldAsString (i));
boost::put(*feature,fld_name,ustr);
break;
UnicodeString ustr = tr_->transcode((*feat)->GetFieldAsString(i));
boost::put(*feature, fld_name, ustr);
break;
}
case OFTIntegerList:
@ -140,37 +144,37 @@ feature_ptr ogr_featureset::next()
case OFTStringList:
case OFTWideStringList: // deprecated !
{
#ifdef MAPNIK_DEBUG
std::clog << "OGR Plugin: unhandled type_oid=" << type_oid << std::endl;
#endif
break;
#ifdef MAPNIK_DEBUG
std::clog << "OGR Plugin: unhandled type_oid=" << type_oid << std::endl;
#endif
break;
}
case OFTBinary:
{
#ifdef MAPNIK_DEBUG
std::clog << "OGR Plugin: unhandled type_oid=" << type_oid << std::endl;
#endif
//boost::put(*feature,name,feat->GetFieldAsBinary (i, size));
break;
#ifdef MAPNIK_DEBUG
std::clog << "OGR Plugin: unhandled type_oid=" << type_oid << std::endl;
#endif
//boost::put(*feature,name,feat->GetFieldAsBinary (i, size));
break;
}
case OFTDate:
case OFTTime:
case OFTDateTime: // unhandled !
{
#ifdef MAPNIK_DEBUG
std::clog << "OGR Plugin: unhandled type_oid=" << type_oid << std::endl;
#endif
break;
#ifdef MAPNIK_DEBUG
std::clog << "OGR Plugin: unhandled type_oid=" << type_oid << std::endl;
#endif
break;
}
default: // unknown
{
#ifdef MAPNIK_DEBUG
std::clog << "OGR Plugin: unknown type_oid=" << type_oid << std::endl;
#endif
break;
#ifdef MAPNIK_DEBUG
std::clog << "OGR Plugin: unknown type_oid=" << type_oid << std::endl;
#endif
break;
}
}
}
@ -182,4 +186,3 @@ feature_ptr ogr_featureset::next()
#endif
return feature_ptr();
}

View file

@ -2,7 +2,7 @@
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2007 Artem Pavlenko
* Copyright (C) 2011 Artem Pavlenko
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@ -37,30 +37,32 @@
class ogr_featureset : public mapnik::Featureset
{
OGRDataSource & dataset_;
OGRLayer & layer_;
OGRFeatureDefn * layerdef_;
boost::scoped_ptr<mapnik::transcoder> tr_;
const char* fidcolumn_;
bool multiple_geometries_;
mutable int count_;
public:
ogr_featureset(OGRDataSource & dataset,
OGRLayer & layer,
OGRGeometry & extent,
const std::string& encoding,
const bool multiple_geometries);
public:
ogr_featureset(OGRDataSource & dataset,
OGRLayer & layer,
OGRGeometry & extent,
const std::string& encoding,
const bool multiple_geometries);
ogr_featureset(OGRDataSource & dataset,
OGRLayer & layer,
const mapnik::box2d<double> & extent,
const std::string& encoding,
const bool multiple_geometries);
virtual ~ogr_featureset();
mapnik::feature_ptr next();
private:
ogr_featureset(const ogr_featureset&);
const ogr_featureset& operator=(const ogr_featureset&);
ogr_featureset(OGRDataSource & dataset,
OGRLayer & layer,
const mapnik::box2d<double> & extent,
const std::string& encoding,
const bool multiple_geometries);
virtual ~ogr_featureset();
mapnik::feature_ptr next();
private:
ogr_featureset(const ogr_featureset&);
const ogr_featureset& operator=(const ogr_featureset&);
OGRDataSource& dataset_;
OGRLayer& layer_;
OGRFeatureDefn* layerdef_;
boost::scoped_ptr<mapnik::transcoder> tr_;
const char* fidcolumn_;
bool multiple_geometries_;
mutable int count_;
};
#endif // OGR_FEATURESET_HPP

View file

@ -2,7 +2,7 @@
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2006 Artem Pavlenko
* Copyright (C) 2011 Artem Pavlenko
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@ -37,18 +37,18 @@ template <typename filterT, typename IStream = std::ifstream>
class ogr_index
{
public:
static void query(const filterT& filter, IStream& file,std::vector<int>& pos);
static void query(const filterT& filter, IStream& file, std::vector<int>& pos);
private:
ogr_index();
~ogr_index();
ogr_index(const ogr_index&);
ogr_index& operator=(const ogr_index&);
static int read_ndr_integer(IStream & in);
static void read_envelope(IStream & in,box2d<double> &envelope);
static void query_node(const filterT& filter,IStream & in,std::vector<int>& pos);
static int read_ndr_integer(IStream& in);
static void read_envelope(IStream& in, box2d<double>& envelope);
static void query_node(const filterT& filter, IStream& in, std::vector<int>& pos);
};
template <typename filterT,typename IStream>
template <typename filterT, typename IStream>
void ogr_index<filterT, IStream>::query(const filterT& filter,IStream & file,std::vector<int>& pos)
{
file.seekg(16,std::ios::beg);
@ -56,50 +56,49 @@ void ogr_index<filterT, IStream>::query(const filterT& filter,IStream & file,std
}
template <typename filterT, typename IStream>
void ogr_index<filterT,IStream>::query_node(const filterT& filter,IStream & file,std::vector<int>& ids)
void ogr_index<filterT,IStream>::query_node(const filterT& filter, IStream& file, std::vector<int>& ids)
{
int offset=read_ndr_integer(file);
const int offset = read_ndr_integer(file);
box2d<double> node_ext;
read_envelope(file,node_ext);
read_envelope(file, node_ext);
int num_shapes=read_ndr_integer(file);
const int num_shapes = read_ndr_integer(file);
if (!filter.pass(node_ext))
if (! filter.pass(node_ext))
{
file.seekg(offset+num_shapes*4+4,std::ios::cur);
file.seekg(offset + num_shapes * 4 + 4, std::ios::cur);
return;
}
for (int i=0;i<num_shapes;++i)
for (int i = 0; i < num_shapes; ++i)
{
int id=read_ndr_integer(file);
const int id = read_ndr_integer(file);
ids.push_back(id);
}
int children=read_ndr_integer(file);
const int children = read_ndr_integer(file);
for (int j=0;j<children;++j)
for (int j = 0; j < children; ++j)
{
query_node(filter,file,ids);
query_node(filter, file, ids);
}
}
template <typename filterT,typename IStream>
int ogr_index<filterT,IStream>::read_ndr_integer(IStream & file)
template <typename filterT, typename IStream>
int ogr_index<filterT,IStream>::read_ndr_integer(IStream& file)
{
char b[4];
file.read(b,4);
return (b[0]&0xff) | (b[1]&0xff)<<8 | (b[2]&0xff)<<16 | (b[3]&0xff)<<24;
file.read(b, 4);
return (b[0] & 0xff) | (b[1] & 0xff) << 8 | (b[2] & 0xff) << 16 | (b[3] & 0xff) << 24;
}
template <typename filterT,typename IStream>
void ogr_index<filterT,IStream>::read_envelope(IStream & file,box2d<double>& envelope)
template <typename filterT, typename IStream>
void ogr_index<filterT, IStream>::read_envelope(IStream& file, box2d<double>& envelope)
{
file.read(reinterpret_cast<char*>(&envelope),sizeof(envelope));
file.read(reinterpret_cast<char*>(&envelope), sizeof(envelope));
}
#endif //SHP_INDEX_HH
#endif // OGR_INDEX_HH

View file

@ -2,7 +2,7 @@
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2007 Artem Pavlenko
* Copyright (C) 2011 Artem Pavlenko
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@ -32,29 +32,29 @@
template <typename filterT>
class ogr_index_featureset : public mapnik::Featureset
{
OGRDataSource & dataset_;
OGRLayer & layer_;
OGRFeatureDefn * layerdef_;
filterT filter_;
std::vector<int> ids_;
std::vector<int>::iterator itr_;
boost::scoped_ptr<mapnik::transcoder> tr_;
const char* fidcolumn_;
bool multiple_geometries_;
public:
ogr_index_featureset(OGRDataSource& dataset,
OGRLayer& layer,
const filterT& filter,
const std::string& index_file,
const std::string& encoding,
const bool multiple_geometries);
virtual ~ogr_index_featureset();
mapnik::feature_ptr next();
public:
ogr_index_featureset(OGRDataSource & dataset,
OGRLayer & layer,
const filterT& filter,
const std::string& index_file,
const std::string& encoding,
const bool multiple_geometries);
virtual ~ogr_index_featureset();
mapnik::feature_ptr next();
private:
//no copying
ogr_index_featureset(const ogr_index_featureset&);
ogr_index_featureset& operator=(const ogr_index_featureset&);
private:
ogr_index_featureset(const ogr_index_featureset&);
ogr_index_featureset& operator=(const ogr_index_featureset&);
OGRDataSource& dataset_;
OGRLayer& layer_;
OGRFeatureDefn* layerdef_;
filterT filter_;
std::vector<int> ids_;
std::vector<int>::iterator itr_;
boost::scoped_ptr<mapnik::transcoder> tr_;
const char* fidcolumn_;
bool multiple_geometries_;
};
#endif // OGR_FEATURESET_HPP
#endif // OGR_INDEX_FEATURESET_HPP

View file

@ -65,6 +65,10 @@ raster_datasource::raster_datasource(const parameters& params, bool bind)
else
filename_ = *file;
multi_tiles_ = *params_.get<bool>("multi", false);
tile_size_ = *params_.get<unsigned>("tile_size", 256);
tile_stride_ = *params_.get<unsigned>("tile_stride", 1);
format_=*params_.get<std::string>("format","tiff");
boost::optional<double> lox = params_.get<double>("lox");
@ -96,33 +100,50 @@ void raster_datasource::bind() const
{
if (is_bound_) return;
if (! boost::filesystem::exists(filename_))
throw datasource_exception("Raster Plugin: " + filename_ + " does not exist");
try
{
std::auto_ptr<image_reader> reader(mapnik::get_image_reader(filename_, format_));
if (reader.get())
{
width_ = reader->width();
height_ = reader->height();
if (multi_tiles_)
{
boost::optional<unsigned> x_width = params_.get<unsigned>("x_width");
boost::optional<unsigned> y_width = params_.get<unsigned>("y_width");
#ifdef MAPNIK_DEBUG
std::clog << "Raster Plugin: RASTER SIZE(" << width_ << "," << height_ << ")" << std::endl;
#endif
}
if (!x_width)
throw datasource_exception("Raster Plugin: x-width parameter not supplied for multi-tiled data source.");
if (!y_width)
throw datasource_exception("Raster Plugin: y-width parameter not supplied for multi-tiled data source.");
width_ = x_width.get() * tile_size_;
height_ = y_width.get() * tile_size_;
}
catch (mapnik::image_reader_exception const& ex)
else
{
std::cerr << "Raster Plugin: image reader exception caught: " << ex.what() << std::endl;
throw;
}
catch (...)
{
std::cerr << "Raster Plugin: exception caught" << std::endl;
throw;
if (! boost::filesystem::exists(filename_))
throw datasource_exception("Raster Plugin: " + filename_ + " does not exist");
try
{
std::auto_ptr<image_reader> reader(mapnik::get_image_reader(filename_, format_));
if (reader.get())
{
width_ = reader->width();
height_ = reader->height();
}
}
catch (mapnik::image_reader_exception const& ex)
{
std::cerr << "Raster Plugin: image reader exception caught: " << ex.what() << std::endl;
throw;
}
catch (...)
{
std::cerr << "Raster Plugin: exception caught" << std::endl;
throw;
}
}
#ifdef MAPNIK_DEBUG
std::clog << "Raster Plugin: RASTER SIZE(" << width_ << "," << height_ << ")" << std::endl;
#endif
is_bound_ = true;
}
@ -165,7 +186,16 @@ featureset_ptr raster_datasource::features(query const& q) const
std::clog << "Raster Plugin: BOX SIZE(" << width << " " << height << ")" << std::endl;
#endif
if (width * height > 512*512)
if (multi_tiles_)
{
#ifdef MAPNIK_DEBUG
std::clog << "Raster Plugin: MULTI-TILED policy" << std::endl;
#endif
tiled_multi_file_policy policy(filename_, format_, tile_size_, extent_, q.get_bbox(), width_, height_, tile_stride_);
return boost::make_shared<raster_featureset<tiled_multi_file_policy> >(policy, extent_, q);
}
else if (width * height > 512*512)
{
#ifdef MAPNIK_DEBUG
std::clog << "Raster Plugin: TILED policy" << std::endl;

View file

@ -37,6 +37,9 @@ class raster_datasource : public mapnik::datasource
std::string format_;
mapnik::box2d<double> extent_;
bool extent_initialized_;
bool multi_tiles_;
unsigned tile_size_;
unsigned tile_stride_;
mutable unsigned width_;
mutable unsigned height_;
public:

View file

@ -27,6 +27,7 @@
#include "raster_featureset.hpp"
#include <boost/algorithm/string/replace.hpp>
using mapnik::query;
using mapnik::CoordTransform;
@ -67,16 +68,18 @@ feature_ptr raster_featureset<LookupPolicy>::next()
std::clog << "Raster Plugin: READER = " << curIter_->format() << " " << curIter_->file()
<< " size(" << curIter_->width() << "," << curIter_->height() << ")" << std::endl;
#endif
if (reader.get())
{
int image_width=reader->width();
int image_height=reader->height();
int image_width = policy_.img_width(reader->width());
int image_height = policy_.img_height(reader->height());
if (image_width>0 && image_height>0)
{
CoordTransform t(image_width,image_height,extent_,0,0);
box2d<double> intersect=bbox_.intersect(curIter_->envelope());
box2d<double> ext=t.forward(intersect);
box2d<double> rem=policy_.transform(ext);
if ( ext.width()>0.5 && ext.height()>0.5 )
{
//select minimum raster containing whole ext
@ -96,7 +99,8 @@ feature_ptr raster_featureset<LookupPolicy>::next()
int width = end_x - x_off;
int height = end_y - y_off;
//calculate actual box2d of returned raster
box2d<double> feature_raster_extent(x_off, y_off, x_off+width, y_off+height);
box2d<double> feature_raster_extent(rem.minx() + x_off, rem.miny() + y_off,
rem.maxx() + x_off + width, rem.maxy() + y_off + height);
intersect = t.backward(feature_raster_extent);
image_data_32 image(width,height);
@ -121,5 +125,20 @@ feature_ptr raster_featureset<LookupPolicy>::next()
return feature_ptr();
}
std::string
tiled_multi_file_policy::interpolate(std::string const &pattern, int x, int y) const
{
// TODO: make from some sort of configurable interpolation
int tms_y = tile_stride_ * ((image_height_ / tile_size_) - y - 1);
int tms_x = tile_stride_ * x;
std::string xs = (boost::format("%03d/%03d/%03d") % (tms_x / 1000000) % ((tms_x / 1000) % 1000) % (tms_x % 1000)).str();
std::string ys = (boost::format("%03d/%03d/%03d") % (tms_y / 1000000) % ((tms_y / 1000) % 1000) % (tms_y % 1000)).str();
std::string rv(pattern);
boost::algorithm::replace_all(rv, "${x}", xs);
boost::algorithm::replace_all(rv, "${y}", ys);
return rv;
}
template class raster_featureset<single_file_policy>;
template class raster_featureset<tiled_file_policy>;
template class raster_featureset<tiled_multi_file_policy>;

View file

@ -29,7 +29,7 @@
// boost
#include <boost/utility.hpp>
#include <boost/format.hpp>
class single_file_policy
{
@ -95,6 +95,21 @@ public:
{
return const_iterator();
}
inline int img_width(int reader_width) const
{
return reader_width;
}
inline int img_height(int reader_height) const
{
return reader_height;
}
inline box2d<double> transform(box2d<double> &) const
{
return box2d<double>(0, 0, 0, 0);
}
};
class tiled_file_policy
@ -154,11 +169,125 @@ public:
return infos_.end();
}
inline int img_width(int reader_width) const
{
return reader_width;
}
inline int img_height(int reader_height) const
{
return reader_height;
}
inline box2d<double> transform(box2d<double> &) const
{
return box2d<double>(0, 0, 0, 0);
}
private:
std::vector<raster_info> infos_;
};
class tiled_multi_file_policy
{
public:
typedef std::vector<raster_info>::const_iterator const_iterator;
tiled_multi_file_policy(std::string const& file_pattern, std::string const& format, unsigned tile_size,
box2d<double> extent, box2d<double> bbox,unsigned width, unsigned height,
unsigned tile_stride)
: image_width_(width), image_height_(height), tile_size_(tile_size), tile_stride_(tile_stride)
{
double lox = extent.minx();
double loy = extent.miny();
int max_x = int(std::ceil(double(width)/double(tile_size)));
int max_y = int(std::ceil(double(height)/double(tile_size)));
double pixel_x = extent.width()/double(width);
double pixel_y = extent.height()/double(height);
#ifdef MAPNIK_DEBUG
std::clog << "Raster Plugin: PIXEL SIZE("<< pixel_x << "," << pixel_y << ")" << std::endl;
#endif
// intersection of query with extent => new query
box2d<double> e = bbox.intersect(extent);
const int x_min = int(std::floor((e.minx() - lox) / (tile_size * pixel_x)));
const int y_min = int(std::floor((e.miny() - loy) / (tile_size * pixel_y)));
const int x_max = int(std::ceil((e.maxx() - lox) / (tile_size * pixel_x)));
const int y_max = int(std::ceil((e.maxy() - loy) / (tile_size * pixel_y)));
for (int x = x_min ; x < x_max ; ++x)
{
for (int y = y_min ; y < y_max ; ++y)
{
// x0, y0, x1, y1 => projection-space image coordinates.
double x0 = lox + x*tile_size*pixel_x;
double y0 = loy + y*tile_size*pixel_y;
double x1 = x0 + tile_size*pixel_x;
double y1 = y0 + tile_size*pixel_y;
// check if it intersects the query
if (e.intersects(box2d<double>(x0,y0,x1,y1)))
{
// tile_box => intersection of tile with query in projection-space.
box2d<double> tile_box = e.intersect(box2d<double>(x0,y0,x1,y1));
std::string file = interpolate(file_pattern, x, y);
raster_info info(file,format,tile_box,tile_size,tile_size);
infos_.push_back(info);
}
}
}
#ifdef MAPNIK_DEBUG
std::clog << "Raster Plugin: INFO SIZE=" << infos_.size() << " " << file_pattern << std::endl;
#endif
}
const_iterator begin()
{
return infos_.begin();
}
const_iterator end()
{
return infos_.end();
}
inline int img_width(int) const
{
return image_width_;
}
inline int img_height(int) const
{
return image_height_;
}
inline box2d<double> transform(box2d<double> &box) const
{
int x_offset = int(std::floor(box.minx() / tile_size_));
int y_offset = int(std::floor(box.miny() / tile_size_));
box2d<double> rem(x_offset * tile_size_, y_offset * tile_size_,
x_offset * tile_size_, y_offset * tile_size_);
box.init(box.minx() - rem.minx(),
box.miny() - rem.miny(),
box.maxx() - rem.maxx(),
box.maxy() - rem.maxy());
return rem;
}
private:
std::string interpolate(std::string const &pattern, int x, int y) const;
unsigned int image_width_, image_height_, tile_size_, tile_stride_;
std::vector<raster_info> infos_;
};
template <typename LookupPolicy>
class raster_featureset : public mapnik::Featureset

View file

@ -32,6 +32,7 @@
// boost
#include <boost/shared_ptr.hpp>
#include <boost/algorithm/string.hpp>
// sqlite
extern "C" {
@ -45,13 +46,11 @@ class sqlite_utils
{
public:
static void dequote(std::string& s)
static void dequote(std::string & z)
{
if (s[0] == '[' || s[0] == '\'' || s[0] == '"' || s[0] == '`')
{
s = s.substr(1, s.length() - 1);
}
boost::algorithm::trim_if(z,boost::algorithm::is_any_of("[]'\"`"));
}
};

View file

@ -73,7 +73,7 @@
// boost
#include <boost/utility.hpp>
#include <boost/make_shared.hpp>
// stl
#ifdef MAPNIK_DEBUG
@ -121,8 +121,31 @@ agg_renderer<T>::agg_renderer(Map const& m, T & pixmap, double scale_factor, uns
t_(m.width(),m.height(),m.get_current_extent(),offset_x,offset_y),
font_engine_(),
font_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()))),
ras_ptr(new rasterizer)
{
setup(m);
}
template <typename T>
agg_renderer<T>::agg_renderer(Map const& m, T & pixmap, boost::shared_ptr<label_collision_detector4> detector,
double scale_factor, unsigned offset_x, unsigned offset_y)
: feature_style_processor<agg_renderer>(m, scale_factor),
pixmap_(pixmap),
width_(pixmap_.width()),
height_(pixmap_.height()),
scale_factor_(scale_factor),
t_(m.width(),m.height(),m.get_current_extent(),offset_x,offset_y),
font_engine_(),
font_manager_(font_engine_),
detector_(detector),
ras_ptr(new rasterizer)
{
setup(m);
}
template <typename T>
void agg_renderer<T>::setup(Map const &m)
{
boost::optional<color> const& bg = m.background();
if (bg) pixmap_.set_background(*bg);
@ -189,7 +212,7 @@ void agg_renderer<T>::start_layer_processing(layer const& lay)
#endif
if (lay.clear_label_cache())
{
detector_.clear();
detector_->clear();
}
}

View file

@ -77,12 +77,12 @@ void agg_renderer<T>::process(glyph_symbolizer const& sym,
// final box so we can check for a valid placement
box2d<double> dim = ren.prepare_glyphs(path.get());
box2d<double> ext(x-dim.width()/2, y-dim.height()/2, x+dim.width()/2, y+dim.height()/2);
if ((sym.get_allow_overlap() || detector_.has_placement(ext)) &&
(!sym.get_avoid_edges() || detector_.extent().contains(ext)))
if ((sym.get_allow_overlap() || detector_->has_placement(ext)) &&
(!sym.get_avoid_edges() || detector_->extent().contains(ext)))
{
// Placement is valid, render glyph and update detector.
ren.render(x, y);
detector_.insert(ext);
detector_->insert(ext);
metawriter_with_properties writer = sym.get_metawriter();
if (writer.first) writer.first->add_box(ext, feature, t_, writer.second);
}

View file

@ -109,7 +109,7 @@ void agg_renderer<T>::process(markers_symbolizer const& sym,
}
path_type path(t_,geom,prj_trans);
markers_placement<path_type, label_collision_detector4> placement(path, extent, detector_,
markers_placement<path_type, label_collision_detector4> placement(path, extent, *detector_,
sym.get_spacing() * scale_factor_,
sym.get_max_error(),
sym.get_allow_overlap());
@ -194,7 +194,7 @@ void agg_renderer<T>::process(markers_symbolizer const& sym,
box2d<double> label_ext (px, py, px + dx +1, py + dy +1);
if (sym.get_allow_overlap() ||
detector_.has_placement(label_ext))
detector_->has_placement(label_ext))
{
agg::ellipse c(x, y, w, h);
marker.concat_path(c);
@ -215,7 +215,7 @@ void agg_renderer<T>::process(markers_symbolizer const& sym,
ren.color(agg::rgba8(s_r, s_g, s_b, int(s_a*stroke_.get_opacity())));
agg::render_scanlines(*ras_ptr, sl_line, ren);
}
detector_.insert(label_ext);
detector_->insert(label_ext);
if (writer.first) writer.first->add_box(label_ext, feature, t_, writer.second);
}
}
@ -226,7 +226,7 @@ void agg_renderer<T>::process(markers_symbolizer const& sym,
marker.concat_path(arrow_);
path_type path(t_,geom,prj_trans);
markers_placement<path_type, label_collision_detector4> placement(path, extent, detector_,
markers_placement<path_type, label_collision_detector4> placement(path, extent, *detector_,
sym.get_spacing() * scale_factor_,
sym.get_max_error(),
sym.get_allow_overlap());

View file

@ -99,13 +99,13 @@ void agg_renderer<T>::process(point_symbolizer const& sym,
label_ext.re_center(x,y);
if (sym.get_allow_overlap() ||
detector_.has_placement(label_ext))
detector_->has_placement(label_ext))
{
render_marker(floor(x - 0.5 * w),floor(y - 0.5 * h) ,**marker,tr, sym.get_opacity());
if (!sym.get_ignore_placement())
detector_.insert(label_ext);
detector_->insert(label_ext);
metawriter_with_properties writer = sym.get_metawriter();
if (writer.first) writer.first->add_box(label_ext, feature, t_, writer.second);
}

View file

@ -135,7 +135,7 @@ void agg_renderer<T>::process(shield_symbolizer const& sym,
ren.set_halo_radius(sym.get_halo_radius() * scale_factor_);
ren.set_opacity(sym.get_text_opacity());
placement_finder<label_collision_detector4> finder(detector_);
placement_finder<label_collision_detector4> finder(*detector_);
string_info info(text);
@ -210,13 +210,13 @@ void agg_renderer<T>::process(shield_symbolizer const& sym,
label_ext.re_center(label_x,label_y);
}
if ( sym.get_allow_overlap() || detector_.has_placement(label_ext) )
if ( sym.get_allow_overlap() || detector_->has_placement(label_ext) )
{
render_marker(px,py,**marker,tr,sym.get_opacity());
box2d<double> dim = ren.prepare_glyphs(&text_placement.placements[0]);
ren.render(x,y);
detector_.insert(label_ext);
detector_->insert(label_ext);
finder.update_detector(text_placement);
if (writer.first) {
writer.first->add_box(label_ext, feature, t_, writer.second);

View file

@ -110,7 +110,7 @@ void agg_renderer<T>::process(text_symbolizer const& sym,
ren.set_opacity(sym.get_text_opacity());
box2d<double> dims(0,0,width_,height_);
placement_finder<label_collision_detector4> finder(detector_,dims);
placement_finder<label_collision_detector4> finder(*detector_,dims);
string_info info(text);

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View file

@ -18,10 +18,6 @@ class FeatureTest(unittest.TestCase):
f = self.makeOne(1, 'POLYGON ((35 10, 10 20, 15 40, 45 45, 35 10),(20 30, 35 35, 30 20, 20 30))', foo="bar")
self.failUnlessEqual(f['foo'], 'bar')
self.failUnlessEqual(f.envelope(),Box2d(10.0,10.0,45.0,45.0))
area = 0.0
for g in f.geometries():
area += g.area()
self.failUnlessEqual(area,-450.0)
def test_set_get_properties(self):
f = self.makeOne(1)

View file

@ -0,0 +1,70 @@
#!/usr/bin/env python
from nose.tools import *
from utilities import execution_path, save_data, contains_word
import os, mapnik2
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_multi_tile_policy():
srs = '+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs'
lyr = mapnik2.Layer('raster')
lyr.datasource = mapnik2.Raster(
file = '../data/raster_tiles/${x}/${y}.tif',
lox = -180,
loy = -90,
hix = 180,
hiy = 90,
multi = 1,
tile_size = 256,
x_width = 2,
y_width = 2
)
lyr.srs = srs
_map = mapnik2.Map(256, 256, srs)
style = mapnik2.Style()
rule = mapnik2.Rule()
sym = mapnik2.RasterSymbolizer()
rule.symbols.append(sym)
style.rules.append(rule)
_map.append_style('foo', style)
lyr.styles.append('foo')
_map.layers.append(lyr)
_map.zoom_to_box(lyr.envelope())
im = mapnik2.Image(_map.width, _map.height)
mapnik2.render(_map, im)
save_data('test_multi_tile_policy.png', im.tostring('png'))
# test green chunk
assert im.view(0,64,1,1).tostring() == '\x00\xff\x00\xff'
assert im.view(127,64,1,1).tostring() == '\x00\xff\x00\xff'
assert im.view(0,127,1,1).tostring() == '\x00\xff\x00\xff'
assert im.view(127,127,1,1).tostring() == '\x00\xff\x00\xff'
# test blue chunk
assert im.view(128,64,1,1).tostring() == '\x00\x00\xff\xff'
assert im.view(255,64,1,1).tostring() == '\x00\x00\xff\xff'
assert im.view(128,127,1,1).tostring() == '\x00\x00\xff\xff'
assert im.view(255,127,1,1).tostring() == '\x00\x00\xff\xff'
# test red chunk
assert im.view(0,128,1,1).tostring() == '\xff\x00\x00\xff'
assert im.view(127,128,1,1).tostring() == '\xff\x00\x00\xff'
assert im.view(0,191,1,1).tostring() == '\xff\x00\x00\xff'
assert im.view(127,191,1,1).tostring() == '\xff\x00\x00\xff'
# test magenta chunk
assert im.view(128,128,1,1).tostring() == '\xff\x00\xff\xff'
assert im.view(255,128,1,1).tostring() == '\xff\x00\xff\xff'
assert im.view(128,191,1,1).tostring() == '\xff\x00\xff\xff'
assert im.view(255,191,1,1).tostring() == '\xff\x00\xff\xff'
if __name__ == "__main__":
setup()
[eval(run)() for run in dir() if 'test_' in run]

View file

@ -58,6 +58,37 @@ def test_attachdb_with_explicit_index():
'insert into scratch.myindex values (1,-7799225.5,-7778571.0,1393264.125,1417719.375)\n'
)
def test_dequoting_of_subqueries():
# The point table and index is in the qgis_spatiallite.sqlite
# database. If either is not found, then this fails
ds = mapnik2.SQLite(file='../data/sqlite/world.sqlite',
table='world_merc',
)
fs = ds.featureset()
feature = fs.next()
eq_(feature['OGC_FID'],1)
eq_(feature['fips'],u'AC')
# TODO:
# select * from world_merc fails
# as rowid is dropped
ds = mapnik2.SQLite(file='../data/sqlite/world.sqlite',
table='(select *,rowid from world_merc)',
)
fs = ds.featureset()
feature = fs.next()
print feature
eq_(feature['OGC_FID'],1)
eq_(feature['fips'],u'AC')
ds = mapnik2.SQLite(file='../data/sqlite/world.sqlite',
table='(select GEOMETRY,OGC_FID as rowid,fips from world_merc)',
)
fs = ds.featureset()
feature = fs.next()
print feature
eq_(feature['rowid'],1)
eq_(feature['fips'],u'AC')
if __name__ == "__main__":
setup()

View file

@ -69,8 +69,8 @@ SOURCES += \
$$PWD/../plugins/input/osm/osm_featureset.cpp \
$$PWD/../plugins/input/osm/osm_datasource.cpp \
$$PWD/../plugins/input/osm/render.cpp \
$$PWD/../plugins/input/postgis/postgis.cpp \
$$PWD/../plugins/input/postgis/postgisfs.cpp \
$$PWD/../plugins/input/postgis/postgis_datasource.cpp \
$$PWD/../plugins/input/postgis/postgis_featureset.cpp \
$$PWD/../plugins/input/raster/raster_info.cpp \
$$PWD/../plugins/input/raster/raster_featureset.cpp \
$$PWD/../plugins/input/raster/raster_datasource.cpp \