我如何计算2D多边形的面积?

假设二维空间中的一系列不自相交的点,确定所得多边形面积的有效方法是什么?

作为一个侧面说明,这不是作业,我不是在寻找代码。 我正在寻找一个我可以用来实现我自己的方法的描述。 我有关于从点列表中拉出一系列三angular形的想法,但是我知道有一些关于凸多边形和凹多边形的边缘情况,我可能不会理解。

这是标准方法 ,AFAIK。 基本上总结每个顶点周围的交叉产品。 比三angular测量更简单。

Python代码给定了一个表示为(x,y)顶点坐标列表的多边形,隐式地从最后一个顶点绕到第一个顶点:

def area(p): return 0.5 * abs(sum(x0*y1 - x1*y0 for ((x0, y0), (x1, y1)) in segments(p))) def segments(p): return zip(p, p[1:] + [p[0]]) 

David Lehavi评论道:值得一提的是,为什么这个algorithm是有效的:这是Green函数的定理 –y和x; 就像一个平面仪的工作方式一样。 进一步来说:

以上公式=
integral_over_perimeter(-y dx + x dy) =
integral_over_area((-(-dy)/dy+dx/dx) dy dx) =
2 Area

交叉产品是一个经典的。

如果你有这样的计算要做,请尝试下面的优化版本,需要less一半的乘法:

 area = 0; for( i = 0; i < N; i += 2 ) area += x[i+1]*(y[i+2]-y[i]) + y[i+1]*(x[i]-x[i+2]); area /= 2; 

我使用数组下标清晰。 使用指针更有效率。 虽然好的编译器会为你做。

假定多边形是“闭合的”,这意味着您将第一个点复制为带有下标N的点。它也假定多边形具有偶数个点。 如果N不是偶数,则附加第一个点的附加副本。

该algorithm是通过展开和组合经典叉积algorithm的两个连续迭代而获得的。

我不太确定两种algorithm如何比较数值精度。 我的印象是,上述algorithm比传统algorithm更好,因为乘法倾向于恢复减法精度的损失。 当被限制使用浮点数时,与GPU一样,这可能会产生显着的差异。

编辑: “面积的三angular形和多边形2D和3D”描述了一个更有效的方法

 // "close" polygon x[N] = x[0]; x[N+1] = x[1]; y[N] = y[0]; y[N+1] = y[1]; // compute area area = 0; for( size_t i = 1; i <= N; ++i ) area += x[i]*( y[i+1] - y[i-1] ); area /= 2; 

该页面显示公式

在这里输入图像描述

可以简化为:

在这里输入图像描述

如果按照xi共同因素写出几个词并进行分组,那么平等就不难看出。

最后的求和效率更高,因为它只需要n乘法而不是2n

 def area(x, y): return abs(sum(x[i] * (y[i + 1] - y[i - 1]) for i in xrange(-1, len(x) - 1))) / 2.0 

我从这里学到了Joe Kington的这个简化。


如果你有NumPy,这个版本更快(对于所有非常小的数组):

 def area_np(x, y): x = np.asanyarray(x) y = np.asanyarray(y) n = len(x) shift_up = np.arange(-n+1, 1) shift_down = np.arange(-1, n-1) return (x * (y.take(shift_up) - y.take(shift_down))).sum() / 2.0 

这是一个很好的解释,还没有被链接: http : //www.wikihow.com/Calculate-the-Area-of-a-Polygon

没有任何其他约束的一组点不一定要定义一个多边形。

所以,首先你必须决定从这些点构build多边形 – 可能是凸包? http://en.wikipedia.org/wiki/Convex_hull

然后三angular测量和计算面积。 http://www.mathopenref.com/polygonirregulararea.html

要展开三angular形和总和三angular形区域,那些工作如果你碰巧有一个凸多边形,或者你碰巧select一个点不会产生线与其他点相交的多边形。

对于一般的不相交多边形,需要将vector(参考点,点a),(参考点,点b)的交叉积相加,其中a和b彼此相邻。

假设你有一个按顺序定义多边形的点列表(顺序是点i和i + 1构成多边形的一条直线):

对于i = 1到n-1,和(交叉积((点0,点i),(点0,点i + 1))。

以跨产品的大小,你有表面积。

这将处理凹多边形,而不必担心挑选一个好的参考点; 生成一个不在多边形内部的三angular形的任何三个点都会有一个交叉积,它指向与多边形内部任何三angular形相反的方向,因此可以正确求和区域。

计算多边形的面积

http://community.topcoder.com/tc?module=Static&d1=tutorials&d2=geometry1#polygon_area

 int cross(vct a,vct b,vct c) { vct ab,bc; ab=ba; bc=cb; return ab.x*bc.y-ab.y*bc.x; } double area(vct p[],int n) { int ar=0; for(i=1;i+1<n;i++) { vct a=p[i]-p[0]; vct b=p[i+1]-p[0]; area+=cross(a,b); } return abs(area/2.0); } 

或者做一个轮廓积分。 斯托克斯定理允许您将面积积分表示为轮廓积分。 有一点高斯正交,鲍勃是你的叔叔。

一种方法是将多边形分解为三angular形 ,计算三angular形的面积,并将和作为多边形的面积。

  1. 设置一个基点(最凸点)。 这将是你三angular形的支点。
  2. 计算除了基点以外的最左点(任意)。
  3. 计算第二个最左边的点来完成你的三angular形。
  4. 保存这个三angular区域。
  5. 每次迭代都向右移一个点。
  6. 总结三angular区域

总结三angular形总结好于笛卡尔空间中的梯形:

 area = 0; for (i = 0; i < n; i++) { i1 = (i + 1) % n; area += (vertex[i].y + vertex[i1].y) * (vertex[i1].x - vertex[i].x) / 2.0; } 

语言独立解决scheme

GIVEN:一个多边形总是可以由n-2个不重叠的三angular形组成(n =点数或边数)。 1三angular形= 3边多边形= 1三angular形; 1平方= 4边多边形= 2个三angular形; 等QED令人难堪

因此,可以通过“砍掉”三angular形来减less多边形,并且总面积将是这些三angular形的面积的总和。 尝试用一张纸和剪刀,最好是如果你可以看到之前的过程。

如果在多边形path中采用任意3个连续的点并用这些点创build三angular形,则只有以下三种可能的场景中的一种:

  1. 结果三angular形完全在原来的多边形内
  2. 结果三angular形完全在原始多边形之外
  3. 结果三angular形部分包含在原始多边形中

我们只对第一种select(完全包含)的情况感兴趣。

每当我们find其中的一个时,我们把它砍掉,计算它的面积(容易松动,不会在这里解释公式),并创build一个less一边的新多边形(相当于切掉这个三angular形的多边形)。 直到我们只剩下一个三angular形

如何实现这个编程:

创build一个表示围绕多边形的path的(连续的)点arrays。 从点0开始,从点x,x + 1和x + 2运行三angular形(一次一个)。 将每个三angular形从一个形状转换到一个区域,并与从多边形创build的区域相交。 如果得到的交点与原始三angular形相同,则所述三angular形完全包含在多边形中,并且可以被切掉。 从数组中移除x + 1并从x = 0重新开始。 否则(如果三angular形在[部分或完全]多边形之外),移动到数组中的下一个点x + 1。

此外,如果您正在寻找与地图集成并从地理点开始,则必须从地点转换为FIRST屏幕点。 这需要决定一个地球形状的build模和公式(尽pipe我们倾向于把地球看作一个球体,实际上它是一个不规则的卵圆形(蛋形),有凹痕)。 有很多模型在那里,进一步的信息维基。 一个重要的问题是,你会不会考虑该地区是一个飞机或弯曲。 一般而言,如果考虑平面而不是凸面的,那么点之间相距几公里的“小”区域不会产生显着的误差。

我的倾向是简单地开始切掉三angular形。 我看不出还有什么可以避免变得毛茸茸的。

取三个连续的点组成多边形。 确保angular度小于180.现在有了一个新的三angular形,应该没有问题计算,从多边形列表中删除中点。 重复,直到你只剩下三点。

Shoelace公式的实现可以在Numpy中完成。 假设这些顶点:

 import numpy as np x = np.arange(0,1,0.001) y = np.sqrt(1-x**2) 

我们可以定义以下函数来查找区域:

 def PolyArea(x,y): return 0.5*np.abs(np.dot(x,np.roll(y,1))-np.dot(y,np.roll(x,1))) 

并获得结果:

 print PolyArea(x,y) # 0.26353377782163534 

避免循环使这个函数比PolygonArea快50倍:

 %timeit PolyArea(x,y) # 10000 loops, best of 3: 42 µs per loop %timeit PolygonArea(zip(x,y)) # 100 loops, best of 3: 2.09 ms per loop 

注:我已经写了这个答案的另一个问题 ,我只是提到这里有一个完整的解决scheme列表。

C这样做的方式:

 float areaForPoly(const int numVerts, const Point *verts) { Point v2; float area = 0.0f; for (int i = 0; i<numVerts; i++){ v2 = verts[(i + 1) % numVerts]; area += verts[i].x*v2.y - verts[i].y*v2.x; } return area / 2.0f; } 

我将给出一些简单的计算2D多边形面积的函数。 这适用于凸多边形和凹多边形。 我们简单地将多边形分成许多子三angular形。

 //don't forget to include cmath for abs function struct Point{ double x; double y; } double cp(Point a, Point b){ //returns cross product return ax*by-ay*bx; } double area(Point * vertices, int n){ //n is number of sides double sum=0.0; for(i=0; i<n; i++){ sum+=cp(vertices[i]+vertices[(i+1)%n]); //%n is for last triangle } return abs(sum)/2.0; } 

Python代码

如此处所述: http : //www.wikihow.com/Calculate-the-Area-of-a-Polygon

随着pandas

 import pandas as pd df = pd.DataFrame({'x': [10, 20, 20, 30, 20, 10, 0], 'y': [-10, -10, -10, 0, 10, 30, 20]}) df = df.append(df.loc[0]) first_product = (df['x'].shift(1) * df['y']).fillna(0).sum() second_product = (df['y'].shift(1) * df['x']).fillna(0).sum() (first_product - second_product) / 2 600