经纬度 如何判定 PolygonA 在Polygon B内部或者 PolygonA 和 Polygon B重合?
现成的库也行,语言C# .Net。
数据格式如
[
{
"lon": 113.948212,
"lat": 32.847212
},
{
"lon": 113.648212,
"lat": 32.647212
},
{
"lon": 114.148212,
"lat": 32.647212
},
{
"lon": 114.248212,
"lat": 33.147212
},
{
"lon": 113.948212,
"lat": 32.847212
}
]
参考
https://www.cnblogs.com/hsxian/p/11761571.html
js、python甚至sqlite都行,c#是真没弄过
NetTopologySuite 我也搜到了这个,在研究怎么使
求2个图形的交集,如果交集等于其中一个图形,就满足你说的条件.
你问AI这个应该能实现你的要求
问题是我不会啊,思路是这样的
@echo_lovely:
AI给的代码,看着可行
using NetTopologySuite.Geometries;
using NetTopologySuite.IO;
bool IsAInsideOrSame(Polygon polyA, Polygon polyB, double tol = 1e-9)
{
var inter = polyA.Intersection(polyB);
if (inter.IsEmpty) return false;
return Math.Abs(inter.Area - polyA.Area) < tol && inter.EqualsTopologically(polyA);
}
bool IsSame(Polygon polyA, Polygon polyB, double tol = 1e-9)
{
return Math.Abs(polyA.Area - polyB.Area) < tol && polyA.EqualsTopologically(polyB);
}
// 构造示例:coords = new[] { (lon,lat), ... }
Polygon MakePolygon((double x, double y)[] coords)
{
var pts = Array.ConvertAll(coords, p => new Coordinate(p.x, p.y));
// 闭合点可省略,GeometryFactory 会闭合
return new GeometryFactory().CreatePolygon(pts);
}
// 使用
var A = MakePolygon(new[] { (0,0), (1,0), (1,1), (0,1) });
var B = MakePolygon(new[] { (-1,-1), (2,-1), (2,2), (-1,2) });
bool insideOrSame = IsAInsideOrSame(A, B);
bool same = IsSame(A, B);
using NetTopologySuite.Geometries;
using System;
using System.Collections.Generic;
using System.Linq;
namespace Gis
{
public static class GeometryConverter
{
// 几何工厂(SRID=4326表示WGS84经纬度坐标系)
private static readonly GeometryFactory _wgs84Factory = new GeometryFactory(new PrecisionModel(PrecisionModels.Floating), 4326);
/// <summary>
/// 将自定义Point列表转换为NetTopologySuite的Polygon对象
/// </summary>
/// <param name="points">坐标点列表(建议闭合,若未闭合则自动补全)</param>
/// <returns>有效的Polygon对象</returns>
/// <exception cref="ArgumentException">点数量不足时抛出</exception>
public static Polygon ConvertToPolygon(List<Point> points)
{
if (points == null || points.Count < 3)
throw new ArgumentException("多边形至少需要3个不同的坐标点", nameof(points));
// 转换为NetTopologySuite的Coordinate数组
var coordinates = points.Select(p => new Coordinate(p.Lon, p.Lat)).ToArray();
// 确保多边形闭合(第一个点与最后一个点一致)
if (!coordinates.First().Equals2D(coordinates.Last()))
coordinates = coordinates.Concat(new[] { coordinates.First() }).ToArray();
// 创建线性环(外环)
var linearRing = _wgs84Factory.CreateLinearRing(coordinates);
// 创建多边形并修复无效几何(如自相交)
var polygon = _wgs84Factory.CreatePolygon(linearRing);
return !polygon.IsValid ? (Polygon)polygon.Buffer(0) : polygon;
}
}
}
using NetTopologySuite.Geometries;
using System;
namespace Gis
{
public static class PolygonRelationChecker
{
/// <summary>
/// 判断PolygonA是否在PolygonB内部(包括边界,排除完全重合可额外判断)
/// </summary>
/// <param name="polygonA">待判断多边形</param>
/// <param name="polygonB">容器多边形</param>
/// <returns>是否在内部</returns>
public static bool IsPolygonAInsidePolygonB(Polygon polygonA, Polygon polygonB)
{
if (polygonA == null || polygonB == null)
throw new ArgumentNullException("多边形对象不能为空");
// Within:OGC标准,A的所有点在B内部/边界,且A内部与B内部有交集
// 若需更宽泛的包含(如重合),可使用 polygonB.Covers(polygonA)
return polygonA.Within(polygonB);
}
/// <summary>
/// 判断PolygonA与PolygonB是否重合(完全重合/部分边重合)
/// </summary>
/// <param name="polygonA">多边形A</param>
/// <param name="polygonB">多边形B</param>
/// <param name="tolerance">精度容差(经纬度1e-6≈1米)</param>
/// <returns>是否重合</returns>
public static bool IsPolygonAOverlappingWithPolygonB(Polygon polygonA, Polygon polygonB, double tolerance = 1e-6)
{
if (polygonA == null || polygonB == null)
throw new ArgumentNullException("多边形对象不能为空");
// 1. 完全重合(允许微小精度误差)
if (polygonA.EqualsExact(polygonB, tolerance))
return true;
// 2. 部分边重合(交集为线串且长度大于0)
var intersection = polygonA.Intersection(polygonB);
return intersection switch
{
LineString line => !line.IsEmpty && line.Length > tolerance,
MultiLineString multiLine => !multiLine.IsEmpty && multiLine.Length > tolerance,
_ => false
};
}
/// <summary>
/// 综合判断:PolygonA是否在PolygonB内部,或与PolygonB重合
/// </summary>
/// <param name="polygonA">多边形A</param>
/// <param name="polygonB">多边形B</param>
/// <returns>是否满足条件</returns>
public static bool IsPolygonAInsideOrOverlappingWithPolygonB(Polygon polygonA, Polygon polygonB)
{
return IsPolygonAInsidePolygonB(polygonA, polygonB)
|| IsPolygonAOverlappingWithPolygonB(polygonA, polygonB);
}
}
}
namespace Gis
{
public class Point
{
public double Lon { get; set; }
public double Lat { get; set; }
public Point(double lon, double lat)
{
Lon = lon;
Lat = lat;
}
}
}
using System;
using System.Collections.Generic;
namespace Gis
{
public class Program
{
static void Main(string[] args)
{
Console.WriteLine("Hello World!");
// 示例:PolygonB(外部多边形)
var polygonBPoints = new List<Point>()
{
//new Point(113.123456, 32.754321),
//new Point(113.823456, 32.754321),
//new Point(113.423456, 32.354321),
//new Point(113.823456, 32.054321),
//new Point(113.123456, 32.054321),
//new Point(113.123456, 32.754321),
new Point(0,0),
new Point(2,2),
new Point(4,0),
new Point(0,0)
};
// 示例:PolygonA(内部多边形)
var polygonAPoints = new List<Point>
{
//new Point(113.323456, 32.654321),
//new Point(113.723456, 32.654321),
//new Point(113.723456, 32.154321),
//new Point(113.323456, 32.154321)
//new Point(113.123456, 32.754321),
//new Point(113.823456, 32.754321),
//new Point(113.423456, 32.354321),
//new Point(113.823456, 32.054321),
//new Point(113.123456, 32.054321),
//new Point(113.123456, 32.754321),
new Point(0,0),
new Point(2,2),
new Point(4,0),
new Point(0,0)
};
// 转换为NetTopologySuite多边形
var polygonA = GeometryConverter.ConvertToPolygon(polygonAPoints);
var polygonB = GeometryConverter.ConvertToPolygon(polygonBPoints);
// 可选:大范围多边形投影转换
// polygonA = ProjectionHelper.Project4326To3857(polygonA);
// polygonB = ProjectionHelper.Project4326To3857(polygonB);
// 判断关系
var isInsideOrOverlapping = PolygonRelationChecker.IsPolygonAInsideOrOverlappingWithPolygonB(polygonA, polygonB);
Console.WriteLine($"PolygonA是否在PolygonB内部或重合:{isInsideOrOverlapping}");
}
}
}
AI生成的内容不太好使
– echo_lovely 2天前