首页 新闻 会员 周边

求一个算法,c#判断给定的坐标集合(list)是否能形成一个多边形

0
悬赏园豆:20 [待解决问题]

需求背景:业务上需要给客户提供一个在地图上自已画区域作电子围栏用,区域一般为圆形、矩形和多边形,我们这只探讨多边形区域的实现和验证方法。

实现方式:

  1. 前、后端分离项目,即vue+api模式、后端有一个增加区域的接口,为了便于理解,我们假设该接口仅为增加多边形区域的接口(实际为三合一接口),接收区域名称和一组坐标集合(多边形顶点坐标)两个参数。
    参考高德地图-猎鹰轨迹服务-创建多边形围栏接口(v1/track/geofence/add/polygon)
    https://lbs.amap.com/api/track/lieying-kaifa/api/track_fence

  2. 前端通过使用地图上绘制区域组件,绘制一个多边形区域,绘制完成后会生成一组坐标集合,前端将该坐标集通过调用API接口提交到后端。
    一般情况下,在地图上绘制的多边形是闭合,生成的坐标点也是按顺时针(或反时针)排列的最外侧边缘的拐角顶点。

需求:
后端要对传入的坐标集进行效验,确保传入的这个数组内的坐标是有效的多边形区域。
有效是指:

  1. 坐标点可以形成完全闭合的且面积大于0的区域,
  2. 形成的区域有且只有一个(不能像VS图标这种多个闭合区域的情况),飞地、镂空等情况通过绘制多个区域来实现。
LDMING的主页 LDMING | 初学一级 | 园豆:194
提问于:2024-01-04 16:02
< >
分享
所有回答(3)
0

判断给定的坐标集合是否能形成一个有效的多边形,可以使用射线交点法。以下是一个简单的C#实现:

csharp
Copy code
using System;
using System.Collections.Generic;

class Program
{
static void Main()
{
List<Point> polygon = new List<Point>
{
new Point(0, 0),
new Point(0, 5),
new Point(5, 5),
new Point(5, 0),
new Point(2, 2)
};

    Console.WriteLine(IsPolygonValid(polygon)); // Output: True
}

static bool IsPolygonValid(List<Point> polygon)
{
    int n = polygon.Count;

    // Check if there are at least 3 vertices
    if (n < 3)
        return false;

    // Initialize winding number
    int windingNumber = 0;

    // Loop through each edge of the polygon
    for (int i = 0; i < n; i++)
    {
        Point currentVertex = polygon[i];
        Point nextVertex = polygon[(i + 1) % n];

        // Check for upward crossing
        if (currentVertex.Y <= nextVertex.Y)
        {
            if (currentVertex.Y < 0 && nextVertex.Y >= 0)
            {
                if (IsLeft(currentVertex, nextVertex, new Point(0, 0)) > 0)
                    windingNumber++;
            }
        }
        // Check for downward crossing
        else
        {
            if (currentVertex.Y >= 0 && nextVertex.Y < 0)
            {
                if (IsLeft(currentVertex, nextVertex, new Point(0, 0)) < 0)
                    windingNumber--;
            }
        }
    }

    // The polygon is valid if the winding number is not zero
    return windingNumber != 0;
}

static double IsLeft(Point P0, Point P1, Point P2)
{
    return ((P1.X - P0.X) * (P2.Y - P0.Y) - (P2.X - P0.X) * (P1.Y - P0.Y));
}

}

class Point
{
public double X { get; set; }
public double Y { get; set; }

public Point(double x, double y)
{
    X = x;
    Y = y;
}

}
这个实现使用射线交点法,通过射线从给定点(例如原点)向右水平射出,统计与多边形边界的交点数量来判断是否在多边形内部。这是一个简化的实现,对于一些边界情况可能需要进一步处理。请根据具体需求进行适当调整和测试。

Technologyforgood | 园豆:6772 (大侠五级) | 2024-01-04 20:22

这是AI生成的吗?

支持(0) 反对(0) LDMING | 园豆:194 (初学一级) | 2024-01-05 08:36
0

点大于三个,且首尾点相同,那么肯定能形成多边形,就是多边形是否是你想要的不好判定

echo_lovely | 园豆:1350 (小虾三级) | 2024-01-05 08:48

是的,这种情况只需要排除所有点不在同一直线上,和去掉重复的即可。
如果要检查只有一个面积区域,判断所有相邻的点之间的线段是否相交应该可以。

支持(0) 反对(0) LDMING | 园豆:194 (初学一级) | 2024-01-05 08:57
0

百度文心一言

问:

  1. 请用c#实现一个判断指定的一组坐标集是否能形成一个闭合区域
  2. 请用c#实现一个判断指定的一组坐标集是否能形成一个闭合多边形区域

回:

  1. 要判断一组坐标是否能形成一个闭合区域,你需要确定这些坐标的分布模式。一个简单的方法是检查所有坐标点是否都位于一个多边形内。多边形是闭合区域的一个常见表示形式。
    以下是一个C#方法,用于判断一组坐标(经纬度)是否可以形成一个闭合的多边形:
  2. C#中,可以使用以下方法来判断一组坐标(经纬度)是否可以形成一个闭合的多边形区域:
    两次回复生成代码一样,仅前面的说明有变化
using System;  
using System.Collections.Generic;  
using System.Linq;  
  
public class PolygonChecker  
{  
    public static bool IsCoordinateInPolygon(Coordinate targetCoordinate, List<Coordinate> polygonCoordinates)  
    {  
        // 使用射线交叉法判断点是否在多边形内  
        return CrossingCount(targetCoordinate, polygonCoordinates) % 2 == 1;  
    }  
  
