当前位置: 首页 > news >正文

第03章 - 核心架构解析

第03章 - 核心架构解析

3.1 架构概览

3.1.1 分层架构

OGU4Net采用清晰的分层架构设计,自上而下分为四层:

┌─────────────────────────────────────────────────────────────────┐
│                        应用层 (Application)                      │
│           OguLayerUtil / GtTxtUtil / 业务代码                    │
├─────────────────────────────────────────────────────────────────┤
│                        服务层 (Service)                          │
│              GisEngineFactory / GisEngine                       │
├─────────────────────────────────────────────────────────────────┤
│                        引擎层 (Engine)                           │
│          GdalEngine / GdalReader / GdalWriter                   │
├─────────────────────────────────────────────────────────────────┤
│                        基础层 (Foundation)                       │
│      MaxRev.Gdal.Universal (GDAL/OGR/OSR)                      │
└─────────────────────────────────────────────────────────────────┘

3.1.2 核心模块

OGU4Net由以下核心模块组成:

模块 命名空间 职责
配置模块 Configuration GDAL初始化和全局配置
数据源模块 DataSource 高层数据读写API
引擎模块 Engine GIS引擎核心实现
模型模块 Engine.Model 统一数据模型定义
几何模块 Geometry 几何处理工具
异常模块 Exception 异常类型定义
工具模块 Utils 实用工具类

3.1.3 依赖关系图

                    ┌───────────────┐│ OguLayerUtil  │└───────┬───────┘│▼┌───────────────┐│GisEngineFactory│└───────┬───────┘│▼┌───────────────┐│   GdalEngine  │└───────┬───────┘│┌─────────────┴─────────────┐▼                           ▼┌───────────────┐           ┌───────────────┐│  GdalReader   │           │  GdalWriter   │└───────┬───────┘           └───────┬───────┘│                           │└─────────────┬─────────────┘▼┌───────────────┐│  GeometryUtil ││    CrsUtil    │└───────┬───────┘│▼┌─────────────────────────────┐│  MaxRev.Gdal.Universal      ││  (OSGeo.OGR / OSGeo.OSR)    │└─────────────────────────────┘

3.2 配置模块

3.2.1 GdalConfiguration类

GdalConfiguration 是GDAL配置的核心类,负责初始化GDAL运行环境:

namespace OpenGIS.Utils.Configuration;public static class GdalConfiguration
{private static bool _isConfigured;private static readonly object _lock = new();/// <summary>/// 配置GDAL - 线程安全,可多次调用/// </summary>public static void ConfigureGdal(){lock (_lock){if (_isConfigured) return;// 使用MaxRev.Gdal.Universal自动配置GdalBase.ConfigureAll();// 注册所有驱动RegisterAllDrivers();// 设置配置选项SetConfigOptions();_isConfigured = true;}}/// <summary>/// 获取GDAL版本/// </summary>public static string GetGdalVersion(){EnsureConfigured();return Gdal.VersionInfo("RELEASE_NAME");}/// <summary>/// 获取支持的驱动列表/// </summary>public static IList<string> GetSupportedDrivers(){EnsureConfigured();var drivers = new List<string>();for (int i = 0; i < Ogr.GetDriverCount(); i++){var driver = Ogr.GetDriver(i);if (driver != null)drivers.Add(driver.GetName());}return drivers;}/// <summary>/// 检查驱动是否可用/// </summary>public static bool IsDriverAvailable(string driverName){EnsureConfigured();return Ogr.GetDriverByName(driverName) != null;}
}

设计要点:

  1. 单例模式:使用静态类确保全局唯一配置
  2. 线程安全:使用锁机制保证多线程安全
  3. 延迟初始化:首次使用时自动初始化
  4. 幂等性:多次调用不会重复初始化

3.2.2 配置选项

GDAL配置选项通过 SetConfigOptions 方法设置:

public static void SetConfigOptions()
{// 设置文件名为UTF-8编码Gdal.SetConfigOption("GDAL_FILENAME_IS_UTF8", "YES");// 设置Shapefile默认编码Gdal.SetConfigOption("SHAPE_ENCODING", "UTF-8");// 强制使用传统GIS坐标顺序 (longitude, latitude)Gdal.SetConfigOption("OGR_CT_FORCE_TRADITIONAL_GIS_ORDER", "YES");// 关闭调试信息Gdal.SetConfigOption("CPL_DEBUG", "OFF");
}

3.2.3 LibrarySettings类

LibrarySettings 提供库级别的配置常量:

