www.pudn.com > DEM_TDS.rar > ViewPort.cpp, change:2007-06-03,size:11610b


// ViewPort.cpp: implementation of the ViewPort class. 
// 
////////////////////////////////////////////////////////////////////// 
 
#include "stdafx.h" 
#include "DEM.h" 
#include "ViewPort.h" 
#include "math.h" 
#include "MainFrm.h" 
#include "DEMView.h" 
#include "ChildFrm.h" 
 
#ifdef _DEBUG 
#undef THIS_FILE 
static char THIS_FILE[]=__FILE__; 
#define new DEBUG_NEW 
#endif 
 
////////////////////////////////////////////////////////////////////// 
// Construction/Destruction 
////////////////////////////////////////////////////////////////////// 
FlyList::newFlyList(double x,double y) 
{ 
	nexteyex=x; 
	nexteyey=y; 
} 
 
FlyList::FlyList() 
{ 
	 
} 
 
 
////////////////////////////////////////////////////////////////////////// 
//ViewPort 
////////////////////////////////////////////////////////////////////////// 
ViewPort::ViewPort() 
{    
	flylist=NULL; 
	smoothflylist=NULL; 
	listnumber=11; 
	autoeyez=true; 
	smooth=true; 
	ReFlesh(); 
	BuildFlyList(); 
} 
 
 
void ViewPort::ReFlesh() 
{ 
	eyex=50,eyey=-50,eyez=60; 
	AzRotateStep=1.0,ElRotateStep=1.0; 
	Az=0,El=33.7; 
	speed=0.1; 
	firstfly=true; 
	flyeyenumber=1; 
	flyheight=10; 
	SetCenterPoint(); 
} 
 
ViewPort::~ViewPort() 
{ 
	 DeleteFlyList(); 
} 
 
 
void ViewPort::DeleteFlyList() 
{ 
	if(flylist) 
	{ 
		delete[] flylist; 
		flylist=NULL; 
	} 
	if(smoothflylist) 
	{ 
		delete[] smoothflylist; 
		smoothflylist=NULL; 
	} 
} 
 
 
void   ViewPort::ProcessKeyEvent(UINT   nChar,bool autofly)    
  {    
  switch(nChar)    
  {    
  case   'W': 
	MoveForward(1);	   
	  break;    
  case   'S': 
	MoveForward(-1);  
	  break;  
  case   'A':    
	MoveHorizon(-1); 
	  break;     
  case   'D':   
    MoveHorizon(1); 
	  break;  
  case   'Q': 
	  Az+=AzRotateStep; 
	  if(Az<-180)Az+=360; if(Az>180)Az-=360;  
	  break; 
  case   'E': 
	  Az-=AzRotateStep; 
	  if(Az<-180)Az+=360; if(Az>180)Az-=360; 
	  break; 
  case 'R':	  
	 MoveHigh(1,1.0,autofly); 
	  break; 
  case 'F': 
	 MoveHigh(-1,1.0,autofly); 
	  break; 
  case 187: 
	  speed+=0.1; 
	  break; 
  case 189: 
	  speed-=0.1; 
	  break; 
  case 38: 
	  El-=ElRotateStep; 
	  if(El<=0)El=0.1; if(El>=90)El=89.9; 
	  SetCenterPoint(); 
	  break; 
  case 40: 
	  El+=ElRotateStep; 
	  if(El<=0)El=0.1; if(El>=90)El=89.9; 
	  SetCenterPoint(); 
	  break; 
  default:    
	  break;    
  }  
  SetEl();  
}     
 
void ViewPort::MoveHigh(int dirction,double HighStep,bool autofly) 
{  
	if(autofly&autoeyez) flyheight+=HighStep*dirction;	 
    else  
	{ 
		eyez+=HighStep*dirction; 
		centerz+=HighStep*dirction;  
	} 
} 
 
void ViewPort::MoveForward(int dirction,double ForwardStep,double HorizonStep) 
{ 
	  eyex-=HorizonStep*dirction*sin(-Az*PI/180); 
	  centerx-=HorizonStep*dirction*sin(-Az*PI/180); 
      eyey+=ForwardStep*dirction*cos(-Az*PI/180); 
	  centery+=ForwardStep*dirction*cos(-Az*PI/180);  
} 
 
void ViewPort::MoveHorizon(int dirction,double ForwardStep,double HorizonStep) 
{ 
      eyex+=HorizonStep*dirction*cos(-Az*PI/180); 
	  centerx+=HorizonStep*dirction*cos(-Az*PI/180);  
	  eyey+=ForwardStep*dirction*sin(-Az*PI/180); 
	  centery+=ForwardStep*dirction*sin(-Az*PI/180);  
} 
 
