commit ebcdd3cf90736330c05d7876c07a0a79200a5ad8 Author: Artem Pavlenko Date: Tue Jun 14 15:06:59 2005 +0000 initial import diff --git a/postgis/Jamfile b/postgis/Jamfile new file mode 100644 index 000000000..8f610e410 --- /dev/null +++ b/postgis/Jamfile @@ -0,0 +1,18 @@ +#postgis datasource plugin + +project + : usage-requirements + /opt/postgresql8/include + ; +lib pq + : + : /opt/postgresql8/lib/libpq.so + ; + +lib postgis + : + postgis.cc + postgisfs.cc + pq + ; + diff --git a/postgis/SConscript b/postgis/SConscript new file mode 100644 index 000000000..3e5daad6d --- /dev/null +++ b/postgis/SConscript @@ -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') diff --git a/postgis/connection.hpp b/postgis/connection.hpp new file mode 100644 index 000000000..4e65f087b --- /dev/null +++ b/postgis/connection.hpp @@ -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 "< 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(new ResultSet(result)); + } + result=PQexec(conn_,sql.c_str()); + return ref_ptr(new ResultSet(result)); + } + bool isOK() const + { + return (PQstatus(conn_)!=CONNECTION_BAD); + } + void close() + { + PQfinish(conn_); + } + ~Connection() + { + PQfinish(conn_); + } +}; + +#endif //CONNECTION_HPP diff --git a/postgis/connection_manager.hpp b/postgis/connection_manager.hpp new file mode 100644 index 000000000..1ed8f3567 --- /dev/null +++ b/postgis/connection_manager.hpp @@ -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 +#include "pool.hpp" +#include "utils.hpp" +#include "connection.hpp" + +using namespace mapnik; +using std::string; + +template +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 +{ + + friend class CreateStatic; + typedef Pool PoolType; + typedef std::map > ContType; + typedef ref_ptr HolderType; + ContType pools_; + +public: + + bool registerPool(const ConnectionCreator& 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(new PoolType(creator,initialSize,maxSize)))).second; + } + + return false; + + } + const ref_ptr& 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 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 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 diff --git a/postgis/postgis.cpp b/postgis/postgis.cpp new file mode 100644 index 000000000..c9b7785f6 --- /dev/null +++ b/postgis/postgis.cpp @@ -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 +#include +#include +#include +#include +#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=mgr->getPool(creator_.id()); + if (pool) + { + const ref_ptr& conn = pool->borrowObject(); + if (conn && conn->isOK()) + { + PoolGuard,ref_ptr > > 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='"< rs=conn->executeQuery(s.str()); + + if (rs->next()) + { + try + { + srid_ = lexical_cast(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('"<executeQuery(s.str()); + if (rs->next()) + { + try + { + double lox=lexical_cast(rs->getValue(0)); + double loy=lexical_cast(rs->getValue(1)); + double hix=lexical_cast(rs->getValue(2)); + double hiy=lexical_cast(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 "<executeQuery(s.str()); + if (rs->next()) + { + int count = rs->getNumFields(); + for (int i=0;igetFieldName(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="< const& box=q.get_bbox(); + ConnectionManager *mgr=ConnectionManager::instance(); + ref_ptr > pool=mgr->getPool(creator_.id()); + if (pool) + { + const ref_ptr& conn = pool->borrowObject(); + if (conn && conn->isOK()) + { + PoolGuard,ref_ptr > > guard(conn,pool); + std::ostringstream s; + // can we rely on 'gid' name??? + s << "select gid,asbinary("< const& props=q.property_names(); + std::set::const_iterator pos=props.begin(); + while (pos!=props.end()) + { + s <<",\""<<*pos<<"\""; + ++pos; + } + + s << " from " << table_<<" where "< rs=conn->executeQuery(s.str(),1); + fs=new PostgisFeatureset(rs,props.size()); + } + } + return featureset_ptr(fs); +} + +const Envelope& PostgisDatasource::envelope() const +{ + return extent_; +} + +PostgisDatasource::~PostgisDatasource() {} diff --git a/postgis/postgis.hpp b/postgis/postgis.hpp new file mode 100644 index 000000000..e7524abe9 --- /dev/null +++ b/postgis/postgis.hpp @@ -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 + +#include + +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 extent_; + layer_descriptor desc_; + ConnectionCreator creator_; + static std::string name_; +public: + static std::string name(); + int type() const; + featureset_ptr features(const query& q) const; + mapnik::Envelope const& envelope() const; + layer_descriptor const& get_descriptor() const; + PostgisDatasource(const Parameters ¶ms); + ~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 rs_; + unsigned num_attrs_; + mutable int totalGeomSize_; + mutable int count_; +public: + PostgisFeatureset(const ref_ptr& rs,unsigned num_attrs); + void dispose(); + Feature* next(); + ~PostgisFeatureset(); +private: + PostgisFeatureset(const PostgisFeatureset&); + const PostgisFeatureset& operator=(const PostgisFeatureset&); +}; + +#endif //POSTGIS_HPP diff --git a/postgis/postgisfs.cpp b/postgis/postgisfs.cpp new file mode 100644 index 000000000..d10e7f785 --- /dev/null +++ b/postgis/postgisfs.cpp @@ -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& 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;posgetValue(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="< + +namespace mapnik +{ + template + class property_validator : public filter_visitor + { + public: + property_validator(layer_descriptor& desc) + desc_(desc) {} + + void visit(filter& /*filter*/) + { + //not interested + } + void visit(expression& exp) + { + property* pf; + if ((pf = dynamic_cast*>(&exp))) + { + vector 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 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 diff --git a/postgis/resultset.hpp b/postgis/resultset.hpp new file mode 100644 index 000000000..9627ae1e7 --- /dev/null +++ b/postgis/resultset.hpp @@ -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_=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 + + + diff --git a/raster/raster_datasource.cpp b/raster/raster_datasource.cpp new file mode 100644 index 000000000..4c5c36cd4 --- /dev/null +++ b/raster/raster_datasource.cpp @@ -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(params.get("lox"),lox); + fromString(params.get("loy"),loy); + fromString(params.get("hix"),hix); + fromString(params.get("hiy"),hiy); + + extent_=Envelope(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& envelope) +{ + return true; +} + +const mapnik::Envelope& 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& box) const +{ + RasterInfo info(filename_,format_,extent_); + single_file_policy policy(info); //todo: handle different policies! + return featureset_ptr(new RasterFeatureset(policy,box,t)); +} + + +featureset_ptr raster_datasource::featuresAtPoint(const CoordTransform& t, + const coord2d& pt) const +{ + return featureset_ptr(0); +} diff --git a/raster/raster_datasource.hpp b/raster/raster_datasource.hpp new file mode 100644 index 000000000..865e932ba --- /dev/null +++ b/raster/raster_datasource.hpp @@ -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 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& box) const; + featureset_ptr featuresAtPoint(const CoordTransform& t,const coord2d& pt) const; + const mapnik::Envelope& envelope() const; +private: + //no copying + raster_datasource(const raster_datasource&); + raster_datasource& operator=(const raster_datasource&); + // + bool parseEnvelope(const std::string& str,Envelope& envelope); +}; + +#endif //RASTER_DATASOURCE_H diff --git a/raster/raster_featureset.cpp b/raster/raster_featureset.cpp new file mode 100644 index 000000000..2f245ca10 --- /dev/null +++ b/raster/raster_featureset.cpp @@ -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 +RasterFeatureset::RasterFeatureset(const LookupPolicy& policy, + const Envelope& box, + const CoordTransform& t) + : policy_(policy), + id_(1), + extent_(box), + t_(t), + curIter_(policy_.query(box)), + endIter_(policy_.end()) + +{} + +template +RasterFeatureset::~RasterFeatureset() {} + +template +Feature* RasterFeatureset::next() +{ + Feature* f=0; + if (curIter_!=endIter_) + { + try + { + std::cout<<"RasterFeatureset "<format()<<" "<file()< reader(get_image_reader(curIter_->format(),curIter_->file())); + std::cout<width(); + int image_height=reader->height(); + if (image_width>0 && image_height>0) + { + CoordTransform t(image_width,image_height,curIter_->envelope()); + Envelope intersect=extent_.intersect(curIter_->envelope()); + Envelope ext=t.forward(intersect); + + Envelope 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(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; +//template RasterFeatureset; diff --git a/raster/raster_featureset.hpp b/raster/raster_featureset.hpp new file mode 100644 index 000000000..09738d327 --- /dev/null +++ b/raster/raster_featureset.hpp @@ -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 + +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& box) + { + if (box.intersects(info_.envelope())) + { + return begin(); + } + return end(); + } + + const_iterator end() + { + return const_iterator(); + } +}; + +class os_name_policy +{ + //TODO +}; + +template +class RasterFeatureset : public Featureset +{ + typedef typename LookupPolicy::const_iterator iterator_type; + LookupPolicy policy_; + size_t id_; + Envelope extent_; + CoordTransform t_; + iterator_type curIter_; + iterator_type endIter_; +public: + RasterFeatureset(const LookupPolicy& policy,const Envelope& box,const CoordTransform& t); + virtual ~RasterFeatureset(); + Feature* next(); +}; + +#endif //RASTER_FEATURESET_HH diff --git a/raster/raster_info.cpp b/raster/raster_info.cpp new file mode 100644 index 000000000..c27a2f188 --- /dev/null +++ b/raster/raster_info.cpp @@ -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& 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& 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_; +} diff --git a/raster/raster_info.hpp b/raster/raster_info.hpp new file mode 100644 index 000000000..194d98333 --- /dev/null +++ b/raster/raster_info.hpp @@ -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 + +using mapnik::Envelope; + +class RasterInfo +{ + std::string file_; + std::string format_; + Envelope extent_; + int srid_; + public: + RasterInfo(const std::string& file,const std::string& format,const Envelope& extent,int srid=-1); + RasterInfo(const RasterInfo& rhs); + RasterInfo& operator=(const RasterInfo& rhs); + const Envelope& 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 diff --git a/shape/Jamfile b/shape/Jamfile new file mode 100644 index 000000000..34568bf41 --- /dev/null +++ b/shape/Jamfile @@ -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 + ; + diff --git a/shape/SConscript b/shape/SConscript new file mode 100644 index 000000000..d423b77df --- /dev/null +++ b/shape/SConscript @@ -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) diff --git a/shape/dbf_test.cpp b/shape/dbf_test.cpp new file mode 100644 index 000000000..96d78f9d0 --- /dev/null +++ b/shape/dbf_test.cpp @@ -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 +#include +#include "dbffile.hh" + +using namespace std; + +int main(int argc,char** argv) +{ + if (argc!=2) + { + cout<<"usage: dbfdump "< + +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=0 && col=0 && coladd_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;i0) + { + record_=static_cast(::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); +} diff --git a/shape/dbffile.hpp b/shape/dbffile.hpp new file mode 100644 index 000000000..370b5f5c3 --- /dev/null +++ b/shape/dbffile.hpp @@ -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 +#include +#include +#include + +#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 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 diff --git a/shape/shape.cpp b/shape/shape.cpp new file mode 100644 index 000000000..4cf6c5145 --- /dev/null +++ b/shape/shape.cpp @@ -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 +#include + +DATASOURCE_PLUGIN(shape_datasource); + +shape_datasource::shape_datasource(const Parameters ¶ms) + : 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< extent_; + bool indexed_; + static std::string name_; +public: + int type() const; + static std::string name(); + featureset_ptr features(const query& q) const; + const Envelope& envelope() const; + shape_datasource(const Parameters ¶ms); + virtual ~shape_datasource(); +private: + shape_datasource(const shape_datasource&); + shape_datasource& operator=(const shape_datasource&); + void init(shape_io& shape); +}; + +#endif //SHAPE_HH diff --git a/shape/shape_featureset.cpp b/shape/shape_featureset.cpp new file mode 100644 index 000000000..0be40169b --- /dev/null +++ b/shape/shape_featureset.cpp @@ -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 + +template +shape_featureset::shape_featureset(const filterT& filter, + const std::string& shape_file, + const std::set& 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::const_iterator pos=attribute_names.begin(); + while (pos!=attribute_names.end()) + { + for (int i=0;i +Feature* shape_featureset::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::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="< +shape_featureset::~shape_featureset() {} + +template class shape_featureset; diff --git a/shape/shape_featureset.hpp b/shape/shape_featureset.hpp new file mode 100644 index 000000000..1219080c7 --- /dev/null +++ b/shape/shape_featureset.hpp @@ -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 +class shape_featureset : public Featureset +{ + filterT filter_; + int shape_type_; + shape_io shape_; + Envelope query_ext_; + long file_length_; + std::vector attr_ids_; + mutable Envelope feature_ext_; + mutable int total_geom_size; + mutable int count_; +public: + shape_featureset(const filterT& filter, const std::string& shape_file, + const std::set& 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 diff --git a/shape/shape_index_featureset.cpp b/shape/shape_index_featureset.cpp new file mode 100644 index 000000000..d2263b7b2 --- /dev/null +++ b/shape/shape_index_featureset.cpp @@ -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 +shape_index_featureset::shape_index_featureset(const filterT& filter, + const std::string& shape_file, + const std::set& 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::query(filter,file,ids_); + file.close(); + } + std::cout<< "query size=" << ids_.size() << "\n"; + itr_ = ids_.begin(); + + // deal with attributes + std::set::const_iterator pos=attribute_names.begin(); + while (pos!=attribute_names.end()) + { + for (int i=0;i +Feature* shape_index_featureset::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::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< +shape_index_featureset::~shape_index_featureset() {} + +template class shape_index_featureset; + diff --git a/shape/shape_index_featureset.hpp b/shape/shape_index_featureset.hpp new file mode 100644 index 000000000..4d2790007 --- /dev/null +++ b/shape/shape_index_featureset.hpp @@ -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 +#include + +template +class shape_index_featureset : public Featureset +{ + filterT filter_; + int shape_type_; + shape_io shape_; + std::set ids_; + std::set::iterator itr_; + std::vector attr_ids_; + mutable Envelope 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& 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 diff --git a/shape/shape_io.cpp b/shape/shape_io.cpp new file mode 100644 index 000000000..343e66a72 --- /dev/null +++ b/shape/shape_io.cpp @@ -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& 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;iline_to(x,y); + } + } + else + { + std::vector parts(num_parts); + for (int i=0;imove_to(x,y); + + for (int j=start+1;jline_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;iline_to(x,y); + } + } + else + { + std::vector parts(num_parts); + for (int i=0;imove_to(x,y); + + for (int j=start+1;jline_to(x,y); + } + } + } + // m-range + //double m0=record.read_double(); + //double m1=record.read_double(); + + //for (int i=0;imove_to(x,y); + for (int i=1;iline_to(x,y); + } + } + else + { + std::vector parts(num_parts); + for (int i=0;imove_to(x,y); + + for (int j=start+1;jline_to(x,y); + } + } + } + // z-range + //double z0=record.read_double(); + //double z1=record.read_double(); + //for (int i=0;i parts(num_parts); + geometry_ptr poly(new polygon_impl(-1)); + + for (int i=0;imove_to(x,y); + + for (int j=start+1;jline_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 parts(num_parts); + geometry_ptr poly(new polygon_impl(-1)); + + for (int i=0;imove_to(x,y); + + for (int j=start+1;jline_to(x,y); + } + } + // m-range + //double m0=record.read_double(); + //double m1=record.read_double(); + + //for (int i=0;i parts(num_parts); + geometry_ptr poly(new polygon_impl(-1)); + + for (int i=0;imove_to(x,y); + + for (int j=start+1;jline_to(x,y); + } + } + // z-range + //double z0=record.read_double(); + //double z1=record.read_double(); + //for (int i=0;i 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& 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 diff --git a/shape/shapefile.cpp b/shape/shapefile.cpp new file mode 100644 index 000000000..43d73820b --- /dev/null +++ b/shape/shapefile.cpp @@ -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(); +} + + + diff --git a/shape/shapefile.hpp b/shape/shapefile.hpp new file mode 100644 index 000000000..bc8f1c642 --- /dev/null +++ b/shape/shapefile.hpp @@ -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 + +using namespace mapnik; + +struct shape_record +{ + char* data; + size_t size; + size_t pos; + explicit shape_record(size_t size) + : data(static_cast(::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(&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& envelope) + { +#ifndef WORDS_BIGENDIAN + file_.read(reinterpret_cast(&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 diff --git a/shape/shp_index.cpp b/shape/shp_index.cpp new file mode 100644 index 000000000..9b89c111c --- /dev/null +++ b/shape/shp_index.cpp @@ -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 +void shp_index::query(const filterT& filter,std::ifstream& file,std::set& pos) +{ + file.seekg(16,std::ios::beg); + query_node(filter,file,pos); +} + + +template +void shp_index::query_node(const filterT& filter,std::ifstream& file,std::set& ids) +{ + int offset=read_ndr_integer(file); + + Envelope 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 +int shp_index::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 +void shp_index::read_envelope(std::ifstream& file,Envelope& envelope) +{ + file.read(reinterpret_cast(&envelope),sizeof(envelope)); +} + +template class shp_index; +template class shp_index; diff --git a/shape/shp_index.hpp b/shape/shp_index.hpp new file mode 100644 index 000000000..675284d06 --- /dev/null +++ b/shape/shp_index.hpp @@ -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 +#include + +using namespace mapnik; + +template +class shp_index +{ +public: + static void query(const filterT& filter,std::ifstream& file,std::set& 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 &envelope); + static void query_node(const filterT& filter,std::ifstream& file,std::set& pos); +}; + +#endif //SHP_INDEX_HH