Merge pull request #1021 from mapnik/geometry_type_descriptor
Add Geometry type descriptor
This commit is contained in:
commit
9407991be4
47 changed files with 4919 additions and 160 deletions
|
@ -233,9 +233,6 @@ class _Projection(Projection,_injector):
|
|||
|
||||
class _Datasource(Datasource,_injector):
|
||||
|
||||
def describe(self):
|
||||
return Describe(self)
|
||||
|
||||
def all_features(self,fields=None):
|
||||
query = Query(self.envelope())
|
||||
attributes = fields or self.fields()
|
||||
|
@ -710,7 +707,6 @@ __all__ = [
|
|||
'SQLite',
|
||||
'Osm',
|
||||
'Kismet',
|
||||
'Describe',
|
||||
# version and environment
|
||||
'mapnik_version_string',
|
||||
'mapnik_version',
|
||||
|
|
|
@ -82,30 +82,15 @@ boost::shared_ptr<mapnik::datasource> create_datasource(const dict& d)
|
|||
return mapnik::datasource_cache::create(params, bind);
|
||||
}
|
||||
|
||||
std::string describe(boost::shared_ptr<mapnik::datasource> const& ds)
|
||||
boost::python::dict describe(boost::shared_ptr<mapnik::datasource> const& ds)
|
||||
{
|
||||
std::stringstream ss;
|
||||
if (ds)
|
||||
{
|
||||
ss << ds->get_descriptor() << "\n";
|
||||
}
|
||||
else
|
||||
{
|
||||
ss << "Null\n";
|
||||
}
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
std::string encoding(boost::shared_ptr<mapnik::datasource> const& ds)
|
||||
{
|
||||
layer_descriptor ld = ds->get_descriptor();
|
||||
return ld.get_encoding();
|
||||
}
|
||||
|
||||
std::string name(boost::shared_ptr<mapnik::datasource> const& ds)
|
||||
{
|
||||
layer_descriptor ld = ds->get_descriptor();
|
||||
return ld.get_name();
|
||||
boost::python::dict description;
|
||||
mapnik::layer_descriptor ld = ds->get_descriptor();
|
||||
description["type"] = ds->type();
|
||||
description["name"] = ld.get_name();
|
||||
description["geometry_type"] = ds->get_geometry_type();
|
||||
description["encoding"] = ld.get_encoding();
|
||||
return description;
|
||||
}
|
||||
|
||||
boost::python::list fields(boost::shared_ptr<mapnik::datasource> const& ds)
|
||||
|
@ -163,23 +148,34 @@ void export_datasource()
|
|||
{
|
||||
using namespace boost::python;
|
||||
|
||||
enum_<mapnik::datasource::datasource_t>("DataType")
|
||||
.value("Vector",mapnik::datasource::Vector)
|
||||
.value("Raster",mapnik::datasource::Raster)
|
||||
;
|
||||
|
||||
enum_<mapnik::datasource::geometry_t>("DataGeometryType")
|
||||
.value("Point",mapnik::datasource::Point)
|
||||
.value("LineString",mapnik::datasource::LineString)
|
||||
.value("Polygon",mapnik::datasource::Polygon)
|
||||
.value("Collection",mapnik::datasource::Collection)
|
||||
;
|
||||
|
||||
class_<datasource,boost::shared_ptr<datasource>,
|
||||
boost::noncopyable>("Datasource",no_init)
|
||||
.def("type",&datasource::type)
|
||||
.def("geometry_type",&datasource::get_geometry_type)
|
||||
.def("describe",&describe)
|
||||
.def("envelope",&datasource::envelope)
|
||||
.def("descriptor",&datasource::get_descriptor) //todo
|
||||
.def("features",&datasource::features)
|
||||
.def("bind",&datasource::bind)
|
||||
.def("fields",&fields)
|
||||
.def("field_types",&field_types)
|
||||
.def("encoding",&encoding) //todo expose as property
|
||||
.def("name",&name)
|
||||
.def("features_at_point",&datasource::features_at_point)
|
||||
.def("params",&datasource::params,return_value_policy<copy_const_reference>(),
|
||||
"The configuration parameters of the data source. "
|
||||
"These vary depending on the type of data source.")
|
||||
;
|
||||
|
||||
def("Describe",&describe);
|
||||
def("CreateDatasource",&create_datasource);
|
||||
|
||||
class_<point_datasource, bases<datasource>, boost::noncopyable>("PointDatasource", init<>())
|
||||
|
|
|
@ -33,7 +33,6 @@
|
|||
#include <mapnik/metawriter_inmem.hpp>
|
||||
#include <mapnik/util/deepcopy.hpp>
|
||||
#include "mapnik_enumeration.hpp"
|
||||
#include "python_optional.hpp"
|
||||
|
||||
using mapnik::color;
|
||||
using mapnik::coord;
|
||||
|
@ -213,8 +212,6 @@ void export_map()
|
|||
.value("ADJUST_CANVAS_HEIGHT", mapnik::Map::ADJUST_CANVAS_HEIGHT)
|
||||
;
|
||||
|
||||
python_optional<mapnik::color> ();
|
||||
python_optional<mapnik::box2d<double> > ();
|
||||
class_<std::vector<layer> >("Layers")
|
||||
.def(vector_indexing_suite<std::vector<layer> >())
|
||||
;
|
||||
|
|
|
@ -85,6 +85,7 @@ void export_label_collision_detector();
|
|||
#include <mapnik/save_map.hpp>
|
||||
#include "python_grid_utils.hpp"
|
||||
#include "mapnik_value_converter.hpp"
|
||||
#include "python_optional.hpp"
|
||||
|
||||
#if defined(HAVE_CAIRO) && defined(HAVE_PYCAIRO)
|
||||
#include <pycairo.h>
|
||||
|
@ -630,6 +631,9 @@ BOOST_PYTHON_MODULE(_mapnik)
|
|||
def("has_cairo", &has_cairo, "Get cairo library status");
|
||||
def("has_pycairo", &has_pycairo, "Get pycairo module status");
|
||||
|
||||
python_optional<mapnik::color> ();
|
||||
python_optional<mapnik::box2d<double> > ();
|
||||
python_optional<mapnik::datasource::geometry_t> ();
|
||||
register_ptr_to_python<mapnik::expression_ptr>();
|
||||
register_ptr_to_python<mapnik::path_expression_ptr>();
|
||||
to_python_converter<mapnik::value_holder,mapnik_param_to_python>();
|
||||
|
|
|
@ -40,7 +40,7 @@
|
|||
#include <string>
|
||||
|
||||
namespace mapnik {
|
||||
|
||||
|
||||
typedef MAPNIK_DECL boost::shared_ptr<Feature> feature_ptr;
|
||||
|
||||
struct MAPNIK_DECL Featureset
|
||||
|
@ -68,12 +68,19 @@ public:
|
|||
|
||||
class MAPNIK_DECL datasource : private boost::noncopyable
|
||||
{
|
||||
public:
|
||||
public:
|
||||
enum datasource_t {
|
||||
Vector,
|
||||
Raster
|
||||
};
|
||||
|
||||
enum geometry_t {
|
||||
Point = 1,
|
||||
LineString = 2,
|
||||
Polygon = 3,
|
||||
Collection = 4
|
||||
};
|
||||
|
||||
datasource (parameters const& params)
|
||||
: params_(params),
|
||||
is_bound_(false)
|
||||
|
@ -95,7 +102,7 @@ public:
|
|||
* @brief Get the type of the datasource
|
||||
* @return The type of the datasource (Vector or Raster)
|
||||
*/
|
||||
virtual int type() const=0;
|
||||
virtual datasource_t type() const=0;
|
||||
|
||||
/*!
|
||||
* @brief Connect to the datasource
|
||||
|
@ -105,6 +112,7 @@ public:
|
|||
virtual featureset_ptr features(const query& q) const=0;
|
||||
virtual featureset_ptr features_at_point(coord2d const& pt) const=0;
|
||||
virtual box2d<double> envelope() const=0;
|
||||
virtual boost::optional<geometry_t> get_geometry_type() const=0;
|
||||
virtual layer_descriptor get_descriptor() const=0;
|
||||
virtual ~datasource() {};
|
||||
protected:
|
||||
|
|
|
@ -45,22 +45,22 @@ public:
|
|||
: name_(other.name_),
|
||||
encoding_(other.encoding_),
|
||||
desc_ar_(other.desc_ar_) {}
|
||||
|
||||
|
||||
void set_name(std::string const& name)
|
||||
{
|
||||
name_=name;
|
||||
name_ = name;
|
||||
}
|
||||
|
||||
|
||||
std::string const& get_name() const
|
||||
{
|
||||
return name_;
|
||||
}
|
||||
|
||||
void set_encoding(std::string const& encoding)
|
||||
|
||||
void set_encoding(std::string const& encoding)
|
||||
{
|
||||
encoding_=encoding;
|
||||
encoding_ = encoding;
|
||||
}
|
||||
|
||||
|
||||
std::string const& get_encoding() const
|
||||
{
|
||||
return encoding_;
|
||||
|
@ -70,12 +70,12 @@ public:
|
|||
{
|
||||
desc_ar_.push_back(desc);
|
||||
}
|
||||
|
||||
|
||||
std::vector<attribute_descriptor> const& get_descriptors() const
|
||||
{
|
||||
return desc_ar_;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
std::vector<attribute_descriptor>& get_descriptors()
|
||||
{
|
||||
return desc_ar_;
|
||||
|
@ -86,20 +86,19 @@ private:
|
|||
std::string encoding_;
|
||||
std::vector<attribute_descriptor> desc_ar_;
|
||||
};
|
||||
|
||||
|
||||
template <typename charT,typename traits>
|
||||
inline std::basic_ostream<charT,traits>&
|
||||
operator << (std::basic_ostream<charT,traits>& out,
|
||||
layer_descriptor const& ld)
|
||||
{
|
||||
out << "name=" << ld.get_name() << "\n";
|
||||
out << "encoding=" << ld.get_encoding() << "\n";
|
||||
std::vector<attribute_descriptor> const& desc_ar=ld.get_descriptors();
|
||||
std::vector<attribute_descriptor>::const_iterator pos=desc_ar.begin();
|
||||
out << "name: " << ld.get_name() << "\n";
|
||||
out << "encoding: " << ld.get_encoding() << "\n";
|
||||
std::vector<attribute_descriptor> const& desc_ar = ld.get_descriptors();
|
||||
std::vector<attribute_descriptor>::const_iterator pos = desc_ar.begin();
|
||||
while (pos != desc_ar.end())
|
||||
{
|
||||
out << *pos++ << "\n";
|
||||
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
|
|
@ -39,10 +39,11 @@ public:
|
|||
memory_datasource();
|
||||
virtual ~memory_datasource();
|
||||
void push(feature_ptr feature);
|
||||
int type() const;
|
||||
datasource::datasource_t type() const;
|
||||
featureset_ptr features(const query& q) const;
|
||||
featureset_ptr features_at_point(coord2d const& pt) const;
|
||||
box2d<double> envelope() const;
|
||||
boost::optional<geometry_t> get_geometry_type() const;
|
||||
layer_descriptor get_descriptor() const;
|
||||
size_t size() const;
|
||||
void clear();
|
||||
|
@ -59,8 +60,7 @@ class MAPNIK_DECL point_datasource : public memory_datasource {
|
|||
public:
|
||||
point_datasource() :
|
||||
feature_id_(1) {}
|
||||
void add_point(double x, double y, const char* key, const char* value);
|
||||
inline int type() const { return datasource::Vector; }
|
||||
void add_point(double x, double y, const char* key, const char* value);
|
||||
|
||||
private:
|
||||
int feature_id_;
|
||||
|
|
|
@ -39,8 +39,8 @@
|
|||
namespace mapnik
|
||||
{
|
||||
typedef boost::variant<value_null,int,double,std::string> value_holder;
|
||||
typedef std::pair<const std::string, value_holder> parameter;
|
||||
typedef std::map<const std::string, value_holder> param_map;
|
||||
typedef std::pair<std::string, value_holder> parameter;
|
||||
typedef std::map<std::string, value_holder> param_map;
|
||||
|
||||
template <typename T>
|
||||
struct value_extractor_visitor : public boost::static_visitor<>
|
||||
|
|
66
include/mapnik/util/geometry_to_ds_type.hpp
Normal file
66
include/mapnik/util/geometry_to_ds_type.hpp
Normal file
|
@ -0,0 +1,66 @@
|
|||
/*****************************************************************************
|
||||
*
|
||||
* This file is part of Mapnik (c++ mapping toolkit)
|
||||
*
|
||||
* Copyright (C) 2012 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
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
//$Id$
|
||||
|
||||
#ifndef MAPNIK_GEOMETRY_TO_DS_TYPE
|
||||
#define MAPNIK_GEOMETRY_TO_DS_TYPE
|
||||
|
||||
// mapnik
|
||||
#include <mapnik/global.hpp>
|
||||
#include <mapnik/geometry.hpp>
|
||||
#include <mapnik/datasource.hpp>
|
||||
|
||||
// boost
|
||||
#include <boost/optional.hpp>
|
||||
|
||||
namespace mapnik { namespace util {
|
||||
|
||||
void to_ds_type(mapnik::geometry_container const& paths,
|
||||
boost::optional<mapnik::datasource::geometry_t> & result)
|
||||
{
|
||||
if (paths.size() == 1)
|
||||
{
|
||||
result.reset(static_cast<mapnik::datasource::geometry_t>(paths.front().type()));
|
||||
}
|
||||
else if (paths.size() > 1)
|
||||
{
|
||||
int multi_type = 0;
|
||||
geometry_container::const_iterator itr = paths.begin();
|
||||
geometry_container::const_iterator end = paths.end();
|
||||
for ( ; itr!=end; ++itr)
|
||||
{
|
||||
int type = static_cast<int>(itr->type());
|
||||
if (multi_type > 0 && multi_type != type)
|
||||
{
|
||||
result.reset(datasource::Collection);
|
||||
}
|
||||
multi_type = type;
|
||||
result.reset(static_cast<mapnik::datasource::geometry_t>(type));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}}
|
||||
|
||||
|
||||
#endif // MAPNIK_GEOMETRY_TO_DS_TYPE
|
|
@ -13,6 +13,7 @@
|
|||
#include <mapnik/geometry.hpp>
|
||||
#include <mapnik/memory_featureset.hpp>
|
||||
#include <mapnik/wkt/wkt_factory.hpp>
|
||||
#include <mapnik/util/geometry_to_ds_type.hpp>
|
||||
#include <mapnik/ptree_helpers.hpp> // mapnik::boolean
|
||||
|
||||
// stl
|
||||
|
@ -837,7 +838,7 @@ std::string csv_datasource::name()
|
|||
return "csv";
|
||||
}
|
||||
|
||||
int csv_datasource::type() const
|
||||
datasource::datasource_t csv_datasource::type() const
|
||||
{
|
||||
return datasource::Vector;
|
||||
}
|
||||
|
@ -849,6 +850,29 @@ mapnik::box2d<double> csv_datasource::envelope() const
|
|||
return extent_;
|
||||
}
|
||||
|
||||
boost::optional<mapnik::datasource::geometry_t> csv_datasource::get_geometry_type() const
|
||||
{
|
||||
if (! is_bound_) bind();
|
||||
boost::optional<mapnik::datasource::geometry_t> result;
|
||||
int multi_type = 0;
|
||||
unsigned num_features = features_.size();
|
||||
for (int i = 0; i < num_features && i < 5; ++i)
|
||||
{
|
||||
mapnik::util::to_ds_type(features_[i]->paths(),result);
|
||||
if (result)
|
||||
{
|
||||
int type = static_cast<int>(*result);
|
||||
if (multi_type > 0 && multi_type != type)
|
||||
{
|
||||
result.reset(mapnik::datasource::Collection);
|
||||
return result;
|
||||
}
|
||||
multi_type = type;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
mapnik::layer_descriptor csv_datasource::get_descriptor() const
|
||||
{
|
||||
if (!is_bound_) bind();
|
||||
|
|
|
@ -12,11 +12,12 @@ class csv_datasource : public mapnik::datasource
|
|||
public:
|
||||
csv_datasource(mapnik::parameters const& params, bool bind=true);
|
||||
virtual ~csv_datasource ();
|
||||
int type() const;
|
||||
mapnik::datasource::datasource_t 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;
|
||||
boost::optional<mapnik::datasource::geometry_t> get_geometry_type() const;
|
||||
mapnik::layer_descriptor get_descriptor() const;
|
||||
void bind() const;
|
||||
template <typename T>
|
||||
|
|
|
@ -197,7 +197,7 @@ gdal_datasource::~gdal_datasource()
|
|||
{
|
||||
}
|
||||
|
||||
int gdal_datasource::type() const
|
||||
datasource::datasource_t gdal_datasource::type() const
|
||||
{
|
||||
return datasource::Raster;
|
||||
}
|
||||
|
@ -214,6 +214,11 @@ box2d<double> gdal_datasource::envelope() const
|
|||
return extent_;
|
||||
}
|
||||
|
||||
boost::optional<mapnik::datasource::geometry_t> gdal_datasource::get_geometry_type() const
|
||||
{
|
||||
return boost::optional<mapnik::datasource::geometry_t>();
|
||||
}
|
||||
|
||||
layer_descriptor gdal_datasource::get_descriptor() const
|
||||
{
|
||||
return desc_;
|
||||
|
|
|
@ -37,11 +37,12 @@ class gdal_datasource : public mapnik::datasource
|
|||
public:
|
||||
gdal_datasource(mapnik::parameters const& params, bool bind = true);
|
||||
virtual ~gdal_datasource();
|
||||
int type() const;
|
||||
mapnik::datasource::datasource_t 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;
|
||||
boost::optional<mapnik::datasource::geometry_t> get_geometry_type() const;
|
||||
mapnik::layer_descriptor get_descriptor() const;
|
||||
void bind() const;
|
||||
private:
|
||||
|
|
|
@ -225,7 +225,7 @@ std::string geos_datasource::name()
|
|||
return "geos";
|
||||
}
|
||||
|
||||
int geos_datasource::type() const
|
||||
mapnik::datasource::datasource_t geos_datasource::type() const
|
||||
{
|
||||
return type_;
|
||||
}
|
||||
|
@ -237,6 +237,38 @@ box2d<double> geos_datasource::envelope() const
|
|||
return extent_;
|
||||
}
|
||||
|
||||
boost::optional<mapnik::datasource::geometry_t> geos_datasource::get_geometry_type() const
|
||||
{
|
||||
if (! is_bound_) bind();
|
||||
boost::optional<mapnik::datasource::geometry_t> result;
|
||||
|
||||
// get geometry type
|
||||
const int type = GEOSGeomTypeId(*geometry_);
|
||||
switch (type)
|
||||
{
|
||||
case GEOS_POINT:
|
||||
case GEOS_MULTIPOINT:
|
||||
result.reset(mapnik::datasource::Point);
|
||||
break;
|
||||
case GEOS_LINESTRING:
|
||||
case GEOS_LINEARRING:
|
||||
case GEOS_MULTILINESTRING:
|
||||
result.reset(mapnik::datasource::LineString);
|
||||
break;
|
||||
case GEOS_POLYGON:
|
||||
case GEOS_MULTIPOLYGON:
|
||||
result.reset(mapnik::datasource::Polygon);
|
||||
break;
|
||||
case GEOS_GEOMETRYCOLLECTION:
|
||||
result.reset(mapnik::datasource::Collection);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
layer_descriptor geos_datasource::get_descriptor() const
|
||||
{
|
||||
if (! is_bound_) bind();
|
||||
|
|
|
@ -38,18 +38,19 @@ class geos_datasource : public mapnik::datasource
|
|||
public:
|
||||
geos_datasource(mapnik::parameters const& params, bool bind = true);
|
||||
virtual ~geos_datasource ();
|
||||
int type() const;
|
||||
mapnik::datasource::datasource_t 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;
|
||||
boost::optional<mapnik::datasource::geometry_t> get_geometry_type() const;
|
||||
mapnik::layer_descriptor get_descriptor() const;
|
||||
void bind() const;
|
||||
|
||||
private:
|
||||
mutable mapnik::box2d<double> extent_;
|
||||
mutable bool extent_initialized_;
|
||||
int type_;
|
||||
mapnik::datasource::datasource_t type_;
|
||||
mutable mapnik::layer_descriptor desc_;
|
||||
mutable geos_feature_ptr geometry_;
|
||||
mutable std::string geometry_data_;
|
||||
|
|
|
@ -131,7 +131,7 @@ std::string kismet_datasource::name()
|
|||
return "kismet";
|
||||
}
|
||||
|
||||
int kismet_datasource::type() const
|
||||
mapnik::datasource::datasource_t kismet_datasource::type() const
|
||||
{
|
||||
return type_;
|
||||
}
|
||||
|
@ -142,6 +142,11 @@ box2d<double> kismet_datasource::envelope() const
|
|||
return extent_;
|
||||
}
|
||||
|
||||
boost::optional<mapnik::datasource::geometry_t> kismet_datasource::get_geometry_type() const
|
||||
{
|
||||
return boost::optional<mapnik::datasource::geometry_t>(mapnik::datasource::Point);
|
||||
}
|
||||
|
||||
layer_descriptor kismet_datasource::get_descriptor() const
|
||||
{
|
||||
return desc_;
|
||||
|
|
|
@ -45,11 +45,12 @@ class kismet_datasource : public mapnik::datasource
|
|||
public:
|
||||
kismet_datasource(mapnik::parameters const& params, bool bind = true);
|
||||
virtual ~kismet_datasource ();
|
||||
int type() const;
|
||||
datasource::datasource_t 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;
|
||||
boost::optional<mapnik::datasource::geometry_t> get_geometry_type() const;
|
||||
mapnik::layer_descriptor get_descriptor() const;
|
||||
void bind() const;
|
||||
|
||||
|
@ -60,9 +61,9 @@ private:
|
|||
bool extent_initialized_;
|
||||
std::string host_;
|
||||
unsigned int port_;
|
||||
int type_;
|
||||
mapnik::datasource::datasource_t type_;
|
||||
std::string srs_;
|
||||
mapnik::layer_descriptor desc_;
|
||||
mutable mapnik::layer_descriptor desc_;
|
||||
boost::shared_ptr<boost::thread> kismet_thread;
|
||||
};
|
||||
|
||||
|
|
|
@ -351,7 +351,7 @@ std::string occi_datasource::name()
|
|||
return "occi";
|
||||
}
|
||||
|
||||
int occi_datasource::type() const
|
||||
mapnik::datasource::datasource_t occi_datasource::type() const
|
||||
{
|
||||
return type_;
|
||||
}
|
||||
|
@ -474,6 +474,14 @@ box2d<double> occi_datasource::envelope() const
|
|||
return extent_;
|
||||
}
|
||||
|
||||
|
||||
boost::optional<mapnik::datasource::geometry_t> occi_datasource::get_geometry_type() const
|
||||
{
|
||||
// FIXME
|
||||
//if (! is_bound_) bind();
|
||||
return boost::optional<mapnik::datasource::geometry_t>();
|
||||
}
|
||||
|
||||
layer_descriptor occi_datasource::get_descriptor() const
|
||||
{
|
||||
if (! is_bound_) bind();
|
||||
|
|
|
@ -40,16 +40,17 @@ class occi_datasource : public mapnik::datasource
|
|||
public:
|
||||
occi_datasource(mapnik::parameters const& params, bool bind = true);
|
||||
virtual ~occi_datasource ();
|
||||
int type() const;
|
||||
mapnik::datasource::datasource_t 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;
|
||||
boost::optional<mapnik::datasource::geometry_t> get_geometry_type() const;
|
||||
mapnik::layer_descriptor get_descriptor() const;
|
||||
void bind() const;
|
||||
|
||||
private:
|
||||
int type_;
|
||||
mapnik::datasource::datasource_t type_;
|
||||
mutable std::string table_;
|
||||
mutable std::string table_name_;
|
||||
mutable std::string fields_;
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
#include "ogr_datasource.hpp"
|
||||
#include "ogr_featureset.hpp"
|
||||
#include "ogr_index_featureset.hpp"
|
||||
#include "ogr_feature_ptr.hpp"
|
||||
|
||||
// mapnik
|
||||
#include <mapnik/ptree_helpers.hpp>
|
||||
|
@ -331,7 +332,7 @@ std::string ogr_datasource::name()
|
|||
return "ogr";
|
||||
}
|
||||
|
||||
int ogr_datasource::type() const
|
||||
mapnik::datasource::datasource_t ogr_datasource::type() const
|
||||
{
|
||||
return type_;
|
||||
}
|
||||
|
@ -342,6 +343,79 @@ box2d<double> ogr_datasource::envelope() const
|
|||
return extent_;
|
||||
}
|
||||
|
||||
boost::optional<mapnik::datasource::geometry_t> ogr_datasource::get_geometry_type() const
|
||||
{
|
||||
boost::optional<mapnik::datasource::geometry_t> result;
|
||||
if (dataset_ && layer_.is_valid())
|
||||
{
|
||||
OGRLayer* layer = layer_.layer();
|
||||
// NOTE: wkbFlatten macro in ogr flattens 2.5d types into base 2d type
|
||||
switch (wkbFlatten(layer->GetGeomType()))
|
||||
{
|
||||
case wkbPoint:
|
||||
case wkbMultiPoint:
|
||||
result.reset(mapnik::datasource::Point);
|
||||
break;
|
||||
case wkbLinearRing:
|
||||
case wkbLineString:
|
||||
case wkbMultiLineString:
|
||||
result.reset(mapnik::datasource::LineString);
|
||||
break;
|
||||
case wkbPolygon:
|
||||
case wkbMultiPolygon:
|
||||
result.reset(mapnik::datasource::Polygon);
|
||||
break;
|
||||
case wkbGeometryCollection:
|
||||
result.reset(mapnik::datasource::Collection);
|
||||
break;
|
||||
case wkbNone:
|
||||
case wkbUnknown:
|
||||
{
|
||||
// fallback to inspecting first actual geometry
|
||||
// TODO - csv and shapefile inspect first 4 features
|
||||
if (dataset_ && layer_.is_valid())
|
||||
{
|
||||
OGRLayer* layer = layer_.layer();
|
||||
ogr_feature_ptr feat(layer->GetNextFeature());
|
||||
if ((*feat) != NULL)
|
||||
{
|
||||
OGRGeometry* geom = (*feat)->GetGeometryRef();
|
||||
if (geom && ! geom->IsEmpty())
|
||||
{
|
||||
switch (wkbFlatten(geom->getGeometryType()))
|
||||
{
|
||||
case wkbPoint:
|
||||
case wkbMultiPoint:
|
||||
result.reset(mapnik::datasource::Point);
|
||||
break;
|
||||
case wkbLinearRing:
|
||||
case wkbLineString:
|
||||
case wkbMultiLineString:
|
||||
result.reset(mapnik::datasource::LineString);
|
||||
break;
|
||||
case wkbPolygon:
|
||||
case wkbMultiPolygon:
|
||||
result.reset(mapnik::datasource::Polygon);
|
||||
break;
|
||||
case wkbGeometryCollection:
|
||||
result.reset(mapnik::datasource::Collection);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
layer_descriptor ogr_datasource::get_descriptor() const
|
||||
{
|
||||
if (! is_bound_) bind();
|
||||
|
|
|
@ -41,17 +41,18 @@ class ogr_datasource : public mapnik::datasource
|
|||
public:
|
||||
ogr_datasource(mapnik::parameters const& params, bool bind=true);
|
||||
virtual ~ogr_datasource ();
|
||||
int type() const;
|
||||
mapnik::datasource::datasource_t 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;
|
||||
boost::optional<mapnik::datasource::geometry_t> get_geometry_type() const;
|
||||
mapnik::layer_descriptor get_descriptor() const;
|
||||
void bind() const;
|
||||
|
||||
private:
|
||||
mutable mapnik::box2d<double> extent_;
|
||||
int type_;
|
||||
mapnik::datasource::datasource_t type_;
|
||||
std::string dataset_name_;
|
||||
mutable std::string index_name_;
|
||||
mutable OGRDataSource* dataset_;
|
||||
|
|
|
@ -137,7 +137,7 @@ std::string osm_datasource::name()
|
|||
return "osm";
|
||||
}
|
||||
|
||||
int osm_datasource::type() const
|
||||
mapnik::datasource::datasource_t osm_datasource::type() const
|
||||
{
|
||||
return type_;
|
||||
}
|
||||
|
@ -189,3 +189,9 @@ box2d<double> osm_datasource::envelope() const
|
|||
|
||||
return extent_;
|
||||
}
|
||||
|
||||
boost::optional<mapnik::datasource::geometry_t> osm_datasource::get_geometry_type() const
|
||||
{
|
||||
if (! is_bound_) bind();
|
||||
return boost::optional<mapnik::datasource::geometry_t>(mapnik::datasource::Collection);
|
||||
}
|
|
@ -42,17 +42,18 @@ class osm_datasource : public datasource
|
|||
public:
|
||||
osm_datasource(const parameters& params, bool bind = true);
|
||||
virtual ~osm_datasource();
|
||||
int type() const;
|
||||
mapnik::datasource::datasource_t type() const;
|
||||
featureset_ptr features(const query& q) const;
|
||||
featureset_ptr features_at_point(coord2d const& pt) const;
|
||||
box2d<double> envelope() const;
|
||||
boost::optional<mapnik::datasource::geometry_t> get_geometry_type() const;
|
||||
layer_descriptor get_descriptor() const;
|
||||
static std::string name();
|
||||
void bind() const;
|
||||
private:
|
||||
mutable box2d<double> extent_;
|
||||
mutable osm_dataset* osm_data_;
|
||||
int type_;
|
||||
mapnik::datasource::datasource_t type_;
|
||||
mutable layer_descriptor desc_;
|
||||
// no copying
|
||||
osm_datasource(const osm_datasource&);
|
||||
|
|
|
@ -106,6 +106,8 @@ void postgis_datasource::bind() const
|
|||
ConnectionManager *mgr=ConnectionManager::instance();
|
||||
mgr->registerPool(creator_, *initial_size, *max_size);
|
||||
|
||||
std::string g_type;
|
||||
|
||||
shared_ptr<Pool<Connection,ConnectionCreator> > pool=mgr->getPool(creator_.id());
|
||||
if (pool)
|
||||
{
|
||||
|
@ -113,8 +115,6 @@ void postgis_datasource::bind() const
|
|||
if (conn && conn->isOK())
|
||||
{
|
||||
|
||||
is_bound_ = true;
|
||||
|
||||
PoolGuard<shared_ptr<Connection>,
|
||||
shared_ptr<Pool<Connection,ConnectionCreator> > > guard(conn,pool);
|
||||
|
||||
|
@ -145,14 +145,20 @@ void postgis_datasource::bind() const
|
|||
if (!geometryColumn_.length() > 0 || srid_ == 0)
|
||||
{
|
||||
std::ostringstream s;
|
||||
s << "SELECT f_geometry_column, srid FROM ";
|
||||
s << GEOMETRY_COLUMNS <<" WHERE f_table_name='" << mapnik::sql_utils::unquote_double(geometry_table_) <<"'";
|
||||
s << "SELECT f_geometry_column, srid FROM "
|
||||
<< GEOMETRY_COLUMNS <<" WHERE f_table_name='"
|
||||
<< mapnik::sql_utils::unquote_double(geometry_table_)
|
||||
<< "'";
|
||||
|
||||
if (schema_.length() > 0)
|
||||
s << " AND f_table_schema='" << mapnik::sql_utils::unquote_double(schema_) << "'";
|
||||
s << " AND f_table_schema='"
|
||||
<< mapnik::sql_utils::unquote_double(schema_)
|
||||
<< "'";
|
||||
|
||||
if (geometry_field_.length() > 0)
|
||||
s << " AND f_geometry_column='" << mapnik::sql_utils::unquote_double(geometry_field_) << "'";
|
||||
s << " AND f_geometry_column='"
|
||||
<< mapnik::sql_utils::unquote_double(geometry_field_)
|
||||
<< "'";
|
||||
|
||||
/*
|
||||
if (show_queries_)
|
||||
|
@ -161,7 +167,7 @@ void postgis_datasource::bind() const
|
|||
}
|
||||
*/
|
||||
|
||||
shared_ptr<ResultSet> rs=conn->executeQuery(s.str());
|
||||
shared_ptr<ResultSet> rs = conn->executeQuery(s.str());
|
||||
if (rs->next())
|
||||
{
|
||||
geometryColumn_ = rs->getValue("f_geometry_column");
|
||||
|
@ -196,7 +202,7 @@ void postgis_datasource::bind() const
|
|||
}
|
||||
*/
|
||||
|
||||
shared_ptr<ResultSet> rs=conn->executeQuery(s.str());
|
||||
shared_ptr<ResultSet> rs = conn->executeQuery(s.str());
|
||||
if (rs->next())
|
||||
{
|
||||
try
|
||||
|
@ -238,7 +244,7 @@ void postgis_datasource::bind() const
|
|||
*/
|
||||
|
||||
|
||||
shared_ptr<ResultSet> rs=conn->executeQuery(s.str());
|
||||
shared_ptr<ResultSet> rs = conn->executeQuery(s.str());
|
||||
int count = rs->getNumFields();
|
||||
bool found_key_field = false;
|
||||
for (int i=0;i<count;++i)
|
||||
|
@ -326,7 +332,11 @@ void postgis_datasource::bind() const
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
rs->close();
|
||||
|
||||
is_bound_ = true;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -336,7 +346,7 @@ std::string postgis_datasource::name()
|
|||
return "postgis";
|
||||
}
|
||||
|
||||
int postgis_datasource::type() const
|
||||
mapnik::datasource::datasource_t postgis_datasource::type() const
|
||||
{
|
||||
return type_;
|
||||
}
|
||||
|
@ -686,6 +696,118 @@ box2d<double> postgis_datasource::envelope() const
|
|||
return extent_;
|
||||
}
|
||||
|
||||
boost::optional<mapnik::datasource::geometry_t> postgis_datasource::get_geometry_type() const
|
||||
{
|
||||
if (! is_bound_) bind();
|
||||
boost::optional<mapnik::datasource::geometry_t> result;
|
||||
|
||||
ConnectionManager *mgr=ConnectionManager::instance();
|
||||
shared_ptr<Pool<Connection,ConnectionCreator> > pool=mgr->getPool(creator_.id());
|
||||
if (pool)
|
||||
{
|
||||
shared_ptr<Connection> conn = pool->borrowObject();
|
||||
if (conn && conn->isOK())
|
||||
{
|
||||
PoolGuard<shared_ptr<Connection>,shared_ptr<Pool<Connection,ConnectionCreator> > > guard(conn,pool);
|
||||
|
||||
std::ostringstream s;
|
||||
std::string g_type;
|
||||
|
||||
s << "SELECT lower(type) as type FROM "
|
||||
<< GEOMETRY_COLUMNS <<" WHERE f_table_name='"
|
||||
<< mapnik::sql_utils::unquote_double(geometry_table_)
|
||||
<< "'";
|
||||
|
||||
if (schema_.length() > 0)
|
||||
s << " AND f_table_schema='"
|
||||
<< mapnik::sql_utils::unquote_double(schema_)
|
||||
<< "'";
|
||||
|
||||
if (geometry_field_.length() > 0)
|
||||
s << " AND f_geometry_column='"
|
||||
<< mapnik::sql_utils::unquote_double(geometry_field_)
|
||||
<< "'";
|
||||
|
||||
shared_ptr<ResultSet> rs = conn->executeQuery(s.str());
|
||||
if (rs->next())
|
||||
{
|
||||
g_type = rs->getValue("type");
|
||||
if (boost::algorithm::contains(g_type,"line"))
|
||||
{
|
||||
result.reset(mapnik::datasource::LineString);
|
||||
return result;
|
||||
}
|
||||
else if (boost::algorithm::contains(g_type,"point"))
|
||||
{
|
||||
result.reset(mapnik::datasource::Point);
|
||||
return result;
|
||||
}
|
||||
else if (boost::algorithm::contains(g_type,"polygon"))
|
||||
{
|
||||
result.reset(mapnik::datasource::Polygon);
|
||||
return result;
|
||||
}
|
||||
else // geometry
|
||||
{
|
||||
result.reset(mapnik::datasource::Collection);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
// fallback to querying first several features
|
||||
if (g_type.empty() && !geometryColumn_.empty())
|
||||
{
|
||||
s.str("");
|
||||
std::string prev_type("");
|
||||
s << "SELECT ST_GeometryType(\""
|
||||
<< geometryColumn_ << "\") AS geom"
|
||||
<< " FROM " << populate_tokens(table_);
|
||||
if (row_limit_ > 0 && row_limit_ < 5)
|
||||
{
|
||||
s << " LIMIT " << row_limit_;
|
||||
}
|
||||
else
|
||||
{
|
||||
s << " LIMIT 5";
|
||||
}
|
||||
shared_ptr<ResultSet> rs = conn->executeQuery(s.str());
|
||||
while (rs->next() && !rs->isNull(0))
|
||||
{
|
||||
const char* data = rs->getValue(0);
|
||||
if (boost::algorithm::icontains(data,"line"))
|
||||
{
|
||||
g_type = "linestring";
|
||||
result.reset(mapnik::datasource::LineString);
|
||||
}
|
||||
else if (boost::algorithm::icontains(data,"point"))
|
||||
{
|
||||
g_type = "point";
|
||||
result.reset(mapnik::datasource::Point);
|
||||
}
|
||||
else if (boost::algorithm::icontains(data,"polygon"))
|
||||
{
|
||||
g_type = "polygon";
|
||||
result.reset(mapnik::datasource::Polygon);
|
||||
}
|
||||
else // geometry
|
||||
{
|
||||
result.reset(mapnik::datasource::Collection);
|
||||
return result;
|
||||
}
|
||||
if (!prev_type.empty() && g_type != prev_type)
|
||||
{
|
||||
result.reset(mapnik::datasource::Collection);
|
||||
return result;
|
||||
}
|
||||
prev_type = g_type;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
postgis_datasource::~postgis_datasource()
|
||||
{
|
||||
if (is_bound_ && !persist_connection_)
|
||||
|
|
|
@ -63,7 +63,7 @@ class postgis_datasource : public datasource
|
|||
const int cursor_fetch_size_;
|
||||
const int row_limit_;
|
||||
mutable std::string geometryColumn_;
|
||||
int type_;
|
||||
mapnik::datasource::datasource_t type_;
|
||||
mutable int srid_;
|
||||
mutable bool extent_initialized_;
|
||||
mutable mapnik::box2d<double> extent_;
|
||||
|
@ -79,10 +79,11 @@ class postgis_datasource : public datasource
|
|||
//bool show_queries_;
|
||||
public:
|
||||
static std::string name();
|
||||
int type() const;
|
||||
mapnik::datasource::datasource_t type() const;
|
||||
featureset_ptr features(const query& q) const;
|
||||
featureset_ptr features_at_point(coord2d const& pt) const;
|
||||
mapnik::box2d<double> envelope() const;
|
||||
boost::optional<mapnik::datasource::geometry_t> get_geometry_type() const;
|
||||
layer_descriptor get_descriptor() const;
|
||||
postgis_datasource(const parameters ¶ms, bool bind=true);
|
||||
~postgis_datasource();
|
||||
|
|
|
@ -159,7 +159,7 @@ raster_datasource::~raster_datasource()
|
|||
{
|
||||
}
|
||||
|
||||
int raster_datasource::type() const
|
||||
mapnik::datasource::datasource_t raster_datasource::type() const
|
||||
{
|
||||
return datasource::Raster;
|
||||
}
|
||||
|
@ -174,6 +174,11 @@ mapnik::box2d<double> raster_datasource::envelope() const
|
|||
return extent_;
|
||||
}
|
||||
|
||||
boost::optional<mapnik::datasource::geometry_t> raster_datasource::get_geometry_type() const
|
||||
{
|
||||
return boost::optional<mapnik::datasource::geometry_t>();
|
||||
}
|
||||
|
||||
layer_descriptor raster_datasource::get_descriptor() const
|
||||
{
|
||||
return desc_;
|
||||
|
|
|
@ -33,11 +33,12 @@ class raster_datasource : public mapnik::datasource
|
|||
public:
|
||||
raster_datasource(const mapnik::parameters& params, bool bind=true);
|
||||
virtual ~raster_datasource();
|
||||
int type() const;
|
||||
datasource::datasource_t type() const;
|
||||
static std::string name();
|
||||
mapnik::featureset_ptr features(const mapnik::query& q) const;
|
||||
mapnik::featureset_ptr features_at_point(mapnik::coord2d const& pt) const;
|
||||
mapnik::box2d<double> envelope() const;
|
||||
boost::optional<mapnik::datasource::geometry_t> get_geometry_type() const;
|
||||
mapnik::layer_descriptor get_descriptor() const;
|
||||
void bind() const;
|
||||
private:
|
||||
|
|
|
@ -36,7 +36,7 @@ class rasterlite_datasource : public mapnik::datasource
|
|||
public:
|
||||
rasterlite_datasource(mapnik::parameters const& params, bool bind = true);
|
||||
virtual ~rasterlite_datasource ();
|
||||
int type() const;
|
||||
mapnik::datasource::datasource_t 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;
|
||||
|
|
|
@ -182,8 +182,8 @@ void shape_datasource::init(shape_io& shape) const
|
|||
throw datasource_exception("Shape Plugin: " + (boost::format("invalid version number: %d") % version).str());
|
||||
}
|
||||
|
||||
int shape_type = shape.shp().read_ndr_integer();
|
||||
if (shape_type == shape_io::shape_multipatch)
|
||||
shape_type_ = static_cast<shape_io::shapeType>(shape.shp().read_ndr_integer());
|
||||
if (shape_type_ == shape_io::shape_multipatch)
|
||||
throw datasource_exception("Shape Plugin: shapefile multipatch type is not supported");
|
||||
|
||||
shape.shp().read_envelope(extent_);
|
||||
|
@ -229,7 +229,7 @@ std::string shape_datasource::name()
|
|||
return "shape";
|
||||
}
|
||||
|
||||
int shape_datasource::type() const
|
||||
datasource::datasource_t shape_datasource::type() const
|
||||
{
|
||||
return type_;
|
||||
}
|
||||
|
@ -314,3 +314,39 @@ box2d<double> shape_datasource::envelope() const
|
|||
|
||||
return extent_;
|
||||
}
|
||||
|
||||
boost::optional<mapnik::datasource::geometry_t> shape_datasource::get_geometry_type() const
|
||||
{
|
||||
boost::optional<mapnik::datasource::geometry_t> result;
|
||||
switch (shape_type_)
|
||||
{
|
||||
case shape_io::shape_point:
|
||||
case shape_io::shape_pointm:
|
||||
case shape_io::shape_pointz:
|
||||
case shape_io::shape_multipoint:
|
||||
case shape_io::shape_multipointm:
|
||||
case shape_io::shape_multipointz:
|
||||
{
|
||||
result.reset(mapnik::datasource::Point);
|
||||
break;
|
||||
}
|
||||
case shape_io::shape_polyline:
|
||||
case shape_io::shape_polylinem:
|
||||
case shape_io::shape_polylinez:
|
||||
{
|
||||
result.reset(mapnik::datasource::LineString);
|
||||
break;
|
||||
}
|
||||
case shape_io::shape_polygon:
|
||||
case shape_io::shape_polygonm:
|
||||
case shape_io::shape_polygonz:
|
||||
{
|
||||
result.reset(mapnik::datasource::Polygon);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
|
@ -45,11 +45,12 @@ public:
|
|||
shape_datasource(const parameters ¶ms, bool bind=true);
|
||||
virtual ~shape_datasource();
|
||||
|
||||
int type() const;
|
||||
datasource::datasource_t type() const;
|
||||
static std::string name();
|
||||
featureset_ptr features(const query& q) const;
|
||||
featureset_ptr features_at_point(coord2d const& pt) const;
|
||||
box2d<double> envelope() const;
|
||||
boost::optional<mapnik::datasource::geometry_t> get_geometry_type() const;
|
||||
layer_descriptor get_descriptor() const;
|
||||
void bind() const;
|
||||
private:
|
||||
|
@ -57,9 +58,10 @@ private:
|
|||
shape_datasource& operator=(const shape_datasource&);
|
||||
void init(shape_io& shape) const;
|
||||
private:
|
||||
int type_;
|
||||
datasource::datasource_t type_;
|
||||
std::string shape_name_;
|
||||
mutable boost::shared_ptr<shape_io> shape_;
|
||||
mutable shape_io::shapeType shape_type_;
|
||||
mutable long file_length_;
|
||||
mutable box2d<double> extent_;
|
||||
mutable bool indexed_;
|
||||
|
|
|
@ -71,7 +71,7 @@ void shape_io::move_to(int pos)
|
|||
shp_.seek(pos);
|
||||
id_ = shp_.read_xdr_integer();
|
||||
reclength_ = shp_.read_xdr_integer();
|
||||
type_ = shp_.read_ndr_integer();
|
||||
type_ = static_cast<shape_io::shapeType>(shp_.read_ndr_integer());
|
||||
|
||||
if (type_ != shape_null && type_ != shape_point && type_ != shape_pointm && type_ != shape_pointz)
|
||||
{
|
||||
|
@ -79,7 +79,7 @@ void shape_io::move_to(int pos)
|
|||
}
|
||||
}
|
||||
|
||||
int shape_io::type() const
|
||||
shape_io::shapeType shape_io::type() const
|
||||
{
|
||||
return type_;
|
||||
}
|
||||
|
|
|
@ -25,6 +25,8 @@
|
|||
|
||||
// mapnik
|
||||
#include <mapnik/geometry.hpp>
|
||||
#include <mapnik/datasource.hpp>
|
||||
|
||||
// boost
|
||||
#include <boost/utility.hpp>
|
||||
#include <boost/shared_ptr.hpp>
|
||||
|
@ -71,11 +73,11 @@ public:
|
|||
}
|
||||
|
||||
void move_to(int id);
|
||||
int type() const;
|
||||
shapeType type() const;
|
||||
const box2d<double>& current_extent() const;
|
||||
void read_polyline(mapnik::geometry_container & geom);
|
||||
void read_polygon(mapnik::geometry_container & geom);
|
||||
unsigned type_;
|
||||
shapeType type_;
|
||||
shape_file shp_;
|
||||
dbf_file dbf_;
|
||||
boost::shared_ptr<shape_file> index_;
|
||||
|
|
|
@ -28,6 +28,8 @@
|
|||
// mapnik
|
||||
#include <mapnik/ptree_helpers.hpp>
|
||||
#include <mapnik/sql_utils.hpp>
|
||||
#include <mapnik/util/geometry_to_ds_type.hpp>
|
||||
#include <mapnik/wkb.hpp>
|
||||
|
||||
// boost
|
||||
#include <boost/algorithm/string.hpp>
|
||||
|
@ -69,16 +71,12 @@ sqlite_datasource::sqlite_datasource(parameters const& params, bool bind)
|
|||
/* TODO
|
||||
- throw if no primary key but spatial index is present?
|
||||
- remove auto-indexing
|
||||
- if spatialite - leverage more of the metadata for geometry type detection
|
||||
*/
|
||||
|
||||
boost::optional<std::string> file = params_.get<std::string>("file");
|
||||
if (! file) throw datasource_exception("Sqlite Plugin: missing <file> parameter");
|
||||
|
||||
if (table_.empty())
|
||||
{
|
||||
throw mapnik::datasource_exception("Sqlite Plugin: missing <table> parameter");
|
||||
}
|
||||
|
||||
if (bind)
|
||||
{
|
||||
this->bind();
|
||||
|
@ -147,6 +145,44 @@ void sqlite_datasource::bind() const
|
|||
init_statements_.push_back(*initdb);
|
||||
}
|
||||
|
||||
// now actually create the connection and start executing setup sql
|
||||
dataset_ = boost::make_shared<sqlite_connection>(dataset_name_);
|
||||
|
||||
boost::optional<unsigned> table_by_index = params_.get<unsigned>("table_by_index");
|
||||
|
||||
int passed_parameters = 0;
|
||||
passed_parameters += params_.get<std::string>("table") ? 1 : 0;
|
||||
passed_parameters += table_by_index ? 1 : 0;
|
||||
|
||||
if (passed_parameters > 1)
|
||||
{
|
||||
throw datasource_exception("SQLite Plugin: you can only select an by name "
|
||||
"('table' parameter), by number ('table_by_index' parameter), "
|
||||
"do not supply 2 or more of them at the same time" );
|
||||
}
|
||||
|
||||
if (table_by_index)
|
||||
{
|
||||
std::vector<std::string> tables;
|
||||
sqlite_utils::get_tables(dataset_,tables);
|
||||
if (*table_by_index >= tables.size())
|
||||
{
|
||||
std::ostringstream s;
|
||||
s << "SQLite Plugin: only "
|
||||
<< tables.size()
|
||||
<< " table(s) exist, cannot find table by index '" << *table_by_index << "'";
|
||||
|
||||
throw datasource_exception(s.str());
|
||||
}
|
||||
table_ = tables[*table_by_index];
|
||||
|
||||
}
|
||||
|
||||
if (table_.empty())
|
||||
{
|
||||
throw mapnik::datasource_exception("Sqlite Plugin: missing <table> parameter");
|
||||
}
|
||||
|
||||
if (geometry_table_.empty())
|
||||
{
|
||||
geometry_table_ = mapnik::sql_utils::table_from_sql(table_);
|
||||
|
@ -169,9 +205,6 @@ void sqlite_datasource::bind() const
|
|||
}
|
||||
}
|
||||
|
||||
// now actually create the connection and start executing setup sql
|
||||
dataset_ = boost::make_shared<sqlite_connection>(dataset_name_);
|
||||
|
||||
// Execute init_statements_
|
||||
for (std::vector<std::string>::const_iterator iter = init_statements_.begin();
|
||||
iter != init_statements_.end(); ++iter)
|
||||
|
@ -188,7 +221,11 @@ void sqlite_datasource::bind() const
|
|||
std::ostringstream s;
|
||||
std::string query = populate_tokens(table_);
|
||||
s << "SELECT " << fields_ << " FROM (" << query << ") LIMIT 1";
|
||||
found_types_via_subquery = sqlite_utils::detect_types_from_subquery(s.str(),geometry_field_,desc_,dataset_);
|
||||
found_types_via_subquery = sqlite_utils::detect_types_from_subquery(
|
||||
s.str(),
|
||||
geometry_field_,
|
||||
desc_,
|
||||
dataset_);
|
||||
}
|
||||
|
||||
// TODO - consider removing this
|
||||
|
@ -328,6 +365,7 @@ void sqlite_datasource::bind() const
|
|||
throw datasource_exception(s.str());
|
||||
}
|
||||
}
|
||||
|
||||
is_bound_ = true;
|
||||
}
|
||||
|
||||
|
@ -434,7 +472,7 @@ std::string sqlite_datasource::name()
|
|||
return "sqlite";
|
||||
}
|
||||
|
||||
int sqlite_datasource::type() const
|
||||
mapnik::datasource::datasource_t sqlite_datasource::type() const
|
||||
{
|
||||
return type_;
|
||||
}
|
||||
|
@ -446,6 +484,53 @@ box2d<double> sqlite_datasource::envelope() const
|
|||
return extent_;
|
||||
}
|
||||
|
||||
boost::optional<mapnik::datasource::geometry_t> sqlite_datasource::get_geometry_type() const
|
||||
{
|
||||
if (! is_bound_) bind();
|
||||
boost::optional<mapnik::datasource::geometry_t> result;
|
||||
|
||||
if (dataset_)
|
||||
{
|
||||
// finally, get geometry type by querying first feature
|
||||
std::ostringstream s;
|
||||
s << "SELECT " << geometry_field_
|
||||
<< " FROM " << geometry_table_;
|
||||
if (row_limit_ > 0 && row_limit_ < 5)
|
||||
{
|
||||
s << " LIMIT " << row_limit_;
|
||||
}
|
||||
else
|
||||
{
|
||||
s << " LIMIT 5";
|
||||
}
|
||||
boost::shared_ptr<sqlite_resultset> rs = dataset_->execute_query(s.str());
|
||||
int multi_type = 0;
|
||||
while (rs->is_valid() && rs->step_next())
|
||||
{
|
||||
int size;
|
||||
const char* data = (const char*) rs->column_blob(0, size);
|
||||
if (data)
|
||||
{
|
||||
boost::ptr_vector<mapnik::geometry_type> paths;
|
||||
mapnik::geometry_utils::from_wkb(paths, data, size, mapnik::wkbAuto);
|
||||
mapnik::util::to_ds_type(paths,result);
|
||||
if (result)
|
||||
{
|
||||
int type = static_cast<int>(*result);
|
||||
if (multi_type > 0 && multi_type != type)
|
||||
{
|
||||
result.reset(mapnik::datasource::Collection);
|
||||
return result;
|
||||
}
|
||||
multi_type = type;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
layer_descriptor sqlite_datasource::get_descriptor() const
|
||||
{
|
||||
if (! is_bound_) bind();
|
||||
|
|
|
@ -42,11 +42,12 @@ class sqlite_datasource : public mapnik::datasource
|
|||
public:
|
||||
sqlite_datasource(mapnik::parameters const& params, bool bind = true);
|
||||
virtual ~sqlite_datasource ();
|
||||
int type() const;
|
||||
datasource::datasource_t 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;
|
||||
boost::optional<mapnik::datasource::geometry_t> get_geometry_type() const;
|
||||
mapnik::layer_descriptor get_descriptor() const;
|
||||
void bind() const;
|
||||
|
||||
|
@ -58,7 +59,7 @@ private:
|
|||
|
||||
mutable mapnik::box2d<double> extent_;
|
||||
mutable bool extent_initialized_;
|
||||
int type_;
|
||||
mapnik::datasource::datasource_t type_;
|
||||
mutable std::string dataset_name_;
|
||||
mutable boost::shared_ptr<sqlite_connection> dataset_;
|
||||
mutable std::string table_;
|
||||
|
|
|
@ -12,8 +12,7 @@ using mapnik::parameters;
|
|||
DATASOURCE_PLUGIN(hello_datasource)
|
||||
|
||||
hello_datasource::hello_datasource(parameters const& params, bool bind)
|
||||
: datasource(params),
|
||||
type_(datasource::Vector),
|
||||
: datasource(params)
|
||||
desc_(*params_.get<std::string>("type"), *params_.get<std::string>("encoding","utf-8")),
|
||||
extent_()
|
||||
{
|
||||
|
@ -34,6 +33,10 @@ void hello_datasource::bind() const
|
|||
// see http://spatialreference.org/ref/epsg/4326/ for more details
|
||||
extent_.init(-180,-90,180,90);
|
||||
|
||||
// declare that this datasource is going to provide points
|
||||
// options are point,polygon,linestring, and collection
|
||||
desc_.set_geometry_type("point");
|
||||
|
||||
is_bound_ = true;
|
||||
}
|
||||
|
||||
|
@ -47,9 +50,9 @@ std::string hello_datasource::name()
|
|||
return name_;
|
||||
}
|
||||
|
||||
int hello_datasource::type() const
|
||||
mapnik::datasource::datasource_t hello_datasource::type() const
|
||||
{
|
||||
return type_;
|
||||
return datasource::Vector;
|
||||
}
|
||||
|
||||
mapnik::box2d<double> hello_datasource::envelope() const
|
||||
|
@ -59,6 +62,11 @@ mapnik::box2d<double> hello_datasource::envelope() const
|
|||
return extent_;
|
||||
}
|
||||
|
||||
boost::optional<mapnik::datasource::geometry_t> hello_datasource::get_geometry_type() const
|
||||
{
|
||||
boost::optional<mapnik::datasource::geometry_t>(mapnik::datasource::Point);
|
||||
}
|
||||
|
||||
mapnik::layer_descriptor hello_datasource::get_descriptor() const
|
||||
{
|
||||
if (!is_bound_) bind();
|
||||
|
|
|
@ -15,7 +15,7 @@ public:
|
|||
virtual ~hello_datasource ();
|
||||
|
||||
// mandatory: type of the plugin, used to match at runtime
|
||||
int type() const;
|
||||
mapnik::datasource::datasource_t type() const;
|
||||
|
||||
// mandatory: name of the plugin
|
||||
static std::string name();
|
||||
|
@ -31,6 +31,9 @@ public:
|
|||
// mandatory: return the box2d of the datasource
|
||||
// called during rendering to determine if the layer should be processed
|
||||
mapnik::box2d<double> envelope() const;
|
||||
|
||||
// mandatory: optionally return the overal geometry type of the datasource
|
||||
boost::optional<mapnik::datasource::geometry_t> get_geometry_type() const;
|
||||
|
||||
// mandatory: return the layer descriptor
|
||||
mapnik::layer_descriptor get_descriptor() const;
|
||||
|
@ -42,7 +45,6 @@ private:
|
|||
// recommended naming convention of datasource members:
|
||||
// name_, type_, extent_, and desc_
|
||||
static const std::string name_;
|
||||
int type_;
|
||||
mutable mapnik::layer_descriptor desc_;
|
||||
mutable mapnik::box2d<double> extent_;
|
||||
};
|
||||
|
|
|
@ -143,6 +143,7 @@ void datasource_cache::register_datasources(const std::string& str)
|
|||
mapnik::CreateStatic>::mutex_);
|
||||
#endif
|
||||
boost::filesystem::path path(str);
|
||||
// TODO - only push unique paths
|
||||
plugin_directories_.push_back(str);
|
||||
boost::filesystem::directory_iterator end_itr;
|
||||
|
||||
|
|
|
@ -69,7 +69,7 @@ void memory_datasource::push(feature_ptr feature)
|
|||
features_.push_back(feature);
|
||||
}
|
||||
|
||||
int memory_datasource::type() const
|
||||
datasource::datasource_t memory_datasource::type() const
|
||||
{
|
||||
return datasource::Vector;
|
||||
}
|
||||
|
@ -96,6 +96,12 @@ box2d<double> memory_datasource::envelope() const
|
|||
std::for_each(features_.begin(),features_.end(),func);
|
||||
return ext;
|
||||
}
|
||||
|
||||
boost::optional<datasource::geometry_t> memory_datasource::get_geometry_type() const
|
||||
{
|
||||
// TODO - detect this?
|
||||
return datasource::Collection;
|
||||
}
|
||||
|
||||
layer_descriptor memory_datasource::get_descriptor() const
|
||||
{
|
||||
|
@ -118,7 +124,7 @@ void point_datasource::add_point(double x, double y, const char* key, const char
|
|||
{
|
||||
feature_ptr feature(feature_factory::create(feature_id_));
|
||||
++feature_id_;
|
||||
geometry_type * pt = new geometry_type(Point);
|
||||
geometry_type * pt = new geometry_type(mapnik::Point);
|
||||
pt->move_to(x,y);
|
||||
feature->add_geometry(pt);
|
||||
transcoder tr("utf-8");
|
||||
|
|
4178
tests/data/csv/10m-land.csv
Normal file
4178
tests/data/csv/10m-land.csv
Normal file
File diff suppressed because one or more lines are too long
3
tests/data/csv/line_wkt.csv
Normal file
3
tests/data/csv/line_wkt.csv
Normal file
|
@ -0,0 +1,3 @@
|
|||
type,WKT
|
||||
linestring, "LINESTRING (30 10, 10 30, 40 40)"
|
||||
multilinestring, "MULTILINESTRING ((10 10, 20 20, 10 40),(40 40, 30 30, 40 20, 30 10))"
|
|
5
tests/data/csv/multi_poly_wkt.csv
Normal file
5
tests/data/csv/multi_poly_wkt.csv
Normal file
|
@ -0,0 +1,5 @@
|
|||
type,WKT
|
||||
polygon, "POLYGON ((30 10, 10 20, 20 40, 40 40, 30 10))"
|
||||
polygon, "POLYGON ((35 10, 10 20, 15 40, 45 45, 35 10),(20 30, 35 35, 30 20, 20 30))"
|
||||
multipolygon, "MULTIPOLYGON (((30 20, 10 40, 45 40, 30 20)),((15 5, 40 10, 10 20, 5 10, 15 5)))"
|
||||
multipolygon, "MULTIPOLYGON (((40 40, 20 45, 45 30, 40 40)),((20 35, 45 20, 30 5, 10 10, 10 30, 20 35),(30 20, 20 25, 20 15, 30 20)))"
|
|
3
tests/data/csv/point_wkt.csv
Normal file
3
tests/data/csv/point_wkt.csv
Normal file
|
@ -0,0 +1,3 @@
|
|||
type,WKT
|
||||
point, "POINT (30 10)"
|
||||
multipoint, "MULTIPOINT ((10 40), (40 30), (20 20), (30 10))"
|
|
3
tests/data/csv/poly_wkt.csv
Normal file
3
tests/data/csv/poly_wkt.csv
Normal file
|
@ -0,0 +1,3 @@
|
|||
type,WKT
|
||||
polygon, "POLYGON ((30 10, 10 20, 20 40, 40 40, 30 10))"
|
||||
polygon, "POLYGON ((35 10, 10 20, 15 40, 45 45, 35 10),(20 30, 35 35, 30 20, 20 30))"
|
|
|
@ -54,12 +54,14 @@ if 'csv' in mapnik.DatasourceCache.instance().plugin_names():
|
|||
attr = {'City': u'New York, NY', 'geo_accuracy': u'house', 'Phone': u'(212) 334-0711', 'Address': u'19 Elizabeth Street', 'Precinct': u'5th Precinct', 'geo_longitude': -70, 'geo_latitude': 40}
|
||||
eq_(feat.attributes,attr)
|
||||
eq_(len(ds.all_features()),2)
|
||||
eq_(ds.describe(),{'geometry_type': mapnik.DataGeometryType.Point, 'type': mapnik.DataType.Vector, 'name': 'csv', 'encoding': 'utf-8'})
|
||||
|
||||
def test_skipping_blank_rows(**kwargs):
|
||||
ds = get_csv_ds('blank_rows.csv')
|
||||
eq_(ds.fields(),['x','y','name'])
|
||||
eq_(ds.field_types(),['int','int','str'])
|
||||
eq_(len(ds.all_features()),2)
|
||||
eq_(ds.describe(),{'geometry_type': mapnik.DataGeometryType.Point, 'type': mapnik.DataType.Vector, 'name': 'csv', 'encoding': 'utf-8'})
|
||||
|
||||
def test_empty_rows(**kwargs):
|
||||
ds = get_csv_ds('empty_rows.csv')
|
||||
|
@ -75,6 +77,7 @@ if 'csv' in mapnik.DatasourceCache.instance().plugin_names():
|
|||
eq_(len(feat),10)
|
||||
eq_(feat['empty_column'],u'')
|
||||
feat = fs.next()
|
||||
eq_(ds.describe(),{'geometry_type': mapnik.DataGeometryType.Point, 'type': mapnik.DataType.Vector, 'name': 'csv', 'encoding': 'utf-8'})
|
||||
|
||||
def test_slashes(**kwargs):
|
||||
ds = get_csv_ds('has_attributes_with_slashes.csv')
|
||||
|
@ -83,6 +86,7 @@ if 'csv' in mapnik.DatasourceCache.instance().plugin_names():
|
|||
eq_(fs[0].attributes,{'x':0,'y':0,'name':u'a/a'})
|
||||
eq_(fs[1].attributes,{'x':1,'y':4,'name':u'b/b'})
|
||||
eq_(fs[2].attributes,{'x':10,'y':2.5,'name':u'c/c'})
|
||||
eq_(ds.describe(),{'geometry_type': mapnik.DataGeometryType.Point, 'type': mapnik.DataType.Vector, 'name': 'csv', 'encoding': 'utf-8'})
|
||||
|
||||
def test_wkt_field(**kwargs):
|
||||
ds = get_csv_ds('wkt.csv')
|
||||
|
@ -92,24 +96,25 @@ if 'csv' in mapnik.DatasourceCache.instance().plugin_names():
|
|||
fs = ds.all_features()
|
||||
#import pdb;pdb.set_trace()
|
||||
eq_(len(fs[0].geometries()),1)
|
||||
eq_(fs[0].geometries()[0].type(),mapnik.GeometryType.Point)
|
||||
eq_(fs[0].geometries()[0].type(),mapnik.DataGeometryType.Point)
|
||||
eq_(len(fs[1].geometries()),1)
|
||||
eq_(fs[1].geometries()[0].type(),mapnik.GeometryType.LineString)
|
||||
eq_(fs[1].geometries()[0].type(),mapnik.DataGeometryType.LineString)
|
||||
eq_(len(fs[2].geometries()),1)
|
||||
eq_(fs[2].geometries()[0].type(),mapnik.GeometryType.Polygon)
|
||||
eq_(fs[2].geometries()[0].type(),mapnik.DataGeometryType.Polygon)
|
||||
eq_(len(fs[3].geometries()),1) # one geometry, two parts
|
||||
eq_(fs[3].geometries()[0].type(),mapnik.GeometryType.Polygon)
|
||||
eq_(fs[3].geometries()[0].type(),mapnik.DataGeometryType.Polygon)
|
||||
# tests assuming we want to flatten geometries
|
||||
# ideally we should not have to:
|
||||
# https://github.com/mapnik/mapnik/issues?labels=multigeom+robustness&sort=created&direction=desc&state=open&page=1
|
||||
eq_(len(fs[4].geometries()),4)
|
||||
eq_(fs[4].geometries()[0].type(),mapnik.GeometryType.Point)
|
||||
eq_(fs[4].geometries()[0].type(),mapnik.DataGeometryType.Point)
|
||||
eq_(len(fs[5].geometries()),2)
|
||||
eq_(fs[5].geometries()[0].type(),mapnik.GeometryType.LineString)
|
||||
eq_(fs[5].geometries()[0].type(),mapnik.DataGeometryType.LineString)
|
||||
eq_(len(fs[6].geometries()),2)
|
||||
eq_(fs[6].geometries()[0].type(),mapnik.GeometryType.Polygon)
|
||||
eq_(fs[6].geometries()[0].type(),mapnik.DataGeometryType.Polygon)
|
||||
eq_(len(fs[7].geometries()),2)
|
||||
eq_(fs[7].geometries()[0].type(),mapnik.GeometryType.Polygon)
|
||||
eq_(fs[7].geometries()[0].type(),mapnik.DataGeometryType.Polygon)
|
||||
eq_(ds.describe(),{'geometry_type': mapnik.DataGeometryType.Collection, 'type': mapnik.DataType.Vector, 'name': 'csv', 'encoding': 'utf-8'})
|
||||
|
||||
|
||||
def test_handling_of_missing_header(**kwargs):
|
||||
|
@ -119,6 +124,7 @@ if 'csv' in mapnik.DatasourceCache.instance().plugin_names():
|
|||
fs = ds.featureset()
|
||||
feat = fs.next()
|
||||
eq_(feat['_4'],'missing')
|
||||
eq_(ds.describe(),{'geometry_type': mapnik.DataGeometryType.Point, 'type': mapnik.DataType.Vector, 'name': 'csv', 'encoding': 'utf-8'})
|
||||
|
||||
def test_handling_of_headers_that_are_numbers(**kwargs):
|
||||
ds = get_csv_ds('numbers_for_headers.csv')
|
||||
|
@ -144,6 +150,7 @@ if 'csv' in mapnik.DatasourceCache.instance().plugin_names():
|
|||
eq_(fs[2]['label'],"0,5")
|
||||
eq_(fs[3]['label'],"5,0")
|
||||
eq_(fs[4]['label'],"2.5,2.5")
|
||||
eq_(ds.describe(),{'geometry_type': mapnik.DataGeometryType.Point, 'type': mapnik.DataType.Vector, 'name': 'csv', 'encoding': 'utf-8'})
|
||||
|
||||
def test_windows_newlines(**kwargs):
|
||||
ds = get_csv_ds('windows_newlines.csv')
|
||||
|
@ -155,6 +162,7 @@ if 'csv' in mapnik.DatasourceCache.instance().plugin_names():
|
|||
eq_(feat['x'],1)
|
||||
eq_(feat['y'],10)
|
||||
eq_(feat['z'],9999.9999)
|
||||
eq_(ds.describe(),{'geometry_type': mapnik.DataGeometryType.Point, 'type': mapnik.DataType.Vector, 'name': 'csv', 'encoding': 'utf-8'})
|
||||
|
||||
def test_mac_newlines(**kwargs):
|
||||
ds = get_csv_ds('windows_newlines.csv')
|
||||
|
@ -166,6 +174,7 @@ if 'csv' in mapnik.DatasourceCache.instance().plugin_names():
|
|||
eq_(feat['x'],1)
|
||||
eq_(feat['y'],10)
|
||||
eq_(feat['z'],9999.9999)
|
||||
eq_(ds.describe(),{'geometry_type': mapnik.DataGeometryType.Point, 'type': mapnik.DataType.Vector, 'name': 'csv', 'encoding': 'utf-8'})
|
||||
|
||||
def test_tabs(**kwargs):
|
||||
ds = get_csv_ds('tabs_in_csv.csv')
|
||||
|
@ -176,6 +185,7 @@ if 'csv' in mapnik.DatasourceCache.instance().plugin_names():
|
|||
eq_(feat['x'],-122)
|
||||
eq_(feat['y'],48)
|
||||
eq_(feat['z'],0)
|
||||
eq_(ds.describe(),{'geometry_type': mapnik.DataGeometryType.Point, 'type': mapnik.DataType.Vector, 'name': 'csv', 'encoding': 'utf-8'})
|
||||
|
||||
def test_separator_pipes(**kwargs):
|
||||
ds = get_csv_ds('pipe_delimiters.csv')
|
||||
|
@ -186,6 +196,7 @@ if 'csv' in mapnik.DatasourceCache.instance().plugin_names():
|
|||
eq_(feat['x'],0)
|
||||
eq_(feat['y'],0)
|
||||
eq_(feat['z'],'hello')
|
||||
eq_(ds.describe(),{'geometry_type': mapnik.DataGeometryType.Point, 'type': mapnik.DataType.Vector, 'name': 'csv', 'encoding': 'utf-8'})
|
||||
|
||||
def test_separator_semicolon(**kwargs):
|
||||
ds = get_csv_ds('semicolon_delimiters.csv')
|
||||
|
@ -196,6 +207,7 @@ if 'csv' in mapnik.DatasourceCache.instance().plugin_names():
|
|||
eq_(feat['x'],0)
|
||||
eq_(feat['y'],0)
|
||||
eq_(feat['z'],'hello')
|
||||
eq_(ds.describe(),{'geometry_type': mapnik.DataGeometryType.Point, 'type': mapnik.DataType.Vector, 'name': 'csv', 'encoding': 'utf-8'})
|
||||
|
||||
def test_that_null_and_bool_keywords_are_empty_strings(**kwargs):
|
||||
ds = get_csv_ds('nulls_and_booleans_as_strings.csv')
|
||||
|
@ -213,6 +225,7 @@ if 'csv' in mapnik.DatasourceCache.instance().plugin_names():
|
|||
eq_(feat['y'],0)
|
||||
eq_(feat['null'],'')
|
||||
eq_(feat['boolean'],'false')
|
||||
eq_(ds.describe(),{'geometry_type': mapnik.DataGeometryType.Point, 'type': mapnik.DataType.Vector, 'name': 'csv', 'encoding': 'utf-8'})
|
||||
|
||||
@raises(RuntimeError)
|
||||
def test_that_nonexistant_query_field_throws(**kwargs):
|
||||
|
@ -226,6 +239,7 @@ if 'csv' in mapnik.DatasourceCache.instance().plugin_names():
|
|||
# also add an invalid one, triggering throw
|
||||
query.add_property_name('bogus')
|
||||
fs = ds.features(query)
|
||||
eq_(ds.describe(),{'geometry_type': mapnik.DataGeometryType.Point, 'type': mapnik.DataType.Vector, 'name': 'csv', 'encoding': 'utf-8'})
|
||||
|
||||
def test_that_leading_zeros_mean_strings(**kwargs):
|
||||
ds = get_csv_ds('leading_zeros.csv')
|
||||
|
@ -245,6 +259,17 @@ if 'csv' in mapnik.DatasourceCache.instance().plugin_names():
|
|||
eq_(feat['x'],0)
|
||||
eq_(feat['y'],0)
|
||||
eq_(feat['fips'],'005')
|
||||
eq_(ds.describe(),{'geometry_type': mapnik.DataGeometryType.Point, 'type': mapnik.DataType.Vector, 'name': 'csv', 'encoding': 'utf-8'})
|
||||
|
||||
def test_advanced_geometry_detection(**kwargs):
|
||||
ds = get_csv_ds('point_wkt.csv')
|
||||
eq_(ds.describe()['geometry_type'],mapnik.DataGeometryType.Point)
|
||||
ds = get_csv_ds('poly_wkt.csv')
|
||||
eq_(ds.describe()['geometry_type'],mapnik.DataGeometryType.Polygon)
|
||||
ds = get_csv_ds('multi_poly_wkt.csv')
|
||||
eq_(ds.describe()['geometry_type'],mapnik.DataGeometryType.Polygon)
|
||||
ds = get_csv_ds('line_wkt.csv')
|
||||
eq_(ds.describe()['geometry_type'],mapnik.DataGeometryType.LineString)
|
||||
|
||||
if __name__ == "__main__":
|
||||
setup()
|
||||
|
|
|
@ -15,65 +15,68 @@ def test_that_datasources_exist():
|
|||
print '***NOTICE*** - no datasource plugins have been loaded'
|
||||
|
||||
def test_field_listing():
|
||||
lyr = mapnik.Layer('test')
|
||||
if 'shape' in mapnik.DatasourceCache.instance().plugin_names():
|
||||
lyr.datasource = mapnik.Shapefile(file='../data/shp/poly.shp')
|
||||
fields = lyr.datasource.fields()
|
||||
ds = mapnik.Shapefile(file='../data/shp/poly.shp')
|
||||
fields = ds.fields()
|
||||
eq_(fields, ['AREA', 'EAS_ID', 'PRFEDEA'])
|
||||
eq_(ds.describe(),{'geometry_type': mapnik.DataGeometryType.Polygon, 'type': mapnik.DataType.Vector, 'name': 'shape', 'encoding': 'utf-8'})
|
||||
|
||||
def test_total_feature_count_shp():
|
||||
lyr = mapnik.Layer('test')
|
||||
if 'shape' in mapnik.DatasourceCache.instance().plugin_names():
|
||||
lyr.datasource = mapnik.Shapefile(file='../data/shp/poly.shp')
|
||||
features = lyr.datasource.all_features()
|
||||
ds = mapnik.Shapefile(file='../data/shp/poly.shp')
|
||||
features = ds.all_features()
|
||||
num_feats = len(features)
|
||||
eq_(num_feats, 10)
|
||||
|
||||
def test_total_feature_count_json():
|
||||
lyr = mapnik.Layer('test')
|
||||
if 'ogr' in mapnik.DatasourceCache.instance().plugin_names():
|
||||
lyr.datasource = mapnik.Ogr(file='../data/json/points.json',layer_by_index=0)
|
||||
features = lyr.datasource.all_features()
|
||||
ds = mapnik.Ogr(file='../data/json/points.json',layer_by_index=0)
|
||||
eq_(ds.describe(),{'geometry_type': mapnik.DataGeometryType.Point, 'type': mapnik.DataType.Vector, 'name': 'ogr', 'encoding': 'utf-8'})
|
||||
features = ds.all_features()
|
||||
num_feats = len(features)
|
||||
eq_(num_feats, 5)
|
||||
|
||||
def test_sqlite_reading():
|
||||
if 'sqlite' in mapnik.DatasourceCache.instance().plugin_names():
|
||||
ds = mapnik.SQLite(file='../data/sqlite/world.sqlite',table_by_index=0)
|
||||
eq_(ds.describe(),{'geometry_type': mapnik.DataGeometryType.Polygon, 'type': mapnik.DataType.Vector, 'name': 'sqlite', 'encoding': 'utf-8'})
|
||||
features = ds.all_features()
|
||||
num_feats = len(features)
|
||||
eq_(num_feats, 245)
|
||||
|
||||
def test_reading_json_from_string():
|
||||
json = open('../data/json/points.json','r').read()
|
||||
lyr = mapnik.Layer('test')
|
||||
if 'ogr' in mapnik.DatasourceCache.instance().plugin_names():
|
||||
lyr.datasource = mapnik.Ogr(file=json,layer_by_index=0)
|
||||
features = lyr.datasource.all_features()
|
||||
ds = mapnik.Ogr(file=json,layer_by_index=0)
|
||||
features = ds.all_features()
|
||||
num_feats = len(features)
|
||||
eq_(num_feats, 5)
|
||||
|
||||
def test_feature_envelope():
|
||||
lyr = mapnik.Layer('test')
|
||||
if 'shape' in mapnik.DatasourceCache.instance().plugin_names():
|
||||
lyr.datasource = mapnik.Shapefile(file='../data/shp/poly.shp')
|
||||
features = lyr.datasource.all_features()
|
||||
ds = mapnik.Shapefile(file='../data/shp/poly.shp')
|
||||
features = ds.all_features()
|
||||
for feat in features:
|
||||
env = feat.envelope()
|
||||
contains = lyr.envelope().contains(env)
|
||||
contains = ds.envelope().contains(env)
|
||||
eq_(contains, True)
|
||||
intersects = lyr.envelope().contains(env)
|
||||
intersects = ds.envelope().contains(env)
|
||||
eq_(intersects, True)
|
||||
|
||||
def test_feature_attributes():
|
||||
lyr = mapnik.Layer('test')
|
||||
if 'shape' in mapnik.DatasourceCache.instance().plugin_names():
|
||||
lyr.datasource = mapnik.Shapefile(file='../data/shp/poly.shp')
|
||||
features = lyr.datasource.all_features()
|
||||
ds = mapnik.Shapefile(file='../data/shp/poly.shp')
|
||||
features = ds.all_features()
|
||||
feat = features[0]
|
||||
attrs = {'PRFEDEA': u'35043411', 'EAS_ID': 168, 'AREA': 215229.266}
|
||||
eq_(feat.attributes, attrs)
|
||||
eq_(lyr.datasource.fields(),['AREA', 'EAS_ID', 'PRFEDEA'])
|
||||
eq_(lyr.datasource.field_types(),['float','int','str'])
|
||||
eq_(ds.fields(),['AREA', 'EAS_ID', 'PRFEDEA'])
|
||||
eq_(ds.field_types(),['float','int','str'])
|
||||
|
||||
def test_ogr_layer_by_sql():
|
||||
lyr = mapnik.Layer('test')
|
||||
if 'ogr' in mapnik.DatasourceCache.instance().plugin_names():
|
||||
lyr.datasource = mapnik.Ogr(file='../data/shp/poly.shp', layer_by_sql='SELECT * FROM poly WHERE EAS_ID = 168')
|
||||
features = lyr.datasource.all_features()
|
||||
ds = mapnik.Ogr(file='../data/shp/poly.shp', layer_by_sql='SELECT * FROM poly WHERE EAS_ID = 168')
|
||||
features = ds.all_features()
|
||||
num_feats = len(features)
|
||||
eq_(num_feats, 1)
|
||||
|
||||
|
|
|
@ -58,8 +58,8 @@ def test_adding_datasource_to_layer():
|
|||
m.layers[0].datasource = ds
|
||||
|
||||
# now ensure it is attached
|
||||
eq_(m.layers[0].datasource.name(),"shape")
|
||||
eq_(lyr.datasource.name(),"shape")
|
||||
eq_(m.layers[0].datasource.describe()['name'],"shape")
|
||||
eq_(lyr.datasource.describe()['name'],"shape")
|
||||
|
||||
# and since we have now added a shapefile in spherical mercator, adjust the projection
|
||||
lyr.srs = '+proj=merc +lon_0=0 +lat_ts=0 +x_0=0 +y_0=0 +ellps=WGS84 +datum=WGS84 +units=m +no_defs'
|
||||
|
|
|
@ -20,7 +20,7 @@ def call(cmd,silent=False):
|
|||
stdin, stderr = Popen(cmd, shell=True, stdout=PIPE, stderr=PIPE).communicate()
|
||||
if not stderr:
|
||||
return stdin.strip()
|
||||
elif not silent:
|
||||
elif not silent and not 'NOTICE' in stderr:
|
||||
raise RuntimeError(stderr.strip())
|
||||
|
||||
def psql_can_connect():
|
||||
|
@ -63,12 +63,23 @@ def createdb_and_dropdb_on_path():
|
|||
print 'Notice: skipping postgis tests (createdb/dropdb)'
|
||||
return False
|
||||
|
||||
insert_sql = """
|
||||
INSERT INTO test(geom) values (GeomFromEWKT('SRID=4326;POINT(0 0)'));
|
||||
INSERT INTO test(geom) values (GeomFromEWKT('SRID=4326;POINT(-2 2)'));
|
||||
INSERT INTO test(geom) values (GeomFromEWKT('SRID=4326;MULTIPOINT(2 1,1 2)'));
|
||||
INSERT INTO test(geom) values (GeomFromEWKT('SRID=4326;LINESTRING(0 0,1 1,1 2)'));
|
||||
INSERT INTO test(geom) values (GeomFromEWKT('SRID=4326;MULTILINESTRING((1 0,0 1,3 2),(3 2,5 4))'));
|
||||
INSERT INTO test(geom) values (GeomFromEWKT('SRID=4326;POLYGON((0 0,4 0,4 4,0 4,0 0),(1 1, 2 1, 2 2, 1 2,1 1))'));
|
||||
INSERT INTO test(geom) values (GeomFromEWKT('SRID=4326;MULTIPOLYGON(((1 1,3 1,3 3,1 3,1 1),(1 1,2 1,2 2,1 2,1 1)), ((-1 -1,-1 -2,-2 -2,-2 -1,-1 -1)))'));
|
||||
INSERT INTO test(geom) values (GeomFromEWKT('SRID=4326;GEOMETRYCOLLECTION(POLYGON((1 1, 2 1, 2 2, 1 2,1 1)),POINT(2 3),LINESTRING(2 3,3 4))'));
|
||||
"""
|
||||
|
||||
def postgis_setup():
|
||||
call('dropdb %s' % MAPNIK_TEST_DBNAME,silent=True)
|
||||
call('createdb -T %s %s' % (POSTGIS_TEMPLATE_DBNAME,MAPNIK_TEST_DBNAME),silent=False)
|
||||
call('shp2pgsql -s 3857 -g geom -W LATIN1 %s world_merc | psql -q %s' % (SHAPEFILE,MAPNIK_TEST_DBNAME), silent=True)
|
||||
call('''psql %s -c "CREATE TABLE \"empty\" (key serial);SELECT AddGeometryColumn('','empty','geom','-1','GEOMETRY',4);"''' % MAPNIK_TEST_DBNAME,silent=True)
|
||||
|
||||
call('''psql -q %s -c "CREATE TABLE \"empty\" (key serial);SELECT AddGeometryColumn('','empty','geom','-1','GEOMETRY',4);"''' % MAPNIK_TEST_DBNAME,silent=False)
|
||||
call('''psql -q %s -c "create table test(gid serial PRIMARY KEY, geom geometry);%s"''' % (MAPNIK_TEST_DBNAME,insert_sql),silent=False)
|
||||
def postgis_takedown():
|
||||
pass
|
||||
# fails as the db is in use: https://github.com/mapnik/mapnik/issues/960
|
||||
|
@ -98,6 +109,7 @@ if 'postgis' in mapnik.DatasourceCache.instance().plugin_names() \
|
|||
eq_(feature['subregion'],29)
|
||||
eq_(feature['lon'],-61.783)
|
||||
eq_(feature['lat'],17.078)
|
||||
eq_(ds.describe()['geometry_type'],mapnik.DataGeometryType.Polygon)
|
||||
|
||||
def test_subquery():
|
||||
ds = mapnik.PostGIS(dbname=MAPNIK_TEST_DBNAME,table='(select * from world_merc) as w')
|
||||
|
@ -115,6 +127,7 @@ if 'postgis' in mapnik.DatasourceCache.instance().plugin_names() \
|
|||
eq_(feature['subregion'],29)
|
||||
eq_(feature['lon'],-61.783)
|
||||
eq_(feature['lat'],17.078)
|
||||
eq_(ds.describe()['geometry_type'],mapnik.DataGeometryType.Polygon)
|
||||
|
||||
ds = mapnik.PostGIS(dbname=MAPNIK_TEST_DBNAME,table='(select gid,geom,fips as _fips from world_merc) as w')
|
||||
fs = ds.featureset()
|
||||
|
@ -122,12 +135,39 @@ if 'postgis' in mapnik.DatasourceCache.instance().plugin_names() \
|
|||
eq_(feature['gid'],1)
|
||||
eq_(feature['_fips'],u'AC')
|
||||
eq_(len(feature),2)
|
||||
eq_(ds.describe()['geometry_type'],mapnik.DataGeometryType.Polygon)
|
||||
|
||||
def test_empty_db():
|
||||
ds = mapnik.PostGIS(dbname=MAPNIK_TEST_DBNAME,table='empty')
|
||||
fs = ds.featureset()
|
||||
feature = fs.next()
|
||||
eq_(feature,None)
|
||||
eq_(ds.describe()['geometry_type'],mapnik.DataGeometryType.Collection)
|
||||
|
||||
def test_geometry_detection():
|
||||
ds = mapnik.PostGIS(dbname=MAPNIK_TEST_DBNAME,table='test',
|
||||
geometry_field='geom')
|
||||
eq_(ds.describe()['geometry_type'],mapnik.DataGeometryType.Collection)
|
||||
|
||||
ds = mapnik.PostGIS(dbname=MAPNIK_TEST_DBNAME,table='test',
|
||||
geometry_field='geom',
|
||||
row_limit=1)
|
||||
eq_(ds.describe()['geometry_type'],mapnik.DataGeometryType.Point)
|
||||
|
||||
ds = mapnik.PostGIS(dbname=MAPNIK_TEST_DBNAME,table='test',
|
||||
geometry_field='geom',
|
||||
row_limit=2)
|
||||
eq_(ds.describe()['geometry_type'],mapnik.DataGeometryType.Point)
|
||||
|
||||
ds = mapnik.PostGIS(dbname=MAPNIK_TEST_DBNAME,table='test',
|
||||
geometry_field='geom',
|
||||
row_limit=3)
|
||||
eq_(ds.describe()['geometry_type'],mapnik.DataGeometryType.Point)
|
||||
|
||||
ds = mapnik.PostGIS(dbname=MAPNIK_TEST_DBNAME,table='test',
|
||||
geometry_field='geom',
|
||||
row_limit=4)
|
||||
eq_(ds.describe()['geometry_type'],mapnik.DataGeometryType.Collection)
|
||||
|
||||
@raises(RuntimeError)
|
||||
def test_that_nonexistant_query_field_throws(**kwargs):
|
||||
|
|
Loading…
Reference in a new issue