第04章 - 统一图层模型详解
第04章 - 统一图层模型详解
4.1 模型体系概述
4.1.1 模型层次结构
OGU4Net定义了一套简洁而完整的GIS数据模型体系:
OguLayer (图层)
├── Fields: IList<OguField> (字段定义列表)
├── Features: IList<OguFeature> (要素列表)
└── Metadata: OguLayerMetadata? (图层元数据)
OguFeature (要素)
├── Fid: int (要素ID)
├── Wkt: string? (几何信息,WKT格式)
└── Attributes: Dictionary<string, OguFieldValue> (属性值)
OguField (字段定义)
├── Name: string (字段名)
├── Alias: string? (别名)
├── DataType: FieldDataType (数据类型)
├── Length: int? (字段长度)
├── Precision: int? (精度)
├── Scale: int? (小数位数)
├── IsNullable: bool (是否可空)
└── DefaultValue: object? (默认值)
OguFieldValue (字段值)
└── Value: object? (原始值)
+ 类型安全的转换方法
4.1.2 设计原则
- 独立性:模型不依赖任何底层GIS库
- 序列化友好:支持JSON序列化/反序列化
- 类型安全:OguFieldValue提供类型安全的访问方法
- 可验证:内置数据完整性验证
- 可克隆:支持深拷贝操作
4.2 OguLayer类详解
4.2.1 类定义
namespace OpenGIS.Utils.Engine.Model.Layer;
/// <summary>
/// 统一的GIS图层定义类
/// </summary>
public class OguLayer
{
/// <summary>
/// 图层名称
/// </summary>
public string Name { get; set; } = string.Empty;
/// <summary>
/// 坐标系WKID (Well-Known ID)
/// </summary>
public int? Wkid { get; set; }
/// <summary>
/// 几何类型
/// </summary>
public GeometryType GeometryType { get; set; }
/// <summary>
/// 字段定义列表
/// </summary>
public IList<OguField> Fields { get; set; }
/// <summary>
/// 要素集合
/// </summary>
public IList<OguFeature> Features { get; set; }
/// <summary>
/// 图层元数据
/// </summary>
public OguLayerMetadata? Metadata { get; set; }
public OguLayer()
{
Fields = new List<OguField>();
Features = new List<OguFeature>();
}
}
4.2.2 核心方法
添加字段:
/// <summary>
/// 添加字段
/// </summary>
/// <exception cref="LayerValidationException">字段名重复时抛出</exception>
public void AddField(OguField field)
{
if (Fields.Any(f => f.Name == field.Name))
throw new LayerValidationException($"Field '{field.Name}' already exists");
Fields.Add(field);
}
// 使用示例
layer.AddField(new OguField
{
Name = "ID",
DataType = FieldDataType.INTEGER
});
layer.AddField(new OguField
{
Name = "Name",
DataType = FieldDataType.STRING,
Length = 100,
IsNullable = false
});
获取字段:
/// <summary>
/// 根据字段名获取字段定义
/// </summary>
public OguField? GetField(string fieldName)
{
return Fields.FirstOrDefault(f => f.Name == fieldName);
}
// 使用示例
var idField = layer.GetField("ID");
if (idField != null)
{
Console.WriteLine($"ID字段类型: {idField.DataType}");
}
添加/移除要素:
/// <summary>
/// 添加要素
/// </summary>
public void AddFeature(OguFeature feature)
{
Features.Add(feature);
}
/// <summary>
/// 移除要素
/// </summary>
/// <returns>是否成功移除</returns>
public bool RemoveFeature(int fid)
{
var feature = Features.FirstOrDefault(f => f.Fid == fid);
if (feature != null)
{
Features.Remove(feature);
return true;
}
return false;
}
// 使用示例
var feature = new OguFeature { Fid = 1, Wkt = "POINT (0 0)" };
layer.AddFeature(feature);
layer.RemoveFeature(1);
过滤要素:
/// <summary>
/// 过滤要素
/// </summary>
public IList<OguFeature> Filter(Func<OguFeature, bool> filter)
{
return Features.Where(filter).ToList();
}
// 使用示例:查找人口超过1000万的城市
var bigCities = layer.Filter(f =>
{
var pop = f.GetAttribute("Population")?.GetLongValue();
return pop.HasValue && pop.Value > 10000000;
});
4.2.3 验证机制
/// <summary>
/// 验证图层数据完整性
/// </summary>
/// <exception cref="LayerValidationException">验证失败时抛出</exception>
public void Validate()
{
// 1. 验证图层名称
if (string.IsNullOrWhiteSpace(Name))
throw new LayerValidationException("Layer name cannot be null or empty");
// 2. 验证必须有字段
if (Fields == null || Fields.Count == 0)
throw new LayerValidationException("Layer must have at least one field");
// 3. 验证字段名唯一性
var fieldNameSet = new HashSet<string>();
foreach (var field in Fields)
{
if (!fieldNameSet.Add(field.Name))
throw new LayerValidationException($"Field name '{field.Name}' is duplicated");
}
// 4. 验证要素属性与字段定义一致
foreach (var feature in Features)
{
foreach (var fieldName in feature.Attributes.Keys)
{
if (!fieldNameSet.Contains(fieldName))
throw new LayerValidationException(
$"Feature contains attribute '{fieldName}' not defined in Fields");
}
}
}
// 使用示例
try
{
layer.Validate();
Console.WriteLine("Layer validation passed");
}
catch (LayerValidationException ex)
{
Console.WriteLine($"Validation failed: {ex.Message}");
}
4.2.4 序列化支持
/// <summary>
/// 转换为JSON字符串
/// </summary>
public string ToJson()
{
return JsonSerializer.Serialize(this, new JsonSerializerOptions
{
WriteIndented = true
});
}
/// <summary>
/// 从JSON创建图层
/// </summary>
public static OguLayer? FromJson(string json)
{
return JsonSerializer.Deserialize<OguLayer>(json);
}
// 使用示例
string json = layer.ToJson();
Console.WriteLine(json);
OguLayer? restored = OguLayer.FromJson(json);
4.2.5 深拷贝
/// <summary>
/// 深拷贝
/// </summary>
public OguLayer Clone()
{
var clone = new OguLayer
{
Name = Name,
Wkid = Wkid,
GeometryType = GeometryType
};
// 复制字段
foreach (var field in Fields)
clone.Fields.Add(field.Clone());
// 复制要素
foreach (var feature in Features)
clone.Features.Add(feature.Clone());
// 复制元数据
if (Metadata != null)
{
clone.Metadata = new OguLayerMetadata
{
DataSource = Metadata.DataSource,
CoordinateSystemName = Metadata.CoordinateSystemName,
ZoneDivision = Metadata.ZoneDivision,
ProjectionType = Metadata.ProjectionType,
MeasureUnit = Metadata.MeasureUnit,
CreateTime = Metadata.CreateTime,
ModifyTime = Metadata.ModifyTime
};
foreach (var kvp in Metadata.ExtendedProperties)
clone.Metadata.ExtendedProperties[kvp.Key] = kvp.Value;
}
return clone;
}
4.3 OguFeature类详解
4.3.1 类定义
namespace OpenGIS.Utils.Engine.Model.Layer;
/// <summary>
/// 统一的要素类
/// </summary>
public class OguFeature
{
/// <summary>
/// 要素ID
/// </summary>
public int Fid { get; set; }
/// <summary>
/// 几何信息(WKT格式)
/// </summary>
public string? Wkt { get; set; }
/// <summary>
/// 属性值字典
/// </summary>
public Dictionary<string, OguFieldValue> Attributes { get; set; }
public OguFeature()
{
Attributes = new Dictionary<string, OguFieldValue>();
}
}
4.3.2 属性操作
设置属性值:
/// <summary>
/// 设置属性值
/// </summary>
public void SetValue(string fieldName, object? value)
{
if (Attributes.TryGetValue(fieldName, out var fieldValue))
fieldValue.Value = value;
else
Attributes[fieldName] = new OguFieldValue(value);
}
// 使用示例
feature.SetValue("ID", 1);
feature.SetValue("Name", "北京");
feature.SetValue("Population", 21540000L);
feature.SetValue("Area", 16410.54);
feature.SetValue("CreateDate", DateTime.Now);
获取属性值:
/// <summary>
/// 获取属性原始值
/// </summary>
public object? GetValue(string fieldName)
{
return Attributes.TryGetValue(fieldName, out var fieldValue)
? fieldValue.Value
: null;
}
/// <summary>
/// 获取字段值对象
/// </summary>
public OguFieldValue? GetAttribute(string fieldName)
{
return Attributes.TryGetValue(fieldName, out var fieldValue)
? fieldValue
: null;
}
/// <summary>
/// 判断是否存在属性
/// </summary>
public bool HasAttribute(string fieldName)
{
return Attributes.ContainsKey(fieldName);
}
// 使用示例
var name = feature.GetValue("Name");
Console.WriteLine($"城市名: {name}");
var popAttr = feature.GetAttribute("Population");
if (popAttr != null && !popAttr.IsNull)
{
long? pop = popAttr.GetLongValue();
Console.WriteLine($"人口: {pop:N0}");
}
if (feature.HasAttribute("Area"))
{
Console.WriteLine("存在面积字段");
}
4.3.3 完整使用示例
// 创建要素
var feature = new OguFeature
{
Fid = 1,
Wkt = "POLYGON ((116.3 39.9, 116.5 39.9, 116.5 40.0, 116.3 40.0, 116.3 39.9))"
};
// 设置各类型属性
feature.SetValue("ID", 1);
feature.SetValue("Name", "北京朝阳区");
feature.SetValue("Population", 3650000L);
feature.SetValue("Area", 470.8);
feature.SetValue("IsCapital", true);
feature.SetValue("CreateTime", new DateTime(2024, 1, 1));
// 类型安全地获取属性
var popAttr = feature.GetAttribute("Population");
long population = popAttr?.GetLongValue() ?? 0;
var areaAttr = feature.GetAttribute("Area");
double area = areaAttr?.GetDoubleValue() ?? 0;
var isCapitalAttr = feature.GetAttribute("IsCapital");
bool isCapital = isCapitalAttr?.GetBoolValue() ?? false;
var timeAttr = feature.GetAttribute("CreateTime");
DateTime? createTime = timeAttr?.GetDateTimeValue();
Console.WriteLine($"人口: {population:N0}");
Console.WriteLine($"面积: {area:F2} 平方公里");
Console.WriteLine($"是否首都: {isCapital}");
Console.WriteLine($"创建时间: {createTime:yyyy-MM-dd}");
4.4 OguField类详解
4.4.1 类定义
namespace OpenGIS.Utils.Engine.Model.Layer;
/// <summary>
/// 统一的字段定义类
/// </summary>
public class OguField
{
/// <summary>
/// 字段名称
/// </summary>
public string Name { get; set; } = string.Empty;
/// <summary>
/// 字段别名
/// </summary>
public string? Alias { get; set; }
/// <summary>
/// 数据类型
/// </summary>
public FieldDataType DataType { get; set; }
/// <summary>
/// 字段长度(字符串类型)
/// </summary>
public int? Length { get; set; }
/// <summary>
/// 精度(数字类型总位数)
/// </summary>
public int? Precision { get; set; }
/// <summary>
/// 小数位数(数字类型)
/// </summary>
public int? Scale { get; set; }
/// <summary>
/// 是否可为空
/// </summary>
public bool IsNullable { get; set; } = true;
/// <summary>
/// 默认值
/// </summary>
public object? DefaultValue { get; set; }
}
4.4.2 字段数据类型
namespace OpenGIS.Utils.Engine.Enums;
/// <summary>
/// 字段数据类型枚举
/// </summary>
public enum FieldDataType
{
STRING, // 字符串
INTEGER, // 32位整数
LONG, // 64位整数
DOUBLE, // 双精度浮点
FLOAT, // 单精度浮点
BOOLEAN, // 布尔值
DATE, // 日期
DATETIME, // 日期时间
BINARY, // 二进制
UNKNOWN // 未知类型
}
4.4.3 创建各类型字段
// 整数字段
var idField = new OguField
{
Name = "ID",
DataType = FieldDataType.INTEGER,
IsNullable = false
};
// 字符串字段(指定长度)
var nameField = new OguField
{
Name = "Name",
Alias = "名称",
DataType = FieldDataType.STRING,
Length = 100,
IsNullable = false,
DefaultValue = "未命名"
};
// 长整数字段
var populationField = new OguField
{
Name = "Population",
Alias = "人口",
DataType = FieldDataType.LONG
};
// 双精度浮点字段(指定精度)
var areaField = new OguField
{
Name = "Area",
Alias = "面积",
DataType = FieldDataType.DOUBLE,
Precision = 15,
Scale = 4
};
// 日期时间字段
var createTimeField = new OguField
{
Name = "CreateTime",
Alias = "创建时间",
DataType = FieldDataType.DATETIME,
DefaultValue = DateTime.Now
};
// 布尔字段
var isActiveField = new OguField
{
Name = "IsActive",
Alias = "是否激活",
DataType = FieldDataType.BOOLEAN,
DefaultValue = true
};
4.5 OguFieldValue类详解
4.5.1 类定义
namespace OpenGIS.Utils.Engine.Model.Layer;
/// <summary>
/// 字段值容器,提供类型安全的转换方法
/// </summary>
public class OguFieldValue
{
/// <summary>
/// 原始值
/// </summary>
public object? Value { get; set; }
/// <summary>
/// 是否为空
/// </summary>
public bool IsNull => Value == null;
public OguFieldValue() { }
public OguFieldValue(object? value)
{
Value = value;
}
}
4.5.2 类型转换方法
/// <summary>
/// 转为字符串
/// </summary>
public string? GetStringValue()
{
return Value?.ToString();
}
/// <summary>
/// 转为整数
/// </summary>
public int? GetIntValue()
{
if (IsNull) return null;
if (Value is int i) return i;
if (int.TryParse(Value?.ToString(), out int result))
return result;
return null;
}
/// <summary>
/// 转为长整数
/// </summary>
public long? GetLongValue()
{
if (IsNull) return null;
if (Value is long l) return l;
if (long.TryParse(Value?.ToString(), out long result))
return result;
return null;
}
/// <summary>
/// 转为双精度浮点
/// </summary>
public double? GetDoubleValue()
{
if (IsNull) return null;
if (Value is double d) return d;
if (double.TryParse(Value?.ToString(), out double result))
return result;
return null;
}
/// <summary>
/// 转为单精度浮点
/// </summary>
public float? GetFloatValue()
{
if (IsNull) return null;
if (Value is float f) return f;
if (float.TryParse(Value?.ToString(), out float result))
return result;
return null;
}
/// <summary>
/// 转为布尔值
/// </summary>
public bool? GetBoolValue()
{
if (IsNull) return null;
if (Value is bool b) return b;
if (bool.TryParse(Value?.ToString(), out bool result))
return result;
return null;
}
/// <summary>
/// 转为日期时间
/// </summary>
public DateTime? GetDateTimeValue()
{
if (IsNull) return null;
if (Value is DateTime dt) return dt;
if (DateTime.TryParse(Value?.ToString(), out DateTime result))
return result;
return null;
}
/// <summary>
/// 转为Decimal
/// </summary>
public decimal? GetDecimalValue()
{
if (IsNull) return null;
if (Value is decimal dec) return dec;
if (decimal.TryParse(Value?.ToString(), out decimal result))
return result;
return null;
}
4.5.3 类型转换示例
// 创建要素并设置属性
var feature = new OguFeature { Fid = 1 };
feature.SetValue("IntValue", 42);
feature.SetValue("StringValue", "Hello");
feature.SetValue("DoubleValue", 3.14159);
feature.SetValue("DateValue", DateTime.Now);
feature.SetValue("BoolValue", true);
feature.SetValue("NullValue", null);
// 类型安全的转换
var intAttr = feature.GetAttribute("IntValue");
int? intVal = intAttr?.GetIntValue(); // 42
string? strVal = intAttr?.GetStringValue(); // "42"
var doubleAttr = feature.GetAttribute("DoubleValue");
double? doubleVal = doubleAttr?.GetDoubleValue(); // 3.14159
int? intFromDouble = doubleAttr?.GetIntValue(); // null (转换失败)
var nullAttr = feature.GetAttribute("NullValue");
bool isNull = nullAttr?.IsNull ?? true; // true
string? nullStr = nullAttr?.GetStringValue(); // null
// 安全获取值(带默认值)
long population = feature.GetAttribute("Population")?.GetLongValue() ?? 0;
string name = feature.GetAttribute("Name")?.GetStringValue() ?? "未知";
double area = feature.GetAttribute("Area")?.GetDoubleValue() ?? 0.0;
4.6 OguCoordinate类
4.6.1 类定义
namespace OpenGIS.Utils.Engine.Model.Layer;
/// <summary>
/// 坐标点类(支持2D/3D)
/// </summary>
public class OguCoordinate
{
/// <summary>
/// X坐标(经度)
/// </summary>
public double X { get; set; }
/// <summary>
/// Y坐标(纬度)
/// </summary>
public double Y { get; set; }
/// <summary>
/// Z坐标(高程,可选)
/// </summary>
public double? Z { get; set; }
/// <summary>
/// 点号(用于TXT格式)
/// </summary>
public string? PointNumber { get; set; }
/// <summary>
/// 圈号(用于TXT格式)
/// </summary>
public string? RingNumber { get; set; }
/// <summary>
/// 备注
/// </summary>
public string? Remark { get; set; }
}
4.6.2 WKT转换
/// <summary>
/// 转换为WKT
/// </summary>
public string ToWkt()
{
if (Z.HasValue)
return $"POINT Z ({X} {Y} {Z.Value})";
return $"POINT ({X} {Y})";
}
/// <summary>
/// 从WKT创建
/// </summary>
public static OguCoordinate FromWkt(string wkt)
{
// 解析 POINT (x y) 或 POINT Z (x y z) 格式
var match = Regex.Match(wkt, @"POINT\s*Z?\s*\(\s*([\d.-]+)\s+([\d.-]+)\s*([\d.-]+)?\s*\)");
if (!match.Success)
throw new FormatException($"Invalid WKT: {wkt}");
var coord = new OguCoordinate
{
X = double.Parse(match.Groups[1].Value),
Y = double.Parse(match.Groups[2].Value)
};
if (!string.IsNullOrEmpty(match.Groups[3].Value))
coord.Z = double.Parse(match.Groups[3].Value);
return coord;
}
4.6.3 使用示例
// 创建2D坐标
var coord2d = new OguCoordinate
{
X = 116.404,
Y = 39.915
};
Console.WriteLine(coord2d.ToWkt()); // POINT (116.404 39.915)
// 创建3D坐标
var coord3d = new OguCoordinate
{
X = 116.404,
Y = 39.915,
Z = 50.5
};
Console.WriteLine(coord3d.ToWkt()); // POINT Z (116.404 39.915 50.5)
// 创建带点号的坐标(用于国土TXT)
var coordWithNumber = new OguCoordinate
{
X = 456789.123,
Y = 4321098.456,
PointNumber = "J1",
RingNumber = "1",
Remark = "界址点1"
};
// 从WKT创建
var fromWkt = OguCoordinate.FromWkt("POINT (116.404 39.915)");
Console.WriteLine($"X: {fromWkt.X}, Y: {fromWkt.Y}");
4.7 OguLayerMetadata类
4.7.1 类定义
namespace OpenGIS.Utils.Engine.Model.Layer;
/// <summary>
/// 图层元数据
/// </summary>
public class OguLayerMetadata
{
/// <summary>
/// 数据来源
/// </summary>
public string? DataSource { get; set; }
/// <summary>
/// 坐标系名称
/// </summary>
public string? CoordinateSystemName { get; set; }
/// <summary>
/// 分带方式(3度带/6度带)
/// </summary>
public string? ZoneDivision { get; set; }
/// <summary>
/// 投影类型
/// </summary>
public string? ProjectionType { get; set; }
/// <summary>
/// 计量单位
/// </summary>
public string? MeasureUnit { get; set; }
/// <summary>
/// 创建时间
/// </summary>
public DateTime? CreateTime { get; set; }
/// <summary>
/// 修改时间
/// </summary>
public DateTime? ModifyTime { get; set; }
/// <summary>
/// 扩展属性
/// </summary>
public Dictionary<string, object> ExtendedProperties { get; set; }
= new Dictionary<string, object>();
}
4.7.2 使用示例
// 创建元数据
var metadata = new OguLayerMetadata
{
DataSource = "自然资源部",
CoordinateSystemName = "CGCS2000 / 3-degree Gauss-Kruger zone 39",
ZoneDivision = "3度带",
ProjectionType = "高斯-克吕格投影",
MeasureUnit = "米",
CreateTime = DateTime.Now
};
// 添加扩展属性
metadata.ExtendedProperties["Author"] = "张三";
metadata.ExtendedProperties["Version"] = "1.0";
metadata.ExtendedProperties["Quality"] = "A级";
// 关联到图层
layer.Metadata = metadata;
// 读取元数据
if (layer.Metadata != null)
{
Console.WriteLine($"数据来源: {layer.Metadata.DataSource}");
Console.WriteLine($"坐标系: {layer.Metadata.CoordinateSystemName}");
if (layer.Metadata.ExtendedProperties.TryGetValue("Author", out var author))
{
Console.WriteLine($"作者: {author}");
}
}
4.8 几何类型枚举
4.8.1 GeometryType定义
namespace OpenGIS.Utils.Engine.Enums;
/// <summary>
/// 几何类型枚举
/// </summary>
public enum GeometryType
{
POINT, // 点
LINESTRING, // 线
POLYGON, // 面
MULTIPOINT, // 多点
MULTILINESTRING, // 多线
MULTIPOLYGON, // 多面
GEOMETRYCOLLECTION, // 几何集合
UNKNOWN // 未知类型
}
4.8.2 几何类型与WKT
| GeometryType | WKT示例 |
|---|---|
| POINT | POINT (0 0) |
| LINESTRING | LINESTRING (0 0, 1 1, 2 0) |
| POLYGON | POLYGON ((0 0, 10 0, 10 10, 0 10, 0 0)) |
| MULTIPOINT | MULTIPOINT ((0 0), (1 1)) |
| MULTILINESTRING | MULTILINESTRING ((0 0, 1 1), (2 2, 3 3)) |
| MULTIPOLYGON | MULTIPOLYGON (((0 0, 1 0, 1 1, 0 1, 0 0))) |
4.9 实战示例
4.9.1 创建完整图层
using OpenGIS.Utils.Engine.Enums;
using OpenGIS.Utils.Engine.Model.Layer;
// 创建城市图层
var cityLayer = new OguLayer
{
Name = "中国主要城市",
GeometryType = GeometryType.POINT,
Wkid = 4326
};
// 添加字段定义
cityLayer.AddField(new OguField
{
Name = "ID",
DataType = FieldDataType.INTEGER,
IsNullable = false
});
cityLayer.AddField(new OguField
{
Name = "Name",
Alias = "城市名称",
DataType = FieldDataType.STRING,
Length = 50,
IsNullable = false
});
cityLayer.AddField(new OguField
{
Name = "Province",
Alias = "所属省份",
DataType = FieldDataType.STRING,
Length = 50
});
cityLayer.AddField(new OguField
{
Name = "Population",
Alias = "人口(万)",
DataType = FieldDataType.LONG
});
cityLayer.AddField(new OguField
{
Name = "GDP",
Alias = "GDP(亿元)",
DataType = FieldDataType.DOUBLE,
Precision = 15,
Scale = 2
});
// 添加北京
var beijing = new OguFeature
{
Fid = 1,
Wkt = "POINT (116.404 39.915)"
};
beijing.SetValue("ID", 1);
beijing.SetValue("Name", "北京");
beijing.SetValue("Province", "北京市");
beijing.SetValue("Population", 2154L);
beijing.SetValue("GDP", 40269.6);
cityLayer.AddFeature(beijing);
// 添加上海
var shanghai = new OguFeature
{
Fid = 2,
Wkt = "POINT (121.473 31.230)"
};
shanghai.SetValue("ID", 2);
shanghai.SetValue("Name", "上海");
shanghai.SetValue("Province", "上海市");
shanghai.SetValue("Population", 2487L);
shanghai.SetValue("GDP", 43214.85);
cityLayer.AddFeature(shanghai);
// 添加广州
var guangzhou = new OguFeature
{
Fid = 3,
Wkt = "POINT (113.264 23.129)"
};
guangzhou.SetValue("ID", 3);
guangzhou.SetValue("Name", "广州");
guangzhou.SetValue("Province", "广东省");
guangzhou.SetValue("Population", 1867L);
guangzhou.SetValue("GDP", 28839.0);
cityLayer.AddFeature(guangzhou);
// 添加元数据
cityLayer.Metadata = new OguLayerMetadata
{
DataSource = "国家统计局",
CoordinateSystemName = "WGS 84",
MeasureUnit = "度",
CreateTime = DateTime.Now
};
// 验证图层
cityLayer.Validate();
Console.WriteLine($"图层创建完成: {cityLayer.Name}");
Console.WriteLine($"要素数量: {cityLayer.GetFeatureCount()}");
4.9.2 遍历和查询
// 遍历所有要素
Console.WriteLine("\n所有城市:");
foreach (var feature in cityLayer.Features)
{
var name = feature.GetValue("Name");
var pop = feature.GetAttribute("Population")?.GetLongValue();
var gdp = feature.GetAttribute("GDP")?.GetDoubleValue();
Console.WriteLine($" {name}: 人口 {pop}万, GDP {gdp:N2}亿元");
}
// 查询GDP超过30000亿的城市
Console.WriteLine("\nGDP超过30000亿的城市:");
var richCities = cityLayer.Filter(f =>
{
var gdp = f.GetAttribute("GDP")?.GetDoubleValue();
return gdp.HasValue && gdp.Value > 30000;
});
foreach (var city in richCities)
{
Console.WriteLine($" {city.GetValue("Name")}");
}
// 按人口排序
Console.WriteLine("\n按人口排序:");
var sortedByPop = cityLayer.Features
.OrderByDescending(f => f.GetAttribute("Population")?.GetLongValue() ?? 0)
.ToList();
foreach (var city in sortedByPop)
{
var name = city.GetValue("Name");
var pop = city.GetAttribute("Population")?.GetLongValue();
Console.WriteLine($" {name}: {pop}万人");
}
4.10 小结
本章详细介绍了OGU4Net的统一图层模型:
- OguLayer:图层容器,包含字段定义、要素集合、元数据
- OguFeature:要素类,包含几何(WKT)和属性
- OguField:字段定义,支持多种数据类型
- OguFieldValue:类型安全的字段值容器
- OguCoordinate:坐标点,支持2D/3D和点号
- OguLayerMetadata:图层元数据
这套模型的优势:
- 独立于底层GIS库
- 支持JSON序列化
- 类型安全
- 可验证
- 可克隆
掌握这些核心模型,是使用OGU4Net进行GIS开发的基础。

浙公网安备 33010602011771号