多邊形面積的計算一般是將其剖分爲三角形,利用海倫公式計算每個三角形的面積,然後將所有三角形的面積加起來。但是,這種方法程序實現起來比較複雜,因爲無法預知多邊形的形狀,需要判斷多邊形的“凸凹”,從而避免重複計算。本文采用向量的叉乘的方法,不管座標原點怎樣選取,只要順序輸入多邊形每個頂點的座標,按同樣的順序(順時針或反時針)兩兩叉乘。這些叉乘的和的絕對值的一半就是該多邊形面積。這就是所謂的“鞋帶公式”(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