void ViewPort::SetEl() 
{ 
fosi=sqrt((eyex-centerx)*(eyex-centerx)+(eyey-centery)*(eyey-centery)+(eyez-centerz)*(eyez-centerz)); 
El=atan2(eyez-centerz,sqrt((eyex-centerx)*(eyex-centerx)+(eyey-centery)*(eyey-centery)))/PI*180.0; 
} 
 
void ViewPort::SetCenterPoint() 
{ 
	fosi=eyez/sin(El/180*PI); 
	centerx=eyex; 
	centery=eyey+fosi*cos(-El/180*PI); 
	centerz=eyez+fosi*sin(-El/180*PI); 
} 
 
bool ViewPort::Flying(double nexteyex, double nexteyey) 
{ 
if(firstfly) 
	{ 
	  Az=atan2(nexteyex-eyex/100,nexteyey-eyey/100)*180/PI; 
	  dirctionx=nexteyex>eyex/100?1:-1; 
	  dirctiony=nexteyey>eyey/100?1:-1; 
	  firstfly=false; 
	} 
 MoveForward(1,speed,speed); 
 if((nexteyex-eyex/100)*dirctionx<=0){firstfly=true;return true;} 
 if((nexteyey-eyey/100)*dirctiony<=0){firstfly=true;return true;} 
  
 return false; 
} 
 
void ViewPort::BuildFlyList() 
{ 
  flylist=new FlyList[listnumber]; 
  FlyList newflylist; 
  newflylist.newFlyList(0.1,0);flylist[0]=newflylist; 
  newflylist.newFlyList(0.3,0.6);flylist[1]=newflylist; 
  newflylist.newFlyList(0.5,0);flylist[2]=newflylist; 
  newflylist.newFlyList(0.7,0.6);flylist[3]=newflylist; 
  newflylist.newFlyList(1,0);flylist[4]=newflylist; 
 
  newflylist.newFlyList(1,0.6);flylist[5]=newflylist; 
  newflylist.newFlyList(0.7,0);flylist[6]=newflylist; 
  newflylist.newFlyList(0.5,0.6);flylist[7]=newflylist; 
  newflylist.newFlyList(0.3,0);flylist[8]=newflylist; 
  newflylist.newFlyList(0.1,0.6);flylist[9]=newflylist; 
  newflylist.newFlyList(0.1,0.0);flylist[10]=newflylist; 
 
  SmoothFlyList(); 
} 
 
void ViewPort::SmoothFlyList() 
{ 
  CFoldPointList pList,pDestList; 
  for(int i=0;i<listnumber;i++) 
  { 
	  pList.AddTail(&flylist[i]); 
  } 
  SPLine(&pList,&pDestList,100,0); 
  smoothlistnumber=pDestList.GetCount(); 
  smoothflylist=new FlyList[smoothlistnumber]; 
  POSITION pos=pDestList.GetHeadPosition(); 
  for(i=0;i<smoothlistnumber;i++) 
  { 
	FlyList *list=pDestList.GetNext(pos); 
	smoothflylist[i]=*list; 
	delete list; 
  } 
  pList.RemoveAll(); 
  pDestList.RemoveAll(); 
} 
 
void ViewPort::SetViewPort(int eyenumber) 
{ 
	if(!smooth)list=flylist; 
	else list=smoothflylist; 
	eyex=list[eyenumber].nexteyex*100; 
	eyey=list[eyenumber].nexteyey*100; 
	SetCenterPoint(); 
} 
 
void ViewPort::AutoFly() 
{ 
	if(!smooth){list=flylist;number=listnumber;} 
	else {list=smoothflylist;number=smoothlistnumber;} 
	if(Flying(list[flyeyenumber].nexteyex,list[flyeyenumber].nexteyey)) 
	{ 
		SetViewPort(flyeyenumber); 
		flyeyenumber++; 
		firstfly=true; 
	} 
	if(flyeyenumber==number) 
	{ 
		SetViewPort(0); 
		flyeyenumber=1; 
		firstfly=true; 
	} 
	if(autoeyez) 
	{ 
		CMainFrame *pMainFrm=(CMainFrame *)AfxGetMainWnd(); 
		CMDIChildWnd *pChild = pMainFrm->MDIGetActive(); 
		int x,y; 
	    CDEMView *pView=(CDEMView*)pChild->GetActiveView(); 
		x=eyex/100*pView->demdata->Com_3D; 
		y=eyey/100*pView->demdata->Com_3D; 
		if(eyex<0)x=0;if(eyex/100*pView->demdata->Com_3D>pView->demdata->SizeX)x=pView->demdata->SizeX; 
		if(eyey<0)y=0;if(eyey/100*pView->demdata->Com_3D>pView->demdata->SizeY)y=pView->demdata->SizeY; 
		 
		eyez=(pView->demdata->data[y][x]/pView->demdata->Hzoom*pView->demdata->s)*100+flyheight; 
		SetCenterPoint(); 
	} 
 
} 
 
