对gdal库进行了简单的封装,用来打开矢量数据文件 处理矢量数据 几何数据 以及获取表结构和一条条读数据 直接把源码放在这里 有需要的可以参考
头文件
#include <iostream>
#include <vector>
#include <string>
#include <gdal.h>
#include <gdal_priv.h>
#include <ogrsf_frmts.h>
#include "ogr_core.h" // 包含 OGRFieldType 枚举等基本定义
#include<geos/io/WKTReader.h>
#include<geos/io/WKTWriter.h>
#include<geos/geom/Geometry.h>
#include<geos/geom/Point.h>
#include<geos/geom/LineString.h>
#include<geos/geom/Polygon.h>
#include <fstream>
#include<sstream>
class ShapefileReader {
public:
struct Feature {
// std::vector<std::pair<double, double>> geometry; // 存储几何数据,假设为坐标对
//geometry使用geos库
//geos::geometry
std::shared_ptr<geos::geom::Geometry> geometry; // 使用GEOS Geometry类存储几何数据
std::vector<std::pair<std::string, std::string>> attributes; // 属性名-值对
};
enum class GeometryType
{
unknown,
Point,
Line,
Polygon
};
ShapefileReader();
~ShapefileReader();
// 打开 Shapefile 文件 过滤条件 (属性过滤,空间过滤)
bool open(const std::string& filePath, std::string filter = "", std::string geometryFilter = "");
//实现返回表结构函数
std::vector<std::pair<std::string, std::string>> getClassPro();
//getGeoType() 返回几何类型枚举 点线面
GeometryType getGeoType(std::shared_ptr<geos::geom::Geometry> geometry);
//一条一条获取数据
Feature ReadNext();
// 获取表结构中的所有数据 (所有数据包括几何数据)
std::vector<Feature> getAllFeatures();
// 关闭 Shapefile 文件
void close();
private:
GDALDataset* dataset = nullptr;
OGRLayer* layer = nullptr;
// 编码几何数据
// void encodeGeometry(OGRGeometry* geometry, Feature& feature);
};
源文件
#include "ShapefileReader.h"
#include <gdal.h>
#include <gdal_priv.h>
#include <ogrsf_frmts.h>
ShapefileReader::ShapefileReader() : dataset(nullptr), layer(nullptr) {
GDALAllRegister(); // 注册所有 GDAL 驱动
}
ShapefileReader::~ShapefileReader() {
close(); // 确保释放资源
}
// 打开 Shapefile 文件 过滤条件 (属性过滤,空间过滤)
bool ShapefileReader::open(const std::string& filePath, std::string filter, std::string geometryFilter) {
CPLSetConfigOption("GDAL_FILENAME_IS_UTF8", "NO"); // 支持中文路径
CPLSetConfigOption("SHAPE_ENCODING", ""); //属性表支持中文字段
// 如果已有数据集,先关闭
close();
// 打开数据集
dataset = static_cast<GDALDataset*>(GDALOpenEx(filePath.c_str(), GDAL_OF_VECTOR, nullptr, nullptr, nullptr));
if (!dataset) {
std::cerr << "Failed to open shapefile: " << filePath << std::endl;
return false;
}
std::cerr << "Success to open shapefile: " << filePath << std::endl;
// 获取第一个图层
layer = dataset->GetLayer(0);
if (!layer) {
std::cerr << "Failed to get layer from shapefile." << std::endl;
GDALClose(dataset);
dataset = nullptr;
return false;
}
//如果有属性过滤条件,设置属性过滤
if (!filter.empty()) {
layer->SetAttributeFilter(filter.c_str());
}
//如果有几何过滤条件,设置几何过滤
if (!geometryFilter.empty()) {
OGRGeometry* poGeometry = nullptr;
//假设是wkt的字符串
if (OGRGeometryFactory::createFromWkt(geometryFilter.c_str(), nullptr, &poGeometry) == OGRERR_NONE) {
layer->SetSpatialFilter(poGeometry);
OGRGeometryFactory::destroyGeometry(poGeometry);
}
else {
//如果无法解析wkt格式,则尝试解析边界框过滤
std::istringstream stream(geometryFilter);
double minX, minY, maxX, maxY;
if (stream >> minX >> minY >> maxX >> maxY) {
//设置空间过滤:最小和最大坐标
layer->SetSpatialFilterRect(minX, minY, maxX, maxY);
}
else {
std::cerr << "无效的过滤方式" << std::endl;
GDALClose(dataset);
dataset = nullptr;
return false;
}
}
}
return true;
}
//实现返回表结构函数
std::vector<std::pair<std::string, std::string>>ShapefileReader::getClassPro() {
//用来存储字段名称和字段类型
std::vector<std::pair<std::string, std::string>> fileInfo;
//获取图层的字段定义
OGRFeatureDefn* defn = layer->GetLayerDefn();
if (defn == nullptr) {
return fileInfo;
}
//便利每个字段
for (int i = 0; i < defn->GetFieldCount(); i++) {
OGRFieldDefn* fieldDefn = defn->GetFieldDefn(i);
//获取字段名称
std::string fieldName = fieldDefn->GetNameRef();
//获取字段类型并转为字符串
OGRFieldType fieldType = fieldDefn->GetType();
std::string fieldTypeStr;
switch (fieldType)
{
case OFTInteger:
fieldTypeStr = "Integer";
break;
case OFTReal:
fieldTypeStr = "Real";
break;
case OFTString:
fieldTypeStr = "String";
break;
case OFTDate:
fieldTypeStr = "Date";
break;
case OFTTime:
fieldTypeStr = "Time";
break;
case OFTDateTime:
fieldTypeStr = "DateTime";
break;
case OFTBinary:
fieldTypeStr = "Binary";
break;
case OFTIntegerList:
fieldTypeStr = "IntegerList";
break;
case OFTRealList:
fieldTypeStr = "RealList";
break;
case OFTStringList:
fieldTypeStr = "StringList";
break;
default:
break;
}
//将字段名称和类型添加到返回的向量中
fileInfo.emplace_back(fieldName, fieldTypeStr);
}
return fileInfo;
}
//getGeoType() 返回几何类型枚举 点线面
ShapefileReader::GeometryType ShapefileReader::getGeoType(std::shared_ptr<geos::geom::Geometry> geometry) {
if (!geometry) {
return GeometryType::unknown;
}
//判断几何类型
if (dynamic_cast<geos::geom::Point*>(geometry.get())) {
return GeometryType::Point;
}
else if (dynamic_cast<geos::geom::LineString*>(geometry.get())) {
return GeometryType::Line;
}
else if (dynamic_cast<geos::geom::Polygon*>(geometry.get())) {
return GeometryType::Polygon;
}
else {
return GeometryType::unknown;
}
}
ShapefileReader::Feature ShapefileReader::ReadNext()
{
OGRFeature* ogrFeature = nullptr;
Feature feature;
// 创建 WKTReader 实例
geos::io::WKTReader wktReader;
if ((ogrFeature = layer->GetNextFeature()) != nullptr) {
OGRFeatureDefn* defn = layer->GetLayerDefn();
for (int i = 0; i < defn->GetFieldCount(); i++) {
OGRFieldDefn* fieldDefn = defn->GetFieldDefn(i);
if (ogrFeature->IsFieldSet(i)) {
feature.attributes.emplace_back(fieldDefn->GetNameRef(), ogrFeature->GetFieldAsString(i));
}
}
//获取几何数据并将其转化为GEOS 对象
OGRGeometry* ogrGeometry = ogrFeature->GetGeometryRef();
if (ogrGeometry) {
//将ogrGeometry转化为wkt字符串
char* wkt = nullptr;
ogrGeometry->exportToWkt(&wkt);
if (wkt) {
// 使用 GEOS WKTReader 来解析 WKT 字符串并创建 GEOS 几何对象
try {
std::shared_ptr<geos::geom::Geometry> geometry = wktReader.read(wkt);
feature.geometry = geometry; // 将解析的 GEOS 几何对象保存到 Feature 中
}
catch (const geos::util::GEOSException& e) {
std::cerr << "Error parsing geometry: " << e.what() << std::endl;
}
CPLFree(wkt); // 释放 WKT 字符串
}
}
OGRFeature::DestroyFeature(ogrFeature);
}
return feature;
}
// 获取表结构中的所有数据 (所有数据包括几何数据)
std::vector<ShapefileReader::Feature> ShapefileReader::getAllFeatures() {
std::vector<Feature> features;
if (!layer) {
std::cerr << "Layer is not loaded." << std::endl;
return features;
}
layer->ResetReading();
OGRFeature* ogrFeature = nullptr;
//GEOS WKTReader 用来解析几何数据
geos::io::WKTReader wktReader;
while ((ogrFeature = layer->GetNextFeature()) != nullptr) {
Feature feature;
// 处理属性字段
OGRFeatureDefn* defn = layer->GetLayerDefn();
for (int i = 0; i < defn->GetFieldCount(); i++) {
OGRFieldDefn* fieldDefn = defn->GetFieldDefn(i);
if (ogrFeature->IsFieldSet(i)) {
feature.attributes.emplace_back(fieldDefn->GetNameRef(), ogrFeature->GetFieldAsString(i));
}
}
//获取几何数据并将它转为geos几何对象
OGRGeometry* ogrGeometry = ogrFeature->GetGeometryRef();
if (ogrFeature) {
//将OGRGeometry转为WKT字符串
char* wkt = nullptr;
ogrGeometry->exportToWkt(&wkt);
// 使用 GEOS 的 WKTReader 解析 WKT 字符串并创建 GEOS 几何对象
if (wkt) {
try
{
std::shared_ptr<geos::geom::Geometry> geometry = wktReader.read(wkt);
feature.geometry = geometry; // 将解析的 GEOS 几何对象保存到 Feature 中
}
catch (const geos::util::GEOSException& e)
{
std::cerr << "Error parsing geometry: " << e.what() << std::endl;
}
CPLFree(wkt); // 释放 WKT 字符串
}
}
features.push_back(feature); // 将处理后的 Feature 添加到结果集
OGRFeature::DestroyFeature(ogrFeature); // 释放 OGRFeature 对象
}
return features;
}
// 关闭 Shapefile 文件
void ShapefileReader::close() {
if (dataset) {
GDALClose(dataset);
dataset = nullptr;
layer = nullptr;
}
}
注:本篇博客主要用来自己总结学习 技术有限 给有需要的人做个参考