之前,应朋友所托,完成个四边形面积计算程序,于是不由自主考虑来个扩展,解决任意多边形面积的计算。
一开始想到了某定点的三角形剖分,但遇到凹凸多边形引发的多种情况,过于复杂,放弃。
后来想到用图形学中填充算法中的扫描线方法,切分成梯形与三角形,将交点存入活性边表后再计算面积,感觉也较复杂,放弃。
再然后,找到个计算几何大神O’Rourke在1998年公开的成果。
*(书名:Computational Geometry in C,第二版P20)*
1-原理介绍
上书中给出定理:
任意多边形的面积可由任意一点与多边形上依次两点连线构成的三角形矢量面积求和得出。
矢量面积=三角形两边矢量的叉乘。
如下图:
按定理,多边形面积由P点与A-G的各顶点连接所构成的三角形矢量面积构成,假定多边形顶点坐标顺序为A-G,逆时针为正方向,则有如下结论:
PAB,PBC,PCD均为顺时针,面积为负;
PDE,PEF,PFG,PGA均未逆时针,面积为正;
但无论正负,均可通过P点与顶点连线的矢量叉乘完成,叉乘结果中已包含面积的正负。
2-程序设计
采用C++的vector(动态数组)存储顶点坐标。
为方便计算,直接将P点定为原点(0,0),则多边形顶点xy坐标即为向量在xy上分量。
循环计算多边形顶点坐标每一点与下一点之间的线段,及这两点与P连线的矢量所围成的三角形面积。
计算面积的函数代码如下:
iArea=iArea+(vecPoly[iCycle].x*vecPoly[(iCycle+1) % iCount].y-vecPoly[(iCycle+1) % iCount].x*vecPoly[iCycle].y); int intAreaCalc(vector<myPoint> &vecPoly) { int iCycle,iCount,iArea; iCycle=0; iArea=0; iCount=vecPoly.size(); for(iCycle=0;iCycle<iCount;iCycle++) { iArea=iArea+(vecPoly[iCycle].x*vecPoly[(iCycle+1) % iCount].y-vecPoly[(iCycle+1) % iCount].x*vecPoly[iCycle].y); } return abs(0.5*iArea); }
注意,要注意的是最后一个顶点,要与第一个顶点练成三角形,可将循环变量对顶点总数求同余,则循环过程中的最后一点+1后,自然会成为第一个顶点,上述代码中的“% iCount”即为解决此问题。
完整程序,请下载工程文件。
http://files.cnblogs.com/vbspine/sdkPoly.rar
Ps:上述程序在Win7x64,VS2008环境下编译通过。
转载:http://www.cnblogs.com/vbspine/archive/2013/03/28/2987818.html
方法:转自红黑联盟:http://www.2cto.com/kf/201210/162799.html
题目:输入一个点列,顺次连接成一个封闭多边形,计算多边形的面积
分析:方法一,计算面积可以考虑定积分的形式,定积分有正有负,顺次求和,重复部分相互抵消,最后剩下的总面积的绝对值就是多边形的面积。
从线性积分后的结果可以容易的看出,直线段的积分实际上就是求该直线段与x轴所围成的区域的梯形的面积Int(P1, P2) = Int(k*x + b, P1.x, P2.x) = 0.5 * (P2.x - P1.x) * (P2.y + P1.y), 斜率k = (P1.y - P2.y) / (P1.x - P2.x),截距b = P1.y - k*P1.x;
算法的复杂度为:O(N),N为顶点的个数。
[cpp code]
struct Point {
float x, y;
};
float LinearIntegration(const Point &p1, const Point &p2) {
return 0.5 * (p2.x - p1.x) * (p2.y + p1.y);
}
float ComputePolygonArea(const Point points[], int N) {
if (points == NULL || N <= 0) return 0.0;
float area = 0.0;
for (int i = 0; i < N - 1; ++ i) {
area += LinearIntegration(points[i], points[i + 1]);
}
area += LinearIntegration(points[N - 1], points[0]);
return area >= 0.0 ? area : -area;
}
方法二,考虑到平面上知道三角形三个顶点的坐标可以运用行列式det直接求解三角形的面积。如P1(x1,y1),P2(x2,y2),P3(x3,y3),则
S(P1, P2, P3) = det[ x1 y1 1; x2 y2 1; x3 y3 1] * 0.5 = [(x2 - x1) * (y3 - y1) - (x3 - x1) * (y2 - y1)] * 0.5;
可以在多边形的平面中任意的找到一个点,与多边形的每条边形成有向三角形,并顺次求取有向三角形的面积,再加和,因为是有向面积同上述定积分类似,面积有正有负可抵消重复部分,剩下的面积的绝对值即为多边形的面积。
[cpp code]
struct Point {
float x, y;
Point() {x = 0.0; y = 0.0;}
Point(float _x, float _y) {x = _x; y = _y;}
};
float ComputeTriangleArea(const Point &p1, const Point &p2, const Point &p3) {
return 0.5 * ((p2.x - p1.x) * (p3.y - p1.y) - (p3.x - p1.x) * (p2.y - p1.y));
}
float ComputePolygonAreaTri(const Point points[], int N) {
if (points == NULL || N <= 0) return 0.0;
Point p0(0.0, 0.0);
float area = 0.0;
for (int i = 0; i < N - 1; ++ i) {
area += ComputeTriangleArea(p0, points[i], points[i + 1]);
}
area += ComputeTriangleArea(p0, points[N - 1], points[0]);
return area >= 0.0 ? area : -area;
}
实例:
[cpp test code]
#include
using namespace std;
struct Point
{
};
float LinearIntegration(const Point &p1, const Point &p2)
{
}
float ComputePolygonArea(const Point points[], int length)
{
}
int main()
{
}
题目:http://acm.whu.edu.cn/learn/problem/detail?problem_id=1402
Mr. Tenant is going to buy a new house. In fact, he is going to buy a piece of land and build his new house on it. In order to decide which piece of land to buy, Mr. Tenant needs a program which will give a score to each piece. Each candidate piece of land is a polygonal shape (not necessarily convex), and Mr.
3 0.001 0 1.999 0 0 2
5 10 10 10 12 11 11 12 12 12.0 10.0
0
2
3
转载:http://blog.sina.com.cn/s/blog_a2ae2da90101ofk7.html