namespace OpenGIS.Utils.Configuration;public static class LibrarySettings
{/// <summary>/// 默认容差值/// </summary>public const double DefaultTolerance = 0.001;/// <summary>/// 默认缓冲区分段数/// </summary>public const int DefaultBufferSegments = 30;/// <summary>/// 默认字段长度/// </summary>public const int DefaultFieldLength = 254;
}

3.3 引擎模块

3.3.1 引擎抽象设计

OGU4Net使用抽象工厂模式设计引擎层,便于扩展:

namespace OpenGIS.Utils.Engine;/// <summary>
/// GIS引擎抽象基类
/// </summary>
public abstract class GisEngine
{/// <summary>/// 引擎类型/// </summary>public abstract GisEngineType EngineType { get; }/// <summary>/// 支持的格式列表/// </summary>public abstract IList<DataFormatType> SupportedFormats { get; }/// <summary>/// 创建读取器/// </summary>public abstract ILayerReader CreateReader();/// <summary>/// 创建写入器/// </summary>public abstract ILayerWriter CreateWriter();/// <summary>/// 检查是否支持指定格式/// </summary>public virtual bool SupportsFormat(DataFormatType format){return SupportedFormats.Contains(format);}
}

3.3.2 GisEngineFactory

工厂类负责创建和管理引擎实例:

namespace OpenGIS.Utils.Engine;public static class GisEngineFactory
{// 使用单例模式private static readonly GdalEngine _gdalEngineInstance = new();/// <summary>/// 根据引擎类型获取引擎实例/// </summary>public static GisEngine GetEngine(GisEngineType engineType){return engineType switch{GisEngineType.GDAL => _gdalEngineInstance,GisEngineType.GEOTOOLS => _gdalEngineInstance, // 兼容性:重定向到GDAL_ => throw new EngineNotSupportedException($"Engine {engineType} not supported")};}/// <summary>/// 根据数据格式自动选择引擎/// </summary>public static GisEngine GetEngine(DataFormatType format){// 所有格式都使用GDAL引擎return _gdalEngineInstance;}/// <summary>/// 尝试获取引擎/// </summary>public static bool TryGetEngine(DataFormatType format, out GisEngine? engine){engine = _gdalEngineInstance;return true;}
}

设计要点:

  1. 单例引擎:引擎实例全局唯一,避免重复创建
  2. 自动选择:根据数据格式自动选择合适的引擎
  3. 向后兼容:GEOTOOLS类型重定向到GDAL

3.3.3 GdalEngine实现

namespace OpenGIS.Utils.Engine;public class GdalEngine : GisEngine
{public override GisEngineType EngineType => GisEngineType.GDAL;public override IList<DataFormatType> SupportedFormats => new List<DataFormatType>{DataFormatType.SHP,DataFormatType.GEOJSON,DataFormatType.FILEGDB,DataFormatType.GEOPACKAGE,DataFormatType.KML,DataFormatType.DXF,DataFormatType.POSTGIS};public override ILayerReader CreateReader(){return new GdalReader();}public override ILayerWriter CreateWriter(){return new GdalWriter();}
}

3.4 读写器接口

3.4.1 ILayerReader接口

namespace OpenGIS.Utils.Engine.IO;public interface ILayerReader
{/// <summary>/// 读取图层/// </summary>/// <param name="path">数据源路径</param>/// <param name="layerName">图层名称,null则读取第一个图层</param>/// <param name="attributeFilter">属性过滤条件(SQL WHERE子句)</param>/// <param name="spatialFilterWkt">空间过滤几何(WKT格式)</param>/// <param name="options">附加选项</param>OguLayer Read(string path,string? layerName = null,string? attributeFilter = null,string? spatialFilterWkt = null,Dictionary<string, object>? options = null);/// <summary>/// 获取图层名称列表/// </summary>IList<string> GetLayerNames(string path);
}

3.4.2 ILayerWriter接口

namespace OpenGIS.Utils.Engine.IO;public interface ILayerWriter
{/// <summary>/// 写入图层/// </summary>/// <param name="layer">图层对象</param>/// <param name="path">输出路径</param>/// <param name="layerName">图层名称,null则使用layer.Name</param>/// <param name="options">附加选项</param>void Write(OguLayer layer,string path,string? layerName = null,Dictionary<string, object>? options = null);/// <summary>/// 追加要素到已存在的图层/// </summary>void Append(OguLayer layer,string path,string? layerName = null,Dictionary<string, object>? options = null);
}

