📄 lsdoc.cpp
字号:
void CLSDoc::CalcBlockBorders()
{//1
LONG curpos=0;
m_BlockBorders.RemoveAll();
LONG index;
BlockBorder tmpBorder;
long tmpID;
for(long ID=1;ID<=m_BlockNum;ID++)
{//2
Block curblock=m_LittleBlocks[ID-1]; // 当前斑块
curpos=m_BlockBorders.GetSize(); // 该斑块的邻居在数组中的起始位置
// 搜索该斑块的矩形
for(long y=curblock.UPY;y<=curblock.DOWNY;y++)
{//3
for(long x=curblock.LEFTX;x<=curblock.RIGHTX;x++)
{//4
// 找着边界点
if((m_BlockID[x+y*m_nWidth].IsBorder)&&
(m_BlockID[x+y*m_nWidth].ID==ID))
{//5
// 斑块上边界且未被计入
if((y>0)&&((tmpID=m_BlockID[x+(y-1)*m_nWidth].ID)>ID))
{//6
// 检查是否为新类型
for(index=m_BlockBorders.GetUpperBound();
index>=curpos;index--)
{//7
if(m_BlockBorders[index].ID2>tmpID)
continue;
else if(m_BlockBorders[index].ID2==tmpID) // 不是新类型
{
m_BlockBorders[index].Leng++; // 该类型长度加一
break;
}
else // 是新类型,插在ID比他大的前面
{
tmpBorder.ID1=ID;
tmpBorder.ID2=tmpID;
tmpBorder.Leng=1;
m_BlockBorders.InsertAt(index+1,tmpBorder,1);
break;
}
}//7
if(index<curpos) // 如果比数组中所有类型的ID都比他大,插在最前面
{
tmpBorder.ID1=ID;
tmpBorder.ID2=tmpID;
tmpBorder.Leng=1;
m_BlockBorders.InsertAt(index+1,tmpBorder,1);
}
}//6
// 斑块左边界且未被计入
if((x>0)&&((tmpID=m_BlockID[x-1+y*m_nWidth].ID)>ID))
{//6
for(index=m_BlockBorders.GetUpperBound();
index>=curpos;index--)
{//7
if(m_BlockBorders[index].ID2>tmpID)
continue;
else if(m_BlockBorders[index].ID2==tmpID)
{
m_BlockBorders[index].Leng++;
break;
}
else
{
tmpBorder.ID1=ID;
tmpBorder.ID2=tmpID;
tmpBorder.Leng=1;
m_BlockBorders.InsertAt(index+1,tmpBorder,1);
break;
}
}//7
if(index<curpos)
{
tmpBorder.ID1=ID;
tmpBorder.ID2=tmpID;
tmpBorder.Leng=1;
m_BlockBorders.InsertAt(index+1,tmpBorder,1);
}
}//6
// 斑块右边界且未被计入
if((x<(m_nWidth-1))&&((tmpID=m_BlockID[x+1+y*m_nWidth].ID)>ID))
{//6
for(index=m_BlockBorders.GetUpperBound();
index>=curpos;index--)
{//7
if(m_BlockBorders[index].ID2>tmpID)
continue;
else if(m_BlockBorders[index].ID2==tmpID)
{
m_BlockBorders[index].Leng++;
break;
}
else
{
tmpBorder.ID1=ID;
tmpBorder.ID2=tmpID;
tmpBorder.Leng=1;
m_BlockBorders.InsertAt(index+1,tmpBorder,1);
break;
}
}//7
if(index<curpos)
{
tmpBorder.ID1=ID;
tmpBorder.ID2=tmpID;
tmpBorder.Leng=1;
m_BlockBorders.InsertAt(index+1,tmpBorder,1);
}
}
// 斑块下边界且未被计入
if((y<(m_nHeight-1))&&((tmpID=m_BlockID[x+(y+1)*m_nWidth].ID)>ID))
{//6
for(index=m_BlockBorders.GetUpperBound();
index>=curpos;index--)
{//7
if(m_BlockBorders[index].ID2>tmpID)
continue;
else if(m_BlockBorders[index].ID2==tmpID)
{
m_BlockBorders[index].Leng++;
break;
}
else
{
tmpBorder.ID1=ID;
tmpBorder.ID2=tmpID;
tmpBorder.Leng=1;
m_BlockBorders.InsertAt(index+1,tmpBorder,1);
break;
}
}//7
if(index<curpos)
{//7
tmpBorder.ID1=ID;
tmpBorder.ID2=tmpID;
tmpBorder.Leng=1;
m_BlockBorders.InsertAt(index+1,tmpBorder,1);
}//7
}//6
}//5
}//4
}//3
}//2
}//1
BOOL CLSDoc::OnSaveDocument(LPCTSTR lpszPathName)
{
if(!m_bCanExecute)
{
AfxMessageBox("该图像不能用于景观分析,没有结果可以保存!",MB_OK,0);
return FALSE;
}
if(!m_bDone)
{
CString error;
error.Format("尚未命名和计算,没有结果可保存,请先选择菜单:\t\n\n[景观属性]-->[命名和计算], 然后再选择此菜单!");
AfxMessageBox(error,MB_OK,0);
return FALSE;
}
CFile file;
CString path,string;
long id;
CFileDialog FileDialogBox
(FALSE,"txt","*.txt",OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT,
"Text file(*.txt)|*.TXT|",NULL);
if(FileDialogBox.DoModal()==IDOK)
{
CString Eo=FileDialogBox.GetFileExt();
Eo.MakeUpper();
if(Eo=="TXT")
{
path=FileDialogBox.GetPathName();
LPCTSTR nName=LPCTSTR(path);
file.Open(path,CFile::modeCreate|CFile::modeWrite);
switch(m_nShow)
{
case 0:
string.Format("序号\t景观名\t颜色\t块数(不过滤)\t总面积\t总周长\r\n");
file.Write(LPCTSTR(string),string.GetLength());
for(id=1;id<=m_BlockTypes.GetSize();id++)
{
Types tmpType=m_BlockTypes[id-1];
string.Format("%2d\t%s\t%3d\t%10ld\t%ld\t%ld\r\n",
id,tmpType.Name,tmpType.Val,tmpType.Number,
tmpType.Area,tmpType.Length);
file.Write(LPCTSTR(string),string.GetLength());
}
break;
case 1:
string.Format("块ID\t景观名\t颜色\t块面积\r\n");
file.Write(LPCTSTR(string),string.GetLength());
for(id=1;id<=m_BlockNum;id++)
{
Block tmpBlock=m_LittleBlocks[id-1];
if(tmpBlock.AREA<=m_nMinArea)
continue;
Types tmpType=m_BlockTypes[tmpBlock.TYPEINDEX];
string.Format("%ld\t%s\t%3d\t%ld\r\n",
id,tmpType.Name,tmpType.Val,tmpBlock.AREA);
file.Write(LPCTSTR(string),string.GetLength());
}
break;
case 2:
string.Format("块ID\t景观名\t颜色\t块周长\r\n");
file.Write(LPCTSTR(string),string.GetLength());
for(id=1;id<=m_BlockNum;id++)
{
Block tmpBlock=m_LittleBlocks[id-1];
if(tmpBlock.AREA<=m_nMinArea)
continue;
Types tmpType=m_BlockTypes[tmpBlock.TYPEINDEX];
string.Format("%ld\t%s\t%3d\t%ld\r\n",
id,tmpType.Name,tmpType.Val,tmpBlock.LENG);
file.Write(LPCTSTR(string),string.GetLength());
}
break;
case 3:
string.Format("Id①\t景观①\t颜色①\tId②\t景观②\t颜色②\t交界长\r\n");
file.Write(LPCTSTR(string),string.GetLength());
for(id=1;id<=m_BlockBorders.GetSize();id++)
{
BlockBorder tmpBorder=m_BlockBorders[id-1];
long id1=tmpBorder.ID1;
long id2=tmpBorder.ID2;
Block tmpBlock1=m_LittleBlocks[id1-1];
Block tmpBlock2=m_LittleBlocks[id2-1];
if((tmpBlock1.AREA<=m_nMinArea)||(tmpBlock2.AREA<=m_nMinArea))
continue;
Types tmpType1=m_BlockTypes[tmpBlock1.TYPEINDEX];
Types tmpType2=m_BlockTypes[tmpBlock2.TYPEINDEX];
string.Format("%ld\t%s\t%3d\t%ld\t%s\t%3d\t%ld\r\n",
id1,tmpType1.Name,tmpType1.Val,
id2,tmpType2.Name,tmpType2.Val,tmpBorder.Leng);
file.Write(LPCTSTR(string),string.GetLength());
}
break;
case 4:
string.Format("块ID\t景观名\t颜色\t中心点横坐标\t中心点纵坐标\r\n");
file.Write(LPCTSTR(string),string.GetLength());
for(id=1;id<=m_BlockNum;id++)
{
Block tmpBlock=m_LittleBlocks[id-1];
if(tmpBlock.AREA<=m_nMinArea)
continue;
Types tmpType=m_BlockTypes[tmpBlock.TYPEINDEX];
string.Format("%ld\t%s\t%3d\t%10.4f\t%10.4f\r\n",
id,tmpType.Name,tmpType.Val,
tmpBlock.CX,tmpBlock.CY);
file.Write(LPCTSTR(string),string.GetLength());
}
break;
case 5:
string.Format("块ID\t景观名\t颜色\t块面积\t块周长\t中心点横坐标\t中心点纵坐标\r\n");
file.Write(LPCTSTR(string),string.GetLength());
for(id=1;id<=m_BlockNum;id++)
{
Block tmpBlock=m_LittleBlocks[id-1];
if(tmpBlock.AREA<=m_nMinArea)
continue;
Types tmpType=m_BlockTypes[tmpBlock.TYPEINDEX];
string.Format("%ld\t%s\t%3d\t%ld\t%ld\t%10.4f\t%10.4f\r\n",
id,tmpType.Name,tmpType.Val,tmpBlock.AREA,tmpBlock.LENG,
tmpBlock.CX,tmpBlock.CY);
file.Write(LPCTSTR(string),string.GetLength());
}
break;
}
file.Close();
return TRUE;
}
else
{
AfxMessageBox("请确认文件名扩展名是否为 .TXT !",MB_OK,0);
return FALSE;
}
}
return FALSE;
}
void CLSDoc::IndexCalc()
{
// 定义公用变量
int type=m_BlockTypes.GetSize();
double Area=m_nWidth*m_nHeight;
// 初始化形状类指数数组
m_Results.Split.SetSize(type);
m_Results.Shape.SetSize(type);
m_Results.TypeChip.SetSize(type);
m_Results.TypeChip2.SetSize(type);
// H 为多样性指数,Hm 为最大多样性指数
double Pi=0,Hm,EPk=0;
double AllMPS=double(Area)/double(m_BlockNum);
for(int i=0;i<type;i++)
{
double MPS=double(m_BlockTypes[i].Area/m_BlockTypes[i].Number);
double TypeArea=m_BlockTypes[i].Area;
// 多样性类指数计算
Pi=TypeArea/Area;
EPk=EPk+Pi*log(Pi);
// 形状类指数计算
double Ed=0,Es2=0; // D 为分维指数, S2 为形状指数
double blocknum=m_BlockTypes[i].Number;
for(int j=0;j<m_BlockNum;j++)
{
if(m_LittleBlocks[j].TYPEINDEX==i)
{
double blockarea=m_LittleBlocks[j].AREA;
double blockleng=m_LittleBlocks[j].LENG;
if(blockleng>4)
Ed=Ed+double(log10(blockarea))/double(log10(blockleng/4));
Es2=Es2+blockleng/(4*sqrt(blockarea));
}
}
m_Results.Split[i]=Ed/blocknum; // 分维指数
m_Results.Shape[i]=Es2/blocknum; // 形状指数
m_Results.TypeChip[i]=MPS*(blocknum-1)/Area; // 各类型碎裂化程度
m_Results.TypeChip2[i]=(blocknum-1)/MPS;
}
Hm=log(type);
EPk=-EPk;
m_Results.TrueDiversity=EPk; // 多样性指数
m_Results.MaxDiversity=Hm; // 最大多样性指数
if(Hm==0)
{
m_Results.Blance=0;
}
else
{
m_Results.Blance=EPk/Hm; // 均匀度指数
}
m_Results.Vantage=Hm-EPk; // 优势度指数
m_Results.AllChip=(m_BlockNum-1)/double(Area); // 整体碎裂化程度
m_Results.AllChip2=(m_BlockNum-1)/AllMPS;
CalcRolloverIndex();
CalcContagion();
}
void CLSDoc::CalcRolloverIndex() // 计算连结度指数
{
BYTE typenum=m_BlockTypes.GetSize();
double *Ds=(double *)malloc(sizeof(double)*typenum);
double *Rs=(double *)malloc(sizeof(double)*typenum);
ZeroMemory(Ds,sizeof(double)*typenum);
ZeroMemory(Rs,sizeof(double)*typenum);
long i,j;
double maxdist=m_nHeight*m_nHeight+m_nWidth*m_nWidth+1;
for(i=0;i<m_BlockNum;i++)
{
BYTE type=m_LittleBlocks[i].TYPEINDEX;
double thex=m_LittleBlocks[i].CX;
double they=m_LittleBlocks[i].CY;
double dist=maxdist;
long area1=m_LittleBlocks[i].AREA;
long area2;
long id2;
for(j=0;j<m_BlockNum;j++)
{
if(j==i)
continue;
if(m_LittleBlocks[j].TYPEINDEX==type)
{
double xx=m_LittleBlocks[j].CX-thex;
double yy=m_LittleBlocks[j].CY-they;
double thedist=xx*xx+yy*yy;
if(thedist<dist)
{
dist=thedist;
id2=j;
}
}
}
area2=m_LittleBlocks[id2].AREA;
Ds[type]=Ds[type]+sqrt(dist);
Rs[type]=Rs[type]+sqrt(area1*area2)/dist ;
}
m_Results.MinDistance.SetSize(typenum);
m_Results.Neighbour.SetSize(typenum);
m_Results.Interaction.SetSize(typenum);
for(BYTE k=0;k<typenum;k++)
{
long N=m_BlockTypes[k].Number;
m_Results.MinDistance[k]=Ds[k]/N;
m_Results.Neighbour[k]=2*sqrt(double(N)/double(m_nWidth*m_nHeight))*m_Results.MinDistance[k];
m_Results.Interaction[k]=Rs[k]/m_BlockTypes[k].Number;
}
return;
}
void CLSDoc::CalcContagion()
{
BYTE typenum=m_BlockTypes.GetSize();
double * Eqlog=(double *)malloc(sizeof(double)*typenum);
long * Eq=(long *)malloc(sizeof(long)*typenum);
ZeroMemory(Eqlog,sizeof(double)*typenum);
ZeroMemory(Eq,sizeof(long)*typenum);
for(long i=0;i<m_BlockBorders.GetSize();i++)
{
long leng=m_BlockBorders[i].Leng;
long id1=m_BlockBorders[i].ID1-1;
long id2=m_BlockBorders[i].ID2-1;
BYTE type1=m_LittleBlocks[id1].TYPEINDEX;
BYTE type2=m_LittleBlocks[id2].TYPEINDEX;
Eqlog[type1]=Eqlog[type1]+leng*log10(leng);
Eqlog[type2]=Eqlog[type2]+leng*log10(leng);
Eq[type1]=Eq[type1]+leng;
Eq[type2]=Eq[type2]+leng;
}
double contagion=2*typenum*log10(typenum);
for(BYTE j=0;j<typenum;j++)
{
double Ej=Eqlog[j]/Eq[j]-log10(Eq[j]);
contagion=contagion+Ej;
}
m_Results.Contagion=contagion;
return;
}
void CLSDoc::Calc4Index()
{
double city=0;
double jamming=0;
double plant=0;
double risk=0;
for(int i=0;i<m_BlockTypes.GetSize();i++)
{
city+=m_BlockTypes[i].Area*m_Coefficient[4*i];
jamming+=m_BlockTypes[i].Area*m_Coefficient[4*i+1];
plant+=m_BlockTypes[i].Area*m_Coefficient[4*i+2];
risk+=m_BlockTypes[i].Area*m_Coefficient[4*i+3];
}
double allarea=m_nHeight*m_nWidth;
m_Results.City=city/allarea;
m_Results.Jamming=jamming/allarea;
m_Results.Plant=plant/allarea;
m_Results.Risk=risk/allarea;
return;
}
long * CLSDoc::CalcFloc(UINT slipnum, long * slips, BYTE type)
{
slips[slipnum-1]=m_nHeight*m_nWidth;
BYTE line=(m_BlockTypes.GetSize()+1)*2;
long * retarray=(long *)malloc(sizeof(long)*line*slipnum);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -