use memory mapped files for reading shape files
This commit is contained in:
parent
57cb2edef1
commit
a8859645b3
14 changed files with 307 additions and 331 deletions
|
@ -162,6 +162,7 @@ BOOST_LIBSHEADERS = [
|
||||||
# ['system', 'boost/system/system_error.hpp', True], # uncomment this on Darwin + boost_1_35
|
# ['system', 'boost/system/system_error.hpp', True], # uncomment this on Darwin + boost_1_35
|
||||||
['filesystem', 'boost/filesystem/operations.hpp', True],
|
['filesystem', 'boost/filesystem/operations.hpp', True],
|
||||||
['regex', 'boost/regex.hpp', True],
|
['regex', 'boost/regex.hpp', True],
|
||||||
|
['iostreams','boost/iostreams/device/mapped_file.hpp',True],
|
||||||
['program_options', 'boost/program_options.hpp', False]
|
['program_options', 'boost/program_options.hpp', False]
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
|
@ -33,11 +33,17 @@ shape_src = Split(
|
||||||
shapefile.cpp
|
shapefile.cpp
|
||||||
shape_index_featureset.cpp
|
shape_index_featureset.cpp
|
||||||
shape_io.cpp
|
shape_io.cpp
|
||||||
shp_index.cpp
|
|
||||||
"""
|
"""
|
||||||
)
|
)
|
||||||
|
thread_suffix = '-mt'
|
||||||
libraries = []
|
if env['PLATFORM'] == 'FreeBSD':
|
||||||
|
thread_suffix = ''
|
||||||
|
|
||||||
|
if env['THREADING'] == 'multi':
|
||||||
|
libraries = ['boost_iostreams%s%s' % (env['BOOST_APPEND'],thread_suffix) ]
|
||||||
|
else:
|
||||||
|
libraries = ['boost_iostreams%s' % (env['BOOST_APPEND']) ]
|
||||||
|
|
||||||
if env['PLATFORM'] == 'Darwin':
|
if env['PLATFORM'] == 'Darwin':
|
||||||
libraries.append('mapnik')
|
libraries.append('mapnik')
|
||||||
libraries.append('iconv')
|
libraries.append('iconv')
|
||||||
|
|
|
@ -35,13 +35,13 @@ dbf_file::dbf_file()
|
||||||
record_length_(0),
|
record_length_(0),
|
||||||
record_(0) {}
|
record_(0) {}
|
||||||
|
|
||||||
dbf_file::dbf_file(const char* file_name)
|
dbf_file::dbf_file(std::string const& file_name)
|
||||||
:num_records_(0),
|
:num_records_(0),
|
||||||
num_fields_(0),
|
num_fields_(0),
|
||||||
record_length_(0),
|
record_length_(0),
|
||||||
|
file_(file_name),
|
||||||
record_(0)
|
record_(0)
|
||||||
{
|
{
|
||||||
file_.open(file_name);
|
|
||||||
if (file_.is_open())
|
if (file_.is_open())
|
||||||
{
|
{
|
||||||
read_header();
|
read_header();
|
||||||
|
@ -52,16 +52,6 @@ dbf_file::dbf_file(const char* file_name)
|
||||||
dbf_file::~dbf_file()
|
dbf_file::~dbf_file()
|
||||||
{
|
{
|
||||||
::operator delete(record_);
|
::operator delete(record_);
|
||||||
file_.close();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bool dbf_file::open(const std::string& file_name)
|
|
||||||
{
|
|
||||||
file_.open(file_name.c_str(),std::ios::in|std::ios::binary);
|
|
||||||
if (file_.is_open())
|
|
||||||
read_header();
|
|
||||||
return file_?true:false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -23,12 +23,16 @@
|
||||||
#ifndef DBFFILE_HPP
|
#ifndef DBFFILE_HPP
|
||||||
#define DBFFILE_HPP
|
#define DBFFILE_HPP
|
||||||
|
|
||||||
|
#include <mapnik/feature.hpp>
|
||||||
|
// boost
|
||||||
|
#include <boost/iostreams/stream.hpp>
|
||||||
|
#include <boost/iostreams/device/file.hpp>
|
||||||
|
#include <boost/iostreams/device/mapped_file.hpp>
|
||||||
|
// stl
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <fstream>
|
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
|
|
||||||
#include <mapnik/feature.hpp>
|
|
||||||
|
|
||||||
using mapnik::transcoder;
|
using mapnik::transcoder;
|
||||||
using mapnik::Feature;
|
using mapnik::Feature;
|
||||||
|
@ -44,37 +48,36 @@ struct field_descriptor
|
||||||
int offset_;
|
int offset_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
using namespace boost::iostreams;
|
||||||
|
|
||||||
class dbf_file
|
class dbf_file
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
|
int num_records_;
|
||||||
int num_records_;
|
int num_fields_;
|
||||||
int num_fields_;
|
int record_length_;
|
||||||
int record_length_;
|
std::vector<field_descriptor> fields_;
|
||||||
std::vector<field_descriptor> fields_;
|
stream<mapped_file_source> file_;
|
||||||
std::ifstream file_;
|
char* record_;
|
||||||
char* record_;
|
|
||||||
public:
|
public:
|
||||||
dbf_file();
|
dbf_file();
|
||||||
dbf_file(const char* file_name);
|
dbf_file(const std::string& file_name);
|
||||||
dbf_file(const std::string& file_name);
|
~dbf_file();
|
||||||
~dbf_file();
|
bool is_open();
|
||||||
bool open(const std::string& file_name);
|
void close();
|
||||||
bool is_open();
|
int num_records() const;
|
||||||
void close();
|
int num_fields() const;
|
||||||
int num_records() const;
|
field_descriptor const& descriptor(int col) const;
|
||||||
int num_fields() const;
|
void move_to(int index);
|
||||||
field_descriptor const& descriptor(int col) const;
|
std::string string_value(int col) const;
|
||||||
void move_to(int index);
|
void add_attribute(int col, transcoder const& tr, Feature const& f) const throw();
|
||||||
std::string string_value(int col) const;
|
private:
|
||||||
void add_attribute(int col, transcoder const& tr, Feature const& f) const throw();
|
dbf_file(const dbf_file&);
|
||||||
private:
|
dbf_file& operator=(const dbf_file&);
|
||||||
dbf_file(const dbf_file&);
|
void read_header();
|
||||||
dbf_file& operator=(const dbf_file&);
|
int read_short();
|
||||||
void read_header();
|
int read_int();
|
||||||
int read_short();
|
void skip(int bytes);
|
||||||
int read_int();
|
|
||||||
void skip(int bytes);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif //DBFFILE_HPP
|
#endif //DBFFILE_HPP
|
||||||
|
|
|
@ -23,8 +23,15 @@
|
||||||
//$Id: shape_index_featureset.cc 36 2005-04-05 14:32:18Z pavlenko $
|
//$Id: shape_index_featureset.cc 36 2005-04-05 14:32:18Z pavlenko $
|
||||||
|
|
||||||
#include <mapnik/feature_factory.hpp>
|
#include <mapnik/feature_factory.hpp>
|
||||||
|
// boost
|
||||||
|
#include <boost/iostreams/stream.hpp>
|
||||||
|
#include <boost/iostreams/device/file.hpp>
|
||||||
|
#include <boost/iostreams/device/mapped_file.hpp>
|
||||||
|
|
||||||
#include "shape_index_featureset.hpp"
|
#include "shape_index_featureset.hpp"
|
||||||
|
|
||||||
|
using namespace boost::iostreams;
|
||||||
|
|
||||||
template <typename filterT>
|
template <typename filterT>
|
||||||
shape_index_featureset<filterT>::shape_index_featureset(const filterT& filter,
|
shape_index_featureset<filterT>::shape_index_featureset(const filterT& filter,
|
||||||
const std::string& shape_file,
|
const std::string& shape_file,
|
||||||
|
@ -38,17 +45,17 @@ shape_index_featureset<filterT>::shape_index_featureset(const filterT& filter,
|
||||||
|
|
||||||
{
|
{
|
||||||
shape_.shp().skip(100);
|
shape_.shp().skip(100);
|
||||||
std::string indexname(shape_file + ".index");
|
stream<mapped_file_source> file(shape_file + ".index");
|
||||||
std::ifstream file(indexname.c_str(),std::ios::in|std::ios::binary);
|
|
||||||
if (file)
|
if (file)
|
||||||
{
|
{
|
||||||
shp_index<filterT>::query(filter,file,ids_);
|
shp_index<filterT,stream<mapped_file_source> >::query(filter,file,ids_);
|
||||||
file.close();
|
file.close();
|
||||||
}
|
}
|
||||||
|
std::sort(ids_.begin(),ids_.end());
|
||||||
#ifdef MAPNIK_DEBUG
|
|
||||||
|
//#ifdef MAPNIK_DEBUG
|
||||||
std::clog<< "query size=" << ids_.size() << "\n";
|
std::clog<< "query size=" << ids_.size() << "\n";
|
||||||
#endif
|
//#endif
|
||||||
|
|
||||||
itr_ = ids_.begin();
|
itr_ = ids_.begin();
|
||||||
|
|
||||||
|
@ -60,7 +67,7 @@ shape_index_featureset<filterT>::shape_index_featureset(const filterT& filter,
|
||||||
{
|
{
|
||||||
if (shape_.dbf().descriptor(i).name_ == *pos)
|
if (shape_.dbf().descriptor(i).name_ == *pos)
|
||||||
{
|
{
|
||||||
attr_ids_.push_back(i);
|
attr_ids_.insert(i);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -170,7 +177,7 @@ feature_ptr shape_index_featureset<filterT>::next()
|
||||||
if (attr_ids_.size())
|
if (attr_ids_.size())
|
||||||
{
|
{
|
||||||
shape_.dbf().move_to(shape_.id_);
|
shape_.dbf().move_to(shape_.id_);
|
||||||
std::vector<int>::const_iterator pos=attr_ids_.begin();
|
std::set<int>::const_iterator pos=attr_ids_.begin();
|
||||||
while (pos!=attr_ids_.end())
|
while (pos!=attr_ids_.end())
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
|
|
|
@ -35,9 +35,9 @@ class shape_index_featureset : public Featureset
|
||||||
int shape_type_;
|
int shape_type_;
|
||||||
shape_io shape_;
|
shape_io shape_;
|
||||||
boost::scoped_ptr<transcoder> tr_;
|
boost::scoped_ptr<transcoder> tr_;
|
||||||
std::set<int> ids_;
|
std::vector<int> ids_;
|
||||||
std::set<int>::iterator itr_;
|
std::vector<int>::iterator itr_;
|
||||||
std::vector<int> attr_ids_;
|
std::set<int> attr_ids_;
|
||||||
mutable Envelope<double> feature_ext_;
|
mutable Envelope<double> feature_ext_;
|
||||||
mutable int total_geom_size;
|
mutable int total_geom_size;
|
||||||
mutable int count_;
|
mutable int count_;
|
||||||
|
|
|
@ -32,11 +32,12 @@ const std::string shape_io::DBF = ".dbf";
|
||||||
|
|
||||||
shape_io::shape_io(const std::string& shape_name)
|
shape_io::shape_io(const std::string& shape_name)
|
||||||
: type_(shape_null),
|
: type_(shape_null),
|
||||||
|
shp_(shape_name + SHP),
|
||||||
|
dbf_(shape_name + DBF),
|
||||||
reclength_(0),
|
reclength_(0),
|
||||||
id_(0)
|
id_(0)
|
||||||
{
|
{
|
||||||
bool ok = (shp_.open(shape_name + SHP) &&
|
bool ok = (shp_.is_open() && dbf_.is_open());
|
||||||
dbf_.open(shape_name + DBF));
|
|
||||||
if (!ok)
|
if (!ok)
|
||||||
{
|
{
|
||||||
throw datasource_exception("cannot read shape file");
|
throw datasource_exception("cannot read shape file");
|
||||||
|
@ -49,7 +50,6 @@ shape_io::~shape_io()
|
||||||
dbf_.close();
|
dbf_.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void shape_io::move_to (int pos)
|
void shape_io::move_to (int pos)
|
||||||
{
|
{
|
||||||
shp_.seek(pos);
|
shp_.seek(pos);
|
||||||
|
@ -57,6 +57,12 @@ void shape_io::move_to (int pos)
|
||||||
reclength_ = shp_.read_xdr_integer();
|
reclength_ = shp_.read_xdr_integer();
|
||||||
type_ = shp_.read_ndr_integer();
|
type_ = shp_.read_ndr_integer();
|
||||||
|
|
||||||
|
if (shp_.is_eof()) {
|
||||||
|
id_ = 0;
|
||||||
|
reclength_ = 0;
|
||||||
|
type_ = shape_null;
|
||||||
|
}
|
||||||
|
|
||||||
if (type_ != shape_point && type_ != shape_pointm && type_ != shape_pointz)
|
if (type_ != shape_point && type_ != shape_pointm && type_ != shape_pointz)
|
||||||
{
|
{
|
||||||
shp_.read_envelope(cur_extent_);
|
shp_.read_envelope(cur_extent_);
|
||||||
|
|
|
@ -31,36 +31,36 @@ using mapnik::geometry2d;
|
||||||
|
|
||||||
struct shape_io
|
struct shape_io
|
||||||
{
|
{
|
||||||
static const std::string SHP;
|
static const std::string SHP;
|
||||||
static const std::string SHX;
|
static const std::string SHX;
|
||||||
static const std::string DBF;
|
static const std::string DBF;
|
||||||
|
unsigned type_;
|
||||||
|
shape_file shp_;
|
||||||
|
shape_file shx_;
|
||||||
|
dbf_file dbf_;
|
||||||
|
|
||||||
|
unsigned reclength_;
|
||||||
|
unsigned id_;
|
||||||
|
Envelope<double> cur_extent_;
|
||||||
|
|
||||||
shape_file shp_;
|
public:
|
||||||
shape_file shx_;
|
enum shapeType
|
||||||
dbf_file dbf_;
|
{
|
||||||
unsigned type_;
|
shape_null = 0,
|
||||||
unsigned reclength_;
|
shape_point = 1,
|
||||||
unsigned id_;
|
shape_polyline = 3,
|
||||||
Envelope<double> cur_extent_;
|
shape_polygon = 5,
|
||||||
|
shape_multipoint = 8,
|
||||||
public:
|
shape_pointz = 11,
|
||||||
enum shapeType
|
shape_polylinez = 13,
|
||||||
{
|
shape_polygonz = 15,
|
||||||
shape_null = 0,
|
shape_multipointz = 18,
|
||||||
shape_point = 1,
|
shape_pointm = 21,
|
||||||
shape_polyline = 3,
|
shape_polylinem = 23,
|
||||||
shape_polygon = 5,
|
shape_polygonm = 25,
|
||||||
shape_multipoint = 8,
|
shape_multipointm = 28,
|
||||||
shape_pointz = 11,
|
shape_multipatch = 31
|
||||||
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(const std::string& shape_name);
|
||||||
~shape_io();
|
~shape_io();
|
||||||
|
|
|
@ -25,25 +25,9 @@
|
||||||
shape_file::shape_file() {}
|
shape_file::shape_file() {}
|
||||||
|
|
||||||
shape_file::shape_file(const std::string& file_name)
|
shape_file::shape_file(const std::string& file_name)
|
||||||
{
|
: file_(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;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
shape_file::~shape_file() {}
|
||||||
|
|
||||||
bool shape_file::is_open()
|
bool shape_file::is_open()
|
||||||
{
|
{
|
||||||
|
|
|
@ -20,64 +20,66 @@
|
||||||
*
|
*
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
||||||
//$Id: shapefile.hh 33 2005-04-04 13:01:03Z pavlenko $
|
//$Id: shapefile.hpp 33 2005-04-04 13:01:03Z pavlenko $
|
||||||
|
|
||||||
#ifndef SHAPEFILE_HPP
|
#ifndef SHAPEFILE_HPP
|
||||||
#define SHAPEFILE_HPP
|
#define SHAPEFILE_HPP
|
||||||
|
|
||||||
#include <fstream>
|
|
||||||
|
|
||||||
#include <mapnik/envelope.hpp>
|
#include <mapnik/envelope.hpp>
|
||||||
|
// boost
|
||||||
|
#include <boost/utility.hpp>
|
||||||
|
#include <boost/iostreams/stream.hpp>
|
||||||
|
#include <boost/iostreams/device/file.hpp>
|
||||||
|
#include <boost/iostreams/device/mapped_file.hpp>
|
||||||
|
|
||||||
using mapnik::Envelope;
|
using mapnik::Envelope;
|
||||||
|
|
||||||
struct shape_record
|
struct shape_record
|
||||||
{
|
{
|
||||||
char* data;
|
const char* data;
|
||||||
size_t size;
|
size_t size;
|
||||||
size_t pos;
|
mutable size_t pos;
|
||||||
explicit shape_record(size_t size)
|
explicit shape_record(size_t size)
|
||||||
: data(static_cast<char*>(::operator new(sizeof(char)*size))),
|
: size(size),
|
||||||
size(size),
|
pos(0) {}
|
||||||
pos(0) {}
|
|
||||||
|
void set_data(const char * data_)
|
||||||
char* rawdata()
|
{
|
||||||
{
|
data = data_;
|
||||||
return &data[0];
|
}
|
||||||
}
|
|
||||||
|
void skip(unsigned n)
|
||||||
void skip(unsigned n)
|
{
|
||||||
{
|
pos+=n;
|
||||||
pos+=n;
|
}
|
||||||
}
|
|
||||||
|
int read_ndr_integer()
|
||||||
int read_ndr_integer()
|
{
|
||||||
{
|
int val=(data[pos] & 0xff) |
|
||||||
int val=(data[pos] & 0xff) |
|
|
||||||
(data[pos+1] & 0xff) << 8 |
|
(data[pos+1] & 0xff) << 8 |
|
||||||
(data[pos+2] & 0xff) << 16 |
|
(data[pos+2] & 0xff) << 16 |
|
||||||
(data[pos+3] & 0xff) << 24;
|
(data[pos+3] & 0xff) << 24;
|
||||||
pos+=4;
|
pos+=4;
|
||||||
return val;
|
return val;
|
||||||
}
|
}
|
||||||
|
|
||||||
int read_xdr_integer()
|
int read_xdr_integer()
|
||||||
{
|
{
|
||||||
int val=(data[pos] & 0xff) << 24 |
|
int val=(data[pos] & 0xff) << 24 |
|
||||||
(data[pos+1] & 0xff) << 16 |
|
(data[pos+1] & 0xff) << 16 |
|
||||||
(data[pos+2] & 0xff) << 8 |
|
(data[pos+2] & 0xff) << 8 |
|
||||||
(data[pos+3] & 0xff);
|
(data[pos+3] & 0xff);
|
||||||
pos+=4;
|
pos+=4;
|
||||||
return val;
|
return val;
|
||||||
}
|
}
|
||||||
|
|
||||||
double read_double()
|
double read_double()
|
||||||
{
|
{
|
||||||
double val;
|
double val;
|
||||||
#ifndef WORDS_BIGENDIAN
|
#ifndef WORDS_BIGENDIAN
|
||||||
std::memcpy(&val,&data[pos],8);
|
std::memcpy(&val,&data[pos],8);
|
||||||
#else
|
#else
|
||||||
long long bits = ((long long)data[pos] & 0xff) |
|
long long bits = ((long long)data[pos] & 0xff) |
|
||||||
((long long)data[pos+1] & 0xff) << 8 |
|
((long long)data[pos+1] & 0xff) << 8 |
|
||||||
((long long)data[pos+2] & 0xff) << 16 |
|
((long long)data[pos+2] & 0xff) << 16 |
|
||||||
((long long)data[pos+3] & 0xff) << 24 |
|
((long long)data[pos+3] & 0xff) << 24 |
|
||||||
|
@ -85,64 +87,62 @@ struct shape_record
|
||||||
((long long)data[pos+5] & 0xff) << 40 |
|
((long long)data[pos+5] & 0xff) << 40 |
|
||||||
((long long)data[pos+6] & 0xff) << 48 |
|
((long long)data[pos+6] & 0xff) << 48 |
|
||||||
((long long)data[pos+7] & 0xff) << 56 ;
|
((long long)data[pos+7] & 0xff) << 56 ;
|
||||||
std::memcpy(&val,&bits,8);
|
std::memcpy(&val,&bits,8);
|
||||||
#endif
|
#endif
|
||||||
pos+=8;
|
pos+=8;
|
||||||
return val;
|
return val;
|
||||||
}
|
}
|
||||||
long remains()
|
long remains()
|
||||||
{
|
{
|
||||||
return (size-pos);
|
return (size-pos);
|
||||||
}
|
}
|
||||||
~shape_record()
|
~shape_record() {}
|
||||||
{
|
|
||||||
::operator delete(data);
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class shape_file
|
using namespace boost::iostreams;
|
||||||
|
|
||||||
|
class shape_file : boost::noncopyable
|
||||||
{
|
{
|
||||||
std::ifstream file_;
|
stream<mapped_file_source> file_;
|
||||||
//static const int buffer_size = 16;
|
public:
|
||||||
//char buff_[buffer_size];
|
shape_file();
|
||||||
public:
|
shape_file(const std::string& file_name);
|
||||||
shape_file();
|
~shape_file();
|
||||||
shape_file(const std::string& file_name);
|
bool is_open();
|
||||||
~shape_file();
|
void close();
|
||||||
bool open(const std::string& file_name);
|
|
||||||
bool is_open();
|
inline void read_record(shape_record& rec)
|
||||||
void close();
|
{
|
||||||
|
rec.set_data(file_->data() + file_.tellg());
|
||||||
inline void read_record(shape_record& rec)
|
file_.seekg(rec.size,std::ios::cur);
|
||||||
{
|
}
|
||||||
file_.read(rec.rawdata(),rec.size);
|
|
||||||
}
|
inline int read_xdr_integer()
|
||||||
|
{
|
||||||
inline int read_xdr_integer()
|
char b[4];
|
||||||
{
|
file_.read(b, 4);
|
||||||
char b[4];
|
return b[3] & 0xffu | (b[2] & 0xffu) << 8 |
|
||||||
file_.read(b, 4);
|
|
||||||
return b[3] & 0xffu | (b[2] & 0xffu) << 8 |
|
|
||||||
(b[1] & 0xffu) << 16 | (b[0] & 0xffu) << 24;
|
(b[1] & 0xffu) << 16 | (b[0] & 0xffu) << 24;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline int read_ndr_integer()
|
inline int read_ndr_integer()
|
||||||
{
|
{
|
||||||
char b[4];
|
char b[4];
|
||||||
file_.read(b,4);
|
file_.read(b,4);
|
||||||
return b[0]&0xffu | (b[1]&0xffu) << 8 |
|
return b[0]&0xffu | (b[1]&0xffu) << 8 |
|
||||||
(b[2]&0xffu) << 16 | (b[3]&0xffu) << 24;
|
(b[2]&0xffu) << 16 | (b[3]&0xffu) << 24;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline double read_double()
|
inline double read_double()
|
||||||
{
|
{
|
||||||
double val;
|
double val;
|
||||||
#ifndef WORDS_BIGENDIAN
|
#ifndef WORDS_BIGENDIAN
|
||||||
file_.read(reinterpret_cast<char*>(&val),8);
|
file_.read(reinterpret_cast<char*>(&val),8);
|
||||||
#else
|
#else
|
||||||
char b[8];
|
char b[8];
|
||||||
file_.read(b,8);
|
file_.read(b,8);
|
||||||
long long bits = ((long long)b[0] & 0xff) |
|
long long bits = ((long long)b[0] & 0xff) |
|
||||||
((long long)b[1] & 0xff) << 8 |
|
((long long)b[1] & 0xff) << 8 |
|
||||||
((long long)b[2] & 0xff) << 16 |
|
((long long)b[2] & 0xff) << 16 |
|
||||||
((long long)b[3] & 0xff) << 24 |
|
((long long)b[3] & 0xff) << 24 |
|
||||||
|
@ -150,52 +150,48 @@ public:
|
||||||
((long long)b[5] & 0xff) << 40 |
|
((long long)b[5] & 0xff) << 40 |
|
||||||
((long long)b[6] & 0xff) << 48 |
|
((long long)b[6] & 0xff) << 48 |
|
||||||
((long long)b[7] & 0xff) << 56 ;
|
((long long)b[7] & 0xff) << 56 ;
|
||||||
memcpy(&val,&bits,8);
|
memcpy(&val,&bits,8);
|
||||||
#endif
|
#endif
|
||||||
return val;
|
return val;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void read_envelope(Envelope<double>& envelope)
|
inline void read_envelope(Envelope<double>& envelope)
|
||||||
{
|
{
|
||||||
#ifndef WORDS_BIGENDIAN
|
#ifndef WORDS_BIGENDIAN
|
||||||
file_.read(reinterpret_cast<char*>(&envelope),sizeof(envelope));
|
file_.read(reinterpret_cast<char*>(&envelope),sizeof(envelope));
|
||||||
#else
|
#else
|
||||||
double minx=read_double();
|
double minx=read_double();
|
||||||
double miny=read_double();
|
double miny=read_double();
|
||||||
double maxx=read_double();
|
double maxx=read_double();
|
||||||
double maxy=read_double();
|
double maxy=read_double();
|
||||||
envelope.init(minx,miny,maxx,maxy);
|
envelope.init(minx,miny,maxx,maxy);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void skip(std::streampos bytes)
|
inline void skip(std::streampos bytes)
|
||||||
{
|
{
|
||||||
file_.seekg(bytes,std::ios::cur);
|
file_.seekg(bytes,std::ios::cur);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void rewind()
|
inline void rewind()
|
||||||
{
|
{
|
||||||
seek(100);
|
seek(100);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void seek(std::streampos pos)
|
inline void seek(std::streampos pos)
|
||||||
{
|
{
|
||||||
file_.seekg(pos,std::ios::beg);
|
file_.seekg(pos,std::ios::beg);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline std::streampos pos()
|
inline std::streampos pos()
|
||||||
{
|
{
|
||||||
return file_.tellg();
|
return file_.tellg();
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool is_eof()
|
inline bool is_eof()
|
||||||
{
|
{
|
||||||
return file_.eof();
|
return file_.eof();
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
|
||||||
shape_file(const shape_file&);
|
|
||||||
shape_file& operator=(const shape_file&);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif //SHAPEFILE_HPP
|
#endif //SHAPEFILE_HPP
|
||||||
|
|
|
@ -1,80 +0,0 @@
|
||||||
/*****************************************************************************
|
|
||||||
*
|
|
||||||
* This file is part of Mapnik (c++ mapping toolkit)
|
|
||||||
*
|
|
||||||
* Copyright (C) 2006 Artem Pavlenko
|
|
||||||
*
|
|
||||||
* This library is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU Lesser General Public
|
|
||||||
* License as published by the Free Software Foundation; either
|
|
||||||
* version 2.1 of the License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This library is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
* Lesser General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public
|
|
||||||
* License along with this library; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|
||||||
*
|
|
||||||
*****************************************************************************/
|
|
||||||
#include <mapnik/geom_util.hpp>
|
|
||||||
#include "shp_index.hpp"
|
|
||||||
|
|
||||||
template <typename filterT>
|
|
||||||
void shp_index<filterT>::query(const filterT& filter,std::ifstream& file,std::set<int>& pos)
|
|
||||||
{
|
|
||||||
file.seekg(16,std::ios::beg);
|
|
||||||
query_node(filter,file,pos);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
template <typename filterT>
|
|
||||||
void shp_index<filterT>::query_node(const filterT& filter,std::ifstream& file,std::set<int>& ids)
|
|
||||||
{
|
|
||||||
int offset=read_ndr_integer(file);
|
|
||||||
|
|
||||||
Envelope<double> node_ext;
|
|
||||||
read_envelope(file,node_ext);
|
|
||||||
|
|
||||||
int num_shapes=read_ndr_integer(file);
|
|
||||||
|
|
||||||
if (!filter.pass(node_ext))
|
|
||||||
{
|
|
||||||
file.seekg(offset+num_shapes*4+4,std::ios::cur);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i=0;i<num_shapes;++i)
|
|
||||||
{
|
|
||||||
int id=read_ndr_integer(file);
|
|
||||||
ids.insert(id);
|
|
||||||
}
|
|
||||||
|
|
||||||
int children=read_ndr_integer(file);
|
|
||||||
|
|
||||||
for (int j=0;j<children;++j)
|
|
||||||
{
|
|
||||||
query_node(filter,file,ids);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
template <typename filterT>
|
|
||||||
int shp_index<filterT>::read_ndr_integer(std::ifstream& file)
|
|
||||||
{
|
|
||||||
char b[4];
|
|
||||||
file.read(b,4);
|
|
||||||
return (b[0]&0xff) | (b[1]&0xff)<<8 | (b[2]&0xff)<<16 | (b[3]&0xff)<<24;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
template <typename filterT>
|
|
||||||
void shp_index<filterT>::read_envelope(std::ifstream& file,Envelope<double>& envelope)
|
|
||||||
{
|
|
||||||
file.read(reinterpret_cast<char*>(&envelope),sizeof(envelope));
|
|
||||||
}
|
|
||||||
|
|
||||||
template class shp_index<mapnik::filter_in_box>;
|
|
||||||
template class shp_index<mapnik::filter_at_point>;
|
|
|
@ -25,7 +25,7 @@
|
||||||
|
|
||||||
// st
|
// st
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <set>
|
#include <vector>
|
||||||
// mapnik
|
// mapnik
|
||||||
#include <mapnik/envelope.hpp>
|
#include <mapnik/envelope.hpp>
|
||||||
#include <mapnik/query.hpp>
|
#include <mapnik/query.hpp>
|
||||||
|
@ -33,19 +33,73 @@
|
||||||
using mapnik::Envelope;
|
using mapnik::Envelope;
|
||||||
using mapnik::query;
|
using mapnik::query;
|
||||||
|
|
||||||
template <typename filterT>
|
template <typename filterT, typename IStream = std::ifstream>
|
||||||
class shp_index
|
class shp_index
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
static void query(const filterT& filter,std::ifstream& file,std::set<int>& pos);
|
static void query(const filterT& filter, IStream& file,std::vector<int>& pos);
|
||||||
private:
|
private:
|
||||||
shp_index();
|
shp_index();
|
||||||
~shp_index();
|
~shp_index();
|
||||||
shp_index(const shp_index&);
|
shp_index(const shp_index&);
|
||||||
shp_index& operator=(const shp_index&);
|
shp_index& operator=(const shp_index&);
|
||||||
static int read_ndr_integer(std::ifstream& in);
|
static int read_ndr_integer(IStream & in);
|
||||||
static void read_envelope(std::ifstream& in,Envelope<double> &envelope);
|
static void read_envelope(IStream & in,Envelope<double> &envelope);
|
||||||
static void query_node(const filterT& filter,std::ifstream& file,std::set<int>& pos);
|
static void query_node(const filterT& filter,IStream & in,std::vector<int>& pos);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template <typename filterT,typename IStream>
|
||||||
|
void shp_index<filterT, IStream>::query(const filterT& filter,IStream & file,std::vector<int>& pos)
|
||||||
|
{
|
||||||
|
file.seekg(16,std::ios::beg);
|
||||||
|
query_node(filter,file,pos);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename filterT, typename IStream>
|
||||||
|
void shp_index<filterT,IStream>::query_node(const filterT& filter,IStream & file,std::vector<int>& ids)
|
||||||
|
{
|
||||||
|
int offset=read_ndr_integer(file);
|
||||||
|
|
||||||
|
Envelope<double> node_ext;
|
||||||
|
read_envelope(file,node_ext);
|
||||||
|
|
||||||
|
int num_shapes=read_ndr_integer(file);
|
||||||
|
|
||||||
|
if (!filter.pass(node_ext))
|
||||||
|
{
|
||||||
|
file.seekg(offset+num_shapes*4+4,std::ios::cur);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i=0;i<num_shapes;++i)
|
||||||
|
{
|
||||||
|
int id=read_ndr_integer(file);
|
||||||
|
ids.push_back(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
int children=read_ndr_integer(file);
|
||||||
|
|
||||||
|
for (int j=0;j<children;++j)
|
||||||
|
{
|
||||||
|
query_node(filter,file,ids);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template <typename filterT,typename IStream>
|
||||||
|
int shp_index<filterT,IStream>::read_ndr_integer(IStream & file)
|
||||||
|
{
|
||||||
|
char b[4];
|
||||||
|
file.read(b,4);
|
||||||
|
return (b[0]&0xff) | (b[1]&0xff)<<8 | (b[2]&0xff)<<16 | (b[3]&0xff)<<24;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template <typename filterT,typename IStream>
|
||||||
|
void shp_index<filterT,IStream>::read_envelope(IStream & file,Envelope<double>& envelope)
|
||||||
|
{
|
||||||
|
file.read(reinterpret_cast<char*>(&envelope),sizeof(envelope));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#endif //SHP_INDEX_HH
|
#endif //SHP_INDEX_HH
|
||||||
|
|
|
@ -42,9 +42,13 @@ source = Split(
|
||||||
headers = ['#plugins/input/shape'] + env['CPPPATH']
|
headers = ['#plugins/input/shape'] + env['CPPPATH']
|
||||||
|
|
||||||
boost_program_options = 'boost_program_options%s' % env['BOOST_APPEND']
|
boost_program_options = 'boost_program_options%s' % env['BOOST_APPEND']
|
||||||
|
boost_iostreams = 'boost_iostreams%s' % env['BOOST_APPEND']
|
||||||
if env['THREADING'] == 'multi':
|
if env['THREADING'] == 'multi':
|
||||||
boost_program_options = '%s%s' % (boost_program_options,thread_suffix)
|
boost_program_options = '%s%s' % (boost_program_options,thread_suffix)
|
||||||
shapeindex = env.Program('shapeindex', source, CPPPATH=headers, LIBS=boost_program_options)
|
boost_iostreams = '%s%s' % (boost_iostreams,thread_suffix)
|
||||||
|
libraries = [boost_program_options,boost_iostreams]
|
||||||
|
|
||||||
|
shapeindex = env.Program('shapeindex', source, CPPPATH=headers, LIBS=libraries)
|
||||||
|
|
||||||
env.Install(install_prefix + '/bin', shapeindex)
|
env.Install(install_prefix + '/bin', shapeindex)
|
||||||
env.Alias('install', install_prefix + '/bin')
|
env.Alias('install', install_prefix + '/bin')
|
||||||
|
|
|
@ -31,7 +31,8 @@
|
||||||
#include <boost/algorithm/string.hpp>
|
#include <boost/algorithm/string.hpp>
|
||||||
#include <boost/program_options.hpp>
|
#include <boost/program_options.hpp>
|
||||||
#include "quadtree.hpp"
|
#include "quadtree.hpp"
|
||||||
#include "shape.hpp"
|
#include "shapefile.hpp"
|
||||||
|
#include "shape_io.hpp"
|
||||||
|
|
||||||
const int MAXDEPTH = 64;
|
const int MAXDEPTH = 64;
|
||||||
const int DEFAULT_DEPTH = 8;
|
const int DEFAULT_DEPTH = 8;
|
||||||
|
@ -45,6 +46,7 @@ int main (int argc,char** argv)
|
||||||
namespace po = boost::program_options;
|
namespace po = boost::program_options;
|
||||||
using std::string;
|
using std::string;
|
||||||
using std::vector;
|
using std::vector;
|
||||||
|
using std::clog;
|
||||||
|
|
||||||
bool verbose=false;
|
bool verbose=false;
|
||||||
unsigned int depth=DEFAULT_DEPTH;
|
unsigned int depth=DEFAULT_DEPTH;
|
||||||
|
@ -112,14 +114,17 @@ int main (int argc,char** argv)
|
||||||
while (itr != shape_files.end())
|
while (itr != shape_files.end())
|
||||||
{
|
{
|
||||||
std::clog<<"processing "<<*itr << std::endl;
|
std::clog<<"processing "<<*itr << std::endl;
|
||||||
shape_file shp;
|
//shape_file shp;
|
||||||
std::string shapename(*itr++);
|
std::string shapename(*itr++);
|
||||||
if (!shp.open(shapename+".shp")) {
|
shape_file shp(shapename+".shp");
|
||||||
|
|
||||||
|
if (!shp.is_open()) {
|
||||||
std::clog<<"error : cannot open "<< (shapename+".shp") <<"\n";
|
std::clog<<"error : cannot open "<< (shapename+".shp") <<"\n";
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
shp.read_xdr_integer(); //file_code == 9994
|
int code = shp.read_xdr_integer(); //file_code == 9994
|
||||||
|
std::clog << code << "\n";
|
||||||
shp.skip(5*4);
|
shp.skip(5*4);
|
||||||
|
|
||||||
int file_length=shp.read_xdr_integer();
|
int file_length=shp.read_xdr_integer();
|
||||||
|
|
Loading…
Add table
Reference in a new issue