3.4.3 GdalReader实现要点

public class GdalReader : ILayerReader
{static GdalReader(){// 确保GDAL已初始化GdalConfiguration.ConfigureGdal();}public OguLayer Read(string path, string? layerName = null, ...){// 1. 打开数据源using var dataSource = Ogr.Open(path, 0); // 0 = 只读// 2. 获取图层var ogrLayer = layerName != null? dataSource.GetLayerByName(layerName): dataSource.GetLayerByIndex(0);// 3. 读取并转换return ReadOgrLayer(ogrLayer, attributeFilter, spatialFilterWkt);}private OguLayer ReadOgrLayer(Layer ogrLayer, ...){var layer = new OguLayer { Name = ogrLayer.GetName() };// 读取字段定义var layerDefn = ogrLayer.GetLayerDefn();for (int i = 0; i < layerDefn.GetFieldCount(); i++){var fieldDefn = layerDefn.GetFieldDefn(i);layer.AddField(new OguField{Name = fieldDefn.GetName(),DataType = MapOgrFieldType(fieldDefn.GetFieldType()),Length = fieldDefn.GetWidth(),Precision = fieldDefn.GetPrecision()});}// 读取几何类型layer.GeometryType = MapOgrGeometryType(ogrLayer.GetGeomType());// 应用过滤条件if (!string.IsNullOrWhiteSpace(attributeFilter))ogrLayer.SetAttributeFilter(attributeFilter);// 读取要素int fid = 1;Feature? ogrFeature;while ((ogrFeature = ogrLayer.GetNextFeature()) != null){using (ogrFeature){var feature = ReadOgrFeature(ogrFeature, layer.Fields, fid++);layer.AddFeature(feature);}}return layer;}
}

关键设计:

  1. 资源管理:使用using确保DataSource正确释放
  2. 类型映射:OGR类型到OGU类型的映射
  3. 过滤支持:属性过滤和空间过滤
  4. 延迟读取:使用迭代器模式读取要素

3.5 数据源模块

3.5.1 OguLayerUtil设计

OguLayerUtil 是面向应用层的高级API,封装了引擎选择和读写操作:

namespace OpenGIS.Utils.DataSource;public static class OguLayerUtil
{/// <summary>/// 读取图层/// </summary>public static OguLayer ReadLayer(DataFormatType format,string path,string? layerName = null,string? attributeFilter = null,string? spatialFilterWkt = null,GisEngineType? engineType = null,Dictionary<string, object>? options = null){// 参数验证if (string.IsNullOrWhiteSpace(path))throw new ArgumentException("Path cannot be null or empty", nameof(path));// 获取引擎var engine = engineType.HasValue? GisEngineFactory.GetEngine(engineType.Value): GisEngineFactory.GetEngine(format);// 创建读取器并读取var reader = engine.CreateReader();return reader.Read(path, layerName, attributeFilter, spatialFilterWkt, options);}/// <summary>/// 异步读取图层/// </summary>public static Task<OguLayer> ReadLayerAsync(...){return Task.Run(() => ReadLayer(...));}/// <summary>/// 写入图层/// </summary>public static void WriteLayer(DataFormatType format,OguLayer layer,string path,string? layerName = null,GisEngineType? engineType = null,Dictionary<string, object>? options = null){// 参数验证if (layer == null)throw new ArgumentNullException(nameof(layer));if (string.IsNullOrWhiteSpace(path))throw new ArgumentException("Path cannot be null or empty", nameof(path));// 获取引擎var engine = engineType.HasValue? GisEngineFactory.GetEngine(engineType.Value): GisEngineFactory.GetEngine(format);// 创建写入器并写入var writer = engine.CreateWriter();writer.Write(layer, path, layerName, options);}/// <summary>/// 格式转换/// </summary>public static void ConvertFormat(string inputPath,DataFormatType inputFormat,string outputPath,DataFormatType outputFormat,GisEngineType? engineType = null,string? layerName = null){// 读取var layer = ReadLayer(inputFormat, inputPath, layerName, engineType: engineType);// 写入WriteLayer(outputFormat, layer, outputPath, layerName, engineType);}
}

设计特点:

