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

This commit is contained in:
kunitoki 2011-10-26 00:58:57 +02:00
commit ab5e59477e
23 changed files with 453 additions and 115 deletions

View file

@ -485,10 +485,11 @@ def Ogr(**keywords):
Required keyword arguments:
file -- path to OGR supported dataset
layer -- name of layer to use within datasource (optional if layer_by_index is used)
layer -- name of layer to use within datasource (optional if layer_by_index or layer_by_sql is used)
Optional keyword arguments:
layer_by_index -- choose layer by index number instead of by layer name.
layer_by_index -- choose layer by index number instead of by layer name or sql.
layer_by_sql -- choose layer by sql query number instead of by layer name or index.
base -- path prefix (default None)
encoding -- file encoding (default 'utf-8')
multiple_geometries -- boolean, direct the Mapnik wkb reader to interpret as multigeometries (default False)

View file

@ -15,11 +15,33 @@ Look through the code to get an idea, and do not hesitate to ask questions.
Also read the design philosophy page for the motivations that lead to code decisions.
Templates are good, within reason. We seek to use templates were possible for flexible code, but not in cases where functional
patterns would be just as concise and clear.
In general we use Boost, it makes more possible in C++. It is a big build time dependency (as in time to compile against and # of headers) but ultimately compiles to small object code and is very fast (particularly spirit). It also has no dependencies itself (it's really an extension to the C++ language) so requiring it is much easier than requiring a hard dependency that itself has other dependencies. This is a big reason that we prefer AGG to Cairo as our primary renderer. Also AGG, besides producing the best visual output, strikes an excellent balance between speed and thread safety by using very lightweight objects. Cairo not so much.
You will also notice that we don't use many of the standard geo libraries when we could. For instance we don't use GDAL, OGR, or GEOS anywhere in core, and only leverage them in optional plugins. We feel we can often write code that is faster and more thread safe than these libraries but that still does the job. If this ever changes we can adapt and start using these libraries or others as dependencies - nothing is nicer than standing on the shoulders of giants when it makes sense.
## Code commits best practices.
#### Big changes - awesome as pull requests
We love big, aggressive refactoring - but ideally in branches. Even if the changes should go directly into the mainline code and are stable, very big changes are useful to see as a group and branches are cheap. So, branch and commit then create a pull request against master so that other developers can take a quick look. This is a great way for informal code review when a full issue is not warrented.
#### Commits that fix issues should note the issue #
git commit plugins/input/ogr/ -m "implemented sql query in OGR plugin (closes #472)"
#### Commits that relate to issues should reference them:
git commit tests/python_tests/sqlite_test.py -m "more robust sqlite tests - refs #928"
#### Commits that add a new feature or fix should be added to the CHANGELOG
Ideally the CHANGELOG can be a very concise place to look for the most important recent development and should not read like a full commit log. So, some developers may prefer to weekly or monthly look back over their commits and summarize all at once with additions to the CHANGELOG. Other developers may prefer to add as they go.
## License
Mapnik is licensed LGPL, which means that you are a free to use the code in any of your applications whether they be open source or not. It also means that if you contribute code to Mapnik that others are free to continue using Mapnik in the same way, even with your new additions. If you choose to redistribute an application using Mapnik just make sure to provide any source code modifications you make back to the community. For the actual details see the full LGPL license in the COPYING doc.
@ -67,13 +89,19 @@ If you see bits of code around that do not follow these please don't hesitate to
#### Indentation is four spaces
#### Use C++ style casts
static_cast<int>(value); // yes
(int)value; // no
#### Shared pointers should be created with [boost::make_shared](http://www.boost.org/doc/libs/1_47_0/libs/smart_ptr/make_shared.html) where possible
#### Function definitions should not be separated from their arguments:
void foo(int a) { ... } // please
void foo(int a) // please
void foo (int a) { ... } // no
void foo (int a) // no
#### Separate arguments by a single space:
@ -87,7 +115,18 @@ If you see bits of code around that do not follow these please don't hesitate to
if(a==b) // no
#### Braces should ideally be on a separate line:
#### Braces should always be used:
if (!file)
{
throw mapnik::datasource_exception("not found"); // please
}
if (!file)
throw mapnik::datasource_exception("not found"); // no
#### Braces should be on a separate line:
if (a == b)
{

View file

@ -159,8 +159,8 @@ public:
std::string to_string() const
{
std::stringstream ss;
ss << "feature (" << std::endl;
ss << " id:" << id_ << std::endl;
ss << "feature "
<< id_ << " (" << std::endl;
for (std::map<std::string,value>::const_iterator itr=props_.begin();
itr != props_.end();++itr)
{

View file

@ -56,7 +56,7 @@ 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")),
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");
@ -66,7 +66,7 @@ ogr_datasource::ogr_datasource(parameters const& params, bool bind)
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)
{
@ -95,6 +95,9 @@ ogr_datasource::~ogr_datasource()
{
if (is_bound_)
{
// free layer before destroying the datasource
layer_.free_layer();
OGRDataSource::DestroyDataSource (dataset_);
}
}
@ -122,19 +125,27 @@ void ogr_datasource::bind() const
}
// 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");
boost::optional<std::string> layer_by_sql = params_.get<std::string>("layer_by_sql");
if (layer_by_name && layer_by_index)
int passed_parameters = 0;
passed_parameters += layer_by_name ? 1 : 0;
passed_parameters += layer_by_index ? 1 : 0;
passed_parameters += layer_by_sql ? 1 : 0;
if (passed_parameters > 1)
{
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" );
throw datasource_exception("OGR Plugin: you can only select an ogr layer by name "
"('layer' parameter), by number ('layer_by_index' parameter), "
"or by sql ('layer_by_sql' parameter), "
"do not supply 2 or more of them at the same time" );
}
if (layer_by_name)
{
layerName_ = *layer_by_name;
layer_ = dataset_->GetLayerByName(layerName_.c_str());
layer_name_ = *layer_by_name;
layer_.layer_by_name(dataset_, layer_name_);
}
else if (layer_by_index)
{
@ -149,21 +160,19 @@ void ogr_datasource::bind() const
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;
}
}
layer_.layer_by_index(dataset_, *layer_by_index);
layer_name_ = layer_.layer_name();
}
else if (layer_by_sql)
{
layer_.layer_by_sql(dataset_, *layer_by_sql);
layer_name_ = layer_.layer_name();
}
else
{
std::ostringstream s;
s << "OGR Plugin: missing <layer> or <layer_by_index> parameter, available layers are: ";
s << "OGR Plugin: missing <layer> or <layer_by_index> or <layer_by_sql> "
<< "parameter, available layers are: ";
unsigned num_layers = dataset_->GetLayerCount();
bool layer_found = false;
@ -186,7 +195,7 @@ void ogr_datasource::bind() const
throw datasource_exception(s.str());
}
if (! layer_)
if (! layer_.is_valid())
{
std::string s("OGR Plugin: ");
@ -198,15 +207,22 @@ void ogr_datasource::bind() const
{
s += "cannot find layer by index number '" + *layer_by_index;
}
else if (layer_by_sql)
{
s += "cannot find layer by sql query '" + *layer_by_sql;
}
s += "' in dataset '" + dataset_name_ + "'";
throw datasource_exception(s);
}
// work with real OGR layer
OGRLayer* layer = layer_.layer();
// initialize envelope
OGREnvelope envelope;
layer_->GetExtent(&envelope);
layer->GetExtent(&envelope);
extent_.init(envelope.MinX, envelope.MinY, envelope.MaxX, envelope.MaxY);
// scan for index file
@ -220,7 +236,7 @@ void ogr_datasource::bind() const
}
index_name_ = dataset_name_.substr(0, breakpoint) + ".ogrindex";
std::ifstream index_file (index_name_.c_str(), std::ios::in | std::ios::binary);
std::ifstream index_file(index_name_.c_str(), std::ios::in | std::ios::binary);
if (index_file)
{
indexed_ = true;
@ -237,7 +253,7 @@ void ogr_datasource::bind() const
#endif
// deal with attributes descriptions
OGRFeatureDefn* def = layer_->GetLayerDefn();
OGRFeatureDefn* def = layer->GetLayerDefn();
if (def != 0)
{
const int fld_count = def->GetFieldCount();
@ -323,39 +339,16 @@ featureset_ptr ogr_datasource::features(query const& q) const
{
if (! is_bound_) bind();
if (dataset_ && layer_)
if (dataset_ && layer_.is_valid())
{
#if 0
// TODO - actually filter fields!
// http://trac.osgeo.org/gdal/wiki/rfc29_desired_fields
// http://trac.osgeo.org/gdal/wiki/rfc28_sqlfunc
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();
while (pos != end)
{
s << ",\"" << *pos << "\"";
++pos;
}
s << " from " << layerName_ ;
// execute existing SQL
OGRLayer* layer = dataset_->ExecuteSQL(s.str(), poly);
// layer must be freed
dataset_->ReleaseResultSet(layer);
#endif
OGRLayer* layer = layer_.layer();
if (indexed_)
{
filter_in_box filter(q.get_bbox());
return featureset_ptr(new ogr_index_featureset<filter_in_box>(*dataset_,
*layer_,
*layer,
filter,
index_name_,
desc_.get_encoding(),
@ -364,12 +357,13 @@ featureset_ptr ogr_datasource::features(query const& q) const
else
{
return featureset_ptr(new ogr_featureset (*dataset_,
*layer_,
*layer,
q.get_bbox(),
desc_.get_encoding(),
multiple_geometries_));
}
}
return featureset_ptr();
}
@ -377,14 +371,16 @@ featureset_ptr ogr_datasource::features_at_point(coord2d const& pt) const
{
if (!is_bound_) bind();
if (dataset_ && layer_)
if (dataset_ && layer_.is_valid())
{
OGRLayer* layer = layer_.layer();
if (indexed_)
{
filter_at_point filter(pt);
return featureset_ptr(new ogr_index_featureset<filter_at_point> (*dataset_,
*layer_,
*layer,
filter,
index_name_,
desc_.get_encoding(),
@ -397,11 +393,12 @@ featureset_ptr ogr_datasource::features_at_point(coord2d const& pt) const
point.setY (pt.y);
return featureset_ptr(new ogr_featureset (*dataset_,
*layer_,
*layer,
point,
desc_.get_encoding(),
multiple_geometries_));
}
}
return featureset_ptr();
}

View file

@ -34,12 +34,13 @@
// ogr
#include <ogrsf_frmts.h>
#include "ogr_layer_ptr.hpp"
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;
@ -54,8 +55,8 @@ private:
std::string dataset_name_;
mutable std::string index_name_;
mutable OGRDataSource* dataset_;
mutable OGRLayer* layer_;
mutable std::string layerName_;
mutable ogr_layer_ptr layer_;
mutable std::string layer_name_;
mutable mapnik::layer_descriptor desc_;
bool multiple_geometries_;
mutable bool indexed_;

View file

@ -29,15 +29,17 @@
class ogr_feature_ptr
{
public:
ogr_feature_ptr (OGRFeature* const feat)
: feat_ (feat)
ogr_feature_ptr(OGRFeature* const feat)
: feat_(feat)
{
}
~ogr_feature_ptr ()
~ogr_feature_ptr()
{
if (feat_ != NULL)
OGRFeature::DestroyFeature (feat_);
{
OGRFeature::DestroyFeature(feat_);
}
}
OGRFeature* operator*()

View file

@ -0,0 +1,194 @@
/*****************************************************************************
*
* 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
*
*****************************************************************************/
#ifndef OGR_LAYER_PTR_HPP
#define OGR_LAYER_PTR_HPP
// stl
#include <iostream>
#include <fstream>
#include <stdexcept>
// ogr
#include <ogrsf_frmts.h>
class ogr_layer_ptr
{
public:
ogr_layer_ptr()
: datasource_(NULL),
layer_(NULL),
owns_layer_(false),
is_valid_(false)
{
}
~ogr_layer_ptr()
{
free_layer();
}
void free_layer()
{
if (owns_layer_ && layer_ != NULL && datasource_ != NULL)
{
datasource_->ReleaseResultSet(layer_);
}
datasource_ = NULL;
layer_ = NULL;
layer_name_ = "";
owns_layer_ = false;
is_valid_ = false;
}
void layer_by_name(OGRDataSource* const datasource,
const std::string& layer_name)
{
free_layer();
datasource_ = datasource;
OGRLayer* ogr_layer = datasource_->GetLayerByName(layer_name.c_str());
if (ogr_layer)
{
layer_name_ = layer_name;
layer_ = ogr_layer;
is_valid_ = true;
#ifdef MAPNIK_DEBUG
std::clog << "OGR Plugin: layer_from_name layer is " << layer_name_ << std::endl;
#endif
}
#ifdef MAPNIK_DEBUG
debug_print_last_error();
#endif
}
void layer_by_index(OGRDataSource* const datasource,
int layer_index)
{
free_layer();
datasource_ = datasource;
OGRLayer* ogr_layer = datasource_->GetLayer(layer_index);
if (ogr_layer)
{
OGRFeatureDefn* def = ogr_layer->GetLayerDefn();
if (def != 0)
{
layer_ = ogr_layer;
layer_name_ = def->GetName();
is_valid_ = true;
#ifdef MAPNIK_DEBUG
std::clog << "OGR Plugin: layer_from_index layer is " << layer_name_ << std::endl;
#endif
}
}
#ifdef MAPNIK_DEBUG
debug_print_last_error();
#endif
}
void layer_by_sql(OGRDataSource* const datasource,
const std::string& layer_sql)
{
free_layer();
datasource_ = datasource;
owns_layer_ = true;
// TODO - actually filter fields!
// http://trac.osgeo.org/gdal/wiki/rfc29_desired_fields
// http://trac.osgeo.org/gdal/wiki/rfc28_sqlfunc
OGRGeometry* spatial_filter = NULL;
const char* sql_dialect = NULL;
OGRLayer* ogr_layer = datasource_->ExecuteSQL(layer_sql.c_str(), spatial_filter, sql_dialect);
if (ogr_layer)
{
OGRFeatureDefn* def = ogr_layer->GetLayerDefn();
if (def != 0)
{
layer_ = ogr_layer;
layer_name_ = def->GetName();
is_valid_ = true;
#ifdef MAPNIK_DEBUG
std::clog << "OGR Plugin: layer_from_sql layer is " << layer_name_ << std::endl;
#endif
}
}
#ifdef MAPNIK_DEBUG
debug_print_last_error();
#endif
}
const std::string& layer_name() const
{
return layer_name_;
}
OGRLayer* layer() const
{
return layer_;
}
bool is_valid() const
{
return is_valid_;
}
private:
#ifdef MAPNIK_DEBUG
void debug_print_last_error()
{
if (! is_valid_)
{
const std::string err = CPLGetLastErrorMsg();
if (err.size() == 0)
{
std::clog << "OGR Plugin: error getting layer" << std::endl;
}
else
{
std::clog << "OGR Plugin: " << err << std::endl;
}
}
}
#endif
OGRDataSource* datasource_;
OGRLayer* layer_;
std::string layer_name_;
bool owns_layer_;
bool is_valid_;
};
#endif // OGR_LAYER_PTR_HPP

View file

@ -67,7 +67,7 @@ public:
wkbGeometryCollectionZ=1007
};
wkb_reader(const char* wkb,unsigned size, wkbFormat format)
wkb_reader(const char* wkb, unsigned size, wkbFormat format)
: wkb_(wkb),
size_(size),
pos_(0),
@ -76,16 +76,16 @@ public:
// try to determine WKB format automatically
if (format_ == wkbAuto)
{
if (size >= 44
&& (unsigned char)(wkb_[0]) == (unsigned char)(0x00)
&& (unsigned char)(wkb_[38]) == (unsigned char)(0x7C))
{
format_ = wkbSpatiaLite;
}
else
{
format_ = wkbGeneric;
}
if (size >= 44
&& (unsigned char)(wkb_[0]) == (unsigned char)(0x00)
&& (unsigned char)(wkb_[38]) == (unsigned char)(0x7C))
{
format_ = wkbSpatiaLite;
}
else
{
format_ = wkbGeneric;
}
}
switch (format_)

View file

@ -25,7 +25,6 @@
<Parameter name="type">sqlite</Parameter>
<Parameter name="file">../sqlite/qgis_spatiallite.sqlite</Parameter>
<Parameter name="table">multipolygon</Parameter>
<Parameter name="wkb_format">spatialite</Parameter>
</Datasource>
</Layer>
</Map>

View file

@ -3,7 +3,6 @@
<Datasource name="sqlite">
<Parameter name="type">sqlite</Parameter>
<Parameter name="file">../sqlite/qgis_spatiallite.sqlite</Parameter>
<Parameter name="wkb_format">spatialite</Parameter>
<Parameter name="multiple_geometries">true</Parameter>
</Datasource>

View file

@ -13,7 +13,6 @@
<Parameter name="type">sqlite</Parameter>
<Parameter name="file">../sqlite/qgis_spatiallite.sqlite</Parameter>
<Parameter name="table">lines</Parameter>
<Parameter name="wkb_format">spatialite</Parameter>
</Datasource>
</Layer>

View file

@ -37,7 +37,6 @@
<Parameter name="type">sqlite</Parameter>
<Parameter name="file">../sqlite/qgis_spatiallite.sqlite</Parameter>
<Parameter name="table">point</Parameter>
<Parameter name="wkb_format">spatialite</Parameter>
</Datasource>
</Layer>
<!--

View file

@ -1,4 +1,4 @@
<Map srs="+init=epsg:4326" minimum-version="0.7.2">
<Map srs="+init=epsg:4326" background-color="white" minimum-version="0.7.2">
<Style name="1">
<Rule>

View file

@ -23,7 +23,6 @@
<Parameter name="type">sqlite</Parameter>
<Parameter name="file">../sqlite/qgis_spatiallite.sqlite</Parameter>
<Parameter name="table">point</Parameter>
<Parameter name="wkb_format">spatialite</Parameter>
</Datasource>
</Layer>
</Map>

View file

@ -45,7 +45,6 @@
<Parameter name="type">sqlite</Parameter>
<Parameter name="file">../sqlite/qgis_spatiallite.sqlite</Parameter>
<Parameter name="table">point</Parameter>
<Parameter name="wkb_format">spatialite</Parameter>
</Datasource>
</Layer>

View file

@ -20,7 +20,6 @@
<Parameter name="type">sqlite</Parameter>
<Parameter name="file">../sqlite/qgis_spatiallite.sqlite</Parameter>
<Parameter name="table">point</Parameter>
<Parameter name="wkb_format">spatialite</Parameter>
</Datasource>
</Layer>

View file

@ -48,7 +48,6 @@
<Parameter name="type">sqlite</Parameter>
<Parameter name="file">../sqlite/qgis_spatiallite.sqlite</Parameter>
<Parameter name="table">point</Parameter>
<Parameter name="wkb_format">spatialite</Parameter>
</Datasource>
</Layer>
</Map>

View file

@ -38,7 +38,6 @@
<Parameter name="file">../sqlite/qgis_spatiallite.sqlite</Parameter>
<Parameter name="geometry_field">geometry</Parameter>
<Parameter name="table">point</Parameter>
<Parameter name="wkb_format">spatialite</Parameter>
</Datasource>
</Layer>

Binary file not shown.

View file

@ -59,6 +59,13 @@ def test_feature_attributes():
eq_(lyr.datasource.fields(),['AREA', 'EAS_ID', 'PRFEDEA'])
eq_(lyr.datasource.field_types(),['float','int','str'])
def test_ogr_layer_by_sql():
lyr = mapnik2.Layer('test')
lyr.datasource = mapnik2.Ogr(file='../data/shp/poly.shp', layer_by_sql='SELECT * FROM poly WHERE EAS_ID = 168')
features = lyr.datasource.all_features()
num_feats = len(features)
eq_(num_feats, 1)
def test_hit_grid():
import os
from itertools import groupby

View file

@ -10,10 +10,6 @@ def setup():
# from another directory we need to chdir()
os.chdir(execution_path('.'))
# Note that without an extent or a spatial index, a sqlite
# datasource will error on creation. We use this fact to test
# database attachdb and initdb options
def test_attachdb_with_relative_file():
# The point table and index is in the qgis_spatiallite.sqlite
# database. If either is not found, then this fails
@ -21,15 +17,24 @@ def test_attachdb_with_relative_file():
table='point',
attachdb='scratch@qgis_spatiallite.sqlite'
)
fs = ds.featureset()
feature = fs.next()
eq_(feature['pkuid'],1)
def test_attachdb_with_multiple_files():
ds = mapnik2.SQLite(file='../data/sqlite/world.sqlite',
table='attachedtest',
attachdb='scratch1@:memory:,scratch2@:memory:',
initdb='create table scratch1.attachedtest (the_geom);\n' +
'create virtual table scratch2.idx_attachedtest_the_geom using rtree(pkid,xmin,xmax,ymin,ymax);\n' +
'insert into scratch2.idx_attachedtest_the_geom values (1,-7799225.5,-7778571.0,1393264.125,1417719.375)\n'
initdb='''
create table scratch1.attachedtest (the_geom);
create virtual table scratch2.idx_attachedtest_the_geom using rtree(pkid,xmin,xmax,ymin,ymax);
insert into scratch2.idx_attachedtest_the_geom values (1,-7799225.5,-7778571.0,1393264.125,1417719.375);
'''
)
fs = ds.featureset()
feature = fs.next()
# the above should not throw but will result in no features
eq_(feature,None)
def test_attachdb_with_absolute_file():
# The point table and index is in the qgis_spatiallite.sqlite
@ -38,29 +43,88 @@ def test_attachdb_with_absolute_file():
table='point',
attachdb='scratch@qgis_spatiallite.sqlite'
)
fs = ds.featureset()
feature = fs.next()
eq_(feature['pkuid'],1)
def test_attachdb_with_index():
ds = mapnik2.SQLite(file='../data/sqlite/world.sqlite',
table='attachedtest',
attachdb='scratch@:memory:',
initdb='create table scratch.attachedtest (the_geom);\n' +
'create virtual table scratch.idx_attachedtest_the_geom using rtree(pkid,xmin,xmax,ymin,ymax);\n' +
'insert into scratch.idx_attachedtest_the_geom values (1,-7799225.5,-7778571.0,1393264.125,1417719.375)\n'
initdb='''
create table scratch.attachedtest (the_geom);
create virtual table scratch.idx_attachedtest_the_geom using rtree(pkid,xmin,xmax,ymin,ymax);
insert into scratch.idx_attachedtest_the_geom values (1,-7799225.5,-7778571.0,1393264.125,1417719.375);
'''
)
fs = ds.featureset()
feature = fs.next()
eq_(feature,None)
def test_attachdb_with_explicit_index():
ds = mapnik2.SQLite(file='../data/sqlite/world.sqlite',
table='attachedtest',
index_table='myindex',
attachdb='scratch@:memory:',
initdb='create table scratch.attachedtest (the_geom);\n' +
'create virtual table scratch.myindex using rtree(pkid,xmin,xmax,ymin,ymax);\n' +
'insert into scratch.myindex values (1,-7799225.5,-7778571.0,1393264.125,1417719.375)\n'
initdb='''
create table scratch.attachedtest (the_geom);
create virtual table scratch.myindex using rtree(pkid,xmin,xmax,ymin,ymax);
insert into scratch.myindex values (1,-7799225.5,-7778571.0,1393264.125,1417719.375);
'''
)
fs = ds.featureset()
feature = fs.next()
eq_(feature,None)
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
def test_attachdb_with_sql_join():
ds = mapnik2.SQLite(file='../data/sqlite/world.sqlite',
table='(select * from world_merc INNER JOIN business on world_merc.iso3 = business.ISO3 limit 100)',
attachdb='busines@business.sqlite'
)
fs = ds.featureset()
feature = fs.next()
eq_(feature.id(),1)
expected = {
1995:0,
1996:0,
1997:0,
1998:0,
1999:0,
2000:0,
2001:0,
2002:0,
2003:0,
2004:0,
2005:0,
2006:0,
2007:0,
2008:0,
2009:0,
2010:0,
# this appears to be sqlites way of
# automatically handling clashing column names
'ISO3:1':'ATG',
'OGC_FID':1,
'area':44,
'fips':u'AC',
'iso2':u'AG',
'iso3':u'ATG',
'lat':17.078,
'lon':-61.783,
'name':u'Antigua and Barbuda',
'pop2005':83039,
'region':19,
'subregion':29,
'un':28
}
for k,v in expected.items():
try:
eq_(feature[str(k)],v)
except:
#import pdb;pdb.set_trace()
print 'invalid key/v %s/%s for: %s' % (k,v,feature)
def test_subqueries():
ds = mapnik2.SQLite(file='../data/sqlite/world.sqlite',
table='world_merc',
)
@ -68,25 +132,65 @@ def test_dequoting_of_subqueries():
feature = fs.next()
eq_(feature['OGC_FID'],1)
eq_(feature['fips'],u'AC')
eq_(feature['iso2'],u'AG')
eq_(feature['iso3'],u'ATG')
eq_(feature['un'],28)
eq_(feature['name'],u'Antigua and Barbuda')
eq_(feature['area'],44)
eq_(feature['pop2005'],83039)
eq_(feature['region'],19)
eq_(feature['subregion'],29)
eq_(feature['lon'],-61.783)
eq_(feature['lat'],17.078)
# TODO:
# select * from world_merc fails
# as rowid is dropped
ds = mapnik2.SQLite(file='../data/sqlite/world.sqlite',
table='(select *,rowid from world_merc)',
table='(select * from world_merc)',
)
fs = ds.featureset()
feature = fs.next()
eq_(feature['OGC_FID'],1)
eq_(feature['fips'],u'AC')
eq_(feature['iso2'],u'AG')
eq_(feature['iso3'],u'ATG')
eq_(feature['un'],28)
eq_(feature['name'],u'Antigua and Barbuda')
eq_(feature['area'],44)
eq_(feature['pop2005'],83039)
eq_(feature['region'],19)
eq_(feature['subregion'],29)
eq_(feature['lon'],-61.783)
eq_(feature['lat'],17.078)
ds = mapnik2.SQLite(file='../data/sqlite/world.sqlite',
table='(select OGC_FID,GEOMETRY as geom from world_merc)',
)
fs = ds.featureset()
feature = fs.next()
eq_(feature['OGC_FID'],1)
eq_(len(feature),1)
ds = mapnik2.SQLite(file='../data/sqlite/world.sqlite',
table='(select GEOMETRY,OGC_FID,fips 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)',
table='(select GEOMETRY,rowid as aliased_id,fips from world_merc)',
key_field='aliased_id'
)
fs = ds.featureset()
feature = fs.next()
eq_(feature['aliased_id'],1)
eq_(feature['fips'],u'AC')
ds = mapnik2.SQLite(file='../data/sqlite/world.sqlite',
table='(select GEOMETRY,OGC_FID,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')

View file

@ -1,11 +1,16 @@
# -------------------------------------------------
# QtCreator Project For Mapnik2
# -------------------------------------------------
QT -= core gui
QT =
TARGET = mapnik2
TEMPLATE = lib
INCLUDEPATH = \
../deps/agg/include \
../include/mapnik2 \
/usr/include
HEADERS += \
../include/mapnik/svg/marker_cache.hpp \
../include/mapnik/svg/svg_converter.hpp \
@ -211,8 +216,4 @@ include(bindings.pri)
unix {
DEFINES += LINUX=1
INCLUDEPATH = \
../deps/agg/include \
../include/mapnik2 \
/usr/include
}

View file

@ -16,6 +16,7 @@ HEADERS += \
$$PWD/../plugins/input/ogr/ogr_converter.hpp \
$$PWD/../plugins/input/ogr/ogr_featureset.hpp \
$$PWD/../plugins/input/ogr/ogr_datasource.hpp \
$$PWD/../plugins/input/ogr/ogr_layer_ptr.hpp \
$$PWD/../plugins/input/ogr/ogr_feature_ptr.hpp \
$$PWD/../plugins/input/ogr/ogr_index.hpp \
$$PWD/../plugins/input/ogr/ogr_index_featureset.hpp \