initial import

This commit is contained in:
Artem Pavlenko 2005-06-14 15:06:59 +00:00
commit ebcdd3cf90
32 changed files with 3163 additions and 0 deletions

18
postgis/Jamfile Normal file
View file

@ -0,0 +1,18 @@
#postgis datasource plugin
project
: usage-requirements
<include>/opt/postgresql8/include
;
lib pq
:
: <file>/opt/postgresql8/lib/libpq.so
;
lib postgis
:
postgis.cc
postgisfs.cc
pq
;

24
postgis/SConscript Normal file
View file

@ -0,0 +1,24 @@
#mapnik
Import ('env')
prefix = env['PREFIX']
boost_root = env['BOOST_ROOT']
postgresql_root = env['POSTGRESQL_ROOT']
agg_root = env['AGG_ROOT']
agg_headers = agg_root + '/include'
postgresql_headers=postgresql_root+"/include"
postgresql_libs=postgresql_root+"/lib"
postgis_src = Split(
"""
postgis.cpp
postgisfs.cpp
"""
)
headers = ['#include',boost_root,agg_headers,postgresql_headers]
postgis_datasource = env.SharedLibrary('postgis',source=postgis_src,SHLIBPREFIX='',CPPPATH=headers,LIBS="pq",LIBPATH=postgresql_libs)
env.Install(prefix + '/datasources',postgis_datasource)
env.Alias("install",prefix + '/datasources')

85
postgis/connection.hpp Normal file
View file