  1. 静态工具类:无状态,线程安全
  2. 参数灵活:支持可选参数,简化常见用法
  3. 异步支持:提供异步版本方法
  4. 格式转换:一键实现格式转换

3.6 类型映射系统

3.6.1 几何类型映射

// OGR几何类型 → OGU几何类型
private GeometryType MapOgrGeometryType(wkbGeometryType geomType)
{// 移除Z/M维度标志var flatType = wkbFlatten((int)geomType);return flatType switch{wkbGeometryType.wkbPoint => GeometryType.POINT,wkbGeometryType.wkbLineString => GeometryType.LINESTRING,wkbGeometryType.wkbPolygon => GeometryType.POLYGON,wkbGeometryType.wkbMultiPoint => GeometryType.MULTIPOINT,wkbGeometryType.wkbMultiLineString => GeometryType.MULTILINESTRING,wkbGeometryType.wkbMultiPolygon => GeometryType.MULTIPOLYGON,wkbGeometryType.wkbGeometryCollection => GeometryType.GEOMETRYCOLLECTION,_ => GeometryType.UNKNOWN};
}// OGU几何类型 → OGR几何类型
private wkbGeometryType MapToOgrGeometryType(GeometryType geomType)
{return geomType switch{GeometryType.POINT => wkbGeometryType.wkbPoint,GeometryType.LINESTRING => wkbGeometryType.wkbLineString,GeometryType.POLYGON => wkbGeometryType.wkbPolygon,GeometryType.MULTIPOINT => wkbGeometryType.wkbMultiPoint,GeometryType.MULTILINESTRING => wkbGeometryType.wkbMultiLineString,GeometryType.MULTIPOLYGON => wkbGeometryType.wkbMultiPolygon,GeometryType.GEOMETRYCOLLECTION => wkbGeometryType.wkbGeometryCollection,_ => wkbGeometryType.wkbUnknown};
}

3.6.2 字段类型映射

// OGR字段类型 → OGU字段类型
private FieldDataType MapOgrFieldType(FieldType ogrType)
{return ogrType switch{FieldType.OFTInteger => FieldDataType.INTEGER,FieldType.OFTInteger64 => FieldDataType.LONG,FieldType.OFTReal => FieldDataType.DOUBLE,FieldType.OFTString => FieldDataType.STRING,FieldType.OFTDate => FieldDataType.DATE,FieldType.OFTDateTime => FieldDataType.DATETIME,FieldType.OFTBinary => FieldDataType.BINARY,_ => FieldDataType.STRING  // 默认为字符串};
}// OGU字段类型 → OGR字段类型
private FieldType MapToOgrFieldType(FieldDataType dataType)
{return dataType switch{FieldDataType.INTEGER => FieldType.OFTInteger,FieldDataType.LONG => FieldType.OFTInteger64,FieldDataType.DOUBLE => FieldType.OFTReal,FieldDataType.FLOAT => FieldType.OFTReal,FieldDataType.STRING => FieldType.OFTString,FieldDataType.DATE => FieldType.OFTDate,FieldDataType.DATETIME => FieldType.OFTDateTime,FieldDataType.BINARY => FieldType.OFTBinary,_ => FieldType.OFTString};
}

3.6.3 驱动名称推断

private string InferDriverName(string path, Dictionary<string, object>? options)
{// 优先从选项中获取if (options?.TryGetValue("driver", out var driverObj) == true)return driverObj.ToString() ?? "ESRI Shapefile";// 根据扩展名推断var extension = Path.GetExtension(path).ToLowerInvariant();return extension switch{".shp" => "ESRI Shapefile",".gdb" => "FileGDB",".gpkg" => "GPKG",".kml" => "KML",".dxf" => "DXF",".geojson" or ".json" => "GeoJSON",_ => "ESRI Shapefile"  // 默认};
}

3.7 资源管理

3.7.1 GDAL对象生命周期

GDAL/OGR对象需要正确管理以避免内存泄漏:

// 正确的资源管理方式
public OguLayer Read(string path, ...)
{OgrDataSource? dataSource = null;try{dataSource = Ogr.Open(path, 0);if (dataSource == null)throw new DataSourceException($"Failed to open: {path}");// 处理逻辑...return layer;}finally{dataSource?.Dispose();}
}

3.7.2 要素迭代模式

// 逐个处理要素,及时释放资源
Feature? ogrFeature;
while ((ogrFeature = ogrLayer.GetNextFeature()) != null)
{using (ogrFeature)  // 确保每个要素都被释放{var feature = ConvertFeature(ogrFeature);layer.AddFeature(feature);}
}

3.7.3 几何对象管理

public void Write(OguLayer layer, string path, ...)
{foreach (var oguFeature in layer.Features){Feature? ogrFeature = null;OSGeo.OGR.Geometry? geometry = null;try{ogrFeature = new Feature(layerDefn);// 创建几何(需要单独管理)geometry = OSGeo.OGR.Geometry.CreateFromWkt(oguFeature.Wkt);if (geometry != null)ogrFeature.SetGeometry(geometry);// 写入要素ogrLayer.CreateFeature(ogrFeature);}finally{geometry?.Dispose();  // 先释放几何ogrFeature?.Dispose(); // 再释放要素}}
}

3.8 扩展点设计

3.8.1 添加新引擎

如需添加新的GIS引擎,可以:

  1. 继承 GisEngine 抽象类
  2. 实现 ILayerReaderILayerWriter 接口
  3. GisEngineFactory 中注册
// 示例:添加新引擎
public class MyCustomEngine : GisEngine
{public override GisEngineType EngineType => GisEngineType.CUSTOM;public override IList<DataFormatType> SupportedFormats => new List<DataFormatType> { DataFormatType.CUSTOM };public override ILayerReader CreateReader() => new MyCustomReader();public override ILayerWriter CreateWriter() => new MyCustomWriter();
}

3.8.2 添加新数据格式

添加新格式支持:

  1. DataFormatType 枚举中添加新类型
  2. 在驱动名称推断逻辑中添加映射
  3. 确保GDAL支持该格式的驱动

3.9 小结

本章详细解析了OGU4Net的核心架构:

  1. 分层架构:应用层、服务层、引擎层、基础层清晰分离
  2. 配置模块:线程安全的GDAL初始化和配置管理
  3. 引擎模块:抽象工厂模式,支持扩展
  4. 读写器设计:接口驱动,职责单一
  5. 类型映射:OGR与OGU类型的双向映射
  6. 资源管理:正确管理GDAL对象生命周期

理解这些架构设计,有助于更好地使用和扩展OGU4Net框架。

http://www.jsqmd.com/news/59594/

相关文章:

  • 2025年房梁榫卯产品定制厂家权威推荐榜单:房梁榫卯产品介绍图‌/房梁结构‌/房梁榫卯产品介绍‌源头厂家精选
  • 2025热处理行业厂家TOP5指南:甄选制造商助力工业升级
  • day4敏捷冲刺
  • 深入解析:微信小程序如何优雅地跳转外部链接?WebView + 复制方案实战
  • 2025年高性价比金属探测仪品牌推荐,看看哪家实力强
  • 2025年中国十大热处理服务商家推荐:看看哪家技术实力更强
  • 2025年成都值得信赖的网络推广服务商排行,网络推广/网络公关/GEO优化/SEO优化/网站建设/小红书代运营/小红书推广网络推广公司找哪家
  • 全自动咖啡机品牌排名 哪些品牌值得关注
  • day3敏捷冲刺
  • 什么是Hook?
  • 全自动咖啡机推荐:多场景适用的品质之选
  • 习题解析之:查找特征数
  • 云监控 UModel Explorer:用“图形化”重新定义可观测数据建模
  • 小红书种草公司哪家专业,哪家更推荐?
  • 国产全自动咖啡机排名:主流品牌实力解析
  • 国产全自动咖啡机品牌推荐:高口碑国产品牌精选
  • Abaqus 2025 全新体验 仿真效率再提升,让复杂工况更真实 下载安装步骤
  • 洛珈山下冲刺博客3rd
  • 2025年最新ISO认证机构客户满意度排名,ISO9001/ISO14001/ISO45001/ISO认证代办哪家好
  • 2025年中国十大高精度称重模块解决方案公司推荐:看哪家口碑
  • 从0开始重新学python+neo4j之文件读写、函数、异常
  • 2025年度圆吐司去皮机制造厂五大推荐,显裕机械性能优异
  • 2025年石化行业正规供应商TOP5推荐:中阳机械技术精湛
  • 2025年石化行业资深厂商TOP5推荐:源头石化老牌厂家全解
  • 实用指南:Nestjs框架: 微服务事件驱动通信与超时处理机制优化基于Event-Based 通信及异常捕获实践
  • 2025 年 12 月纳米砂磨机,卧式砂磨机,工业砂磨机厂家最新推荐,产能、专利、环保三维数据透视!
  • P1.语义分割与MMSegmentation
  • 迅为RK3588开发板Android系统烧写及注意事项
  • 博士留学面试辅导红黑榜:谁的模拟训练最接近实战?
  • c语言判断某个点是否在凸四边形内部,边界范围用