C/C++通过shapelib开源库读取shapefile文件
C/C++通过shapelib开源库读取shapefile文件
·
C/C++通过shapelib开源库读取shapefile文件
shapelib下载
链接: http://download.osgeo.org/shapelib/
shapelib编译
作者使用的是deepin操作系统(linux),下载的是shapelib-1.5.0.tar.gz压缩包,解压后会有一个源码目录shapelib-1.5.0。进入源码路径即CMakeList.txt所在路径。
命令行分别输入:
./configure
mkdir build
cd build
cmake ..
然后在build路径下就会生成libshp.so,通过源码路径下的shapefil.h就可以调用libshp.so库
如果不想使用库,希望把源码和你的项目编译到一起可以直接将CMakeLists.txt中lib_SRC 所包含的源码文件添加到你的项目中进行编译即可
C++使用二次封装
作者在C++项目中使用到了这个库对其进行了二次封装,该项目读取的是.dbf文件和.shp文件
read_shapefile.h
#ifndef __READ_SHAPEFILE_H__
#define __READ_SHAPEFILE_H__
#include "shapefil.h"
#include <unistd.h>
#include <memory>
#include <iostream>
#include <vector>
#include <assert.h>
#include <bits/stdc++.h>
using namespace std;
class ReadShapeFile;
#define SUCCESS (0)
#define FAILURE (-1)
using SpReadShapeFile = std::shared_ptr<ReadShapeFile>;
typedef struct {
double x;
double y;
double z;
} Point3D;
using Point3DS = vector<Point3D>;
#define SHAPEFILE_DBF_TITLE_SIZE (50) // dbf文件标题长度
class ReadShapeFile
{
public:
static SpReadShapeFile createSpReadShapeFile(const string &file_name)
{ // file_name中应为路径和文件前缀
if(access((file_name + ".dbf").c_str(), F_OK) != 0)return NULL;
SpReadShapeFile ptr(new ReadShapeFile(file_name));
return ptr;
}
~ReadShapeFile();
/**
* @brief 获取DBF文件的记录数目和字段数目
*
* @param [out] record 记录数
* @param [out] field 字段数
* @return int 成功——SUCCESS 失败——FAILURE
*/
int GetDBFRecordAndField(int32_t &record, int32_t &field);
/**
* @brief 获取SHP文件的记录数
*
* @param [out] record 记录数
* @return int 成功——SUCCESS 失败——FAILURE
*/
int GetSHPRecord(int32_t &record);
/**
* @brief 如果不知道DBF文件类型可以通过该方法获取目前支持int;double;string
*
* @param [in] field 字段
* @param [out] data_type 该字段的数据类型
* @return int 成功——SUCCESS 失败——FAILURE
*/
int GetDBFDataType(const int32_t field, DBFFieldType &data_type) const;
/**
* @brief 获取DBF中int类型的字段
*
* @param [in] record 记录
* @param [in] field 字段
* @param [out] data
* @return int 成功——SUCCESS 失败——FAILURE
*/
int GetDBFIntData(const int32_t record, const int32_t field,
int32_t &data) const;
/**
* @brief 获取DBF中double类型的字段
*
* @param [in] record 记录
* @param [in] field 字段
* @param [out] data
* @return int 成功——SUCCESS 失败——FAILURE
*/
int GetDBFDoubleData(const int32_t record, const int32_t field,
double &data) const;
/**
* @brief 获取DBF中string类型的字段
*
* @param [in] record 记录
* @param [in] field 字段
* @param [out] data
* @return int 成功——SUCCESS 失败——FAILURE
*/
int GetDBFStringData(const int32_t record, const int32_t field,
string &data) const;
/**
* @brief 获取SHP文件中的点信息
*
* @param [in] record 记录
* @param [out] data 点集合可能是一个或者多个
* @return int 成功——SUCCESS 失败——FAILURE
*/
int GetSHP3DPoints(const int32_t record, Point3DS &data) const;
private:
ReadShapeFile(const string &file_name);
private:
string file_name_;
DBFHandle h_dbf_;
SHPHandle h_shp_;
};
#endif //__READ_SHAPEFILE_H__
read_shapefile.cpp
#include "readshapfile.h"
ReadShapeFile::ReadShapeFile(const string &file_name)
: file_name_(file_name), h_dbf_(NULL), h_shp_(NULL)
{
h_dbf_ = DBFOpen((file_name + ".dbf").c_str(), "r");
h_shp_ = SHPOpen((file_name + ".shp").c_str(), "r");
}
ReadShapeFile::~ReadShapeFile()
{
if (h_dbf_ != NULL) {
DBFClose(h_dbf_);
}
if (h_shp_ != NULL) {
SHPClose(h_shp_);
}
}
int ReadShapeFile::GetDBFRecordAndField(int32_t &record, int32_t &field)
{
if(h_dbf_ == NULL) return FAILURE;
record = h_dbf_->nRecords;
field = h_dbf_->nFields;
return SUCCESS;
}
int ReadShapeFile::GetSHPRecord(int32_t &record)
{
if(h_shp_ == NULL) return FAILURE;
record = h_shp_->nRecords;
return SUCCESS;
}
int ReadShapeFile::GetDBFDataType(const int32_t field,
DBFFieldType &data_type) const
{
if(h_dbf_ == NULL) return FAILURE;
if(field > h_dbf_->nFields) return FAILURE;
char title[SHAPEFILE_DBF_TITLE_SIZE] = "";
// int32_t len; //字段长度 单位:bit
// int32_t decimals; //小数位数
// DBFFieldType data_type = DBFGetFieldInfo(h_dbf_, field, title, &len,
// &decimals);
data_type = DBFGetFieldInfo(h_dbf_, field, title, NULL, NULL);
cout << title;
return SUCCESS;
}
int ReadShapeFile::GetDBFIntData(const int32_t record, const int32_t field,
int32_t &data) const
{
if(h_dbf_ == NULL) return FAILURE;
if(record > h_dbf_->nRecords || field > h_dbf_->nFields) return FAILURE;
data = DBFReadIntegerAttribute(h_dbf_, record, field);
return SUCCESS;
}
int ReadShapeFile::GetDBFDoubleData(const int32_t record, const int32_t field,
double &data) const
{
if(h_dbf_ == NULL) return FAILURE;
if(record > h_dbf_->nRecords || field > h_dbf_->nFields) return FAILURE;
data = DBFReadDoubleAttribute(h_dbf_, record, field);
return SUCCESS;
}
int ReadShapeFile::GetDBFStringData(const int32_t record, const int32_t field,
string &data) const
{
if(h_dbf_ == NULL) return FAILURE;
if(record > h_dbf_->nRecords || field > h_dbf_->nFields) return FAILURE;
data = DBFReadStringAttribute(h_dbf_, record, field);
return SUCCESS;
}
int ReadShapeFile::GetSHP3DPoints(const int32_t record,
Point3DS &data) const
{
if(h_shp_ == NULL) return FAILURE;
if(record > h_shp_->nRecords) return FAILURE;
SHPObject *shp_obj = SHPReadObject(h_shp_, record);
if(shp_obj == NULL) return FAILURE;
Point3DS.clear();
for (int i = 0; i < shp_obj->nVertices; ++i) {
Point3D point = {(shp_obj->padfX[i]),
(shp_obj->padfY[i]),
(shp_obj->padfZ[i])};
data.emplace_back(std::move(point));
}
return SUCCESS;
}
main.cpp
#include<iostream>
#include "readshapfile.h"
using namespace std;
int main()
{
auto fp =ReadShapeFile::createSpReadShapeFile("file_name");
if(fp==NULL) return ;
int32_t record, field;
fp->GetDBFRecordAndField(record, field);
int32_t shp_record;
fp->GetSHPRecord(shp_record);
int32_t int_data;
double double_data;
string string_data;
Point3DS points;
for(int i=0;i<record;++i)
{
for(int j= 0; j< field; ++j){
DBFFieldType type;
fp->GetDBFDataType(j,type);
switch(type){
case FTString:
fp->GetDBFStringData(i,j,string_data);
cout<<" string: "<<string_data<<endl;
break;
case FTInteger:
fp->GetDBFIntData(i,j,int_data);
cout<<" int: "<<int_data<<endl;
break;
case FTDouble:
fp->GetDBFDoubleData(i,j,double_data);
cout<<" double: "<<double_data<<endl;
break;
default:
break;
}
}
}
for(int i=0;i<shp_record;++i){
fp->GetSHP3DPoints(i,points);
for(auto &point:points){
cout<<"xyz["<<point.x<<","<<point.y<<","<<point.z<<"] " <<endl;
}
}
}
以上均作者通过查阅资料和自己理解摸索出来的,如有问题望各位及时指出,谢谢!
更多推荐
已为社区贡献2条内容
所有评论(0)