首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何计算二维多边形的面积?

如何计算二维多边形的面积?
EN

Stack Overflow用户
提问于 2009-01-16 18:18:08
回答 16查看 80.2K关注 0票数 91

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

顺便说一句,这不是作业,我也不是在找代码。我正在寻找一种描述,我可以用来实现我自己的方法。我有从点列表中提取一系列三角形的想法,但我知道有一堆关于凸多边形和凹多边形的边缘情况,我可能无法捕捉到。

EN

回答 16

Stack Overflow用户

回答已采纳

发布于 2009-01-16 18:39:05

这是the standard method,AFAIK。基本上对每个顶点周围的叉积求和。比三角测量简单得多。

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

代码语言:javascript
复制
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评论:值得一提的是该算法的工作原理:它是函数−y和x的Green's theorem应用程序;与planimeter的工作方式完全相同。更确切地说:

上面的公式=

integral_over_perimeter(-y dx + x dy) =

integral_over_area((-(-dy)/dy+dx/dx) dy dx) =

2 Area

票数 119
EN

Stack Overflow用户

发布于 2009-04-04 16:38:57

叉积是经典的。

如果你有大量这样的计算要做,试试下面的优化版本,它需要的乘法次数减少了一半:

代码语言:javascript
复制
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不是偶数,则附加第一个点的另一个副本。

该算法是通过展开并结合经典叉积算法的两次连续迭代而获得的。

我不太确定这两种算法在数值精度方面的比较。我的印象是,上述算法比经典算法更好,因为乘法往往会恢复减法的精度损失。当约束使用浮点数时,就像使用GPU一样,这可能会产生很大的差异。

编辑:"Area of Triangles and Polygons 2D & 3D"描述了一种更有效的方法

代码语言:javascript
复制
// "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;
票数 14
EN

Stack Overflow用户

发布于 2013-11-09 19:48:56

This page表明该公式

可以简化为:

如果你写出几个术语,并根据xi的公共因素对它们进行分组,等价性就不难看出。

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

代码语言:javascript
复制
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,here那里学到了这个简化。

如果你有NumPy,这个版本会更快(除了非常小的数组):

代码语言:javascript
复制
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
票数 13
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/451426

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档