我自己封装的包含shp读写操作的类,并不完整,留下了一些接口,有兴趣或者有需要的可以自己补充完整
头文件SHP_RW.h
#pragma once
#include
#include
#include
using namespace std;
class SHP_RW
{
public:
SHP_RW();
~SHP_RW();
OGRGeometry *poGeometry;
OGRLayer *poLayer;
int Get_Point(double &X, double &Y, double &Z);
int Get_LineString(vector &vecX, vector &vecY, vector &vecZ);
int Get_Polygon(map> &coordinate, map < int, map>> &innerring);
int Get_MultiPoint();
int Get_MultiLineString();
int Get_MultiPolygon();
int Get_GeometryCollection();
int Set_Point();
int Set_LineString();
int Set_Polygon();
int Set_MultiPoint();
int Set_MultiLineString();
int Set_MultiPolygon();
int Set_GeometryCollection();
int SetFieldDefn(vector fieldname, vector fieldtype, vector fieldwidth);
private:
};
.cpp文件 SHP_RW.cpp
#include "SHP_RW.h"
SHP_RW::SHP_RW()
{
}
SHP_RW::~SHP_RW()
{
}
int SHP_RW::Get_Point(double &X, double &Y, double &Z)
{
OGRPoint *poPoint = (OGRPoint *)poGeometry;
X = poPoint->getX();
Y = poPoint->getY();
Z = poPoint->getZ();
return 0;
}
int SHP_RW::Get_LineString(vector &vecX, vector &vecY, vector &vecZ)
{
OGRLineString* pLineGeo = (OGRLineString*)poGeometry;
int pointnums = pLineGeo->getNumPoints();
for (int i = 0; i < pointnums; i++)
{
vecX.push_back(pLineGeo->getX(i));
vecY.push_back(pLineGeo->getY(i));
vecZ.push_back(pLineGeo->getZ(i));
}
return 0;
}
int SHP_RW::Get_Polygon(map> &coordinate, map < int, map>> &innerring)
{
OGRPolygon *poPolygon = (OGRPolygon *)poGeometry;
OGRPoint point;
OGRLinearRing *pOGRLinearRing = poPolygon->getExteriorRing();
//printf("nums = %d\n", pOGRLinearRing->getNumPoints());
for (int i = 0; i < pOGRLinearRing->getNumPoints(); i++)
{
coordinate["X"].push_back(pOGRLinearRing->getX(i));
coordinate["Y"].push_back(pOGRLinearRing->getY(i));
coordinate["Z"].push_back(pOGRLinearRing->getZ(i));
//printf("%.3f, %.3f, %.3f\n", pOGRLinearRing->getX(i), pOGRLinearRing->getY(i), pOGRLinearRing->getZ(i));
}
int innernums = poPolygon->getNumInteriorRings();
printf("innernums = %d\n", innernums);
if (innernums > 0)
{
for (int i = 0; i < innernums; i++)
{
pOGRLinearRing = poPolygon->getInteriorRing(i);
for (int j = 0; j < pOGRLinearRing->getNumPoints(); j++)
{
innerring[i]["X"].push_back(pOGRLinearRing->getX(j));
innerring[i]["Y"].push_back(pOGRLinearRing->getY(j));
innerring[i]["Z"].push_back(pOGRLinearRing->getZ(j));
}
}
}
//pOGRLinearRing->getPoint(0, &point); //得到第一个点的坐标
//staX = point.getX();
//staY = point.getY();
return 0;
}
int SHP_RW::Get_MultiPoint()
{
return 0;
}
int SHP_RW::Get_MultiLineString()
{
return 0;
}
int SHP_RW::Get_MultiPolygon()
{
return 0;
}
int SHP_RW::Get_GeometryCollection()
{
return 0;
}
/* *************** 文件写入操作 ********************* */
int SHP_RW::Set_Point()
{
return 0;
}
int SHP_RW::Set_LineString()
{
return 0;
}
int SHP_RW::Set_Polygon()
{
int x, y;
int a = 10, b = 100;
for (int i = 0; i < 10; i++) // 控制要素数量
{
OGRFeature *poFeature;
poFeature = OGRFeature::CreateFeature(poLayer->GetLayerDefn());
poFeature->SetField("ID", i);
//string name = "第" + to_string(i + 1) + "个要素";
poFeature->SetField("NAME", "name");
x = (rand() % (b - a)) + a;
y = (rand() % (b - a)) + a;
poFeature->SetField("VALUE", x + y);
//polygon
OGRPolygon polygon;
// 外环
OGRLinearRing ringOut;
ringOut.addPoint(80, 30);
ringOut.addPoint(80, 40);
ringOut.addPoint(90, 40);
ringOut.addPoint(90, 30);
ringOut.closeRings();
polygon.addRing(&ringOut);
//内环
int numringIn = 5; // 设置内环个数
for (int i = 0; i < numringIn; i++)
{
OGRLinearRing ringIn0;
ringIn0.addPoint(82, 32);
ringIn0.addPoint(82, 38);
ringIn0.addPoint(88, 38);
ringIn0.addPoint(88, 32);
ringIn0.closeRings();
polygon.addRing(&ringIn0);
}
//polygon.addRingDirectly(&ringIn0);
poFeature->SetGeometry((OGRGeometry *)(&polygon));
if (poLayer->CreateFeature(poFeature) != OGRERR_NONE)
{
printf("Failed to create feature in shapefile.\n");
return 0;
}
OGRFeature::DestroyFeature(poFeature);
}
return 0;
}
int SHP_RW::Set_MultiPoint()
{
return 0;
}
int SHP_RW::Set_MultiLineString()
{
return 0;
}
int SHP_RW::Set_MultiPolygon()
{
return 0;
}
int SHP_RW::Set_GeometryCollection()
{
return 0;
}
int SHP_RW::SetFieldDefn(vector fieldname, vector fieldtype, vector fieldwidth)
{
for (int i = 0; i < fieldname.size(); i++)
{
OGRFieldDefn Field(fieldname[i].c_str(), fieldtype[i]); //创建字段 字段+字段类型
Field.SetWidth(fieldwidth[i]); //设置字段宽度,实际操作需要根据不同字段设置不同长度
poLayer->CreateField(&Field);
}
return 0;
}
/* *************** 文件写入操作 ********************* */
读写cpp
#include
#include
#include
#include
#include "SHP_RW.h"
#include
#include
#include
#include
#include
using namespace std;
//读shp文件
int shpread(const char* file_path_name)
{
CPLSetConfigOption("GDAL_FILENAME_IS_UTF8", "NO"); // 支持中文路径
CPLSetConfigOption("SHAPE_ENCODING", ""); //属性表支持中文字段
GDALAllRegister();
GDALDataset *poDS = (GDALDataset*)GDALOpenEx(file_path_name, GDAL_OF_VECTOR, NULL, NULL, NULL);
if (poDS == NULL)
{
printf("Open failed.\n");
exit(1);
}
cout << "Open successfully!" << endl;
//获取图层数量
cout << "<--------获取图层数量-------->" << endl;
int LayerCount = poDS->GetLayerCount();
cout << "图层数量: " << LayerCount << endl;
//获取shp图层
cout << "<--------获取shp图层-------->" << endl;
OGRLayer *poLayer = poDS->GetLayer(0); // 根据序号获取相应shp图层,这里表示第一层
//OGRLayer *poLayer = poDS->GetLayerByName("point"); //根据名称获取相应图层
//获取当前图层的属性表结构
cout << "<--------获取当前图层的属性表结构-------->" << endl;
OGRFeatureDefn *poFDefn = poLayer->GetLayerDefn();
//重置要素读取顺序
cout << "<--------重置要素读取顺序-------->" << endl;
poLayer->ResetReading(); // ResetReading() 函数功能为把要素读取顺序重置为从第一个开始
//设置要素指针
cout << "<--------设置要素指针-------->" << endl;
OGRFeature *poFeature; //用于获取图层上的要素
//创建文件存放数据
shpname = shpname.substr(0, shpname.find_last_of(".")) + "_";
string attrfile = "D:/output/" + shpname + "attrfile_shp.txt"; // 属性文件
string datafile = "D:/output/" + shpname + "datafile_shp.txt"; // 数据文件
cout << attrfile << ' ' << datafile << endl;
fstream tmpfile(attrfile, ios::out);
fstream tmpdatafile(datafile, ios::out);
int num = 0; //用于标记第几个要素
while ((poFeature = poLayer->GetNextFeature()) != NULL)
{
cout << "图层属性->" << endl;
for (int iField = 0; iField < poFDefn->GetFieldCount(); iField++)
{
OGRFieldDefn *poFieldDefn = poFDefn->GetFieldDefn(iField);
cout << poFieldDefn->GetNameRef() << ": "; // 属性表字段名
switch (poFieldDefn->GetType()) // 不同数据类型按不同方式,根据字段号获取相应字段的数据
{
case OFTInteger:
printf("%d,", poFeature->GetFieldAsInteger(iField));
tmpfile << poFeature->GetFieldAsInteger(iField) << "\t"; // 写入文件
break;
case OFTInteger64:
printf(CPL_FRMT_GIB ",", poFeature->GetFieldAsInteger64(iField));
tmpfile << poFeature->GetFieldAsInteger64(iField) << "\t"; // 写入文件
break;
case OFTReal:
printf("%.3f,", poFeature->GetFieldAsDouble(iField));
tmpfile << poFeature->GetFieldAsDouble(iField) << "\t"; // 写入文件
break;
case OFTString:
printf("%s,", poFeature->GetFieldAsString(iField));
tmpfile << poFeature->GetFieldAsString(iField) << "\t"; // 写入文件
break;
default:
printf("%s,", poFeature->GetFieldAsString(iField));
tmpfile << poFeature->GetFieldAsString(iField) << "\t"; // 写入文件
break;
}
/*printf("\n");*/
}
tmpfile << endl;
OGRGeometry *poGeometry = poFeature->GetGeometryRef();
double staX, staY, staZ;
vector vecX, vecY, vecZ;
double area;
//判断当前要素的几何类型,是否为点图层,利用 getGeometryType() 函数获取要素类型
SHP_RW geo;
geo.poGeometry = poGeometry;
if (poGeometry != NULL)
{
auto GeometryType = wkbFlatten(poGeometry->getGeometryType()); // getGeometryType() 返回的类型可能会有2.5D类型,通过宏 wkbFlatten 转换为2D类型
if (GeometryType == wkbPoint) // 1
{
cout << "点图层要素" << endl;
geo.Get_Point(staX, staY, staZ);
//printf("X= %.3f, Y= %.3f, Z= %.3f\n", staX, staY, staZ);
tmpdatafile << staX << "\t" << staY << "\t" << staZ << endl; // 写入文件
}
else if (GeometryType == wkbLineString) // 2
{
cout << "线图层要素" << endl;
geo.Get_LineString(vecX, vecY, vecZ);
for (int i = 0; i < vecX.size(); i++)
//printf("X= %.3f, Y= %.3f, Z= %.3f\n", vecX[i], vecY[i], vecZ[i]);
tmpdatafile << vecX[i] << "\t" << vecY[i] << "\t" << vecZ[i] << endl; // 写入文件
}
else if (GeometryType == wkbPolygon) // 3
{
cout << "多边形图层要素" << endl;
map> coordinate; // 外环
map < int, map>> innerring; //内环
coordinate["X"], coordinate["Y"], coordinate["Z"];
geo.Get_Polygon(coordinate, innerring);
// 将数据写入文件
tmpdatafile << "<----- 第" + to_string(1 + num++) + "个要素 ---->" << endl;
tmpdatafile << "外环数据" << endl;
cout << "数据个数:" << coordinate["X"].size() << endl;
for (int j = 0; j < coordinate["X"].size(); j++)
{
tmpdatafile << coordinate["X"][j] << "\t" << coordinate["Y"][j] << "\t" << coordinate["Z"][j] << endl; // 写入文件
}
tmpdatafile << "内环数据" << endl;
for (int i = 0; i < innerring.size(); i++)
{
for (int k = 0; k < innerring[i]["X"].size(); k++)
tmpdatafile << innerring[i]["X"][k] << "\t" << innerring[i]["Y"][k] << "\t" << innerring[i]["Z"][k] << endl; // 写入文件
}
}
else if (GeometryType == wkbMultiPoint) // 4
{
cout << "点集合图层要素" << endl;
}
else if (GeometryType == wkbMultiLineString) // 5
{
cout << "线集合图层要素" << endl;
}
else if (GeometryType == wkbMultiPolygon) // 6
{
cout << "多边形集合图层要素" << endl;
}
else if (GeometryType == wkbGeometryCollection) // 7
{
cout << "几何体集合图层要素" << endl;
}
else if (GeometryType == wkbNone)
{
cout << "该数据只有属性表" << endl;
}
}
else
{
printf("no geometry\n");
}
OGRFeature::DestroyFeature(poFeature);
}
tmpfile.close();
GDALClose(poDS);
return 0;
}
// 写shp文件
int shpwrite(const char* file_path_name)
{
CPLSetConfigOption("GDAL_FILENAME_IS_UTF8", "NO"); // 支持中文路径
CPLSetConfigOption("SHAPE_ENCODING", ""); //属性表支持中文字段
//注册所有驱动
OGRRegisterAll();
const char *pszDriverName = "ESRI Shapefile";
GDALDriver *poDriver;
poDriver = GetGDALDriverManager()->GetDriverByName(pszDriverName);
if (poDriver == NULL)
{
printf("%s driver not available.\n", pszDriverName);
return 0;
}
//创建数据源
GDALDataset *poDS;
poDS = poDriver->Create(file_path_name, 0, 0, 0, GDT_Unknown, NULL); //创建shp文件
if (poDS == NULL)
{
printf("Creation of output file failed.\n");
return 0;
}
OGRLayer *poLayer;
SHP_RW write_shp;
//OGRwkbGeometryType layertype;
//layertype = wkbPolygon;
string layertype = "多边形";
vector fieldname = { "ID", "NAME", "VALUE" };
vector fieldtype = { OFTInteger, OFTString, OFTReal };
vector fieldwidth = { 32, 32, 32 };
if (layertype == "点")
{
// 创建图层,这里没有指定空间参考,如果需要的话,需要在这里进行指定
poLayer = poDS->CreateLayer("point_out", NULL, wkbPoint, NULL);
write_shp.poLayer = poLayer;
write_shp.SetFieldDefn(fieldname, fieldtype, fieldwidth);
write_shp.Set_Point();
}
else if (layertype == "线")
{
poLayer = poDS->CreateLayer("string_out", NULL, wkbLineString, NULL);
write_shp.poLayer = poLayer;
write_shp.SetFieldDefn(fieldname, fieldtype, fieldwidth);
write_shp.Set_LineString();
}
else if (layertype == "多边形")
{
poLayer = poDS->CreateLayer("string_out", NULL, wkbPolygon, NULL);
write_shp.poLayer = poLayer;
write_shp.SetFieldDefn(fieldname, fieldtype, fieldwidth);
write_shp.Set_Polygon();
}
else if (layertype == "点集合")
{
}
else if (layertype == "线集合")
{
}
else if (layertype == "多边形集合")
{
}
GDALClose(poDS);
return 0;
}
int main()
{
shpread("D:/originshp/tmppath/0806.shp");
system("pause");
return 0;
}