📄 lsdoc.cpp
字号:
// LSDoc.cpp : implementation of the CLSDoc class
//
#include "stdafx.h"
#include "LandSoft.h"
#include "math.h"
#include "LSDoc.h"
#include "malloc.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// CLSDoc
IMPLEMENT_DYNCREATE(CLSDoc, CDocument)
BEGIN_MESSAGE_MAP(CLSDoc, CDocument)
//{{AFX_MSG_MAP(CLSDoc)
// NOTE - the ClassWizard will add and remove mapping macros here.
// DO NOT EDIT what you see in these blocks of generated code!
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
BlockIDs::BlockIDs()
{
ID=0;
IsBorder=FALSE;
}
BlockIDs::~BlockIDs()
{
}
/////////////////////////////////////////////////////////////////////////////
// CLSDoc construction/destruction
CLSDoc::CLSDoc()
{
m_bEverToget=FALSE;
m_bTogether=FALSE;
m_bLineSpace=FALSE;
m_bPointFromFile=FALSE;
m_dPower=2;
m_bRandom=FALSE;
m_nRanBoxNum=2;
m_nRanBoxWidth=1;
m_nRanBoxHeight=1;
m_bEverDefine=FALSE;
oldDiffRange=0;
oldDiffString="";
TANG=tan(PI/8);
// m_bEverAutoCorre=FALSE;
m_bShowPoint=FALSE;
m_bShowBox=FALSE;
m_bEverAllSpace=FALSE;
m_bShowLine=FALSE;
m_bSampleMouse=FALSE;
m_bCanExecute=TRUE;
m_bEverName=FALSE;
m_bDone=FALSE;
m_bOren8=TRUE;
m_nShow=0;
m_nMinArea=0;
m_bSaveTip=TRUE;
m_bInfo=FALSE;
m_bMouseLine=FALSE;
m_nXBox=1;
m_nYBox=1;
}
CLSDoc::~CLSDoc()
{
}
BOOL CLSDoc::OnNewDocument()
{
return FALSE;
}
/////////////////////////////////////////////////////////////////////////////
// CLSDoc serialization
void CLSDoc::Serialize(CArchive& ar)
{
if (ar.IsStoring())
{
}
else
{
}
}
/////////////////////////////////////////////////////////////////////////////
// CLSDoc diagnostics
#ifdef _DEBUG
void CLSDoc::AssertValid() const
{
CDocument::AssertValid();
}
void CLSDoc::Dump(CDumpContext& dc) const
{
CDocument::Dump(dc);
}
#endif //_DEBUG
CSize CLSDoc::GetSize()
{
return m_dib.GetSize();
}
inline BYTE CLSDoc::GetValue(int x,int y)
{
return m_Values[x+m_nWidth*y];
}
inline BYTE CLSDoc::GetNameIndex(BYTE value)
{
for(BYTE i=0;i<m_BlockTypes.GetSize();i++)
if(m_BlockTypes[i].Val==value)
return i;
return NULL;
}
void CLSDoc::ConstructValue()
{
m_Values.SetSize(m_nWidth*m_nHeight);
int datawidth;
for(long nn=0;nn<m_nHeight;nn++)
{
for(long mm=0;mm<m_nWidth;mm++)
{
if(m_dib.m_nBitcount==1)
{
datawidth=m_nWidth/8+0.9;
if(datawidth%4!=0)
{
datawidth=datawidth/4+1;
datawidth=datawidth*4;
}
LONG oo=mm/8+(m_nHeight-nn-1)*datawidth;
BYTE pp=7-mm%8;
m_Values[mm+nn*m_nWidth]=((*(m_dib.GetBits()+oo))&(1<<pp))>>pp;
}
else if(m_dib.m_nBitcount==4)
{
datawidth=m_nWidth/2+0.6;
if(datawidth%4!=0)
{
datawidth=datawidth/4+1;
datawidth=datawidth*4;
}
LONG oo=mm/2+(m_nHeight-nn-1)*datawidth;
if(mm%2==0)
{
m_Values[mm+nn*m_nWidth]=(*(m_dib.GetBits()+oo))>>4;
}
else
{
m_Values[mm+nn*m_nWidth]=(*(m_dib.GetBits()+oo))&15;
}
}
else
{
if(m_nWidth%4==0)
{
datawidth=m_nWidth;
}
else
{
datawidth=m_nWidth/4+1;
datawidth=datawidth*4;
}
LONG oo=mm+(m_nHeight-nn-1)*datawidth;
m_Values[mm+nn*m_nWidth]=*(m_dib.GetBits()+oo);
}
}
}
}
/////////////////////////////////////////////////////////////////////////////
// CLSDoc commands
BOOL CLSDoc::OnOpenDocument(LPCTSTR lpszPathName)
{
if(!(m_dib.Open (lpszPathName)))
return FALSE;
else if(m_dib.m_Colors>0&&m_dib.m_Colors<=256) // 只处理颜色数为 0-256 的图像
{
m_bEverName=FALSE;
m_nWidth=GetSize().cx;
m_nHeight=GetSize().cy;
ConstructValue();
if(m_nWidth*m_nHeight>1000000)
{
int tt=AfxMessageBox("图像较大(>1000x1000),处理时间较长,是否继续?",MB_OKCANCEL,0);
if(tt==IDCANCEL)
return FALSE;
}
// 开始扫描图像得到景观类数和面积
if(!CalcTypes())
return FALSE;
BYTE len=strlen(lpszPathName);
strncpy(m_strPathName,lpszPathName,len-4);
return TRUE;
}
else
{
m_bCanExecute=FALSE;
CString error;
error.Format("该图像是256色以上位图,不能进行景观分析!\n\n按[确定]继续显示,按[取消]不显示。");
int what=AfxMessageBox(error,MB_OKCANCEL,0);
if(what==IDOK)
return TRUE;
else
return FALSE;
}
}
BOOL CLSDoc::CalcTypes()
{
int Width=m_nWidth; // 宽
int Height=m_nHeight; // 高
// 以下定义临时景观类型临时变量,加入第一种类型
Types block;
block.Val=GetValue(0,0);
block.Area=0;
m_BlockTypes.Add(block);
for (int j = 0; j < Height; j++)
{
for (int i = 0; i < Width; i++)
{
for(int index=0; index<=m_BlockTypes.GetUpperBound(); index++)
{
if(GetValue(i,j)==m_BlockTypes[index].Val) //判断是否为新类型
{ // 否则面积加一
m_BlockTypes[index].Area++;
break;
}
}
if(index==m_BlockTypes.GetSize()) // 是新类型则加入景观类型数组
{
block.Val=GetValue(i,j);
block.Area=1;
m_BlockTypes.Add( block );
}
if(m_BlockTypes.GetSize()>MAXTYPE) // 判断景观类型数是否超过20种
{
m_BlockTypes.RemoveAll();
m_bCanExecute=FALSE;
CString error;
error.Format("该图像产生的景观类型大于 %d 种,将不能用此图做景观分析。请分类后再做!\n\n\t\t按[确定]继续显示,按[取消]不显示。",MAXTYPE);
int what=AfxMessageBox(error,MB_OKCANCEL,0);
if (what==IDOK)
return TRUE;
else
return FALSE;
}
}
}
double bitnum=Width*Height;
BYTE size=m_BlockTypes.GetSize();
m_Coefficient.SetSize(size*4);
m_BaseSpace.SetSize(size);
for(BYTE i=0;i<size;i++)
{
m_BaseSpace[i]=bitnum/double(m_BlockTypes[i].Area);
}
return TRUE;
}
void CLSDoc::CalcBlocks()
{//1
int Width=m_nWidth; // 宽
int Height=m_nHeight; // 高
int maxx=m_nWidth-1;
int maxy=m_nHeight-1;
long BitNum = Width*Height; // 数据长
// int bdleng; // 存储一点产生的边界长
m_BlockID.RemoveAll(); // 删除原数组值
m_BlockID.SetSize(BitNum); // 初始化块数据数组
POINT *SearchPtr=(POINT *)malloc(BitNum * sizeof(POINT)); // 初始化搜索临时指针
m_BlockNum = 0; // 初始化块数量
m_LittleBlocks.RemoveAll(); // 删除原来斑块数组
// 把m_BlockTypes中有关斑块的数据充0
for(int ii=0;ii<m_BlockTypes.GetSize();ii++)
{
m_BlockTypes[ii].Length=0;
m_BlockTypes[ii].Number=0;
}
m_nMinBlockArea=BitNum;
m_nMaxBlockArea=1;
m_nMinBlockLeng=BitNum;
m_nMaxBlockLeng=4;
for (int j = 0; j < Height; j++)
{ //2
for (int i = 0; i < Width; i++)
{ //3
// 搜索新斑块
if (m_BlockID[i+Width*j].ID==0)
{ //4
BYTE color=GetValue(i,j); // 颜色值
BYTE index=GetNameIndex(color); // 类型索引
m_BlockNum++; // 块数加一
m_BlockID[i+Width*j].ID=m_BlockNum;
// 初始化临时块结构变量
Block tmpBlock;
tmpBlock.AREA=1;
tmpBlock.TYPEINDEX=index;
tmpBlock.LEFTX=i;
tmpBlock.RIGHTX=i;
tmpBlock.UPY=j;
tmpBlock.DOWNY=j;
LONGLONG xsum=i; // 所有点的横坐标之和(用于计算中心点坐标)
LONGLONG ysum=j; // 所有点的纵坐标之和
tmpBlock.LENG=0;
// if(bdleng=GetBorderLength(i,j))// 是否边界
// tmpBlock.LENG+=bdleng; // 斑块周长增加
// 开始计算该点产生的边界长, 并置边界标志
// (可变为函数,但由于频繁访问,故直接进行计算)
//////////////////////////////////////////////////////////////////
if(i==0) // 图形左边界
tmpBlock.LENG++;
else if( (i>0) && ( GetValue(i-1,j) != color) ) // 斑块左边界
{
tmpBlock.LENG++;
m_BlockID[i+j*m_nWidth].IsBorder=TRUE;
}
if(i==maxx) // 图形右边界
tmpBlock.LENG++;
else if( (i<maxx) && ( GetValue(i+1,j)!=color)) // 斑块右边界
{
tmpBlock.LENG++;
m_BlockID[i+j*m_nWidth].IsBorder=TRUE;
}
if(j==0) // 图形上边界
tmpBlock.LENG++;
else if( (j>0) && ( GetValue(i,j-1) != color) ) // 斑块上边界
{
tmpBlock.LENG++;
m_BlockID[i+j*m_nWidth].IsBorder=TRUE;
}
if (j==maxy) // 图形下边界
tmpBlock.LENG++;
else if ( (j<maxy) && ( GetValue(i,j+1)!=color) ) // 斑块下边界
{
tmpBlock.LENG++;
m_BlockID[i+j*m_nWidth].IsBorder=TRUE;
}
// 结束计算边界
/////////////////////////////////////////////////////////////////////
long start=0; long end =1;
SearchPtr[0].x=i;
SearchPtr[0].y=j;
// 从起点出发搜索所有该斑块的点
while(start<end)
{//5
int xpos=SearchPtr[start].x;
int ypos=SearchPtr[start].y;
start++;
for (int i1=-1; i1<=1; i1++)
{ //6
for (int j1=-1; j1<=1; j1++)
{ //7
int xpos1=xpos+i1;
int ypos1=ypos+j1;
if((i1==0)&&(j1==0)) // 不搜索原来的点
continue;
if((m_bOren8==FALSE)&&(i1*j1!=0)) // 若为四方向,不搜索斜向
continue;
if ((xpos1>=0)&&(xpos1<Width)&&(ypos1>=0)&&(ypos1<Height)
&&(m_BlockID[xpos1+Width*ypos1].ID==0)
&&(GetValue(xpos1,ypos1)==color))
// 如果找着新的属于该块的点
{ // 8
SearchPtr[end].x=xpos1;
SearchPtr[end].y=ypos1;
m_BlockID[xpos1+Width*ypos1].ID=m_BlockNum; // 置该点块ID
// 更新矩形
if(xpos1<tmpBlock.LEFTX)
tmpBlock.LEFTX=xpos1;
else if(xpos1>tmpBlock.RIGHTX)
tmpBlock.RIGHTX=xpos1;
if(ypos1<tmpBlock.UPY)
tmpBlock.UPY=ypos1;
else if(ypos1>tmpBlock.DOWNY)
tmpBlock.DOWNY=ypos1;
tmpBlock.AREA++; // 斑块面积加一
xsum+=xpos1; // 加上该点横坐标
ysum+=ypos1; // 加上该点纵坐标
// 开始计算该点产生的边界长, 并置边界标志
//////////////////////////////////////////////////////////////////
if(xpos1==0) // 图形左边界
tmpBlock.LENG++;
else if( (xpos1>0) && ( GetValue(xpos1-1,ypos1) != color) ) // 斑块左边界
{
tmpBlock.LENG++;
m_BlockID[xpos1+ypos1*m_nWidth].IsBorder=TRUE;
}
if(xpos1==maxx) // 图形右边界
tmpBlock.LENG++;
else if( (xpos1<maxx) && ( GetValue(xpos1+1,ypos1)!=color)) // 斑块右边界
{
tmpBlock.LENG++;
m_BlockID[xpos1+ypos1*m_nWidth].IsBorder=TRUE;
}
if(ypos1==0) // 图形上边界
tmpBlock.LENG++;
else if( (ypos1>0) && ( GetValue(xpos1,ypos1-1) != color) ) // 斑块上边界
{
tmpBlock.LENG++;
m_BlockID[xpos1+ypos1*m_nWidth].IsBorder=TRUE;
}
if (ypos1==maxy) // 图形下边界
tmpBlock.LENG++;
else if ( (ypos1<maxy) && ( GetValue(xpos1,ypos1+1)!=color) ) // 斑块下边界
{
tmpBlock.LENG++;
m_BlockID[xpos1+ypos1*m_nWidth].IsBorder=TRUE;
}
// 结束计算边界
/////////////////////////////////////////////////////////////////////
end++;
} //8
}//7
}//6
}//5
// 计算中心点坐标
tmpBlock.CX=double(xsum)/double(tmpBlock.AREA)+0.5;
tmpBlock.CY=double(ysum)/double(tmpBlock.AREA)+0.5;
// 加入斑块数组
m_LittleBlocks.Add(tmpBlock);
if(tmpBlock.AREA>m_nMaxBlockArea)
m_nMaxBlockArea=tmpBlock.AREA;
if(tmpBlock.AREA<m_nMinBlockArea)
m_nMinBlockArea=tmpBlock.AREA;
if(tmpBlock.LENG>m_nMaxBlockLeng)
m_nMaxBlockLeng=tmpBlock.LENG;
if(tmpBlock.LENG<m_nMinBlockLeng)
m_nMinBlockLeng=tmpBlock.LENG;
m_BlockTypes[index].Number++; // 该类景观的块数加一
m_BlockTypes[index].Length+=tmpBlock.LENG;
// 该类景观的周长加上这个块的周长
}//4
}//3
}//2
return;
}//1
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -