使用這個(gè)公式,可計(jì)算任意多邊形面積
之前嘗試過很多的任意多邊形截面積計(jì)算,都有不同的局限性,直到使用了這個(gè)公式后,問題就解決了,感謝原作者的分享。
//堰槽坐標(biāo)定義 typedef?struct?? { double?x; double?y; }WeirCoorType;
//任意多邊形面積計(jì)算 double?CLASS_NAME::PolygonAreaCalculation(WeirCoorType?*pWeirCoor,?WORD?CoorCnt) { double?sum0?=?0; double?square; //這個(gè)多邊形計(jì)算代碼如此簡(jiǎn)單,可以計(jì)算任意的多邊形,就算是弧形都行,只要你輸入坐標(biāo)點(diǎn)就行 for?(int?i?=?0;?i?<?CoorCnt?-?1;?i++) { sum0?+=?(pWeirCoor[i].x?*?pWeirCoor[i?+?1].y?-?pWeirCoor[i?+?1].x?*?pWeirCoor[i].y); } square?=?(fabs(sum0?+?(pWeirCoor[CoorCnt?-?1].x?*?pWeirCoor[0].y)?-?(pWeirCoor[0].x?*?pWeirCoor[CoorCnt?-?1].y)))?/?2; return?square; }
最后測(cè)試生成的效果,用于對(duì)一個(gè)任意河道的不同過水?dāng)嗝孢M(jìn)行計(jì)算,這個(gè)斷面就是一個(gè)任意多邊形。
代碼的核心就是計(jì)算多邊形面積,以及尋找水位線與斷面(多邊形)的交點(diǎn),根據(jù)交點(diǎn)獲取水位以下河道多邊形的坐標(biāo)。
這個(gè)綠線對(duì)應(yīng)的就是水位與河道形成的多邊形,這個(gè)公式可以允許2個(gè)相連接的多邊形,比如上圖所示的,水位Y值為15,灰色區(qū)域就是河道,沒有水的地方,這個(gè)多邊形計(jì)算公式會(huì)自動(dòng)的計(jì)算左右2個(gè)過水?dāng)嗝娴拿娣e。
//計(jì)算交點(diǎn)的X值 double?CLASS_NAME::CalculateIntersectionX(WeirCoorType?*pWeirCoor1,?WeirCoorType?*pWeirCoor2,?double?y) { double?ftemp; WeirCoorType?*pMaxCoor,?*pMinCoor; if?(pWeirCoor1->y?==?pWeirCoor2->y)?//Y軸一樣,不允許的,隨便輸出一個(gè)X軸 { SYS_LOG.Write(__FILE__?+?__LINE__?+?"?t:不允許2個(gè)坐標(biāo)的Y軸一樣rn"); return?pWeirCoor1->x; } else?if?(pWeirCoor1->y?>?pWeirCoor2->y) { pMaxCoor?=?pWeirCoor1; //Y軸大的點(diǎn) pMinCoor?=?pWeirCoor2; //Y軸小的點(diǎn) } else { pMaxCoor?=?pWeirCoor2; //Y軸大的點(diǎn) pMinCoor?=?pWeirCoor1; //Y軸小的點(diǎn) } if?(y?>=?pMaxCoor->y)?return?pMaxCoor->x; //大于大的點(diǎn) if?(y?y)?return?pMinCoor->x; //小于小的點(diǎn) //斜線,并且處于中間 ftemp?=?((pMaxCoor->y?-?y)?*?(pMaxCoor->x?-?pMinCoor->x))?/?(pMaxCoor->y?-?pMinCoor->y); ftemp?=?pMaxCoor->x?-?ftemp; return?ftemp; }
這個(gè)函數(shù)用于計(jì)算水位(一個(gè)水平橫線)與河道交叉點(diǎn)的X坐標(biāo),由于水位是一個(gè)Y值,X值就是距離河道邊零點(diǎn)的距離,通過這個(gè)就可以知道水位與河道的交叉點(diǎn)坐標(biāo),也就是水位與河道形成的過水?dāng)嗝娑噙呅蔚慕徊钭鴺?biāo)。
通過下面的這個(gè)線程就可以不聽的計(jì)算任意水位對(duì)應(yīng)的過水?dāng)嗝婷娣e,我的做法是人為設(shè)置一個(gè)分辨率,比如1cm,程序會(huì)計(jì)算0cm斷面面積,1cm水位斷面面積,2cm水位斷面面積,依次類推。
//線程-運(yùn)行核心?? System::Void?CLASS_NAME::BackgroundWorker_DoWork(System::Object^??sender,?System::ComponentModel::DoWorkEventArgs^??e) { double?ftemp; double?Y_Inc?=?0.1; //Y軸增量 WORD?i; double?X; int?Status; WORD?count; WORD?StartIndex; int?n; char?buff[32]; WeirCoorType?TempWeirCoor1[256]; try { this->VarY?=?0; for?(n?=?0;?n?<?256;?n++) { //WeirCoorType?WeirCoor1[9]?=?{?{0,0},?{25,0},?{25,50},?{75,50},{75,0},?{90,0},{100,0},?{100,100},{0,100}}; //坐標(biāo)必須按照順序,從左上角,左下角,右下角,右上角順序,X軸依次增加,左上角與右上角Y軸相等并且最大 //WeirCoorType?WeirCoor1[9]?=?{?{?0,?100?},?{?0,?0?},?{?25,?0?},?{?25,?50?},?{?75,?50?},?{?75,?0?},?{?100,?0?},?{?100,?100?}}; //尋找Y軸交點(diǎn)坐標(biāo) i?=?0; count?=?0; for?(int?j?=?0;?j?<?this->WeirCoorNum?/?2;?j++) //循環(huán)尋找交點(diǎn)-一對(duì) { //從第一個(gè)坐標(biāo)開始,先尋找Y值對(duì)應(yīng)的X坐標(biāo) for?(;?i?<?(this->WeirCoorNum?-?1);?i++) { if?(this->pWeirCoorBuff[i].y?>=?this->VarY?&&?this->pWeirCoorBuff[i?+?1].y?<?this->VarY)?//左邊交點(diǎn) { USER_DEBUG.Printf("左交點(diǎn):%f,%f~%f,%frn",?this->pWeirCoorBuff[i].x,?this->pWeirCoorBuff[i].y,?this->pWeirCoorBuff[i?+?1].x,?this->pWeirCoorBuff[i?+?1].y); //計(jì)算交點(diǎn)坐標(biāo) X?=?this->CalculateIntersectionX(&this->pWeirCoorBuff[i],?&this->pWeirCoorBuff[i?+?1],?this->VarY); USER_DEBUG.Printf("左交點(diǎn):(%f,%f)rn",?X,?this->VarY); TempWeirCoor1[count].x?=?X; TempWeirCoor1[count].y?=?this->VarY; count++; StartIndex?=?i?+?1; break; } } //從第一個(gè)坐標(biāo)開始,先尋找Y值對(duì)應(yīng)的X坐標(biāo) for?(;?i?<?(this->WeirCoorNum?-?1);?i++) { if?(this->pWeirCoorBuff[i].y?<?this->VarY?&&?this->pWeirCoorBuff[i?+?1].y?>=?this->VarY)?//右邊交點(diǎn) { USER_DEBUG.Printf("右交點(diǎn):%f,%f~%f,%frn",?this->pWeirCoorBuff[i].x,?this->pWeirCoorBuff[i].y,?this->pWeirCoorBuff[i?+?1].x,?this->pWeirCoorBuff[i?+?1].y); //計(jì)算交點(diǎn)坐標(biāo) X?=?this->CalculateIntersectionX(&this->pWeirCoorBuff[i],?&this->pWeirCoorBuff[i?+?1],?this->VarY); USER_DEBUG.Printf("右交點(diǎn):(%f,%f)rn",?X,?this->VarY); for?(int?k?=?StartIndex;?k?pWeirCoorBuff[k].x; TempWeirCoor1[count].y?=?this->pWeirCoorBuff[k].y; count++; } TempWeirCoor1[count].x?=?X; TempWeirCoor1[count].y?=?this->VarY; count++; break; } } if?(i?>=?this->WeirCoorNum?-?1)?break; } this->SelectCoorCount?=?count;??//選擇的點(diǎn)數(shù)量 memcpy(this->pSelectWeirCoor1,?TempWeirCoor1,?sizeof(WeirCoorType)?*?count); this->mBackgroundWorker->ReportProgress(1); //狀態(tài)改變 //打印最終的坐標(biāo) USER_DEBUG.Printf("多邊形坐標(biāo):"); for?(i?=?0;?i?<?count;?i++) { USER_DEBUG.Printf("%f,%f?t",?TempWeirCoor1[i].x,?TempWeirCoor1[i].y); } USER_DEBUG.Printf("rn"); //WeirCoorType?WeirCoor1[8]?=?{?{0,0},?{100,0},?{100,100},{1,100}}; //任意多邊形面積計(jì)算 ftemp?=?this->PolygonAreaCalculation(TempWeirCoor1,?count); USER_DEBUG.Printf("面積:%frn",?ftemp); this->SectionalArea?=?ftemp; //最終的截面積 this->SectionalAreaBuff[n]?=?this->SectionalArea;?//截面積寫入全局緩沖區(qū)中 this->VarY?+=?this->VerticalResVal; if?(this->VarY?>?this->pWeirCoorBuff[0].y) { USER_DEBUG.Printf("垂直高度超出范圍了,退出!rn"); break; } Sleep(20); } ftemp?=?this->SectionalArea; for?(;?n?<?256;?n++) //補(bǔ)充不足256個(gè)截面數(shù)據(jù),后面截面積固定 { this->SectionalAreaBuff[n]?=?ftemp; ftemp?+=?0.00001;?//截面積只能增大,不能不變,有效位數(shù)5位小數(shù)自增 } //生成datatable this->mDataTable->Rows->Clear(); //清空行 for?(int?i?=?0;?i?<?256;?i++) //循環(huán)添加行 { DataRow?^dr?=?this->mDataTable->NewRow();//新建行 sprintf_s(buff,?31,?"%.5f",?this->SectionalAreaBuff[i]); dr[0]?=?CharToString(buff); this->mDataTable->Rows->Add(dr);//添加行 } } catch?(Exception?^e1) { SYS_LOG.Write(__FILE__?+?__LINE__?+?"t:"?+?e1->Message?+?e1->StackTrace); } }