@ -0,0 +1,85 @@
/* This file is part of Mapnik (c++ mapping toolkit)
* Copyright (C) 2005 Artem Pavlenko
*
* Mapnik is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
//$Id: connection.hpp 17 2005-03-08 23:58:43Z pavlenko $
#ifndef CONNECTION_HPP
#define CONNECTION_HPP
#include "libpq-fe.h"
#include "mapnik.hpp"
#include "resultset.hpp"
using namespace mapnik;
class ResultSet;
class Connection
{
private:
PGconn *conn_;
public:
Connection(const std::string& uri,const std::string& dbname,
const std::string& username,const std::string& password)
{
std::string connStr="host="+uri+" dbname="+dbname+" user="+username+" password="+password;
conn_=PQconnectdb(connStr.c_str());
if (PQstatus(conn_) == CONNECTION_BAD)
{
std::cerr << "connection to "<< connStr << " failed\n"
<< PQerrorMessage(conn_)<< std::endl;
}
else
{
std::cout <<"connected ok "<<std::endl;
}
}
bool execute(const std::string& sql) const
{
PGresult *result=PQexec(conn_,sql.c_str());
bool ok=(result && PQresultStatus(result)==PGRES_COMMAND_OK);
PQclear(result);
return ok;
}
ref_ptr<ResultSet> executeQuery(const std::string& sql,int type=0) const
{
PGresult *result=0;
if (type==1)
{
result=PQexecParams(conn_,sql.c_str(),0,0,0,0,0,1);
return ref_ptr<ResultSet>(new ResultSet(result));
}
result=PQexec(conn_,sql.c_str());
return ref_ptr<ResultSet>(new ResultSet(result));
}
bool isOK() const
{
return (PQstatus(conn_)!=CONNECTION_BAD);
}
void close()
{
PQfinish(conn_);
}
~Connection()
{
PQfinish(conn_);
}
};
#endif //CONNECTION_HPP

View file

@ -0,0 +1,111 @@
/* This file is part of Mapnik (c++ mapping toolkit)
* Copyright (C) 2005 Artem Pavlenko
*
* Mapnik is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
//$Id: connection_manager.hpp 17 2005-03-08 23:58:43Z pavlenko $
#ifndef CONNECTION_MANAGER_HPP
#define CONNECTION_MANAGER_HPP
#include <string>
#include "pool.hpp"
#include "utils.hpp"
#include "connection.hpp"
using namespace mapnik;
using std::string;
template <typename T>
class ConnectionCreator
{
string url_;
string dbname_;
string user_;
string pass_;
public:
ConnectionCreator(const string& url,const string& dbname,
const string& user,const string& pass)
: url_(url),
dbname_(dbname),
user_(user),
pass_(pass) {}
T* operator()() const
{
return new T(url_,dbname_,user_,pass_);
}
std::string id() const
{
return url_+":"+dbname_+":"+user_+":"+pass_;
}
};
class ConnectionManager : public singleton <ConnectionManager,CreateStatic>
{
friend class CreateStatic<ConnectionManager>;
typedef Pool<Connection,ConnectionCreator> PoolType;
typedef std::map<std::string,ref_ptr<PoolType> > ContType;
typedef ref_ptr<Connection> HolderType;
ContType pools_;
public:
bool registerPool(const ConnectionCreator<Connection>& creator,int initialSize,int maxSize)
{
Lock lock(&mutex_);
if (pools_.find(creator.id())==pools_.end())
{
return pools_.insert(std::make_pair(creator.id(),
ref_ptr<PoolType>(new PoolType(creator,initialSize,maxSize)))).second;
}
return false;
}
const ref_ptr<PoolType>& getPool(const std::string& key)
{
Lock lock(&mutex_);
ContType::const_iterator itr=pools_.find(key);
if (itr!=pools_.end())
{
return itr->second;
}
static const ref_ptr<PoolType> emptyPool(0);
return emptyPool;
}
const HolderType& get(const std::string& key)
{
Lock lock(&mutex_);
ContType::const_iterator itr=pools_.find(key);
if (itr!=pools_.end())
{
ref_ptr<PoolType> pool=itr->second;
return pool->borrowObject();
}
static const HolderType EmptyConn(0);
return EmptyConn;
}
private:
ConnectionManager() {}
ConnectionManager(const ConnectionManager&);
ConnectionManager& operator=(const ConnectionManager);
};
#endif //CONNECTION_MANAGER_HPP

214
postgis/postgis.cpp Normal file
View file

@ -0,0 +1,214 @@
/* This file is part of Mapnik (c++ mapping toolkit)
* Copyright (C) 2005 Artem Pavlenko
*
* Mapnik is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
//$Id: postgis.cc 44 2005-04-22 18:53:54Z pavlenko $
#include "postgis.hpp"
#include <netinet/in.h>
#include <string>
#include <algorithm>
#include <set>
#include <sstream>
#include "connection_manager.hpp"
DATASOURCE_PLUGIN(PostgisDatasource);
const std::string PostgisDatasource::GEOMETRY_COLUMNS="geometry_columns";
const std::string PostgisDatasource::SPATIAL_REF_SYS="spatial_ref_system";
using std::cerr;
using std::cout;
using std::endl;
using boost::lexical_cast;
using boost::bad_lexical_cast;
PostgisDatasource::PostgisDatasource(const Parameters& params)
: table_(params.get("table")),
type_(datasource::Vector),
desc_(params.get("name")),
creator_(params.get("host"),
params.get("dbname"),
params.get("user"),
params.get("password"))
{
ConnectionManager *mgr=ConnectionManager::instance();
mgr->registerPool(creator_,10,20);
ref_ptr<Pool<Connection,ConnectionCreator> > pool=mgr->getPool(creator_.id());
if (pool)
{
const ref_ptr<Connection>& conn = pool->borrowObject();
if (conn && conn->isOK())
{
PoolGuard<ref_ptr<Connection>,ref_ptr<Pool<Connection,ConnectionCreator> > > guard(conn,pool);
std::string table_name=table_from_sql(table_);
std::ostringstream s;
s << "select f_geometry_column,srid,type from ";
s << GEOMETRY_COLUMNS <<" where f_table_name='"<<table_name<<"'";
ref_ptr<ResultSet> rs=conn->executeQuery(s.str());
if (rs->next())
{
try
{
srid_ = lexical_cast<int>(rs->getValue("srid"));
desc_.set_srid(srid_);
}
catch (bad_lexical_cast &ex)
{
cerr << ex.what() << endl;
}
geometryColumn_=rs->getValue("f_geometry_column");
std::string postgisType=rs->getValue("type");
}
rs->close();
s.str("");
s << "select xmin(ext),ymin(ext),xmax(ext),ymax(ext)";
s << " from (select estimated_extent('"<<table_name<<"','"<<geometryColumn_<<"') as ext) as tmp";
rs=conn->executeQuery(s.str());
if (rs->next())
{
try
{
double lox=lexical_cast<double>(rs->getValue(0));
double loy=lexical_cast<double>(rs->getValue(1));
double hix=lexical_cast<double>(rs->getValue(2));
double hiy=lexical_cast<double>(rs->getValue(3));
extent_.init(lox,loy,hix,hiy);
}
catch (bad_lexical_cast &ex)
{
cerr << ex.what() << endl;
}
}
rs->close();
// collect attribute desc
s.str("");
s << "select * from "<<table_<<" limit 1";
rs=conn->executeQuery(s.str());
if (rs->next())
{
int count = rs->getNumFields();
for (int i=0;i<count;++i)
{
std::string fld_name=rs->getFieldName(i);
int length = rs->getFieldLength(i);
int type_oid = rs->getTypeOID(i);
switch (type_oid)
{
case 17285: // geometry
desc_.add_descriptor(attribute_descriptor(fld_name,Geometry));
break;
case 21: // int2
case 23: // int4
desc_.add_descriptor(attribute_descriptor(fld_name,Integer,false,length));
break;
case 1043: // varchar
desc_.add_descriptor(attribute_descriptor(fld_name,String));
break;
default: // shouldn't get here
cout << "unknown type_oid="<<type_oid<<endl;
desc_.add_descriptor(attribute_descriptor(fld_name,String));
break;
}
}
}
}
}
}
std::string PostgisDatasource::name_="postgis";
std::string PostgisDatasource::name()
{
return name_;
}
int PostgisDatasource::type() const
{
return type_;
}
layer_descriptor const& PostgisDatasource::get_descriptor() const
{
return desc_;
}
std::string PostgisDatasource::table_from_sql(const std::string& sql)
{
std::string table_name(sql);
transform(table_name.begin(),table_name.end(),table_name.begin(),tolower);
std::string::size_type idx=table_name.rfind("from");
if (idx!=std::string::npos)
{
idx=table_name.find_first_not_of(" ",idx+4);
table_name=table_name.substr(idx);
idx=table_name.find_first_of(" )");
return table_name.substr(0,idx);
}
return table_name;
}
featureset_ptr PostgisDatasource::features(const query& q) const
{
Featureset *fs=0;
Envelope<double> const& box=q.get_bbox();
ConnectionManager *mgr=ConnectionManager::instance();
ref_ptr<Pool<Connection,ConnectionCreator> > pool=mgr->getPool(creator_.id());
if (pool)
{
const ref_ptr<Connection>& conn = pool->borrowObject();
if (conn && conn->isOK())
{
PoolGuard<ref_ptr<Connection>,ref_ptr<Pool<Connection,ConnectionCreator> > > guard(conn,pool);
std::ostringstream s;
// can we rely on 'gid' name???
s << "select gid,asbinary("<<geometryColumn_<<") as geom";
std::set<std::string> const& props=q.property_names();
std::set<std::string>::const_iterator pos=props.begin();
while (pos!=props.end())
{
s <<",\""<<*pos<<"\"";
++pos;
}
s << " from " << table_<<" where "<<geometryColumn_<<" && setSRID('BOX3D(";
s << box.minx() << " " << box.miny() << ",";
s << box.maxx() << " " << box.maxy() << ")'::box3d,"<<srid_<<")";
cout << s.str() << endl;
ref_ptr<ResultSet> rs=conn->executeQuery(s.str(),1);
fs=new PostgisFeatureset(rs,props.size());
}
}
return featureset_ptr(fs);
}
const Envelope<double>& PostgisDatasource::envelope() const
{
return extent_;
}
PostgisDatasource::~PostgisDatasource() {}

79
postgis/postgis.hpp Normal file
View file

@ -0,0 +1,79 @@
/* This file is part of Mapnik (c++ mapping toolkit)
* Copyright (C) 2005 Artem Pavlenko
*
* Mapnik is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
//$Id: postgis.hpp 44 2005-04-22 18:53:54Z pavlenko $
#ifndef POSTGIS_HPP
#define POSTGIS_HPP
#include "mapnik.hpp"
#include "connection_manager.hpp"
#include <boost/lexical_cast.hpp>
#include <set>
using namespace mapnik;
class PostgisDatasource : public datasource
{
static const std::string GEOMETRY_COLUMNS;
static const std::string SPATIAL_REF_SYS;
const std::string uri_;
const std::string username_;
const std::string password_;
const std::string table_;
std::string geometryColumn_;
int type_;
int srid_;
mapnik::Envelope<double> extent_;
layer_descriptor desc_;
ConnectionCreator<Connection> creator_;
static std::string name_;
public:
static std::string name();
int type() const;
featureset_ptr features(const query& q) const;
mapnik::Envelope<double> const& envelope() const;
layer_descriptor const& get_descriptor() const;
PostgisDatasource(const Parameters &params);
~PostgisDatasource();
private:
static std::string table_from_sql(const std::string& sql);
PostgisDatasource(const PostgisDatasource&);
PostgisDatasource& operator=(const PostgisDatasource&);
};
class PostgisFeatureset : public Featureset
{
private:
ref_ptr<ResultSet> rs_;
unsigned num_attrs_;
mutable int totalGeomSize_;
mutable int count_;
public:
PostgisFeatureset(const ref_ptr<ResultSet>& rs,unsigned num_attrs);
void dispose();
Feature* next();
~PostgisFeatureset();
private:
PostgisFeatureset(const PostgisFeatureset&);
const PostgisFeatureset& operator=(const PostgisFeatureset&);
};
#endif //POSTGIS_HPP

92
postgis/postgisfs.cpp Normal file
View file

@ -0,0 +1,92 @@
/* This file is part of Mapnik (c++ mapping toolkit)
* Copyright (C) 2005 Artem Pavlenko
*
* Mapnik is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
//$Id: postgisfs.cc 34 2005-04-04 13:27:23Z pavlenko $
#include "postgis.hpp"
using boost::lexical_cast;
using boost::bad_lexical_cast;
using std::string;
PostgisFeatureset::PostgisFeatureset(const ref_ptr<ResultSet>& rs,
unsigned num_attrs=0)
: rs_(rs),
num_attrs_(num_attrs),
totalGeomSize_(0),
count_(0)
{
}
Feature* PostgisFeatureset::next()
{
Feature *feature=0;
if (rs_->next())
{
const char* buf = rs_->getValue(0);
int id = (buf[0]&255) << 24 | (buf[1]&255) << 16 | (buf[2] & 255) << 8 | buf[3] & 255;
int size=rs_->getFieldLength(1);
const char *data=rs_->getValue(1);
geometry_ptr geom=geometry_utils::from_wkb(data,size,-1);
totalGeomSize_+=size;
if (geom)
{
feature=new Feature(id,geom);
unsigned start=2;
for (unsigned pos=0;pos<num_attrs_;++pos)
{
const char* buf=rs_->getValue(start + pos);
int field_size = rs_->getFieldLength(start + pos);
int oid = rs_->getTypeOID(start + pos);
if (oid==23)
{
int val = (buf[0]&255) << 24 | (buf[1]&255) << 16 | (buf[2] & 255) << 8 | buf[3] & 255;
feature->add_property(val);
}
else if (oid==1043)
{
feature->add_property(string(buf));
}
else
{
feature->add_property(string("null"));
}
}
++count_;
}
}
else
{
rs_->close();
std::cout << "totalGeomSize="<<totalGeomSize_<<" bytes"<<std::endl;
std::cout << "count="<<count_<<std::endl;
}
return feature;
}
PostgisFeatureset::~PostgisFeatureset()
{
rs_->close();
}

View file

@ -0,0 +1,71 @@
/* This file is part of Mapnik (c++ mapping toolkit)
* Copyright (C) 2005 Artem Pavlenko
*
* Mapnik is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
//$Id$
#ifndef PROPERTY_VALIDATOR
#define PROPERTY_VALIDATOR
#include "filter.hh"
#include "expression.hh"
#include <set>
namespace mapnik
{
template <typename FeatureT>
class property_validator : public filter_visitor<FeatureT>
{
public:
property_validator(layer_descriptor& desc)
desc_(desc) {}
void visit(filter<FeatureT>& /*filter*/)
{
//not interested
}
void visit(expression<FeatureT>& exp)
{
property<FeatureT>* pf;
if ((pf = dynamic_cast<property<FeatureT>*>(&exp)))
{
vector<attribute_descriptor> const& attr_desc = desc_.get_descriptors();
for (size_t idx=0; idx < attr_desc.size();++idx)
{
if (attr_desc[idx] == pf->name())
{
pf->set_index(idx);
break;
}
}
}
}
std::set<std::string> const& property_names() const
{
return names_;
}
virtual ~property_validator() {}
private:
property_validator(property_validator const&);
property_validator& operator=(property_validator const&);
private:
layer_descriptor& desc_;
};
}
#endif //PROPERTY_HPP

