前言
多边形面积的计算一般是将其剖分为三角形,利用海伦公式计算每个三角形的面积,然后将所有三角形的面积加起来。但是,这种方法程序实现起来比较复杂,因为无法预知多边形的形状,需要判断多边形的“凸凹”,从而避免重复计算。本文采用向量的叉乘的方法,不管坐标原点怎样选取,只要顺序输入多边形每个顶点的坐标,按同样的顺序(顺时针或反时针)两两叉乘。这些叉乘的和的绝对值的一半就是该多边形面积。这就是所谓的“鞋带公式”(Shoelace formula)。
计算公式
设O为原点,多边形由点
连线围成,则面积S为:
举一个最简单的例子,n=3。也就是三角形的面积。
如图,三角形 的面积(即粉红色部分)等于三角形 减去三角形 和三角形 而得。粗粗看上去好像问题搞复杂了,其实不然,因为三角形 、 和 的面积(带符号)都通过叉乘而得,编程非常简单。这几个带符号面积相加,自动消除了重复计算的部分。可以说非常巧妙。当推广到一般n的时候,这种算法的优势就很明显了。
程序说明
本文用C++实现多边形面积计算。由于程序比较小,所有定义都放在一个文件中。程序中将多边形定义为一个类:Polygon。顶点存储在一个属性ps(数组)中。定义了顶点数据的输入输出函数。为了简便起见,不考虑顶点数据的修改或删除。属性函数getArea()运用以上公式计算多边形面积。
程序源文件
#include<iostream>
#include<vector>
#include<stdio.h>
using namespace std;
struct Point
{
double x, y;
};
double operator*(const Point &p1,const Point &p2) { return (p1.x*p2.y-p1.y*p2.x); }
class Polygon
{
private:
vector<Point> ps;
protected:
public:
double getArea();
void pushPoint(double _x, double _y);
void printPoints();
};
double Polygon::getArea()
{
double area=0.0;
for(size_t i=0;i!=ps.size();++i)
{
area+=ps[i] * ps[(i + 1) % ps.size()];
}
return 0.5 * (area >=0 ? area : -area);
}
void Polygon::pushPoint(double _x, double _y)
{
Point pt;
pt.x=_x;
pt.y=_y;
ps.push_back(pt);
}
void Polygon::printPoints()
{
for (size_t i=0;i!=ps.size();++i) {
cout<<"P["<<i<<"]"<<"=("<<ps[i].x<<","<<ps[i].y<<")"<<endl;
}
}
void inputData(Polygon &plygn) //input data from console
{
double vx,vy;
size_t i=0;
cout<<"\nInput points coordinates, separated by space key. ^Z to end."<<endl;
cout<<"P["<<i<<"]=";
while (cin>>vx>>vy) {
plygn.pushPoint(vx,vy);
cout<<"P["<<++i<<"]=";
}
return;
}
int readData(string &dataFileName, Polygon &plygn) //read data from file
{
int itemsRead=0;
FILE *sf;
double vx,vy;
if (sf=fopen(dataFileName.c_str(),"r")) {
cout<<"Read data from "+dataFileName+" ... ... ";
while (!feof(sf)) {
fscanf(sf,"%lf %lf",&vx,&vy);
plygn.pushPoint(vx,vy);
itemsRead++;
}
cout<<itemsRead<<" points read."<<endl;
fclose(sf);
sf=NULL;
}
else itemsRead=-1;
return itemsRead;
}
// main
int main()
{
Polygon pn;
string sn="data.txt";
if (readData(sn,pn)!=-1) {
pn.printPoints();
cout<<"Area="<<pn.getArea()<<endl;
}
else cout<<"404 File not found."<<endl;
return 0;
}
实验数据文件:data.txt
3 4
5 11
12 8
9 5
5 6
6 5
5 9
8 12
11 5
4 3
参考文献
计算公式参考:
https://en.wikipedia.org/wiki/Shoelace_formula