一键导入
geometry-api-net
geometry-api-net 是一个 .NET Standard 2.0 的空间几何计算库,提供对二维和三维几何对象的创建、解析、序列化以及空间关系运算能力。
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
菜单
geometry-api-net 是一个 .NET Standard 2.0 的空间几何计算库,提供对二维和三维几何对象的创建、解析、序列化以及空间关系运算能力。
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
基于 SOC 职业分类
| name | geometry-api-net |
| description | geometry-api-net 是一个 .NET Standard 2.0 的空间几何计算库,提供对二维和三维几何对象的创建、解析、序列化以及空间关系运算能力。 |
| tags | ["dotnet","geometry","esri","spatial","wkt","wkb","geojson","geodesic","csharp"] |
项目地址: https://github.com/znlgis/geometry-api-net
本文件旨在帮助 AI 快速理解并使用 geometry-api-net 库进行空间几何开发。
这是一个 .NET Standard 2.0 的空间几何计算库,提供 6 种几何类型、25+ 空间运算算子和 4 种序列化格式。
Esri.Geometry.CoreEsri.Geometry.Jsondotnet add package Esri.Geometry.Core
dotnet add package Esri.Geometry.Json # 可选,System.Text.Json 支持
| 命名空间 | 用途 |
|---|---|
OpenGIS.Esri.Geometry.Core | 核心入口,GeometryEngine 便捷 API |
OpenGIS.Esri.Geometry.Core.Geometries | 几何类型(Point, Polygon 等) |
OpenGIS.Esri.Geometry.Core.Operators | 空间运算算子 |
OpenGIS.Esri.Geometry.Core.SpatialReference | 空间参考 / 坐标系统 |
OpenGIS.Esri.Geometry.Core.IO | 序列化(WKT, WKB, GeoJSON, EsriJson) |
OpenGIS.Esri.Geometry.Json.Converters | System.Text.Json 转换器 |
public enum GeometryType
{
Unknown = 0,
Point = 1,
Line = 2,
Envelope = 3,
MultiPoint = 4,
Polyline = 5,
Polygon = 6
}
所有几何类型继承自 Geometry,共有属性和方法:
// 属性
geometry.Type // GeometryType 枚举
geometry.IsEmpty // 是否为空
geometry.Dimension // 维度(Point=0, Line/Polyline=1, Polygon/Envelope=2)
geometry.IsPoint // 是否为点类型
geometry.IsLinear // 是否为线类型
geometry.IsArea // 是否为面类型
// 方法
geometry.GetEnvelope() // 获取外包矩形
geometry.CalculateArea2D() // 计算面积
geometry.CalculateLength2D() // 计算长度
geometry.Copy() // 深拷贝
geometry.IsValid() // 是否有效
var p = new Point(); // 空点 (NaN)
var p = new Point(10, 20); // 2D 点
var p = new Point(10, 20, 30); // 3D 点 (带 Z)
p.X // double, X 坐标
p.Y // double, Y 坐标
p.Z // double?, Z 坐标(可空)
p.M // double?, M 值(可空)
p.Distance(otherPoint) // 计算两点距离
p.Equals(otherPoint, tolerance) // 容差比较
var line = new Line(); // 空线段
var line = new Line(new Point(0, 0), new Point(10, 10));
line.Start // Point, 起点
line.End // Point, 终点
line.Length // double, 长度
var env = new Envelope(); // 空包围盒
var env = new Envelope(0, 0, 100, 100); // xMin, yMin, xMax, yMax
env.XMin, env.YMin, env.XMax, env.YMax // 边界坐标
env.Width // 宽度
env.Height // 高度
env.Center // Point, 中心点
env.Area // 面积
env.Contains(point) // 是否包含点
env.Intersects(otherEnv) // 是否与另一个包围盒相交
env.Merge(point) // 合并点到包围盒
env.Merge(otherEnv) // 合并另一个包围盒
var mp = new MultiPoint();
var mp = new MultiPoint(new[] { new Point(1, 2), new Point(3, 4) });
mp.Add(new Point(5, 6)); // 添加点
mp.Count // 点数量
mp.GetPoint(0) // 获取指定索引的点
mp.GetPoints() // 获取所有点 (IEnumerable<Point>)
var polyline = new Polyline();
// 添加路径(path),每条路径是一组连续的点
polyline.AddPath(new[] {
new Point(0, 0), new Point(10, 0), new Point(10, 10)
});
polyline.PathCount // 路径数量
polyline.Length // 总长度
polyline.GetPath(0) // 获取指定索引的路径 (IReadOnlyList<Point>)
polyline.GetPaths() // 获取所有路径
var polygon = new Polygon();
// 添加环(ring),首尾点必须闭合
polygon.AddRing(new[] {
new Point(0, 0), new Point(10, 0), new Point(10, 10),
new Point(0, 10), new Point(0, 0) // ← 首尾闭合
});
polygon.RingCount // 环数量
polygon.Area // 面积(Shoelace 公式)
polygon.GetRing(0) // 获取指定索引的环 (IReadOnlyList<Point>)
polygon.GetRings() // 获取所有环
GeometryEngine 提供所有操作的便捷静态方法入口,是最简洁的使用方式:
using OpenGIS.Esri.Geometry.Core;
// 空间关系判断
bool result = GeometryEngine.Contains(geometry1, geometry2);
bool result = GeometryEngine.Intersects(geometry1, geometry2);
bool result = GeometryEngine.Within(geometry1, geometry2);
bool result = GeometryEngine.Disjoint(geometry1, geometry2);
bool result = GeometryEngine.Crosses(geometry1, geometry2);
bool result = GeometryEngine.Touches(geometry1, geometry2);
bool result = GeometryEngine.Overlaps(geometry1, geometry2);
bool result = GeometryEngine.Equals(geometry1, geometry2);
double dist = GeometryEngine.Distance(geometry1, geometry2);
// 集合运算
Geometry result = GeometryEngine.Union(geometry1, geometry2);
Geometry result = GeometryEngine.Intersection(geometry1, geometry2);
Geometry result = GeometryEngine.Difference(geometry1, geometry2);
Geometry result = GeometryEngine.SymmetricDifference(geometry1, geometry2);
// 几何运算
Geometry buffer = GeometryEngine.Buffer(geometry, distance);
Geometry hull = GeometryEngine.ConvexHull(geometry);
Geometry simple = GeometryEngine.Simplify(geometry, tolerance);
Geometry simpleOGC = GeometryEngine.SimplifyOGC(geometry, spatialRef);
bool isSimple = GeometryEngine.IsSimpleOGC(geometry, spatialRef);
Geometry general = GeometryEngine.Generalize(geometry, maxDeviation);
Geometry dense = GeometryEngine.Densify(geometry, maxSegmentLength);
Geometry clipped = GeometryEngine.Clip(geometry, clipEnvelope);
Geometry offset = GeometryEngine.Offset(geometry, distance);
Point center = GeometryEngine.Centroid(geometry);
Geometry boundary = GeometryEngine.Boundary(geometry);
double area = GeometryEngine.Area(geometry);
double length = GeometryEngine.Length(geometry);
// 大地测量
double geodesicDist = GeometryEngine.GeodesicDistance(point1, point2);
double geodesicArea = GeometryEngine.GeodesicArea(polygon);
// 邻近搜索
Proximity2DResult nearest = GeometryEngine.GetNearestCoordinate(geometry, point, testPolygonInterior);
Proximity2DResult nearest = GeometryEngine.GetNearestVertex(geometry, point);
Proximity2DResult[] results = GeometryEngine.GetNearestVertices(geometry, point, searchRadius, maxVertexCount);
// 序列化 / 反序列化
string wkt = GeometryEngine.GeometryToWkt(geometry);
Geometry fromWkt = GeometryEngine.GeometryFromWkt(wktString);
byte[] wkb = GeometryEngine.GeometryToWkb(geometry, bigEndian);
Geometry fromWkb = GeometryEngine.GeometryFromWkb(wkbBytes);
string json = GeometryEngine.GeometryToGeoJson(geometry);
Geometry fromJson = GeometryEngine.GeometryFromGeoJson(geoJsonString);
string esri = GeometryEngine.GeometryToEsriJson(geometry);
Geometry fromEsri = GeometryEngine.GeometryFromEsriJson(esriJsonString);
每个算子都通过 Instance 单例属性获取(Lazy 初始化),适合需要更精细控制的场景:
using OpenGIS.Esri.Geometry.Core.Operators;
// 空间关系
bool contains = ContainsOperator.Instance.Execute(geom1, geom2);
bool intersects = IntersectsOperator.Instance.Execute(geom1, geom2);
double distance = DistanceOperator.Instance.Execute(geom1, geom2);
bool equals = EqualsOperator.Instance.Execute(geom1, geom2);
bool disjoint = DisjointOperator.Instance.Execute(geom1, geom2);
bool within = WithinOperator.Instance.Execute(geom1, geom2);
bool crosses = CrossesOperator.Instance.Execute(geom1, geom2);
bool touches = TouchesOperator.Instance.Execute(geom1, geom2);
bool overlaps = OverlapsOperator.Instance.Execute(geom1, geom2);
// 集合运算
Geometry union = UnionOperator.Instance.Execute(geom1, geom2);
Geometry intersection = IntersectionOperator.Instance.Execute(geom1, geom2);
Geometry difference = DifferenceOperator.Instance.Execute(geom1, geom2);
Geometry symDiff = SymmetricDifferenceOperator.Instance.Execute(geom1, geom2);
// 一元运算
Geometry buffer = BufferOperator.Instance.Execute(geometry, distance);
Geometry convexHull = ConvexHullOperator.Instance.Execute(geometry);
Geometry simplified = SimplifyOperator.Instance.Execute(geometry, tolerance);
Point centroid = CentroidOperator.Instance.Execute(geometry);
Geometry boundary = BoundaryOperator.Instance.Execute(geometry);
double area = AreaOperator.Instance.Execute(geometry);
double length = LengthOperator.Instance.Execute(geometry);
Geometry offset = OffsetOperator.Instance.Execute(geometry, distance);
// 大地测量
double geodesicDist = GeodesicDistanceOperator.Instance.Execute(point1, point2);
double geodesicArea = GeodesicAreaOperator.Instance.Execute(polygon);
// 邻近搜索
Proximity2DResult result = Proximity2DOperator.Instance.GetNearestCoordinate(geometry, point, testPolygonInterior);
Proximity2DResult result = Proximity2DOperator.Instance.GetNearestVertex(geometry, point);
Proximity2DResult[] results = Proximity2DOperator.Instance.GetNearestVertices(geometry, point, searchRadius, maxVertexCount);
using OpenGIS.Esri.Geometry.Core.IO;
// 导出
string wkt = WktExportOperator.ExportToWkt(geometry);
// "POINT (10.5 20.7)"
// "POINT Z (10.5 20.7 30.1)"
// "LINESTRING (0 0, 10 0, 10 10)"
// "POLYGON ((0 0, 10 0, 10 10, 0 10, 0 0))"
// "MULTIPOINT ((1 2), (3 4))"
// 导入
Geometry geometry = WktImportOperator.ImportFromWkt("POINT (10.5 20.7)");
// 导出(默认小端序)
byte[] wkb = WkbExportOperator.ExportToWkb(geometry);
byte[] wkb = WkbExportOperator.ExportToWkb(geometry, bigEndian: true);
// 导入(自动检测字节序)
Geometry geometry = WkbImportOperator.ImportFromWkb(wkbBytes);
// 导出
string geoJson = GeoJsonExportOperator.ExportToGeoJson(geometry);
// {"type":"Point","coordinates":[10.5,20.7]}
// 导入
Geometry geometry = GeoJsonImportOperator.ImportFromGeoJson(geoJsonString);
// 导出
string esriJson = EsriJsonExportOperator.Instance.Execute(geometry);
// Point: {"x":10.5,"y":20.7}
// MultiPoint: {"points":[[1,2],[3,4]]}
// Polyline: {"paths":[[[0,0],[10,0],[10,10]]]}
// Polygon: {"rings":[[[0,0],[10,0],[10,10],[0,10],[0,0]]]}
// Envelope: {"xmin":0,"ymin":0,"xmax":10,"ymax":10}
// 导入
Geometry geometry = EsriJsonImportOperator.ImportFromEsriJson(esriJsonString);
using OpenGIS.Esri.Geometry.Json.Converters;
var options = new JsonSerializerOptions();
options.Converters.Add(new PointJsonConverter());
string json = JsonSerializer.Serialize(point, options);
Point point = JsonSerializer.Deserialize<Point>(json, options);
using OpenGIS.Esri.Geometry.Core.SpatialReference;
// 预定义空间参考
var wgs84 = SpatialReference.Wgs84(); // EPSG:4326 (经纬度)
var webMercator = SpatialReference.WebMercator(); // EPSG:3857 (Web 墨卡托)
// 自定义 WKID
var sr = new SpatialReference(4490); // CGCS2000
// 属性
sr.Wkid // int?, WKID 编号
sr.LatestWkid // int?, 最新 WKID
sr.Wkt // string?, WKT 表示
// 组合几何与空间参考
var mapGeom = new MapGeometry(geometry, SpatialReference.Wgs84());
mapGeom.Geometry // Geometry 对象
mapGeom.SpatialReference // SpatialReference 对象
Proximity2DResult result = GeometryEngine.GetNearestCoordinate(geometry, point);
result.IsEmpty // bool, 结果是否为空
result.Coordinate // Point, 最近坐标点
result.VertexIndex // int, 最近顶点索引
result.Distance // double, 距离
result.IsRightSide // bool, 是否在多路径几何的右侧
var polygon = new Polygon();
polygon.AddRing(new[] {
new Point(0, 0), new Point(10, 0), new Point(10, 10),
new Point(0, 10), new Point(0, 0)
});
var point = new Point(5, 5);
bool inside = GeometryEngine.Contains(polygon, point); // true
var beijing = new Point(116.4074, 39.9042);
var shanghai = new Point(121.4737, 31.2304);
double meters = GeometryEngine.GeodesicDistance(beijing, shanghai);
var point = new Point(10, 20);
Geometry buffer = GeometryEngine.Buffer(point, 5.0); // 半径为 5 的缓冲区
var envelope = buffer.GetEnvelope();
// XMin=5, YMin=15, XMax=15, YMax=25
var env1 = new Envelope(0, 0, 10, 10);
var env2 = new Envelope(5, 5, 15, 15);
Geometry result = GeometryEngine.Intersection(env1, env2);
// 交集区域: (5,5) 到 (10,10)
var p1 = new Point(0, 0);
var p2 = new Point(10, 10);
Geometry merged = GeometryEngine.Union(p1, p2);
// 结果为 MultiPoint,包含两个点
var polygon = new Polygon();
polygon.AddRing(new[] {
new Point(0, 0), new Point(1, 0), new Point(1, 1),
new Point(0, 1), new Point(0, 0)
});
string geoJson = GeometryEngine.GeometryToGeoJson(polygon);
Geometry restored = GeometryEngine.GeometryFromGeoJson(geoJson);
var geom1 = GeometryEngine.GeometryFromWkt("POLYGON ((0 0, 10 0, 10 10, 0 10, 0 0))");
var geom2 = GeometryEngine.GeometryFromWkt("POINT (5 5)");
bool contains = GeometryEngine.Contains(geom1, geom2); // true
double distance = GeometryEngine.Distance(geom1, geom2); // 0
var multiPoint = new MultiPoint(new[] {
new Point(0, 0), new Point(10, 0), new Point(5, 10),
new Point(3, 3), new Point(7, 2)
});
Geometry hull = GeometryEngine.ConvexHull(multiPoint);
// 结果为包围所有点的最小凸多边形
var polygon = new Polygon();
polygon.AddRing(new[] {
new Point(0, 0), new Point(10, 0), new Point(10, 10),
new Point(0, 10), new Point(0, 0)
});
Point centroid = GeometryEngine.Centroid(polygon);
// centroid.X = 5, centroid.Y = 5
var polyline = new Polyline();
polyline.AddPath(new[] {
new Point(0, 0), new Point(5, 0.1), new Point(10, 0),
new Point(10, 5), new Point(10, 10)
});
// 简化:移除偏差小于 tolerance 的顶点
Geometry simplified = GeometryEngine.Simplify(polyline, 0.5);
// 加密:确保每段不超过 maxSegmentLength
Geometry densified = GeometryEngine.Densify(polyline, 2.0);
// 泛化:保持形状前提下减少顶点
Geometry generalized = GeometryEngine.Generalize(polyline, 1.0);
# 构建
dotnet build
# 运行测试(xUnit)
dotnet test
# 运行示例
dotnet run --project samples/OpenGIS.Esri.Geometry.Samples
Point、Polyline、Polygon 等构造函数创建几何GeometryEngine 静态方法(API 最简洁);需要精细控制时使用 Operator.Instance 单例模式GeometryEngine.GeometryToGeoJson() / GeometryFromWkt() 等方法进行 WKT、WKB、GeoJSON、Esri JSON 互转GeometryEngine.GeodesicDistance() / GeodesicArea()OpenGIS.Esri.Geometry.Json.Converters 命名空间的 System.Text.Json 转换器Geometry 基类,需根据实际类型做类型转换GeodesicDistance 使用 Vincenty 公式LineString,多路径导出为 MultiLineStringInstance 属性获取单例实例GeometryConstants.DefaultTolerance(1e-10)进行浮点比较,该值为内部常量,不可外部配置Geometry 基类,需根据实际类型做类型转换Instance 属性获取单例实例GetRing(), GetPath() 等返回 IReadOnlyList<Point>GeodesicDistance 使用 Vincenty 公式,GeodesicArea 使用球面超量公式LineString,多路径导出为 MultiLineString;Envelope 导出为 Polygon面向 AI 编程助手的开源 GIS、CAD、C#、AI、IoT、3D 技能集合。覆盖 65 个开源项目,提供一站式技能索引、标签搜索、按需加载指南,让 AI 助手在 GIS/CAD/C#/AI/3D 领域获得更准确的代码生成与问题排查能力。
DocuTranslate(xunbu/docutranslate)是基于大语言模型的轻量级本地文件翻译工具,支持 PDF/Word/Excel/Markdown/EPUB/字幕/JSON 等多格式翻译,内置 MinerU PDF 解析、术语表自动生成、Web UI、REST API、Client SDK 与 MCP 接入。
AI/LLM 技能分类索引,覆盖 LLM 应用开发平台、自学习智能体、个人 AI 助手 Gateway、终端编码代理、多模型编排插件、文件翻译工具、AI 编程方法论等领域共 8 个开源项目,按需加载即可获得 Dify、Hermes Agent、OpenClaw、OpenCode、DocuTranslate 等工具的精准 AI 辅助。
GIS(地理信息系统)技能分类索引,覆盖空间数据处理、地图服务、几何运算、Web 可视化等领域共 23 个开源工具,按需加载即可获得 GDAL、QGIS、GeoServer、PostGIS、JTS 等工具的精准 AI 辅助。
robotgo-flow(znlgis/robotgo-flow)是基于 go-vgo/robotgo 构建的 Windows 桌面 RPA 自动化框架,通过声明式 YAML 定义工作流,利用图像模板匹配定位屏幕 UI 元素,自动执行鼠标/键盘/浏览器操作,内置人类行为模拟、交互式录制器与 .NET 10 WPF 托盘应用。
Others(其它)技能分类索引,覆盖 Go 语言核心语法与工程实践、RobotGo 跨平台桌面自动化(RPA)库、robotgo-flow 基于 YAML 的 Windows RPA 框架、自托管邮件营销平台 BillionMail、Java 微服务后台脚手架 RuoYi-Cloud 与 SSL 证书自动化客户端 acme.sh,按需加载即可获得邮件系统搭建、Spring Cloud 微服务开发、SSL/TLS 证书自动签发续期、Go 语言后端开发、GUI 自动化等通用工具的精准 AI 辅助。