封装gdal库 实现一些简单的处理矢量数据的功能

对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;
    }
}

注:本篇博客主要用来自己总结学习 技术有限 给有需要的人做个参考

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值