第12章 - NTS几何处理集成
第12章:NTS几何处理集成
12.1 NetTopologySuite 概述
12.1.1 NTS 简介
NetTopologySuite (NTS) 是 JTS Topology Suite 的 .NET 移植版本,提供了强大的空间数据模型和空间分析功能。Mapsui 通过 Mapsui.Nts 包与 NTS 深度集成。
// 安装必要的 NuGet 包
// Install-Package Mapsui.Nts
// Install-Package NetTopologySuite
using NetTopologySuite.Geometries;
using Mapsui.Nts;
12.1.2 几何类型
| NTS 类型 | 描述 | WKT 示例 |
|---|---|---|
| Point | 点 | POINT(116.4 39.9) |
| LineString | 线 | LINESTRING(0 0, 10 10, 20 0) |
| Polygon | 多边形 | POLYGON((0 0, 10 0, 10 10, 0 10, 0 0)) |
| MultiPoint | 多点 | MULTIPOINT((0 0), (10 10)) |
| MultiLineString | 多线 | MULTILINESTRING((0 0, 10 10), (20 20, 30 30)) |
| MultiPolygon | 多多边形 | MULTIPOLYGON(((0 0, 10 0, 10 10, 0 0))) |
| GeometryCollection | 几何集合 | 混合几何类型 |
12.2 创建几何对象
12.2.1 GeometryFactory
// 创建 GeometryFactory
var geometryFactory = new GeometryFactory(new PrecisionModel(), 3857);
// 创建点
var point = geometryFactory.CreatePoint(new Coordinate(116.4, 39.9));
// 创建线
var lineCoords = new[]
{
new Coordinate(0, 0),
new Coordinate(10, 10),
new Coordinate(20, 0)
};
var line = geometryFactory.CreateLineString(lineCoords);
// 创建多边形(闭合环)
var polygonCoords = new[]
{
new Coordinate(0, 0),
new Coordinate(10, 0),
new Coordinate(10, 10),
new Coordinate(0, 10),
new Coordinate(0, 0) // 首尾相连
};
var polygon = geometryFactory.CreatePolygon(polygonCoords);
// 创建带孔的多边形
var shell = geometryFactory.CreateLinearRing(new[]
{
new Coordinate(0, 0),
new Coordinate(100, 0),
new Coordinate(100, 100),
new Coordinate(0, 100),
new Coordinate(0, 0)
});
var hole = geometryFactory.CreateLinearRing(new[]
{
new Coordinate(20, 20),
new Coordinate(80, 20),
new Coordinate(80, 80),
new Coordinate(20, 80),
new Coordinate(20, 20)
});
var polygonWithHole = geometryFactory.CreatePolygon(shell, new[] { hole });
12.2.2 WKT 读写
using NetTopologySuite.IO;
// WKT 读取
var wktReader = new WKTReader();
var geometry = wktReader.Read("POLYGON((0 0, 10 0, 10 10, 0 10, 0 0))");
// WKT 写入
var wktWriter = new WKTWriter();
var wkt = wktWriter.Write(geometry);
Console.WriteLine(wkt); // POLYGON ((0 0, 10 0, 10 10, 0 10, 0 0))
12.2.3 GeoJSON 读写
using NetTopologySuite.IO;
// GeoJSON 读取
var geoJsonReader = new GeoJsonReader();
var geometry = geoJsonReader.Read<Geometry>(geoJson);
// GeoJSON 写入
var geoJsonWriter = new GeoJsonWriter();
var geoJson = geoJsonWriter.Write(geometry);
12.3 GeometryFeature
12.3.1 在 Mapsui 中使用 NTS 几何
using Mapsui.Nts;
// 创建 GeometryFeature
var geometryFactory = new GeometryFactory();
var polygon = geometryFactory.CreatePolygon(coordinates);
var feature = new GeometryFeature(polygon);
feature["name"] = "测试多边形";
feature["area"] = polygon.Area;
// 添加样式
feature.Styles = new[] { CreatePolygonStyle() };
// 添加到图层
var layer = new MemoryLayer
{
Name = "NTS Layer",
Features = new[] { feature }
};
12.3.2 从 NTS 几何创建 Mapsui 要素
public static class GeometryFeatureFactory
{
public static IFeature CreateFeature(Geometry geometry)
{
return new GeometryFeature(geometry);
}
public static IEnumerable<IFeature> CreateFeatures(
IEnumerable<Geometry> geometries)
{
return geometries.Select(g => new GeometryFeature(g));
}
public static GeometryFeature CreatePointFeature(double x, double y)
{
var factory = new GeometryFactory();
var point = factory.CreatePoint(new Coordinate(x, y));
return new GeometryFeature(point);
}
public static GeometryFeature CreateLineFeature(
IEnumerable<(double X, double Y)> points)
{
var factory = new GeometryFactory();
var coords = points.Select(p => new Coordinate(p.X, p.Y)).ToArray();
var line = factory.CreateLineString(coords);
return new GeometryFeature(line);
}
}
12.4 空间操作
12.4.1 缓冲区分析
// 创建缓冲区
var point = geometryFactory.CreatePoint(new Coordinate(116.4, 39.9));
var buffer = point.Buffer(1000); // 1000 米缓冲区
// 单侧缓冲区
var line = geometryFactory.CreateLineString(coordinates);
var leftBuffer = line.Buffer(500, BufferParameters.CAP_FLAT);
12.4.2 几何运算
// 联合 (Union)
var union = geometry1.Union(geometry2);
// 交集 (Intersection)
var intersection = geometry1.Intersection(geometry2);
// 差集 (Difference)
var difference = geometry1.Difference(geometry2);
// 对称差 (SymmetricDifference)
var symDiff = geometry1.SymmetricDifference(geometry2);
// 凸包 (ConvexHull)
var hull = geometry.ConvexHull();
// 简化 (Simplify)
var simplified = TopologyPreservingSimplifier.Simplify(geometry, tolerance);
12.4.3 空间关系判断
// 包含
bool contains = geometry1.Contains(geometry2);
// 相交
bool intersects = geometry1.Intersects(geometry2);
// 相离
bool disjoint = geometry1.Disjoint(geometry2);
// 接触
bool touches = geometry1.Touches(geometry2);
// 覆盖
bool covers = geometry1.Covers(geometry2);
// 被覆盖
bool coveredBy = geometry1.CoveredBy(geometry2);
// 相等
bool equals = geometry1.Equals(geometry2);
// 距离
double distance = geometry1.Distance(geometry2);
12.5 空间查询
12.5.1 空间索引
using NetTopologySuite.Index.Strtree;
public class SpatialIndex
{
private readonly STRtree<IFeature> _index = new();
public void Build(IEnumerable<IFeature> features)
{
foreach (var feature in features)
{
if (feature is GeometryFeature gf && gf.Geometry != null)
{
_index.Insert(gf.Geometry.EnvelopeInternal, feature);
}
}
_index.Build();
}
public IEnumerable<IFeature> Query(Envelope envelope)
{
return _index.Query(envelope);
}
public IEnumerable<IFeature> QueryByPoint(Point point, double tolerance)
{
var envelope = new Envelope(
point.X - tolerance, point.X + tolerance,
point.Y - tolerance, point.Y + tolerance
);
return Query(envelope);
}
}
12.5.2 在视口范围内查询
public IEnumerable<IFeature> QueryFeaturesInExtent(
IEnumerable<IFeature> features,
MRect extent)
{
var envelope = new Envelope(
extent.MinX, extent.MaxX,
extent.MinY, extent.MaxY
);
return features
.OfType<GeometryFeature>()
.Where(f => f.Geometry?.EnvelopeInternal.Intersects(envelope) == true);
}
12.6 几何编辑
12.6.1 顶点编辑
public class GeometryEditor
{
public static Geometry MoveVertex(
Geometry geometry,
int vertexIndex,
Coordinate newPosition)
{
var coords = geometry.Coordinates.ToArray();
if (vertexIndex >= 0 && vertexIndex < coords.Length)
{
coords[vertexIndex] = newPosition;
}
return RebuildGeometry(geometry, coords);
}
public static Geometry AddVertex(
LineString line,
int afterIndex,
Coordinate newVertex)
{
var coords = line.Coordinates.ToList();
coords.Insert(afterIndex + 1, newVertex);
return new GeometryFactory().CreateLineString(coords.ToArray());
}
public static Geometry RemoveVertex(
Geometry geometry,
int vertexIndex)
{
var coords = geometry.Coordinates.ToList();
if (vertexIndex >= 0 && vertexIndex < coords.Count)
{
coords.RemoveAt(vertexIndex);
}
return RebuildGeometry(geometry, coords.ToArray());
}
private static Geometry RebuildGeometry(
Geometry original,
Coordinate[] newCoords)
{
var factory = original.Factory;
return original switch
{
Point => factory.CreatePoint(newCoords[0]),
LineString => factory.CreateLineString(newCoords),
Polygon => factory.CreatePolygon(newCoords),
_ => throw new NotSupportedException()
};
}
}
12.6.2 几何变换
using NetTopologySuite.Geometries.Utilities;
// 平移
var translated = AffineTransformation.TranslationInstance(dx, dy)
.Transform(geometry);
// 旋转
var rotated = AffineTransformation.RotationInstance(
Math.PI / 4, // 45度
centerX, centerY
).Transform(geometry);
// 缩放
var scaled = AffineTransformation.ScaleInstance(
scaleX, scaleY,
centerX, centerY
).Transform(geometry);
12.7 实用工具类
12.7.1 几何工具
public static class GeometryUtils
{
/// <summary>
/// 计算几何的中心点
/// </summary>
public static Point GetCentroid(Geometry geometry)
{
return geometry.Centroid;
}
/// <summary>
/// 计算多边形面积(平方米)
/// </summary>
public static double CalculateArea(Polygon polygon)
{
// 如果是 Web Mercator,需要转换计算
return polygon.Area;
}
/// <summary>
/// 计算线长度(米)
/// </summary>
public static double CalculateLength(LineString line)
{
return line.Length;
}
/// <summary>
/// 检查几何是否有效
/// </summary>
public static bool IsValid(Geometry geometry)
{
return geometry.IsValid;
}
/// <summary>
/// 修复无效几何
/// </summary>
public static Geometry MakeValid(Geometry geometry)
{
if (geometry.IsValid) return geometry;
return geometry.Buffer(0); // 常用的修复方法
}
/// <summary>
/// 简化几何
/// </summary>
public static Geometry Simplify(Geometry geometry, double tolerance)
{
return TopologyPreservingSimplifier.Simplify(geometry, tolerance);
}
}
12.8 本章小结
本章详细介绍了 Mapsui 与 NTS 的集成:
- NTS 概述:几何类型和 GeometryFactory
- 创建几何对象:点、线、多边形的创建
- GeometryFeature:在 Mapsui 中使用 NTS 几何
- 空间操作:缓冲区、联合、交集等运算
- 空间关系:包含、相交、距离等判断
- 空间查询:空间索引和范围查询
- 几何编辑:顶点编辑和几何变换
在下一章中,我们将学习导航与视图控制。
12.9 思考与练习
- 实现一个要素属性编辑器,支持修改几何和属性。
- 创建一个空间分析工具,计算两个多边形的重叠面积。
- 实现一个几何简化功能,根据当前缩放级别动态简化几何。
- 创建一个多边形分割工具。
- 实现一个路径分析功能,找出两点间的最短路径。

浙公网安备 33010602011771号