    private static int CrossingCount(Coordinate point, List<Coordinate> polygon)  
    {  
        int count = 0;  
        for (int i = 0; i < polygon.Count; i++)  
        {  
            int j = (i + 1) % polygon.Count; // 获取下一个索引  
            if (CrossesLine(point, polygon[i], polygon[j]))  
            {  
                count++;  
            }  
        }  
        return count;  
    }  
  
    private static bool CrossesLine(Coordinate point, Coordinate lineStart, Coordinate lineEnd)  
    {  
        double px = point.Longitude - lineStart.Longitude;  
        double py = point.Latitude - lineStart.Latitude;  
        double qx = lineEnd.Longitude - lineStart.Longitude;  
        double qy = lineEnd.Latitude - lineStart.Latitude;  
        double r = qx * py - qy * px;  
        if (r == 0) return false; // 线段平行或重合,点在直线上则返回false  
        return (px * qy - py * qx) * r > 0; // 根据射线交叉法判断点是否在线段内部或与线段相交  
    }  
}
List<Coordinate> coordinates = new List<Coordinate>  
{  
    new Coordinate { Latitude = 40.7128, Longitude = -74.0060 }, // 第一个点(例如:纽约的经纬度)  
    new Coordinate { Latitude = 37.7749, Longitude = -122.4194 }, // 第二个点(例如:旧金山的经纬度)  
    // ... 添加更多点以形成多边形 ...  
};  
Coordinate targetPoint = new Coordinate { Latitude = 37.5662, Longitude = -122.0924 }; // 要检查的点(可以是某个城市的经纬度)  
bool isInsidePolygon = PolygonChecker.IsCoordinateInPolygon(targetPoint, coordinates); // 如果返回true,则点在多边形内;否则,不在多边形内。

科大讯飞星火AI

问:
请用c#实现一个判断指定的一组坐标集合(list类型,长度大于3)是否能形成一个闭合区域

回:

using System;
using System.Collections.Generic;
using System.Linq;

public class Coordinate
{
    public double X { get; set; }
    public double Y { get; set; }
}

public class Program
{
    public static void Main()
    {
        List<Coordinate> coordinates = new List<Coordinate>
        {
            new Coordinate { X = 0, Y = 0 },
            new Coordinate { X = 1, Y = 0 },
            new Coordinate { X = 1, Y = 1 },
            new Coordinate { X = 0, Y = 1 }
        };

        bool isClosedArea = IsClosedArea(coordinates);
        Console.WriteLine(isClosedArea);
    }

    public static bool IsClosedArea(List<Coordinate> coordinates)
    {
        if (coordinates == null || coordinates.Count <= 3)
        {
            return false;
        }

        double area = 0;
        for (int i = 0; i < coordinates.Count - 1; i++)
        {
            area += coordinates[i].X * coordinates[i + 1].Y - coordinates[i + 1].X * coordinates[i].Y;
        }
        area += coordinates[coordinates.Count - 1].X * coordinates[0].Y - coordinates[0].X * coordinates[coordinates.Count - 1].Y;

        return Math.Abs(area) > 1e-6;
    }
}

LDMING | 园豆:194 (初学一级) | 2024-01-05 08:49

文心一言第二次
问:
请用c#实现一个判断给定的多个坐标点(数量大于3)是否能形成一个闭合区域(三角形、四边形或多边形)

回:
要判断一组坐标点是否能形成一个闭合的多边形区域,可以使用欧几里得距离算法来判断两点之间的距离。下面是一个简单的C#示例代码,可以用来判断一组坐标点是否可以形成一个闭合的多边形区域:

using System;  
using System.Collections.Generic;  
using System.Linq;  
  
public class PolygonChecker  
{  
    public static bool IsPolygonValid(List<Coordinate> coordinates)  
    {  
        if (coordinates.Count < 3)  
        {  
            throw new ArgumentException("At least 3 coordinates are required to form a polygon.");  
        }  
  
        // 检查是否存在重复的坐标点  
        var uniqueCoordinates = coordinates.Distinct().ToList();  
        if (uniqueCoordinates.Count != coordinates.Count)  
        {  
            throw new ArgumentException("Duplicate coordinates are not allowed.");  
        }  
  
        // 检查是否所有边都闭合  
        for (int i = 0; i < coordinates.Count - 1; i++)  
        {  
            Coordinate start = coordinates[i];  
            Coordinate end = coordinates[i + 1];  
            if (!IsLineSegmentValid(start, end))  
            {  
                return false;  
            }  
        }  
        return true; // 所有边都闭合,形成有效的多边形区域  
    }  
  
    private static bool IsLineSegmentValid(Coordinate start, Coordinate end)  
    {  
        // 计算两点之间的距离的平方差,如果小于一个很小的阈值(例如0.00001),则认为两点是同一点或几乎重合的线段。  
        double distanceSquared = (start.Longitude - end.Longitude) * (start.Longitude - end.Longitude) +  
                                 (start.Latitude - end.Latitude) * (start.Latitude - end.Latitude);  
        double threshold = 0.00001; // 可以根据实际情况调整这个阈值  
        return distanceSquared < threshold;  
    }  
}
支持(0) 反对(0) LDMING | 园豆:194 (初学一级) | 2024-01-05 09:04

这些生成的代码,简单的传入一个正方形都不能通过。
测试数据
一、 4个坐标点(正方形),从左下角反时针排序。
100、100
102、100
102、102
100、102

二、4个坐标点(正方形),从左上角顺时针排序。
100、102
102、102
102、100
100、100

支持(0) 反对(0) LDMING | 园豆:194 (初学一级) | 2024-01-05 10:25
清除回答草稿
   您需要登录以后才能回答,未注册用户请先注册