之前嘗試過很多的任意多邊形截面積計算,都有不同的局限性,直到使用了這個公式后,問題就解決了,感謝原作者的分享。
//堰槽坐標(biāo)定義
typedef?struct??
{
double?x;
double?y;
}WeirCoorType;//任意多邊形面積計算
double?CLASS_NAME::PolygonAreaCalculation(WeirCoorType?*pWeirCoor,?WORD?CoorCnt)
{
double?sum0?=?0;
double?square;
//這個多邊形計算代碼如此簡單,可以計算任意的多邊形,就算是弧形都行,只要你輸入坐標(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;
}最后測試生成的效果,用于對一個任意河道的不同過水?dāng)嗝孢M(jìn)行計算,這個斷面就是一個任意多邊形。
代碼的核心就是計算多邊形面積,以及尋找水位線與斷面(多邊形)的交點(diǎn),根據(jù)交點(diǎn)獲取水位以下河道多邊形的坐標(biāo)。
這個綠線對應(yīng)的就是水位與河道形成的多邊形,這個公式可以允許2個相連接的多邊形,比如上圖所示的,水位Y值為15,灰色區(qū)域就是河道,沒有水的地方,這個多邊形計算公式會自動的計算左右2個過水?dāng)嗝娴拿娣e。
//計算交點(diǎn)的X值
double?CLASS_NAME::CalculateIntersectionX(WeirCoorType?*pWeirCoor1,?WeirCoorType?*pWeirCoor2,?double?y)
{
double?ftemp;
WeirCoorType?*pMaxCoor,?*pMinCoor;
if?(pWeirCoor1->y?==?pWeirCoor2->y)?//Y軸一樣,不允許的,隨便輸出一個X軸
{
SYS_LOG.Write(__FILE__?+?__LINE__?+?"?t:不允許2個坐標(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;
}這個函數(shù)用于計算水位(一個水平橫線)與河道交叉點(diǎn)的X坐標(biāo),由于水位是一個Y值,X值就是距離河道邊零點(diǎn)的距離,通過這個就可以知道水位與河道的交叉點(diǎn)坐標(biāo),也就是水位與河道形成的過水?dāng)嗝娑噙呅蔚慕徊钭鴺?biāo)。
通過下面的這個線程就可以不聽的計算任意水位對應(yīng)的過水?dāng)嗝婷娣e,我的做法是人為設(shè)置一個分辨率,比如1cm,程序會計算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)-一對
{
//從第一個坐標(biāo)開始,先尋找Y值對應(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);
//計算交點(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;
}
}
//從第一個坐標(biāo)開始,先尋找Y值對應(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);
//計算交點(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}};
//任意多邊形面積計算
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個截面數(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);
}
}