bool ViewPort::SetFlyList() 
{  
  if(setflylist.GetCount()<=2)return false; 
  DeleteFlyList(); 
  CFoldPointList pDestList; 
  SPLine(&setflylist,&pDestList,100,0); 
  smoothlistnumber=pDestList.GetCount(); 
  smoothflylist=new FlyList[smoothlistnumber]; 
  POSITION pos=pDestList.GetHeadPosition(); 
  for(int i=0;i<smoothlistnumber;i++) 
  { 
	FlyList *list=pDestList.GetAt(pos); 
	smoothflylist[i]=*list; 
	delete list; 
	pDestList.GetNext(pos); 
  } 
  listnumber=setflylist.GetCount(); 
  pos=setflylist.GetHeadPosition(); 
  flylist=new FlyList[listnumber]; 
  for(i=0;i<listnumber;i++) 
  { 
	FlyList *list=setflylist.GetAt(pos); 
	flylist[i]=*list; 
	delete list; 
	setflylist.GetNext(pos); 
  } 
  setflylist.RemoveAll(); 
  pDestList.RemoveAll(); 
  return true; 
} 
 
//////////////////////////////////////////////////////////////////////////// 
//曲线光滑 
//////////////////////////////////////////////////////////////////////////// 
 
double ViewPort::CalculateDistance(double x1,double y1,double x2,double y2) 
{ 
return sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2)); 
} 
 
void ViewPort::ZG(CDoubleArray *A,CDoubleArray *B,CDoubleArray *C,CDoubleArray *G,int &LOGI) 
{ 
//追赶法 
 register long I; 
 int N; 
 N=A->GetSize(); 
 if(LOGI==0) 
 { 
  (*C)[0]=(*C)[0]/(*B)[0]; 
   for(I=1;I<N;I++) 
   { 
    (*B)[I]=(*B)[I]-(*A)[I]*(*C)[I-1]; 
   (*C)[I]=(*C)[I]/(*B)[I]; 
   } 
   (*A)[0]=0.; 
   (*C)[N-1]=0.; 
   LOGI=1; 
  } 
  (*G)[0]=(*G)[0]/(*B)[0]; 
  for(I=1;I<N;I++) 
  { 
   (*G)[I]=((*G)[I]-(*A)[I]*(*G)[I-1])/(*B)[I]; 
  } 
  for(I=N-2;I>-1;I--)//DO 30 I=N-1,1,-1 
  { 
   (*G)[I]=(*G)[I]-(*C)[I]*(*G)[I+1]; 
  } 
  return; 
} 
 
void ViewPort::SPLine4(CDoubleArray *X,CDoubleArray *Y,double &XI,double&YI,CDoubleArray *A,CDoubleArray *B,CDoubleArray *C,CDoubleArray *G,int &LOGI,int MD) 
{ 
 register long I; 
 double W1,W2,H; 
 int N=X->GetSize(); 
  
 if(LOGI==0) 
 { 
  for(I=1;I<N;I++) 
  { 
   (*B)[I]=(*X)[I]-(*X)[I-1]; 
   (*C)[I]=((*Y)[I]-(*Y)[I-1])/(*B)[I]; 
  } 
  for(I=1;I<N-1;I++) 
  { 
   (*A)[I]=(*B)[I]+(*B)[I+1]; 
   (*G)[I]=6.*((*C)[I+1]-(*C)[I])/(*A)[I]; 
   (*A)[I]=(*B)[I]/(*A)[I]; 
  } 
  for(I=1;I<N;I++) 
  { 
   (*C)[I]=1.-(*A)[I]; 
   (*B)[I]=2.; 
  } 
  (*B)[0]=2.; 
  (*B)[N-1]=2.; 
  if(MD==3) 
  { 
   (*C)[0]=-1.; 
   (*A)[N-1]=-1.; 
   (*A)[0]=0.; 
   (*C)[N-1]=0.; 
  } 
  ZG(A,B,C,G,LOGI); 
 } 
 for(I=1;I<N;I++)  
 { 
  if(XI>=(*X)[I-1] && XI<=(*X)[I])//GE LE 
  { 
   H=(*X)[I]-(*X)[I-1]; 
   W1=(*X)[I]-XI; 
   W2=XI-(*X)[I-1]; 
   YI=W1*W1*W1*(*G)[I-1]/6./H; 
   YI=YI+W2*W2*W2*(*G)[I]/6./H; 
   YI=YI+W1*((*Y)[I-1]-(*G)[I-1]*H*H/6.)/H; 
   YI=YI+W2*((*Y)[I]-(*G)[I]*H*H/6.)/H; 
  } 
 } 
} 
 
