多边形面积的计算
目錄
- 前言
- 計算公式
- 程序說明
- 程序源文件
- 參考文獻
前言
多邊形面積的計算一般是將其剖分為三角形,利用海倫公式計算每個三角形的面積,然后將所有三角形的面積加起來。但是,這種方法程序實現起來比較復雜,因為無法預知多邊形的形狀,需要判斷多邊形的“凸凹”,才能避免重復計算。另外,計算邊長的計算量也比較大。本文采用“鞋帶公式” (Shoelace formula) 計算
,不管坐標原點怎樣選取,只要順序輸入多邊形每個頂點的坐標,按同樣的順序(順時針或反時針)兩兩叉乘。這些叉乘的和的絕對值的一半就是該多邊形面積。這個方法編程簡單,計算量也比較小,優勢明顯。
計算公式
設O為原點,多邊形由點P0,P1,...,Pn?1P_0, P_1, ..., P_{n-1}P0?,P1?,...,Pn?1?連線圍成,則面積S為:
S=12∣∑i=0n?1(OPi ̄×OPi+1 ̄)∣,(Pn=P0)S=\frac{1}{2}|\sum_{i=0}^{n-1}({\overline{OP_i}\times\overline{OP_{i+1}}})|, (P_n=P_0)S=21?∣i=0∑n?1?(OPi??×OPi+1??)∣,(Pn?=P0?)
舉一個最簡單的例子,n=3。也就是三角形的面積。
S=12∣OP0 ̄×OP1 ̄+OP1 ̄×OP2 ̄+OP2 ̄×OP0 ̄∣S=\frac{1}{2}| \overline{OP_0}\times \overline{OP_1}+\overline{OP_1}\times \overline{OP_2}+\overline{OP_2}\times \overline{OP_0}| S=21?∣OP0??×OP1??+OP1??×OP2??+OP2??×OP0??∣
如圖,三角形P0P1P2P_0P_1P_2P0?P1?P2?的面積(即粉紅色部分)等于三角形OP1P2OP_1P_2OP1?P2?減去三角形OP0P1OP_0P_1OP0?P1?和三角形OP2P1OP_2P_1OP2?P1?而得。粗粗看上去好像問題搞復雜了,其實不然,因為三角形OP1P2OP_1P_2OP1?P2?、OP0P1OP_0P_1OP0?P1?和OP2P1OP_2P_1OP2?P1?的面積(帶符號)都通過叉乘而得,編程非常簡單。這幾個帶符號面積相加,自動消除了重復計算的部分。可以說非常巧妙。當推廣到一般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
總結
- 上一篇: 【Azure Data Platform
- 下一篇: VBA 单一单元格的多行内容拆分为多行