是否有任何算法用于计算形状的面积,给定坐标定义形状?

时间:2010-03-12 11:46:29

标签: c# algorithm geometry

所以我有一些函数接收N个随机2D点。

是否有算法计算输入点定义的形状区域?

5 个答案:

答案 0 :(得分:28)

您想要calculate the area of a polygon

(取自链接,转换为C#)

class Point { double x, y; } 

double PolygonArea(Point[] polygon)
{
   int i,j;
   double area = 0; 

   for (i=0; i < polygon.Length; i++) {
      j = (i + 1) % polygon.Length;

      area += polygon[i].x * polygon[j].y;
      area -= polygon[i].y * polygon[j].x;
   }

   area /= 2;
   return (area < 0 ? -area : area);
}

答案 1 :(得分:1)

定义点集合的“区域”可能很难,例如如果你想获得包含你的集合的直线边界的最小区域,那么我不知道如何继续。可能你想要做的是计算你的点集的凸包的面积;这是一个标准问题,Steven Skiena在Stony Brook Algorithms repository给出了解决方案实现链接问题的描述。从那里计算面积的一种方法(在我看来显而易见的方法)是对区域进行三角测量并计算每个三角形的面积。

答案 2 :(得分:1)

你可以使用Timothy Chan的算法在nlogh中找到凸包,其中n是点数,h是凸包顶点的数量。如果您想要一个简单的算法,请选择格雷厄姆扫描。

另外,如果您知道您的数据是按照简单的链排序的,那么点不会相互交叉,您可以使用Melkman的算法来计算O(N)中的凸包。

此外,凸壳的另一个有趣特性是,它具有最小周长。

答案 3 :(得分:0)

您的问题并不直接暗示存在现成的多边形(由this answer假设)。我建议使用三角测量法,例如Delaunay Triangulation,然后平凡地计算每个三角形的面积。 OpenCV(我已经将它用于大量的2D点并且它非常有效)并且CGAL提供了用于确定三角测量的出色实现。

答案 4 :(得分:0)

我发现了另一个function written in Java,所以我将其转换为C#

public static double area(List<Double> lats,List<Double> lons)
{       
double sum=0;
double prevcolat=0;
double prevaz=0;
double colat0=0;
double az0=0;
for (int i=0;i<lats.Count;i++)
{
    double colat=2*Math.Atan2(Math.Sqrt(Math.Pow(Math.Sin(lats[i]*Math.PI/180/2), 2)+ Math.Cos(lats[i]*Math.PI/180)*Math.Pow(Math.Sin(lons[i]*Math.PI/180/2), 2)),
        Math.Sqrt(1-  Math.Pow(Math.Sin(lats[i]*Math.PI/180/2), 2)- Math.Cos(lats[i]*Math.PI/180)*Math.Pow(Math.Sin(lons[i]*Math.PI/180/2), 2)));
    double az=0;
    if (lats[i]>=90)
    {
        az=0;
    }
    else if (lats[i]<=-90)
    {
        az=Math.PI;
    }
    else
    {
        az=Math.Atan2(Math.Cos(lats[i]*Math.PI/180) * Math.Sin(lons[i]*Math.PI/180),Math.Sin(lats[i]*Math.PI/180))% (2*Math.PI);
    }
    if(i==0)
    {
         colat0=colat;
         az0=az;
    }           
    if(i>0 && i<lats.Count)
    {
        sum=sum+(1-Math.Cos(prevcolat  + (colat-prevcolat)/2))*Math.PI*((Math.Abs(az-prevaz)/Math.PI)-2*Math.Ceiling(((Math.Abs(az-prevaz)/Math.PI)-1)/2))* Math.Sign(az-prevaz);
    }
    prevcolat=colat;
    prevaz=az;
}
sum=sum+(1-Math.Cos(prevcolat  + (colat0-prevcolat)/2))*(az0-prevaz);
return 5.10072E14* Math.Min(Math.Abs(sum)/4/Math.PI,1-Math.Abs(sum)/4/Math.PI);
}