//用时候直接调用SPLine函数,入口pList是已知离散点链表,pDestList是生成的点的链表。 
//SM是在两个点中间插入点的数目,continue=0是采样点无规律,要求生成闭合曲线。 
//1是采样点x坐标连续 2是y连续 
void ViewPort::SPLine(CFoldPointList *pList,CFoldPointList *pDestList,int SM,int Continue) 
{ 
 FlyList *pFoldHead,*pFoldTail; 
 FlyList *pFold; 
 POSITION pos; 
 CDoubleArray A,B,C,G,X,Y,T; 
 double XI,YI,XX,YY; 
 register long i; 
 long N; 
 int LOGI; 
 long RealSM; 
 long Bei,Yu; 
//赋初值 
 N=pList->GetCount(); 
 A.SetSize(N); 
 B.SetSize(N); 
 C.SetSize(N); 
 G.SetSize(N); 
 X.SetSize(N); 
 Y.SetSize(N); 
 T.SetSize(N); 
 RealSM=(N-1)*SM+N; 
 pos=pList->GetHeadPosition(); 
 for(i=0;i<N;i++) 
 { 
  pFold=pList->GetNext(pos); 
  X[i]=pFold->nexteyex; 
  Y[i]=pFold->nexteyey; 
 } 
 pFoldHead=pList->GetHead(); 
 pFoldTail=pList->GetTail(); 
 if(Continue==0)//pFoldHead->X==pFoldTail->X && pFoldHead->Y==pFoldTail->Y) 
 { //闭合 
  T[0]=0; 
  for(i=0;i<N-1;i++) 
  { 
   T[i+1]=T[i]+CalculateDistance(X[i],Y[i],X[i+1],Y[i+1])+0.000000001; 
  } 
  LOGI=0; 
  YI=0; 
  for(i=0;i<RealSM;i++)  
  { 
   Bei=i/(SM+1); 
   Yu=i%(SM+1); 
   if(Yu!=0) 
   { 
    XI=T[Bei]+(T[Bei+1]-T[Bei])/(SM+1)*Yu; 
    SPLine4(&T,&Y,XI,YI,&A,&B,&C,&G,LOGI,3); 
    YY=YI;//+Y[Bei]; 
   } 
   else 
   { 
    YY=Y[Bei]; 
   } 
   pFold=new FlyList; 
   pFold->nexteyey=YY; 
   pDestList->AddTail(pFold); 
  } 
  LOGI=0; 
  YI=0; 
  pos=pDestList->GetHeadPosition(); 
  for(i=0;i<RealSM;i++) 
  { 
   Bei=i/(SM+1); 
   Yu=i%(SM+1); 
   if(Yu!=0) 
   { 
    XI=T[Bei]+(T[Bei+1]-T[Bei])/(SM+1)*Yu; 
    SPLine4(&T,&X,XI,YI,&A,&B,&C,&G,LOGI,3); 
    YY=YI;//+X[Bei]; 
   } 
   else 
   { 
    YY=X[Bei]; 
   } 
   pFold=pDestList->GetNext(pos); 
   pFold->nexteyex=YY; 
  } 
 } 
 else if(Continue==1) 
 { 
  //x连续 
  LOGI=0; 
  YI=0; 
  for(i=0;i<RealSM;i++) { 
   Bei=i/(SM+1); 
   Yu=i%(SM+1); 
   if(Yu!=0) 
   { 
    XI=X[Bei]+(X[Bei+1]-X[Bei])/(SM+1)*Yu; 
    SPLine4(&X,&Y,XI,YI,&A,&B,&C,&G,LOGI,3); 
    XX=XI; 
    YY=YI; 
   } 
   else 
   { 
    XX=X[Bei]; 
    YY=Y[Bei]; 
   } 
   pFold=new FlyList; 
   pFold->nexteyex=XX; 
   pFold->nexteyey=YY; 
   pDestList->AddTail(pFold); 
  } 
 } 
 else 
 { 
  //y连续 
  LOGI=0; 
  YI=0; 
  for(i=0;i<RealSM;i++) { 
   Bei=i/(SM+1); 
   Yu=i%(SM+1); 
   if(Yu!=0) 
   { 
    XI=Y[Bei]+(Y[Bei+1]-Y[Bei])/(SM+1)*Yu; 
    SPLine4(&Y,&X,XI,YI,&A,&B,&C,&G,LOGI,3); 
    XX=YI; 
    YY=XI; 
   } 
   else 
   { 
    XX=X[Bei]; 
    YY=Y[Bei]; 
   } 
   pFold=new FlyList; 
   pFold->nexteyex=XX; 
   pFold->nexteyey=YY; 
   pDestList->AddTail(pFold); 
  } 
 } 
 return; 
}