首页 新闻 会员 周边 捐助

经纬度 判定 PolygonA 在Polygon B内部或者 PolygonA 和 Polygon B重合

0
悬赏园豆:50 [已解决问题] 解决于 2025-12-11 16:41

经纬度 如何判定 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
  }
]
echo_lovely的主页 echo_lovely | 小虾三级 | 园豆:1693
提问于:2025-12-11 14:28

AI生成的内容不太好使

echo_lovely 2天前
< >
分享
最佳答案
0

参考
https://www.cnblogs.com/hsxian/p/11761571.html

js、python甚至sqlite都行,c#是真没弄过

收获园豆:30
首席吐槽官秦寿 | 小虾三级 |园豆:633 | 2025-12-11 14:47

NetTopologySuite 我也搜到了这个,在研究怎么使

echo_lovely | 园豆:1693 (小虾三级) | 2025-12-11 14:58
其他回答(2)
0

求2个图形的交集,如果交集等于其中一个图形,就满足你说的条件.
你问AI这个应该能实现你的要求

收获园豆:20
www378660084 | 园豆:1715 (小虾三级) | 2025-12-11 14:59

问题是我不会啊,思路是这样的

支持(0) 反对(0) echo_lovely | 园豆:1693 (小虾三级) | 2025-12-11 15:00

@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);
支持(0) 反对(0) www378660084 | 园豆:1715 (小虾三级) | 2025-12-11 15:06
0
  1. 现成轮子NetTopologySuite,将坐标转为对应轮子的Polygon
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;
        }
    }
}

  1. 做判定
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);
        }
    }
}
  1. 判定例子
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}");
        }
    }
}
echo_lovely | 园豆:1693 (小虾三级) | 2025-12-11 16:40
清除回答草稿
   您需要登录以后才能回答,未注册用户请先注册