多边形面积的计算
目錄
- 前言
- 計(jì)算公式
- 程序說明
- 程序源文件
- 參考文獻(xiàn)
前言
多邊形面積的計(jì)算一般是將其剖分為三角形,利用海倫公式計(jì)算每個(gè)三角形的面積,然后將所有三角形的面積加起來。但是,這種方法程序?qū)崿F(xiàn)起來比較復(fù)雜,因?yàn)闊o法預(yù)知多邊形的形狀,需要判斷多邊形的“凸凹”,才能避免重復(fù)計(jì)算。另外,計(jì)算邊長的計(jì)算量也比較大。本文采用“鞋帶公式” (Shoelace formula) 計(jì)算
,不管坐標(biāo)原點(diǎn)怎樣選取,只要順序輸入多邊形每個(gè)頂點(diǎn)的坐標(biāo),按同樣的順序(順時(shí)針或反時(shí)針)兩兩叉乘。這些叉乘的和的絕對值的一半就是該多邊形面積。這個(gè)方法編程簡單,計(jì)算量也比較小,優(yōu)勢明顯。
計(jì)算公式
設(shè)O為原點(diǎn),多邊形由點(diǎn)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?)
舉一個(gè)最簡單的例子,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?而得。粗粗看上去好像問題搞復(fù)雜了,其實(shí)不然,因?yàn)槿切?span id="ozvdkddzhkzd" class="katex--inline">OP1P2OP_1P_2OP1?P2?、OP0P1OP_0P_1OP0?P1?和OP2P1OP_2P_1OP2?P1?的面積(帶符號)都通過叉乘而得,編程非常簡單。這幾個(gè)帶符號面積相加,自動(dòng)消除了重復(fù)計(jì)算的部分。可以說非常巧妙。當(dāng)推廣到一般n的時(shí)候,這種算法的優(yōu)勢就很明顯了。
程序說明
本文用C++實(shí)現(xiàn)多邊形面積計(jì)算。由于程序比較小,所有定義都放在一個(gè)文件中。程序中將多邊形定義為一個(gè)類:Polygon。頂點(diǎn)存儲(chǔ)在一個(gè)屬性ps(數(shù)組)中。定義了頂點(diǎn)數(shù)據(jù)的輸入輸出函數(shù)。為了簡便起見,不考慮頂點(diǎn)數(shù)據(jù)的修改或刪除。屬性函數(shù)getArea()運(yùn)用以上公式計(jì)算多邊形面積。
程序源文件
#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; }實(shí)驗(yàn)數(shù)據(jù)文件:data.txt
3 4 5 11 12 8 9 5 5 6 6 5 5 9 8 12 11 5 4 3參考文獻(xiàn)
計(jì)算公式參考:
https://en.wikipedia.org/wiki/Shoelace_formula
總結(jié)
- 上一篇: 【Azure Data Platform
- 下一篇: VBA 单一单元格的多行内容拆分为多行