Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

initial import

  • Loading branch information...
commit ebcdd3cf90736330c05d7876c07a0a79200a5ad8 0 parents
@artemp artemp authored
Showing with 3,163 additions and 0 deletions.
  1. +18 −0 postgis/Jamfile
  2. +24 −0 postgis/SConscript
  3. +85 −0 postgis/connection.hpp
  4. +111 −0 postgis/connection_manager.hpp
  5. +214 −0 postgis/postgis.cpp
  6. +79 −0 postgis/postgis.hpp
  7. +92 −0 postgis/postgisfs.cpp
  8. +71 −0 postgis/property_index.hpp
  9. +138 −0 postgis/resultset.hpp
  10. +91 −0 raster/raster_datasource.cpp
  11. +53 −0 raster/raster_datasource.hpp
  12. +81 −0 raster/raster_featureset.cpp
  13. +115 −0 raster/raster_featureset.hpp
  14. +71 −0 raster/raster_info.cpp
  15. +46 −0 raster/raster_info.hpp
  16. +11 −0 shape/Jamfile
  17. +26 −0 shape/SConscript
  18. +60 −0 shape/dbf_test.cpp
  19. +216 −0 shape/dbffile.cpp
  20. +73 −0 shape/dbffile.hpp
  21. +113 −0 shape/shape.cpp
  22. +48 −0 shape/shape.hpp
  23. +180 −0 shape/shape_featureset.cpp
  24. +48 −0 shape/shape_featureset.hpp
  25. +182 −0 shape/shape_index_featureset.cpp
  26. +49 −0 shape/shape_index_featureset.hpp
  27. +414 −0 shape/shape_io.cpp
  28. +82 −0 shape/shape_io.hpp
  29. +58 −0 shape/shapefile.cpp
  30. +195 −0 shape/shapefile.hpp
  31. +76 −0 shape/shp_index.cpp
  32. +43 −0 shape/shp_index.hpp
18 postgis/Jamfile
@@ -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
@@ -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
@@ -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
111 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 <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
@@ -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
@@ -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
@@ -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();
+}
71 postgis/property_index.hpp
@@ -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
@@ -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
+
+
+
91 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<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);
+}
53 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<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
81 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 <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>;
115 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 <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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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>;
48 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 <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
182 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 <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>;
+
49 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 <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
@@ -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);