多边形交叉区域计算面积_使用这个公式,可计算任意多边形面积

本文介绍了一种计算任意多边形交叉面积的方法,通过提供的代码实现,能够计算包括弧形在内的多边形面积。重点是计算多边形面积的算法和寻找水位线与多边形交点的函数,可用于水文计算中的过水断面面积。
摘要由CSDN通过智能技术生成

之前尝试过很多的任意多边形截面积计算,都有不同的局限性,直到使用了这个公式后,问题就解决了,感谢原作者的分享。

//堰槽坐标定义

typedef struct

{

double x;

double y;

}WeirCoorType;

//任意多边形面积计算

double CLASS_NAME::PolygonAreaCalculation(WeirCoorType *pWeirCoor, WORD CoorCnt)

{

double sum0 = 0;

double square;

//这个多边形计算代码如此简单,可以计算任意的多边形,就算是弧形都行,只要你输入坐标点就行

for (int i = 0; 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;

}

最后测试生成的效果,用于对一个任意河道的不同过水断面进行计算,这个断面就是一个任意多边形。

代码的核心就是计算多边形面积,以及寻找水位线与断面(多边形)的交点,根据交点获取水位以下河道多边形的坐标。

这个绿线对应的就是水位与河道形成的多边形,这个公式可以允许2个相连接的多边形,比如上图所示的,水位Y值为15,灰色区域就是河道,没有水的地方,这个多边形计算公式会自动的计算左右2个过水断面的面积。//计算交点的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个坐标的Y轴一样rn");

return pWeirCoor1->x;

}

else if (pWeirCoor1->y > pWeirCoor2->y)

{

pMaxCoor = pWeirCoor1;//Y轴大的点

pMinCoor = pWeirCoor2;//Y轴小的点

}

else

{

pMaxCoor = pWeirCoor2;//Y轴大的点

pMinCoor = pWeirCoor1;//Y轴小的点

}

if (y >= pMaxCoor->y) return pMaxCoor->x;//大于大的点

if (y y) return pMinCoor->x;//小于小的点

//斜线,并且处于中间

ftemp = ((pMaxCoor->y - y) * (pMaxCoor->x - pMinCoor->x)) / (pMaxCoor->y - pMinCoor->y);

ftemp = pMaxCoor->x - ftemp;

return ftemp;

}

这个函数用于计算水位(一个水平横线)与河道交叉点的X坐标,由于水位是一个Y值,X值就是距离河道边零点的距离,通过这个就可以知道水位与河道的交叉点坐标,也就是水位与河道形成的过水断面多边形的交差坐标。

通过下面的这个线程就可以不听的计算任意水位对应的过水断面面积,我的做法是人为设置一个分辨率,比如1cm,程序会计算0cm断面面积,1cm水位断面面积,2cm水位断面面积,依次类推。//线程-运行核心

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 

{

//WeirCoorType WeirCoor1[9] = { {0,0}, {25,0}, {25,50}, {75,50},{75,0}, {90,0},{100,0}, {100,100},{0,100}};

//坐标必须按照顺序,从左上角,左下角,右下角,右上角顺序,X轴依次增加,左上角与右上角Y轴相等并且最大

//WeirCoorType WeirCoor1[9] = { { 0, 100 }, { 0, 0 }, { 25, 0 }, { 25, 50 }, { 75, 50 }, { 75, 0 }, { 100, 0 }, { 100, 100 }};

//寻找Y轴交点坐标

i = 0;

count = 0;

for (int j = 0; j WeirCoorNum / 2; j++)//循环寻找交点-一对

{

//从第一个坐标开始,先寻找Y值对应的X坐标

for (; i WeirCoorNum - 1); i++)

{

if (this->pWeirCoorBuff[i].y >= this->VarY && this->pWeirCoorBuff[i + 1].y VarY) //左边交点

{

USER_DEBUG.Printf("左交点:%f,%f~%f,%frn", this->pWeirCoorBuff[i].x, this->pWeirCoorBuff[i].y, this->pWeirCoorBuff[i + 1].x, this->pWeirCoorBuff[i + 1].y);

//计算交点坐标

X = this->CalculateIntersectionX(&this->pWeirCoorBuff[i], &this->pWeirCoorBuff[i + 1], this->VarY);

USER_DEBUG.Printf("左交点:(%f,%f)rn", X, this->VarY);

TempWeirCoor1[count].x = X;

TempWeirCoor1[count].y = this->VarY;

count++;

StartIndex = i + 1;

break;

}

}

//从第一个坐标开始,先寻找Y值对应的X坐标

for (; i WeirCoorNum - 1); i++)

{

if (this->pWeirCoorBuff[i].y VarY && this->pWeirCoorBuff[i + 1].y >= this->VarY) //右边交点

{

USER_DEBUG.Printf("右交点:%f,%f~%f,%frn", this->pWeirCoorBuff[i].x, this->pWeirCoorBuff[i].y, this->pWeirCoorBuff[i + 1].x, this->pWeirCoorBuff[i + 1].y);

//计算交点坐标

X = this->CalculateIntersectionX(&this->pWeirCoorBuff[i], &this->pWeirCoorBuff[i + 1], this->VarY);

USER_DEBUG.Printf("右交点:(%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;  //选择的点数量

memcpy(this->pSelectWeirCoor1, TempWeirCoor1, sizeof(WeirCoorType) * count);

this->mBackgroundWorker->ReportProgress(1);//状态改变

//打印最终的坐标

USER_DEBUG.Printf("多边形坐标:");

for (i = 0; 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; //截面积写入全局缓冲区中

this->VarY += this->VerticalResVal;

if (this->VarY > this->pWeirCoorBuff[0].y)

{

USER_DEBUG.Printf("垂直高度超出范围了,退出!rn");

break;

}

Sleep(20);

}

ftemp = this->SectionalArea;

for (; n 

{

this->SectionalAreaBuff[n] = ftemp;

ftemp += 0.00001; //截面积只能增大,不能不变,有效位数5位小数自增

}

//生成datatable

this->mDataTable->Rows->Clear();//清空行

for (int i = 0; i 

{

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);

}

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值