技能创建器
skill-creator
创建、改进和评估自定义技能,把专业流程转化为可重复使用的 AI 能力。
nettopologysuite【数据与研究】Use when performing 2D computational geometry in .NET — spatial predicates, overlay operations, buffering, WKT/WKB I/O. NetTopologySuite: the .NET port of JTS, available via NuGet for spatial analysis in C# applications.
独立 GitHub 快照 · 自动分类 · 以原作者文档为准
name: nettopologysuite description: "Use when performing 2D computational geometry in .NET — spatial predicates, overlay operations, buffering, WKT/WKB I/O. NetTopologySuite: the .NET port of JTS, available via NuGet for spatial analysis in C# applications." tags:
项目地址: https://github.com/NetTopologySuite/NetTopologySuite
NuGet:
NetTopologySuite(最新稳定版 2.6.0,截至2026年)官方文档: https://nettopologysuite.github.io/NetTopologySuite/
许可证: BSD-3-Clause
NTS 与 JTS API 几乎一一对应(C# 命名风格):
Point/LineString/Polygon/Multi*/GeometryCollectionEquals/Contains/Within/Intersects/Touches/Crosses/Overlaps/Disjoint/RelateIntersection/Union/Difference/SymmetricDifference/BufferConvexHull/Centroid/Area/Length/Distance/IsValid/SimplifySTRtree/Quadtreedotnet add package NetTopologySuite
dotnet add package NetTopologySuite.IO.GeoJSON
dotnet add package NetTopologySuite.IO.ShapeFile
dotnet add package ProjNet # 坐标变换(可选)
.NET 6+ 推荐。
using NetTopologySuite.Geometries;
var gf = new GeometryFactory(new PrecisionModel(), 4326);
var p = gf.CreatePoint(new Coordinate(116.397, 39.908));
var ls = gf.CreateLineString(new[] {
new Coordinate(116, 39), new Coordinate(117, 40)
});
var poly = gf.CreatePolygon(new[] {
new Coordinate(0,0), new Coordinate(10,0),
new Coordinate(10,10), new Coordinate(0,10), new Coordinate(0,0)
});
bool b = polyA.Intersects(polyB);
var inter = polyA.Intersection(polyB);
var union = polyA.Union(polyB);
var diff = polyA.Difference(polyB);
var buf = p.Buffer(100);
var hull = mp.ConvexHull();
double area = poly.Area;
double len = ls.Length;
double dist = polyA.Distance(polyB);
string rel = polyA.Relate(polyB).ToString();
bool ok = polyA.Relate(polyB, "T*F**F***");
using NetTopologySuite.IO;
var rdr = new WKTReader();
var g = rdr.Read("POINT (116.4 39.9)");
string wkt = new WKTWriter().Write(g);
byte[] wkb = new WKBWriter().Write(g);
using NetTopologySuite.IO.Converters;
using System.Text.Json;
var opts = new JsonSerializerOptions();
opts.Converters.Add(new GeoJsonConverterFactory());
string json = JsonSerializer.Serialize(g, opts);
var g2 = JsonSerializer.Deserialize<Geometry>(json, opts);
using NetTopologySuite.IO.Esri;
foreach (var f in Shapefile.ReadAllFeatures("input.shp"))
Console.WriteLine(quot;{f.Geometry} {f.Attributes["NAME"]}");
Shapefile.WriteAllFeatures(features, "output.shp");
using NetTopologySuite.Index.Strtree;
var tree = new STRtree<Geometry>();
foreach (var g in geometries)
tree.Insert(g.EnvelopeInternal, g);
tree.Build();
var hits = tree.Query(queryEnv);
var nearby = tree.NearestNeighbour(p.EnvelopeInternal, p, new GeometryItemDistance());
using NetTopologySuite.Operation.Valid;
using NetTopologySuite.Simplify;
using NetTopologySuite.Geometries.Utilities;
if (!poly.IsValid)
poly = (Polygon)GeometryFixer.Fix(poly);
var simp = TopologyPreservingSimplifier.Simplify(poly, 0.001);
dotnet add package Microsoft.EntityFrameworkCore.SqlServer.NetTopologySuite
# 或
dotnet add package Npgsql.EntityFrameworkCore.PostgreSQL.NetTopologySuite
public class City {
public int Id { get; set; }
public string Name { get; set; }
public Point Location { get; set; }
public Geometry Boundary { get; set; }
}
services.AddDbContext<AppDb>(o =>
o.UseSqlServer(conn, x => x.UseNetTopologySuite()));
var nearby = db.Cities
.Where(c => c.Location.Distance(target) < 5000)
.OrderBy(c => c.Location.Distance(target))
.Take(10)
.ToList(); // 自动翻译为空间 SQL
using ProjNet.CoordinateSystems;
using ProjNet.CoordinateSystems.Transformations;
var src = GeographicCoordinateSystem.WGS84;
var tgt = ProjectedCoordinateSystem.WebMercator;
var ct = new CoordinateTransformationFactory()
.CreateFromCoordinateSystems(src, tgt);
double[] xy = ct.MathTransform.Transform(new[] { 116.397, 39.908 });
GeometryFactory,固定 SRIDPreparedGeometry:using NetTopologySuite.Geometries.Prepared;
var prep = PreparedGeometryFactory.Prepare(largePoly);
foreach (var p in points) if (prep.Contains(p)) ...
| 问题 | 解决 |
|---|---|
TopologyException | GeometryFixer.Fix 修复无效几何 |
| EF Core 类型冲突 | 用 UseNetTopologySuite() 而非 Microsoft.SqlServer.Types |
| Z/M 坐标丢失 | 配置 WKBWriter 的 HandleOrdinates |
| Buffer 慢 | 减小 quadrantSegments、并行处理 |
new GeometryFactory(new PrecisionModel(), 4326) 创建工厂,SRID 指定坐标系CreatePoint()、CreateLineString()、CreatePolygon() 创建几何Intersects()、Intersection()、Buffer() 等WKTReader/WKTWriter、GeoJsonConverterFactory 进行序列化UseNetTopologySuite() 启用空间查询翻译为 SQLGeometryFactory 实例GeometryFixer.Fix() 修复PreparedGeometryFactory.Prepare() 大幅提速Build() 再 Query(),大数据量场景优于逐几何判断WKBWriter 需配置 HandleOrdinates 保留 Z/M 坐标