小工具—修改.shp文件,删除指定属性的要素(gdal, boost库)
main.cpp:
#include <iostream>
#include "shp_Parser.h"
int main()
{
SHP_Parser shpParser;
shpParser.ReadShapeFile();
return 0;
}
shp_Parser.h:
#ifndef SHP_PARSER_H
#define SHP_PARSER_H
#include <vector>
#include <fstream>
#include <iostream>
#include "gdal_priv.h"
typedef struct ini_file
{
std::string input_path;
std::string output_path;
std::string link_attr;
}INI_FILE;
class SHP_Parser
{
public:
void ReadShapeFile();
void dealRTable(GDALDriver *poDriver);
void dealNTable(GDALDriver *poDriver);
void dealCTable(GDALDriver *poDriver);
void dealR_LNameTable(GDALDriver *poDriver);
private:
bool ReadIni(const char* _path);
int deleteLinkID(char *_pDst, const char *_pSrc);
INI_FILE m_iniFile;
char **m_pRID;
int m_filed_0b01_count;
std::ofstream fout;
};
#endif
shp_Parser.cpp:
#include "shp_Parser.h"
#include <vector>
#include <algorithm>
#include "boost\algorithm\string.hpp"
#include "boost\property_tree\ptree.hpp"
#include "boost\property_tree\ini_parser.hpp"
#include "ogrsf_frmts.h"
#include "gdal.h"
#include "gdal_priv.h"
using namespace std;
// 支持删除的最多的link数,预分配内存
#define DELETE_LINK_NUM_MAX 5000
//// 删除的link的属性类型
//#define ROAD_KIND_ATTR "080a"
void SHP_Parser::ReadShapeFile()
{
//使属性表字段支持中文
CPLSetConfigOption("SHAPE_ENCODING", "");
GDALAllRegister();
CPLSetConfigOption("GDAL_FILENAME_IS_UTF8", "NO");
//创建ESRI shp文件
char *pszDriverName = "ESRI Shapefile";
GDALDriver *poDriver = NULL;
poDriver = GetGDALDriverManager()->GetDriverByName(pszDriverName);
if (poDriver == NULL)
{
cout << pszDriverName << "驱动不可用!" << endl;
return;
}
// R表和R_LNname表中删除要素,N表和C表是修改要素属性
//ReadIni("config.ini");
ReadIni("F:\\lipeng\\tempProj\\delete466163\\Release\\config.ini");
dealRTable(poDriver);
dealNTable(poDriver);
dealCTable(poDriver);
dealR_LNameTable(poDriver);
system("pause");
}
void SHP_Parser::dealRTable(GDALDriver *poDriver)
{
#if 1
string pRshanghaiShp = m_iniFile.input_path + "\\Rshanghai.shp";
string pNewRshanghaiShp = m_iniFile.output_path + "\\Rshanghai.shp";
string RLogFile = m_iniFile.output_path + "\\Rlog.csv";
#endif
//------------------------------------------------------------------------------------------------------------------------------------------
// 修改Rshanghai.shp表
fout.open(RLogFile, ios::out);
GDALDataset *pDataSet_RShanghaiSimplify = (GDALDataset*)GDALOpenEx(pRshanghaiShp.c_str(), GDAL_OF_VECTOR, NULL, NULL, NULL); //RShanghai抽稀shp文件
cout << "正在创建新的Rshanghai.shp文件:" << pNewRshanghaiShp << "...";
GDALDataset *pNewDataSet_RShanghaiSimplify = poDriver->CreateCopy(pNewRshanghaiShp.c_str(), pDataSet_RShanghaiSimplify, 0, 0, 0, NULL);
if (pDataSet_RShanghaiSimplify == NULL || pNewDataSet_RShanghaiSimplify == NULL)
{
cout << "数据集打开失败!" << endl;
return;
}
cout << endl << pNewRshanghaiShp << "创建完成" << endl << "正在处理" << pNewRshanghaiShp << "...";
OGRLayer *poLayer, *poNewLayer = NULL;
poLayer = pDataSet_RShanghaiSimplify->GetLayer(0); // 都只有一个图层
poNewLayer = pNewDataSet_RShanghaiSimplify->GetLayer(0);
OGRFeature *poFeature;
poLayer->ResetReading();
int field_count = 0, iFID = 0;
m_filed_0b01_count = 0; //R表中类型为0b01的记录条数
int ifield = 0;
double dfield = 0.0;
const char *strOneField = NULL;
const char *strSecField = NULL;
vector<GIntBig> vecDelID;
GIntBig RFeatureCount = poLayer->GetFeatureCount(); // 得到要素个数
m_pRID = new char*[DELETE_LINK_NUM_MAX]; // 需要删除的link的ID
for (int i = 0; i < DELETE_LINK_NUM_MAX; ++i) // 分配内存
{
m_pRID[i] = new char[13];
memset(m_pRID[i], 0, 13);
}
fout << "delete Rshanghai.shp "<<m_iniFile.link_attr.c_str()<<":" << endl;
fout << "MapID,ID,Kind,SnodeID,EnodeID" << endl;
while ((poFeature = poLayer->GetNextFeature()) != NULL)
{
iFID = poFeature->GetFID();
strOneField = poFeature->GetFieldAsString(0); // MapID
strSecField = poFeature->GetFieldAsString(3); // Kind
//if ((strcmp(strOneField, "466163") == 0) && (strcmp(strSecField, "0b01") == 0)) // MapID=466163 && Kind=0b01
if ((strcmp(strOneField, "466163") == 0) && (strcmp(strSecField, m_iniFile.link_attr.c_str()) == 0)) // MapID=466163 && Kind=0b01
{
memcpy(m_pRID[m_filed_0b01_count], poFeature->GetFieldAsString(1), 13);
++m_filed_0b01_count;
vecDelID.push_back(poFeature->GetFID());
fout << poFeature->GetFieldAsString(0) << "," << poFeature->GetFieldAsString(1) << "," << poFeature->GetFieldAsString(3)
<< "," << poFeature->GetFieldAsString(9) << "," << poFeature->GetFieldAsString(10) << endl;
}
//int fieldcount = poFDefn->GetFieldCount();
//cout<<"Field count is : %d\n"<<poFDefn->GetFieldCount()<<endl;
//for (field_count = 0; field_count < poFDefn->GetFieldCount(); field_count++)
//{
// OGRFieldDefn * poFieldDefn = poFDefn->GetFieldDefn(field_count);
// if (poFieldDefn->GetType() == OFTInteger)
// {
// ifield = poFeature->GetFieldAsInteger(field_count);
// // printf("%d ", poFeature->GetFieldAsInteger(iField));
// }
// else if (poFieldDefn->GetType() == OFTReal)
// {
// dfield = poFeature->GetFieldAsDouble(field_count);
// // printf("%3f ", poFeature->GetFieldAsDouble(iField));
// }
// else if (poFieldDefn->GetType() == OFTString)
// {
// strfield = poFeature->GetFieldAsString(field_count);
// // printf("%s ", poFeature->GetFieldAsString(iField));
// }
// // else
// // printf("%s", poFeature->GetFieldAsString(iField));
//}
//以上操作与gdal官网一样
//get Geometry获取polygon的信息
// OGRGeometry *poGeometry;
// poGeometry = poFeature->GetGeometryRef();
// double x, y; double area;
// if (poGeometry != NULL && wkbFlatten(poGeometry->getGeometryType()) == wkbPolygon)
// {
// OGRPolygon *poPolygon = (OGRPolygon *)poGeometry;
// area = poPolygon->get_Area();
// OGRPoint point;
// OGRLinearRing *pOGRLinearRing = poPolygon->getExteriorRing();
// pOGRLinearRing->getPoint(0, &point);//得到第一个点的坐标
// x = point.getX();
// y = point.getY();
// // printf("%.6f, %.6f\n", poPoint->getX(), poPoint->getY());
// }
// else
// // printf("no point geometry\n");
OGRFeature::DestroyFeature(poFeature);
}
for_each(vecDelID.begin(), vecDelID.end(), [&poNewLayer](GIntBig _id)
{
poNewLayer->DeleteFeature(_id);
});
GDALClose(pDataSet_RShanghaiSimplify);
GDALClose(pNewDataSet_RShanghaiSimplify);
fout << "delete total: " << m_filed_0b01_count << endl;
fout.close();
cout << endl << pNewRshanghaiShp<< "处理完成" << endl << endl;
}
void SHP_Parser::dealNTable(GDALDriver *poDriver)
{
#if 1
string pNshanghaiShp = m_iniFile.input_path + "\\Nshanghai.shp";
string pNewNshanghaiShp = m_iniFile.output_path + "\\Nshanghai.shp";
string NLogFile = m_iniFile.output_path + "\\Nlog.csv";
#endif
//------------------------------------------------------------------------------------------------------------------------------
// 修改NShanghai.shp表
fout.open(NLogFile, ios::out);
GDALDataset *pDataSet_NShanghai = (GDALDataset*)GDALOpenEx(pNshanghaiShp.c_str(), GDAL_OF_VECTOR, NULL, NULL, NULL); //NShanghai的shp文件
cout << "正在创建新的Nshanghai.shp文件:" << pNewNshanghaiShp << "...";
GDALDataset *pNewDataSet_NShanghai = poDriver->CreateCopy(pNewNshanghaiShp.c_str(), pDataSet_NShanghai, 0, 0, 0, NULL);
if (pDataSet_NShanghai == NULL || pNewDataSet_NShanghai == NULL)
{
cout << "数据集打开失败!" << endl;
return;
}
cout << endl << pNewNshanghaiShp << "创建完成" << endl << "正在处理" << pNewNshanghaiShp << "...";
char ch[254] = { '\0' };
int flag = 0, deleteCount = 0;
vector<GIntBig> vecDelID;
const char *strOneField = NULL;
const char *strSecField = NULL;
OGRLayer *poNewLayer = NULL;
OGRFeature *poFeature = NULL;
poNewLayer = pNewDataSet_NShanghai->GetLayer(0);
poNewLayer->ResetReading();
fout << "delete Nshanghai.shp:" << endl;
fout << "MapID,ID,Kind,Corss_LID,Node_LID" << endl;
while ((poFeature = poNewLayer->GetNextFeature()) != NULL)
{
flag = 0;
strOneField = poFeature->GetFieldAsString(6); // Cross_LID 需要检测的字段
strSecField = poFeature->GetFieldAsString(12); // Node_LID 需要检测的字段
if (deleteLinkID(ch, strOneField) != 0)
{
flag = 1;
poFeature->SetField(6, ch);
poNewLayer->SetFeature(poFeature);
}
memset(ch, 0, 254);
if (deleteLinkID(ch, strSecField) != 0)
{
flag = 1;
poFeature->SetField(12, ch);
poNewLayer->SetFeature(poFeature);
}
if (flag == 1)
{
++deleteCount;
vecDelID.push_back(poFeature->GetFID());
fout << poFeature->GetFieldAsString(0) << "," << poFeature->GetFieldAsString(1) << "," << poFeature->GetFieldAsString(3)
<< "," << poFeature->GetFieldAsString(6) << "," << poFeature->GetFieldAsString(12) << endl;
}
OGRFeature::DestroyFeature(poFeature);
}
GDALClose(pDataSet_NShanghai);
GDALClose(pNewDataSet_NShanghai);
fout << "delete total:" << deleteCount << endl;
fout.close();
cout << endl << pNewNshanghaiShp << "处理完成" << endl << endl;
}
void SHP_Parser::dealCTable(GDALDriver *poDriver)
{
string pCshanghaiShp = m_iniFile.input_path + "\\Cshanghai.shp";
string pNewCshanghaiShp = m_iniFile.output_path + "\\Cshanghai.shp";
string CLogFile = m_iniFile.output_path + "\\Clog.csv";
//------------------------------------------------------------------------------------------------------------------------------
// 修改CShanghai.shp表
fout.open(CLogFile, ios::out);
GDALDataset *pDataSet_CShanghai = (GDALDataset*)GDALOpenEx(pCshanghaiShp.c_str(), GDAL_OF_VECTOR, NULL, NULL, NULL); //NShanghai的shp文件
cout << "正在创建新的Cshanghai.shp文件:" << pNewCshanghaiShp << "...";
GDALDataset *pNewDataSet_CShanghai = poDriver->CreateCopy(pNewCshanghaiShp.c_str(), pDataSet_CShanghai, 0, 0, 0, NULL);
if (pDataSet_CShanghai == NULL || pNewDataSet_CShanghai == NULL)
{
cout << "数据集打开失败!" << endl;
return;
}
cout << endl << pNewCshanghaiShp << "创建完成" << endl << "正在处理" << pNewCshanghaiShp << "...";
char ch[254] = { '\0' };
int flag = 0, deleteCount = 0;
vector<GIntBig> vecDelID;
const char *strOneField = NULL;
const char *strSecField = NULL;
OGRLayer *poNewLayer = NULL;
OGRFeature *poFeature = NULL;
char inLinkID[14] = { '\0' }, outLinkID[14] = { '\0' };
poNewLayer = pNewDataSet_CShanghai->GetLayer(0);
poNewLayer->ResetReading();
fout << "delete Cshanghai.shp:" << endl;
fout << "MapID,ID,inLinkID,outLinkID" << endl;
while ((poFeature = poNewLayer->GetNextFeature()) != NULL)
{
flag = 0;
strOneField = poFeature->GetFieldAsString(3); // inLinkID 需要检测的字段
memcpy(inLinkID, strOneField, 13);
strSecField = poFeature->GetFieldAsString(4); // outLinkID 需要检测的字段
memcpy(outLinkID, strSecField, 13);
if (deleteLinkID(ch, strOneField) != 0)
{
flag = 1;
poFeature->SetField(3, ch);
poNewLayer->SetFeature(poFeature);
}
memset(ch, 0, 254);
if (deleteLinkID(ch, strSecField) != 0)
{
flag = 1;
poFeature->SetField(4, ch);
poNewLayer->SetFeature(poFeature);
}
if (flag == 1)
{
++deleteCount;
vecDelID.push_back(poFeature->GetFID());
fout << poFeature->GetFieldAsString(0) << "," << poFeature->GetFieldAsString(2) << "," << inLinkID
<< "," << outLinkID << endl;
}
OGRFeature::DestroyFeature(poFeature);
memset(inLinkID, '\0', 14);
memset(outLinkID, '\0', 14);
}
GDALClose(pDataSet_CShanghai);
GDALClose(pNewDataSet_CShanghai);
fout << "delete total:" << deleteCount << endl;
fout.close();
cout << endl << pNewCshanghaiShp << "处理完成" << endl << endl;
}
void SHP_Parser::dealR_LNameTable(GDALDriver *poDriver)
{
string pR_LNameshanghaiShp = m_iniFile.input_path + "\\R_LNameshanghai.shp";
string pNewR_LNameshanghaiShp = m_iniFile.output_path + "\\R_LNameshanghai.shp";
string R_LNameLogFile = m_iniFile.output_path + "\\R_LNamelog.csv";
//------------------------------------------------------------------------------------------------------------------------------
// 修改CShanghai.shp表
fout.open(R_LNameLogFile, ios::out);
GDALDataset *pDataSet_R_LNameShanghai = (GDALDataset*)GDALOpenEx(pR_LNameshanghaiShp.c_str(), GDAL_OF_VECTOR | GDAL_OF_UPDATE, NULL, NULL, NULL); //NShanghai的shp文件
cout << "正在创建新的R_LNameshanghai.dbf文件:" << pNewR_LNameshanghaiShp << "...";
//GDALDataset *pNewDataSet_R_LNameShanghai = poDriver->CreateCopy(pNewR_LNameshanghaiShp, pDataSet_R_LNameShanghai, 0, 0, 0, NULL);
CPLCopyFile(pNewR_LNameshanghaiShp.c_str(), pR_LNameshanghaiShp.c_str());
GDALDataset *pNewDataSet_R_LNameShanghai = (GDALDataset*)GDALOpenEx(pNewR_LNameshanghaiShp.c_str(), GDAL_OF_VECTOR | GDAL_OF_UPDATE, NULL, NULL, NULL); //NShanghai的shp文件
if (pDataSet_R_LNameShanghai == NULL || pNewDataSet_R_LNameShanghai == NULL)
{
cout << "数据集打开失败!" << endl;
return;
}
cout <<endl<< pNewR_LNameshanghaiShp << "创建完成" << endl << "正在处理" << pNewR_LNameshanghaiShp << "...";
char ch[254] = { '\0' };
int deleteCount = 0;
vector<GIntBig> vecDelID;
const char *strOneField = NULL;
OGRLayer *poNewLayer = NULL;
OGRFeature *poFeature = NULL;
poNewLayer = pNewDataSet_R_LNameShanghai->GetLayer(0);
poNewLayer->ResetReading();
fout << "delete R_Nameshanghai.dbf:" << endl;
fout << "MapID,ID" << endl;
while ((poFeature = poNewLayer->GetNextFeature()) != NULL)
{
strOneField = poFeature->GetFieldAsString(1); // ID 需要检测的字段
memset(ch, 0, 254);
if (deleteLinkID(ch, strOneField) != 0)
{
++deleteCount;
vecDelID.push_back(poFeature->GetFID());
fout << poFeature->GetFieldAsString(0) << "," << poFeature->GetFieldAsString(1) << endl;
// poFeature->SetField(1, ch); // 删掉该要素,不需要这些代码
// poNewLayer->SetFeature(poFeature);
}
OGRFeature::DestroyFeature(poFeature);
}
for_each(vecDelID.begin(), vecDelID.end(), [&poNewLayer](GIntBig _id)
{
poNewLayer->DeleteFeature(_id);
});
GDALClose(pDataSet_R_LNameShanghai);
GDALClose(pNewDataSet_R_LNameShanghai);
fout << "delete total:" << deleteCount << endl;
fout.close();
cout << endl << pNewR_LNameshanghaiShp << "处理完成" << endl << endl;
}
// 读取配置文件
bool SHP_Parser::ReadIni(const char* _path)
{
if (NULL == _path)
{
return false;
}
boost::property_tree::ptree pt;
boost::property_tree::ini_parser::read_ini(_path, pt);
m_iniFile.input_path = pt.get<string>("PATH.INPUT_PATH");
m_iniFile.output_path = pt.get<string>("PATH.OUTPUT_PATH");
m_iniFile.link_attr = pt.get<string>("LINK_ATTR.DELETE_ATTR_LINK");
return true;
}
// 修改属性字符串,输入原属性字符串_pSrc, 返回修改之后的字符串_pDst,
int SHP_Parser::deleteLinkID(char *_pDst, const char *_pSrc)
{
if (_pDst == NULL || _pSrc == NULL)
return 0;
string str_line = _pSrc;
vector<string> vecLinkID, tempVecLinkID;
boost::algorithm::split(vecLinkID, str_line, boost::is_any_of("|"));
for (size_t i = 0; i < vecLinkID.size(); ++i)
{
size_t j = 0;
for (; j < m_filed_0b01_count; ++j)
{
if (strcmp(m_pRID[j], vecLinkID[i].c_str()) == 0)
{
break;
}
}
if (j == m_filed_0b01_count)
{
tempVecLinkID.push_back(vecLinkID[i]);
}
}
if (tempVecLinkID.size() == vecLinkID.size())
{
return 0;
}
else if (tempVecLinkID.size() == 0 && vecLinkID.size() != 0)
{
strcpy(_pDst, "");
}
else if (tempVecLinkID.size() == 1)
{
strcpy(_pDst, tempVecLinkID[0].c_str());
}
else
{
strcpy(_pDst, tempVecLinkID[0].c_str());
for (size_t i = 1; i < tempVecLinkID.size(); ++i)
{
strcat(_pDst, "|");
strcat(_pDst, tempVecLinkID[i].c_str());
}
}
return 1;
}
配置文件config.ini:
转载自:https://blog.csdn.net/lp310018931/article/details/78968721