138
postgis/resultset.hpp Normal file
View file

@ -0,0 +1,138 @@
/* This file is part of Mapnik (c++ mapping toolkit)
* Copyright (C) 2005 Artem Pavlenko
*
* Mapnik is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
//$Id: resultset.hpp 17 2005-03-08 23:58:43Z pavlenko $
#ifndef RESULTSET_HPP
#define RESULTSET_HPP
#include "connection.hpp"
class ResultSet
{
private:
PGresult* res_;
int pos_;
int numTuples_;
int *refCount_;
public:
ResultSet(PGresult *res)
:res_(res),pos_(-1),refCount_(new int(1))
{
numTuples_=PQntuples(res_);
}
ResultSet(const ResultSet& rhs)
:res_(rhs.res_),
pos_(rhs.pos_),
numTuples_(rhs.numTuples_),
refCount_(rhs.refCount_)
{
(*refCount_)++;
}
ResultSet& operator=(const ResultSet& rhs)
{
if (this==&rhs) return *this;
if (--(refCount_)==0)
{
close();
delete refCount_,refCount_=0;
}
res_=rhs.res_;
pos_=rhs.pos_;
numTuples_=rhs.numTuples_;
refCount_=rhs.refCount_;
(*refCount_)++;
return *this;
}
void close()
{
PQclear(res_),res_=0;
}
~ResultSet()
{
if (--(*refCount_)==0)
{
PQclear(res_);
delete refCount_,refCount_=0;
}
}
int getNumFields() const
{
return PQnfields(res_);
}
bool next()
{
return (++pos_<numTuples_);
}
const char* getFieldName(int index) const
{
return PQfname(res_,index);
}
int getFieldLength(int index) const
{
return PQgetlength(res_,pos_,index);
}
int getFieldLength(const char* name) const
{
int col=PQfnumber(res_,name);
if (col>=0)
return PQgetlength(res_,pos_,col);
return 0;
}
int getTypeOID(int index) const
{
return PQftype(res_,index);
}
int getTypeOID(const char* name) const
{
int col=PQfnumber(res_,name);
if (col>=0)
return PQftype(res_,col);
return 0;
}
const char* getValue(int index) const
{
return PQgetvalue(res_,pos_,index);
}
const char* getValue(const char* name) const
{
int col=PQfnumber(res_,name);
if (col>=0)
return getValue(col);
return 0;
}
};
#endif //RESULTSET_HPP

View file

@ -0,0 +1,91 @@
/* This file is part of Mapnik (c++ mapping toolkit)
* Copyright (C) 2005 Artem Pavlenko
*
* Mapnik is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
//$Id: raster_datasource.cc 44 2005-04-22 18:53:54Z pavlenko $
#include "raster_datasource.hh"
#include "image_reader.hh"
#include "raster_featureset.hh"
#include "raster_info.hh"
DATASOURCE_PLUGIN(raster_datasource);
raster_datasource::raster_datasource(const Parameters& params)
: extent_()
{
filename_=params.get("file");
format_=params.get("format");
double lox,loy,hix,hiy;
fromString<double>(params.get("lox"),lox);
fromString<double>(params.get("loy"),loy);
fromString<double>(params.get("hix"),hix);
fromString<double>(params.get("hiy"),hiy);
extent_=Envelope<double>(lox,loy,hix,hiy);
}
raster_datasource::~raster_datasource()
{
}
std::string raster_datasource::name_="raster";
int raster_datasource::type() const
{
return datasource::Raster;
}
std::string raster_datasource::name()
{
return name_;
}
bool raster_datasource::parseEnvelope(const std::string& str,Envelope<double>& envelope)
{
return true;
}
const mapnik::Envelope<double>& raster_datasource::envelope() const
{
return extent_;
}
featureset_ptr raster_datasource::featuresAll(const CoordTransform& t) const
{
return featureset_ptr(0);
}
featureset_ptr raster_datasource::featuresInBox(const CoordTransform& t,
const mapnik::Envelope<double>& box) const
{
RasterInfo info(filename_,format_,extent_);
single_file_policy policy(info); //todo: handle different policies!
return featureset_ptr(new RasterFeatureset<single_file_policy>(policy,box,t));
}
featureset_ptr raster_datasource::featuresAtPoint(const CoordTransform& t,
const coord2d& pt) const
{
return featureset_ptr(0);
}

View file

@ -0,0 +1,53 @@
/* This file is part of Mapnik (c++ mapping toolkit)
* Copyright (C) 2005 Artem Pavlenko
*
* Mapnik is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
//$Id: raster_datasource.hh 44 2005-04-22 18:53:54Z pavlenko $
#ifndef RASTER_DATASOURCE_HH
#define RASTER_DATASOURCE_HH
#include "mapnik.hh"
#include "image_reader.hh"
using namespace mapnik;
class raster_datasource : public datasource
{
private:
std::string filename_;
std::string format_;
mapnik::Envelope<double> extent_;
static std::string name_;
public:
raster_datasource(const Parameters& params);
virtual ~raster_datasource();
int type() const;
std::string name();
featureset_ptr featuresAll(const CoordTransform& t) const;
featureset_ptr featuresInBox(const CoordTransform& t,const mapnik::Envelope<double>& box) const;
featureset_ptr featuresAtPoint(const CoordTransform& t,const coord2d& pt) const;
const mapnik::Envelope<double>& envelope() const;
private:
//no copying
raster_datasource(const raster_datasource&);
raster_datasource& operator=(const raster_datasource&);
//
bool parseEnvelope(const std::string& str,Envelope<double>& envelope);
};
#endif //RASTER_DATASOURCE_H

View file

@ -0,0 +1,81 @@
/* This file is part of Mapnik (c++ mapping toolkit)
* Copyright (C) 2005 Artem Pavlenko
*
* Mapnik is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "raster_featureset.hh"
#include "image_reader.hh"
template <typename LookupPolicy>
RasterFeatureset<LookupPolicy>::RasterFeatureset(const LookupPolicy& policy,
const Envelope<double>& box,
const CoordTransform& t)
: policy_(policy),
id_(1),
extent_(box),
t_(t),
curIter_(policy_.query(box)),
endIter_(policy_.end())
{}
template <typename LookupPolicy>
RasterFeatureset<LookupPolicy>::~RasterFeatureset() {}
template <typename LookupPolicy>
Feature* RasterFeatureset<LookupPolicy>::next()
{
Feature* f=0;
if (curIter_!=endIter_)
{
try
{
std::cout<<"RasterFeatureset "<<curIter_->format()<<" "<<curIter_->file()<<std::endl;
std::auto_ptr<ImageReader> reader(get_image_reader(curIter_->format(),curIter_->file()));
std::cout<<reader.get()<<std::endl;
if (reader.get())
{
int image_width=reader->width();
int image_height=reader->height();
if (image_width>0 && image_height>0)
{
CoordTransform t(image_width,image_height,curIter_->envelope());
Envelope<double> intersect=extent_.intersect(curIter_->envelope());
Envelope<double> ext=t.forward(intersect);
Envelope<double> image_ext=t_.forward(intersect);
ImageData32 image((int)ext.width(),(int)ext.height());
reader->read((int)ext.minx(),(int)ext.miny(),image);
ImageData32 target((int)(image_ext.width()+0.5),(int)(image_ext.height()+0.5));
scale_image<ImageData32>(target,image);
f=new RasterFeature(++id_,RasterPtr(new raster((int)(image_ext.minx()+0.5),
(int)(image_ext.miny()+0.5),target)));
}
}
}
catch (...)
{
}
++curIter_;
}
return f;
}
template class RasterFeatureset<single_file_policy>;
//template RasterFeatureset<os_name_policy>;

View file

@ -0,0 +1,115 @@
/* This file is part of Mapnik (c++ mapping toolkit)
* Copyright (C) 2005 Artem Pavlenko
*
* Mapnik is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef RASTER_FEATURESET_HH
#define RASTER_FEATURESET_HH
#include "raster_datasource.hh"
#include "raster_info.hh"
#include <vector>
using std::vector;
class single_file_policy
{
RasterInfo info_;
public:
class const_iterator
{
enum {start,end};
bool status_;
const single_file_policy* p_;
public:
explicit const_iterator(const single_file_policy* p)
:status_(start),
p_(p) {}
const_iterator()
:status_(end){}
const_iterator(const const_iterator& other)
:status_(other.status_),
p_(other.p_) {}
const_iterator& operator++()
{
status_=end;
return *this;
}
const RasterInfo& operator*() const
{
return p_->info_;
}
const RasterInfo* operator->() const
{
return &(p_->info_);
}
bool operator!=(const const_iterator& itr)
{
return status_!=itr.status_;
}
};
explicit single_file_policy(const RasterInfo& info)
:info_(info) {}
const_iterator begin()
{
return const_iterator(this);
}
const_iterator query(const Envelope<double>& box)
{
if (box.intersects(info_.envelope()))
{
return begin();
}
return end();
}
const_iterator end()
{
return const_iterator();
}
};
class os_name_policy
{
//TODO
};
template <typename LookupPolicy>
class RasterFeatureset : public Featureset
{
typedef typename LookupPolicy::const_iterator iterator_type;
LookupPolicy policy_;
size_t id_;
Envelope<double> extent_;
CoordTransform t_;
iterator_type curIter_;
iterator_type endIter_;
public:
RasterFeatureset(const LookupPolicy& policy,const Envelope<double>& box,const CoordTransform& t);
virtual ~RasterFeatureset();
Feature* next();
};
#endif //RASTER_FEATURESET_HH

71
raster/raster_info.cpp Normal file
View file

@ -0,0 +1,71 @@
/* This file is part of Mapnik (c++ mapping toolkit)
* Copyright (C) 2005 Artem Pavlenko
*
* Mapnik is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
//$Id: raster_info.cc 17 2005-03-08 23:58:43Z pavlenko $
#include "raster_info.hh"
RasterInfo::RasterInfo(const std::string& file,const std::string& format,const mapnik::Envelope<double>& extent,int srid)
:file_(file),
format_(format),
extent_(extent),
srid_(srid) {}
RasterInfo::RasterInfo(const RasterInfo& rhs)
:file_(rhs.file_),
format_(rhs.format_),
extent_(rhs.extent_),
srid_(rhs.srid_) {}
void RasterInfo::swap(RasterInfo& other) throw()
{
file_=other.file_;
format_=other.format_;
extent_=other.extent_;
srid_=other.srid_;
}
RasterInfo& RasterInfo::operator=(const RasterInfo& rhs)
{
RasterInfo tmp(rhs);
swap(tmp);
return *this;
}
const Envelope<double>& RasterInfo::envelope() const
{
return extent_;
}
const std::string& RasterInfo::file() const
{
return file_;
}
const std::string& RasterInfo::format() const
{
return format_;
}
const int RasterInfo::srid() const
{
return srid_;
}

46
raster/raster_info.hpp Normal file
View file

@ -0,0 +1,46 @@
/* This file is part of Mapnik (c++ mapping toolkit)
* Copyright (C) 2005 Artem Pavlenko
*
* Mapnik is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
//$Id: raster_info.hh 17 2005-03-08 23:58:43Z pavlenko $
#ifndef RASTER_INFO
#define RASTER_INFO
#include "raster_datasource.hh"
#include <string>
using mapnik::Envelope;
class RasterInfo
{
std::string file_;
std::string format_;
Envelope<double> extent_;
int srid_;
public:
RasterInfo(const std::string& file,const std::string& format,const Envelope<double>& extent,int srid=-1);
RasterInfo(const RasterInfo& rhs);
RasterInfo& operator=(const RasterInfo& rhs);
const Envelope<double>& envelope() const;
const std::string& file() const;
const std::string& format() const;
const int srid() const;
private:
void swap(RasterInfo& other) throw();
};
#endif //RASTER_INFO

11
shape/Jamfile Normal file
View file

@ -0,0 +1,11 @@
lib shape :
dbffile.cc
dbf_test.cc
shape.cc
shape_featureset.cc
shapefile.cc
shape_index_featureset.cc
shape_io.cc
shp_index.cc
;

26
shape/SConscript Normal file
View file

@ -0,0 +1,26 @@
#mapnik
Import ('env')
prefix = env['PREFIX']
boost_root = env['BOOST_ROOT']
agg_root = env['AGG_ROOT']
agg_headers = agg_root + '/include'
shape_src = Split(
"""
dbffile.cc
shape.cc
shape_featureset.cc
shapefile.cc
shape_index_featureset.cc
shape_io.cc
shp_index.cc
"""
)
headers = ['#include',boost_root,agg_headers]
shape_datasource = env.SharedLibrary('shape',source=shape_src,SHLIBPREFIX='',CPPPATH=headers)
env.Install('#stage/datasources',shape_datasource)
#env.Default(shape_datasource)

60
shape/dbf_test.cpp Normal file
View file

@ -0,0 +1,60 @@
/* This file is part of Mapnik (c++ mapping toolkit)
* Copyright (C) 2005 Artem Pavlenko
*
* Mapnik is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include <iostream>
#include <iomanip>
#include "dbffile.hh"
using namespace std;
int main(int argc,char** argv)
{
if (argc!=2)
{
cout<<"usage: dbfdump <file_name>"<<endl;
return 0;
}
cout << argv[1]<<endl;
dbf_file dbf(argv[1]);
cout<<endl;
for (int i=0;i<dbf.num_records();++i)
{
dbf.move_to(i+1);
if (!(i%10))
{
for (int j=0;j<dbf.num_fields();++j)
{
int width=dbf.descriptor(j).length_;
string name=dbf.descriptor(j).name_;
char type=dbf.descriptor(j).type_;
cout<<setw(width)<<name<<"("<<type<<")""|";
}
cout<<endl;
}
for (int j=0;j<dbf.num_fields();++j)
{
int width=dbf.descriptor(j).length_;
string val=dbf.string_value(j);
cout <<setw(width)<<val<<"|";
}
cout<<endl;
}
cout<<"done!"<<endl;
return 0;
}

216
shape/dbffile.cpp Normal file
View file

@ -0,0 +1,216 @@
/* This file is part of Mapnik (c++ mapping toolkit)
* Copyright (C) 2005 Artem Pavlenko
*
* Mapnik is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "dbffile.hh"
#include <string>
dbf_file::dbf_file()
: num_records_(0),
num_fields_(0),
record_length_(0),
record_(0) {}
dbf_file::dbf_file(const char* file_name)
:num_records_(0),
num_fields_(0),
record_length_(0),
record_(0)
{
file_.open(file_name);
if (file_.is_open())
{
read_header();
}
}
dbf_file::~dbf_file()
{
::operator delete(record_);
file_.close();
}
bool dbf_file::open(const std::string& file_name)
{
file_.open(file_name.c_str());
if (file_.is_open())
read_header();
return file_?true:false;
}
bool dbf_file::is_open()
{
return file_.is_open();
}
void dbf_file::close()
{
if (file_ && file_.is_open())
file_.close();
}
int dbf_file::num_records() const
{
return num_records_;
}
int dbf_file::num_fields() const
{
return num_fields_;
}
void dbf_file::move_to(int index)
{
if (index>0 && index<=num_records_)
{
long pos=(num_fields_<<5)+34+(index-1)*(record_length_+1);
file_.seekg(pos,std::ios::beg);
file_.read(record_,record_length_);
}
}
std::string dbf_file::string_value(int col) const
{
if (col>=0 && col<num_fields_)
{
return std::string(record_+fields_[col].offset_,fields_[col].length_);
}
return "";
}
const field_descriptor& dbf_file::descriptor(int col) const
{
assert(col>=0 && col<num_fields_);
return fields_[col];
}
void dbf_file::add_attribute(int col,Feature* f) const throw()
{
if (col>=0 && col<num_fields_)
{
std::string name=fields_[col].name_;
std::string str=trim(std::string(record_+fields_[col].offset_,fields_[col].length_));
switch (fields_[col].type_)
{
case 'C':
case 'D'://todo handle date?
case 'M':
case 'L':
{
f->add_property(name,str);
break;
}
case 'N':
case 'F':
{
if (str[0]=='*')
{
break;
}
if (fields_[col].dec_>0)
{
double d;
fromString(str,d);
f->add_property(name,d);
}
else
{
int i;
fromString(str,i);
f->add_property(name,i);
}
break;
}
}
}
}
void dbf_file::read_header()
{
char c=file_.get();
if (c=='\3' || c=='\131')
{
skip(3);
num_records_=read_int();
assert(num_records_>0);
num_fields_=read_short();
assert(num_fields_>0);
num_fields_=(num_fields_-33)/32;
skip(22);
int offset=0;
char name[11];
memset(&name,0,11);
fields_.reserve(num_fields_);
for (int i=0;i<num_fields_;++i)
{
field_descriptor desc;
desc.index_=i;
file_.read(name,10);
desc.name_=trim_left(name);
skip(1);
desc.type_=file_.get();
skip(4);
desc.length_=file_.get();
desc.dec_=file_.get();
skip(14);
desc.offset_=offset;
offset+=desc.length_;
fields_.push_back(desc);
}
record_length_=offset;
if (record_length_>0)
{
record_=static_cast<char*>(::operator new (sizeof(char)*record_length_));
}
}
}
int dbf_file::read_short()
{
char b[2];
file_.read(b,2);
return (b[0] & 0xff) | (b[1] & 0xff) << 8;
}
int dbf_file::read_int()
{
char b[4];
file_.read(b,4);
return (b[0] & 0xff) | (b[1] & 0xff) << 8 |
(b[2] & 0xff) << 16 | (b[3] & 0xff) <<24;
}
void dbf_file::skip(int bytes)
{
file_.seekg(bytes,std::ios::cur);
}

73
shape/dbffile.hpp Normal file
View file

@ -0,0 +1,73 @@
/* This file is part of Mapnik (c++ mapping toolkit)
* Copyright (C) 2005 Artem Pavlenko
*
* Mapnik is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef DBFFILE_HH
#define DBFFILE_HH
#include <vector>
#include <string>
#include <fstream>
#include <cassert>
#include "mapnik.hh"
using namespace mapnik;
struct field_descriptor
{
int index_;
std::string name_;
char type_;
int length_;
int dec_;
int offset_;
};
class dbf_file
{
private:
int num_records_;
int num_fields_;
int record_length_;
std::vector<field_descriptor> fields_;
std::ifstream file_;
char* record_;
public:
dbf_file();
dbf_file(const char* file_name);
dbf_file(const std::string& file_name);
~dbf_file();
bool open(const std::string& file_name);
bool is_open();
void close();
int num_records() const;
int num_fields() const;
const field_descriptor& descriptor(int col) const;
void move_to(int index);
std::string string_value(int col) const;
void add_attribute(int col,Feature* f) const throw();
private:
dbf_file(const dbf_file&);
dbf_file& operator=(const dbf_file&);
void read_header();
int read_short();
int read_int();
void skip(int bytes);
};
#endif //DBFFILE_HH

113
shape/shape.cpp Normal file
View file

@ -0,0 +1,113 @@
/* This file is part of Mapnik (c++ mapping toolkit)
* Copyright (C) 2005 Artem Pavlenko
*
* Mapnik is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "shape.hh"
#include "shape_featureset.hh"
#include "shape_index_featureset.hh"
#include <iostream>
#include <stdexcept>
DATASOURCE_PLUGIN(shape_datasource);
shape_datasource::shape_datasource(const Parameters &params)
: shape_name_(params.get("file")),
type_(datasource::Vector),
file_length_(0),
indexed_(false)
{
try
{
shape_io shape(shape_name_);
init(shape);
}
catch (datasource_exception& ex)
{
std::cerr<<ex.what()<<std::endl;
throw;
}
}
shape_datasource::~shape_datasource()
{
}
std::string shape_datasource::name_="shape";
void shape_datasource::init(shape_io& shape)
{
//first read header from *.shp
int file_code=shape.shp().read_xdr_integer();
if (file_code!=9994)
{
//invalid
throw datasource_exception("wrong file code");
}
shape.shp().skip(5*4);
file_length_=shape.shp().read_xdr_integer();
int version=shape.shp().read_ndr_integer();
if (version!=1000)
{
//invalid version number
throw datasource_exception("invalid version number");
}
int shape_type=shape.shp().read_ndr_integer();
shape.shp().read_envelope(extent_);
shape.shp().skip(4*8);
// check if we have an index file around
std::string index_name(shape_name_+".index");
std::ifstream file(index_name.c_str(),std::ios::in | std::ios::binary);
if (file)
{
indexed_=true;
file.close();
}
std::cout<<extent_<<std::endl;
std::cout<<"file_length="<<file_length_<<std::endl;
std::cout<<"shape_type="<<shape_type<<std::endl;
}
int shape_datasource::type() const
{
return type_;
}
std::string shape_datasource::name()
{
return name_;
}
featureset_ptr shape_datasource::features(const query& q) const
{
filter_in_box filter(q.get_bbox());
if (indexed_)
{
return featureset_ptr(new shape_index_featureset<filter_in_box>(filter,shape_name_,q.property_names()));
}
return featureset_ptr(new shape_featureset<filter_in_box>(filter,shape_name_,q.property_names(),file_length_));
}
const Envelope<double>& shape_datasource::envelope() const
{
return extent_;
}

48
shape/shape.hpp Normal file
View file

@ -0,0 +1,48 @@
/* This file is part of Mapnik (c++ mapping toolkit)
* Copyright (C) 2005 Artem Pavlenko
*
* Mapnik is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef SHAPE_HH
#define SHAPE_HH
#include "mapnik.hh"
#include "shape_io.hh"
using namespace mapnik;
class shape_datasource : public datasource
{
std::string shape_name_;
int type_;
long file_length_;
mapnik::Envelope<double> extent_;
bool indexed_;
static std::string name_;
public:
int type() const;
static std::string name();
featureset_ptr features(const query& q) const;
const Envelope<double>& envelope() const;
shape_datasource(const Parameters &params);
virtual ~shape_datasource();
private:
shape_datasource(const shape_datasource&);
shape_datasource& operator=(const shape_datasource&);
void init(shape_io& shape);
};
#endif //SHAPE_HH

180
shape/shape_featureset.cpp Normal file
View file

@ -0,0 +1,180 @@
/* This file is part of Mapnik (c++ mapping toolkit)
* Copyright (C) 2005 Artem Pavlenko
*
* Mapnik is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "shape_featureset.hh"
#include <iostream>
template <typename filterT>
shape_featureset<filterT>::shape_featureset(const filterT& filter,
const std::string& shape_file,
const std::set<std::string>& attribute_names,
long file_length )
: filter_(filter),
shape_type_(shape_io::shape_null),
shape_(shape_file),
query_ext_(),
file_length_(file_length),
count_(0)
{
shape_.shp().skip(100);
//attributes
typename std::set<std::string>::const_iterator pos=attribute_names.begin();
while (pos!=attribute_names.end())
{
for (int i=0;i<shape_.dbf().num_fields();++i)
{
if (shape_.dbf().descriptor(i).name_ == *pos)
{
attr_ids_.push_back(i);
break;
}
}
++pos;
}
}
template <typename filterT>
Feature* shape_featureset<filterT>::next()
{
Feature* feature=0;
std::streampos pos=shape_.shp().pos();
if (pos < std::streampos(file_length_ * 2))
{
shape_.move_to(pos);
int type=shape_.type();
int id=shape_.id_;
if (type == shape_io::shape_point)
{
double x=shape_.shp().read_double();
double y=shape_.shp().read_double();
geometry_ptr point(new point_impl(-1));
point->move_to(x,y);
feature=new Feature(id,point);
++count_;
}
else if (type == shape_io::shape_pointm)
{
double x=shape_.shp().read_double();
double y=shape_.shp().read_double();
shape_.shp().read_double();//m
geometry_ptr point(new point_impl(-1));
point->move_to(x,y);
feature=new Feature(id,point);
++count_;
}
else if (type == shape_io::shape_pointz)
{
double x=shape_.shp().read_double();
double y=shape_.shp().read_double();
shape_.shp().read_double();//z
shape_.shp().read_double();//m
geometry_ptr point(new point_impl(-1));
point->move_to(x,y);
feature=new Feature(id,point);
++count_;
}
else
{
while (!filter_.pass(shape_.current_extent()))
{
unsigned reclen=shape_.reclength_;
shape_.move_to(long(shape_.shp().pos()) + 2 * reclen - 36);
if ((long)shape_.shp().pos() >= file_length_ * 2)
return 0;
}
switch (type)
{
case shape_io::shape_polyline:
{
geometry_ptr line = shape_.read_polyline();
feature=new Feature(shape_.id_,line);
++count_;
break;
}
case shape_io::shape_polylinem:
{
geometry_ptr line = shape_.read_polylinem();
feature=new Feature(shape_.id_,line);
++count_;
break;
}
case shape_io::shape_polylinez:
{
geometry_ptr line = shape_.read_polylinez();
feature=new Feature(shape_.id_,line);
++count_;
break;
}
case shape_io::shape_polygon:
{
geometry_ptr poly = shape_.read_polygon();
feature=new Feature(shape_.id_,poly);
++count_;
break;
}
case shape_io::shape_polygonm:
{
geometry_ptr poly = shape_.read_polygonm();
feature=new Feature(shape_.id_,poly);
++count_;
break;
}
case shape_io::shape_polygonz:
{
geometry_ptr poly = shape_.read_polygon();
feature=new Feature(shape_.id_,poly);
++count_;
break;
}
default:
return 0;
}
if (attr_ids_.size())
{
shape_.dbf().move_to(shape_.id_);
typename std::vector<int>::const_iterator pos=attr_ids_.begin();
while (pos!=attr_ids_.end())
{
try
{
shape_.dbf().add_attribute(*pos,feature);//TODO optimize!!!
}
catch (...)
{
//TODO
}
++pos;
}
}
}
}
if (!feature)
std::cout<<" total shapes read="<<count_<<"\n";
return feature;
}
template <typename filterT>
shape_featureset<filterT>::~shape_featureset() {}
template class shape_featureset<filter_in_box>;

View file

@ -0,0 +1,48 @@
/* This file is part of Mapnik (c++ mapping toolkit)
* Copyright (C) 2005 Artem Pavlenko
*
* Mapnik is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef SHAPE_FS_HH
#define SHAPE_FS_HH
#include "shape.hh"
using namespace mapnik;
template <typename filterT>
class shape_featureset : public Featureset
{
filterT filter_;
int shape_type_;
shape_io shape_;
Envelope<double> query_ext_;
long file_length_;
std::vector<int> attr_ids_;
mutable Envelope<double> feature_ext_;
mutable int total_geom_size;
mutable int count_;
public:
shape_featureset(const filterT& filter, const std::string& shape_file,
const std::set<std::string>& attribute_names,long file_length);
virtual ~shape_featureset();
Feature* next();
private:
shape_featureset(const shape_featureset&);
const shape_featureset& operator=(const shape_featureset&);
};
#endif //SHAPE_FS_HH

View file

@ -0,0 +1,182 @@
/* This file is part of Mapnik (c++ mapping toolkit)
* Copyright (C) 2005 Artem Pavlenko
*
* Mapnik is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
//$Id: shape_index_featureset.cc 36 2005-04-05 14:32:18Z pavlenko $
#include "shape_index_featureset.hh"
template <typename filterT>
shape_index_featureset<filterT>::shape_index_featureset(const filterT& filter,
const std::string& shape_file,
const std::set<std::string>& attribute_names)
: filter_(filter),
shape_type_(0),
shape_(shape_file),
count_(0)
{
shape_.shp().skip(100);
std::string indexname(shape_file + ".index");
std::ifstream file(indexname.c_str(),std::ios::in|std::ios::binary);
if (file)
{
shp_index<filterT>::query(filter,file,ids_);
file.close();
}
std::cout<< "query size=" << ids_.size() << "\n";
itr_ = ids_.begin();
// deal with attributes
std::set<std::string>::const_iterator pos=attribute_names.begin();
while (pos!=attribute_names.end())
{
for (int i=0;i<shape_.dbf().num_fields();++i)
{
if (shape_.dbf().descriptor(i).name_ == *pos)
{
attr_ids_.push_back(i);
break;
}
}
++pos;
}
}
template <typename filterT>
Feature* shape_index_featureset<filterT>::next()
{
Feature *f=0;
if (itr_!=ids_.end())
{
int pos=*itr_++;
shape_.move_to(pos);
int type=shape_.type();
if (type==shape_io::shape_point)
{
double x=shape_.shp().read_double();
double y=shape_.shp().read_double();
geometry_ptr point(new point_impl(-1));
point->move_to(x,y);
f=new Feature(shape_.id_,point);
++count_;
}
else if (type == shape_io::shape_pointm)
{
double x=shape_.shp().read_double();
double y=shape_.shp().read_double();
shape_.shp().read_double();// m
geometry_ptr point(new point_impl(-1));
point->move_to(x,y);
f=new Feature(shape_.id_,point);
++count_;
}
else if (type == shape_io::shape_pointz)
{
double x=shape_.shp().read_double();
double y=shape_.shp().read_double();
shape_.shp().read_double();// z
shape_.shp().read_double();// m
geometry_ptr point(new point_impl(-1));
point->move_to(x,y);
f=new Feature(shape_.id_,point);
++count_;
}
else
{
while(!filter_.pass(shape_.current_extent()) &&
itr_!=ids_.end())
{
pos=*itr_++;
shape_.move_to(pos);
}
switch (type)
{
case shape_io::shape_polyline:
{
geometry_ptr line = shape_.read_polyline();
f=new Feature(shape_.id_,line);
++count_;
break;
}
case shape_io::shape_polylinem:
{
geometry_ptr line = shape_.read_polylinem();
f=new Feature(shape_.id_,line);
++count_;
break;
}
case shape_io::shape_polylinez:
{
geometry_ptr line = shape_.read_polylinez();
f=new Feature(shape_.id_,line);
++count_;
break;
}
case shape_io::shape_polygon:
{
geometry_ptr poly = shape_.read_polygon();
f=new Feature(shape_.id_,poly);
++count_;
break;
}
case shape_io::shape_polygonm:
{
geometry_ptr poly = shape_.read_polygonm();
f=new Feature(shape_.id_,poly);
++count_;
break;
}
case shape_io::shape_polygonz:
{
geometry_ptr poly = shape_.read_polygonz();
f=new Feature(shape_.id_,poly);
++count_;
break;
}
}
if (attr_ids_.size())
{
shape_.dbf().move_to(shape_.id_);
std::vector<int>::const_iterator pos=attr_ids_.begin();
while (pos!=attr_ids_.end())
{
try
{
shape_.dbf().add_attribute(*pos,f);//TODO optimize!!!
}
catch (...)
{
std::cerr<<"exception caught\n";
}
++pos;
}
}
}
}
if (!f) std::cout<<count_<<" features\n";
return f;
}
template <typename filterT>
shape_index_featureset<filterT>::~shape_index_featureset() {}
template class shape_index_featureset<filter_in_box>;

View file

@ -0,0 +1,49 @@
/* This file is part of Mapnik (c++ mapping toolkit)
* Copyright (C) 2005 Artem Pavlenko
*
* Mapnik is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef SHAPE_SQT_FS_HH
#define SHAPE_SQT_FS_HH
#include "shape_featureset.hh"
#include <set>
#include <vector>
template <typename filterT>
class shape_index_featureset : public Featureset
{
filterT filter_;
int shape_type_;
shape_io shape_;
std::set<int> ids_;
std::set<int>::iterator itr_;
std::vector<int> attr_ids_;
mutable Envelope<double> feature_ext_;
mutable int total_geom_size;
mutable int count_;
public:
shape_index_featureset(const filterT& filter,const std::string& shape_file,
const std::set<std::string>& attribute_names);
virtual ~shape_index_featureset();
Feature* next();
private:
//no copying
shape_index_featureset(const shape_index_featureset&);
shape_index_featureset& operator=(const shape_index_featureset&);
};
#endif //SHAPE_SQT_FS_HH

414
shape/shape_io.cpp Normal file
View file

@ -0,0 +1,414 @@
/* This file is part of Mapnik (c++ mapping toolkit)
* Copyright (C) 2005 Artem Pavlenko
*
* Mapnik is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
//$Id: shape_io.cc 26 2005-03-29 19:18:59Z pavlenko $
#include "shape_io.hh"
#include "shape.hh"
const std::string shape_io::SHP = ".shp";
const std::string shape_io::DBF = ".dbf";
shape_io::shape_io(const std::string& shape_name)
: type_(shape_null),
reclength_(0),
id_(0)
{
bool ok = (shp_.open(shape_name + SHP) &&
dbf_.open(shape_name + DBF));
if (!ok)
{
throw datasource_exception("cannot read shape file");
}
}
shape_io::~shape_io()
{
shp_.close();
dbf_.close();
}
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();
if (type_ != shape_point)
{
shp_.read_envelope(cur_extent_);
}
}
int shape_io::type() const
{
return type_;
}
const Envelope<double>& shape_io::current_extent() const
{
return cur_extent_;
}
shape_file& shape_io::shp()
{
return shp_;
}
shape_file& shape_io::shx()
{
return shx_;
}
dbf_file& shape_io::dbf()
{
return dbf_;
}
geometry_ptr shape_io::read_polyline()
{
shape_record record(reclength_*2-36);
shp_.read_record(record);
int num_parts=record.read_ndr_integer();
int num_points=record.read_ndr_integer();
geometry_ptr line(new line_string_impl(-1));
if (num_parts == 1)
{
record.skip(4);
double x=record.read_double();
double y=record.read_double();
line->move_to(x,y);
for (int i=1;i<num_points;++i)
{
x=record.read_double();
y=record.read_double();
line->line_to(x,y);
}
}
else
{
std::vector<int> parts(num_parts);
for (int i=0;i<num_parts;++i)
{
parts[i]=record.read_ndr_integer();
}
int start,end;
for (int k=0;k<num_parts;++k)
{
start=parts[k];
if (k==num_parts-1)
end=num_points;
else
end=parts[k+1];
double x=record.read_double();
double y=record.read_double();
line->move_to(x,y);
for (int j=start+1;j<end;++j)
{
x=record.read_double();
y=record.read_double();
line->line_to(x,y);
}
}
}
return line;
}
geometry_ptr shape_io::read_polylinem()
{
shape_record record(reclength_*2-36);
shp_.read_record(record);
int num_parts=record.read_ndr_integer();
int num_points=record.read_ndr_integer();
geometry_ptr line(new line_string_impl(-1));
if (num_parts == 1)
{
record.skip(4);
double x=record.read_double();
double y=record.read_double();
line->move_to(x,y);
for (int i=1;i<num_points;++i)
{
x=record.read_double();
y=record.read_double();
line->line_to(x,y);
}
}
else
{
std::vector<int> parts(num_parts);
for (int i=0;i<num_parts;++i)
{
parts[i]=record.read_ndr_integer();
}
int start,end;
for (int k=0;k<num_parts;++k)
{
start=parts[k];
if (k==num_parts-1)
end=num_points;
else
end=parts[k+1];
double x=record.read_double();
double y=record.read_double();
line->move_to(x,y);
for (int j=start+1;j<end;++j)
{
x=record.read_double();
y=record.read_double();
line->line_to(x,y);
}
}
}
// m-range
//double m0=record.read_double();
//double m1=record.read_double();
//for (int i=0;i<num_points;++i)
//{
// double m=record.read_double();
//}
return line;
}
geometry_ptr shape_io::read_polylinez()
{
shape_record record(reclength_*2-36);
shp_.read_record(record);
int num_parts=record.read_ndr_integer();
int num_points=record.read_ndr_integer();
geometry_ptr line(new line_string_impl(-1));
if (num_parts == 1)
{
record.skip(4);
double x=record.read_double();
double y=record.read_double();
line->move_to(x,y);
for (int i=1;i<num_points;++i)
{
x=record.read_double();
y=record.read_double();
line->line_to(x,y);
}
}
else
{
std::vector<int> parts(num_parts);
for (int i=0;i<num_parts;++i)
{
parts[i]=record.read_ndr_integer();
}
int start,end;
for (int k=0;k<num_parts;++k)
{
start=parts[k];
if (k==num_parts-1)
end=num_points;
else
end=parts[k+1];
double x=record.read_double();
double y=record.read_double();
line->move_to(x,y);
for (int j=start+1;j<end;++j)
{
x=record.read_double();
y=record.read_double();
line->line_to(x,y);
}
}
}
// z-range
//double z0=record.read_double();
//double z1=record.read_double();
//for (int i=0;i<num_points;++i)
// {
// double z=record.read_double();
// }
// m-range
//double m0=record.read_double();
//double m1=record.read_double();
//for (int i=0;i<num_points;++i)
//{
// double m=record.read_double();
//}
return line;
}
geometry_ptr shape_io::read_polygon()
{
shape_record record(reclength_*2-36);
shp_.read_record(record);
int num_parts=record.read_ndr_integer();
int num_points=record.read_ndr_integer();
std::vector<int> parts(num_parts);
geometry_ptr poly(new polygon_impl(-1));
for (int i=0;i<num_parts;++i)
{
parts[i]=record.read_ndr_integer();
}
for (int k=0;k<num_parts;k++)
{
int start=parts[k];
int end;
if (k==num_parts-1)
{
end=num_points;
}
else
{
end=parts[k+1];
}
double x=record.read_double();
double y=record.read_double();
poly->move_to(x,y);
for (int j=start+1;j<end;j++)
{
x=record.read_double();
y=record.read_double();
poly->line_to(x,y);
}
}
return poly;
}
geometry_ptr shape_io::read_polygonm()
{
shape_record record(reclength_*2-36);
shp_.read_record(record);
int num_parts=record.read_ndr_integer();
int num_points=record.read_ndr_integer();
std::vector<int> parts(num_parts);
geometry_ptr poly(new polygon_impl(-1));
for (int i=0;i<num_parts;++i)
{
parts[i]=record.read_ndr_integer();
}
for (int k=0;k<num_parts;k++)
{
int start=parts[k];
int end;
if (k==num_parts-1)
{
end=num_points;
}
else
{
end=parts[k+1];
}
double x=record.read_double();
double y=record.read_double();
poly->move_to(x,y);
for (int j=start+1;j<end;j++)
{
x=record.read_double();
y=record.read_double();
poly->line_to(x,y);
}
}
// m-range
//double m0=record.read_double();
//double m1=record.read_double();
//for (int i=0;i<num_points;++i)
//{
// double m=record.read_double();
//}
return poly;
}
geometry_ptr shape_io::read_polygonz()
{
shape_record record(reclength_*2-36);
shp_.read_record(record);
int num_parts=record.read_ndr_integer();
int num_points=record.read_ndr_integer();
std::vector<int> parts(num_parts);
geometry_ptr poly(new polygon_impl(-1));
for (int i=0;i<num_parts;++i)
{
parts[i]=record.read_ndr_integer();
}
for (int k=0;k<num_parts;k++)
{
int start=parts[k];
int end;
if (k==num_parts-1)
{
end=num_points;
}
else
{
end=parts[k+1];
}
double x=record.read_double();
double y=record.read_double();
poly->move_to(x,y);
for (int j=start+1;j<end;j++)
{
x=record.read_double();
y=record.read_double();
poly->line_to(x,y);
}
}
// z-range
//double z0=record.read_double();
//double z1=record.read_double();
//for (int i=0;i<num_points;++i)
//{
// double z=record.read_double();
//}
// m-range
//double m0=record.read_double();
//double m1=record.read_double();
//for (int i=0;i<num_points;++i)
//{
// double m=record.read_double();
//}
return poly;
}

82
shape/shape_io.hpp Normal file
View file

@ -0,0 +1,82 @@
/* This file is part of Mapnik (c++ mapping toolkit)
* Copyright (C) 2005 Artem Pavlenko
*
* Mapnik is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef SHAPE_IO_HH
#define SHAPE_IO_HH
#include "dbffile.hh"
#include "shapefile.hh"
#include "shp_index.hh"
using mapnik::geometry_ptr;
struct shape_io
{
static const std::string SHP;
static const std::string SHX;
static const std::string DBF;
shape_file shp_;
shape_file shx_;
dbf_file dbf_;
unsigned type_;
unsigned reclength_;
unsigned id_;
Envelope<double> cur_extent_;
public:
enum
{
shape_null = 0,
shape_point = 1,
shape_polyline = 3,
shape_polygon = 5,
shape_multipoint = 8,
shape_pointz = 11,
shape_polylinez = 13,
shape_polygonz = 15,
shape_multipointz = 18,
shape_pointm = 21,
shape_polylinem = 23,
shape_polygonm = 25,
shape_multipointm = 28,
shape_multipatch = 31
};
shape_io(const std::string& shape_name);
~shape_io();
shape_file& shp();
shape_file& shx();
dbf_file& dbf();
void move_to(int id);
int type() const;
const Envelope<double>& current_extent() const;
geometry_ptr read_polyline();
geometry_ptr read_polylinem();
geometry_ptr read_polylinez();
geometry_ptr read_polygon();
geometry_ptr read_polygonm();
geometry_ptr read_polygonz();
private:
//void read_record(const shape_record& record);
// no copying
shape_io(const shape_io&);
shape_io& operator=(const shape_io&);
};
#endif //SHAPE_IO_HH

58
shape/shapefile.cpp Normal file
View file

@ -0,0 +1,58 @@
/* This file is part of Mapnik (c++ mapping toolkit)
* Copyright (C) 2005 Artem Pavlenko
*
* Mapnik is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "shapefile.hh"
shape_file::shape_file() {}
shape_file::shape_file(const std::string& file_name)
{
//file_.rdbuf()->pubsetbuf(buff_,buffer_size);
file_.open(file_name.c_str(),std::ios::in|std::ios::binary);
}
shape_file::~shape_file()
{
if (file_ && file_.is_open())
file_.close();
}
bool shape_file::open(const std::string& file_name)
{
//file_.rdbuf()->pubsetbuf(buff_,buffer_size);
file_.open(file_name.c_str(),std::ios::in | std::ios::binary);
return file_?true:false;
}
bool shape_file::is_open()
{
return file_.is_open();
}
void shape_file::close()
{
if (file_ && file_.is_open())
file_.close();
}

195
shape/shapefile.hpp Normal file
View file

@ -0,0 +1,195 @@
/* This file is part of Mapnik (c++ mapping toolkit)
* Copyright (C) 2005 Artem Pavlenko
*
* Mapnik is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
//$Id: shapefile.hh 33 2005-04-04 13:01:03Z pavlenko $
#ifndef SHAPEFILE_HH
#define SHAPEFILE_HH
#include "mapnik.hh"
#include <fstream>
using namespace mapnik;
struct shape_record
{
char* data;
size_t size;
size_t pos;
explicit shape_record(size_t size)
: data(static_cast<char*>(::operator new(sizeof(char)*size))),
size(size),
pos(0) {}
char* rawdata()
{
return &data[0];
}
void skip(unsigned n)
{
pos+=n;
}
int read_ndr_integer()
{
int val=(data[pos] & 0xff) |
(data[pos+1] & 0xff) << 8 |
(data[pos+2] & 0xff) << 16 |
(data[pos+3] & 0xff) << 24;
pos+=4;
return val;
}
int read_xdr_integer()
{
int val=(data[pos] & 0xff) << 24 |
(data[pos+1] & 0xff) << 16 |
(data[pos+2] & 0xff) << 8 |
(data[pos+3] & 0xff);
pos+=4;
return val;
}
double read_double()
{
double val;
#ifndef WORDS_BIGENDIAN
std::memcpy(&val,&data[pos],8);
#else
long long bits = ((long long)data[pos] & 0xff) |
((long long)data[pos+1] & 0xff) << 8 |
((long long)data[pos+2] & 0xff) << 16 |
((long long)data[pos+3] & 0xff) << 24 |
((long long)data[pos+4] & 0xff) << 32 |
((long long)data[pos+5] & 0xff) << 40 |
((long long)data[pos+6] & 0xff) << 48 |
((long long)data[pos+7] & 0xff) << 56 ;
std::memcpy(&val,&bits,8);
#endif
pos+=8;
return val;
}
long remains()
{
return (size-pos);
}
~shape_record()
{
::operator delete(data);
}
};
class shape_file
{
std::ifstream file_;
//static const int buffer_size = 16;
//char buff_[buffer_size];
public:
shape_file();
shape_file(const std::string& file_name);
~shape_file();
bool open(const std::string& file_name);
bool is_open();
void close();
inline void shape_file::read_record(shape_record& rec)
{
file_.read(rec.rawdata(),rec.size);
}
inline int read_xdr_integer()
{
char b[4];
file_.read(b, 4);
return b[3] & 0xffu | (b[2] & 0xffu) << 8 |
(b[1] & 0xffu) << 16 | (b[0] & 0xffu) << 24;
}
inline int read_ndr_integer()
{
char b[4];
file_.read(b,4);
return b[0]&0xffu | (b[1]&0xffu) << 8 |
(b[2]&0xffu) << 16 | (b[3]&0xffu) << 24;
}
inline double read_double()
{
double val;
#ifndef WORDS_BIGENDIAN
file_.read(reinterpret_cast<char*>(&val),8);
#else
char b[8];
file_.read(b,8);
long long bits = ((long long)b[0] & 0xff) |
((long long)b[1] & 0xff) << 8 |
((long long)b[2] & 0xff) << 16 |
((long long)b[3] & 0xff) << 24 |
((long long)b[4] & 0xff) << 32 |
((long long)b[5] & 0xff) << 40 |
((long long)b[6] & 0xff) << 48 |
((long long)b[7] & 0xff) << 56 ;
memcpy(&val,&bits,8);
#endif
return val;
}
inline void read_envelope(Envelope<double>& envelope)
{
#ifndef WORDS_BIGENDIAN
file_.read(reinterpret_cast<char*>(&envelope),sizeof(envelope));
#else
double minx=read_double();
double miny=read_double();
double maxx=read_double();
double maxy=read_double();
envelope.init(minx,miny,maxx,maxy);
#endif
}
inline void skip(std::streampos bytes)
{
file_.seekg(bytes,std::ios::cur);
}
inline void rewind()
{
seek(100);
}
inline void seek(std::streampos pos)
{
file_.seekg(pos,std::ios::beg);
}
inline std::streampos pos()
{
return file_.tellg();
}
inline bool is_eof()
{
return file_.eof();
}
private:
shape_file(const shape_file&);
shape_file& operator=(const shape_file&);
};
#endif //SHAPEFILE_HH

76
shape/shp_index.cpp Normal file
View file

@ -0,0 +1,76 @@
/* This file is part of Mapnik (c++ mapping toolkit)
* Copyright (C) 2005 Artem Pavlenko
*
* Mapnik is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "shp_index.hh"
template <typename filterT>
void shp_index<filterT>::query(const filterT& filter,std::ifstream& file,std::set<int>& pos)
{
file.seekg(16,std::ios::beg);
query_node(filter,file,pos);
}
template <typename filterT>
void shp_index<filterT>::query_node(const filterT& filter,std::ifstream& file,std::set<int>& ids)
{
int offset=read_ndr_integer(file);
Envelope<double> node_ext;
read_envelope(file,node_ext);
int num_shapes=read_ndr_integer(file);
if (!filter.pass(node_ext))
{
file.seekg(offset+num_shapes*4+4,std::ios::cur);
return;
}
for (int i=0;i<num_shapes;++i)
{
int id=read_ndr_integer(file);
ids.insert(id);
}
int children=read_ndr_integer(file);
for (int j=0;j<children;++j)
{
query_node(filter,file,ids);
}
}
template <typename filterT>
int shp_index<filterT>::read_ndr_integer(std::ifstream& file)
{
char b[4];
file.read(b,4);
return (b[0]&0xff) | (b[1]&0xff)<<8 | (b[2]&0xff)<<16 | (b[3]&0xff)<<24;
}
template <typename filterT>
void shp_index<filterT>::read_envelope(std::ifstream& file,Envelope<double>& envelope)
{
file.read(reinterpret_cast<char*>(&envelope),sizeof(envelope));
}
template class shp_index<filter_in_box>;
template class shp_index<filter_at_point>;

43
shape/shp_index.hpp Normal file
View file

@ -0,0 +1,43 @@
/* This file is part of Mapnik (c++ mapping toolkit)
* Copyright (C) 2005 Artem Pavlenko
*
* Mapnik is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef SHP_INDEX_HH
#define SHP_INDEX_HH
#include "mapnik.hh"
#include <fstream>
#include <set>
using namespace mapnik;
template <typename filterT>
class shp_index
{
public:
static void query(const filterT& filter,std::ifstream& file,std::set<int>& pos);
private:
shp_index();
~shp_index();
shp_index(const shp_index&);
shp_index& operator=(const shp_index&);
static int read_ndr_integer(std::ifstream& in);
static void read_envelope(std::ifstream& in,Envelope<double> &envelope);
static void query_node(const filterT& filter,std::ifstream& file,std::set<int>& pos);
};
#endif //SHP_INDEX_HH