www.pudn.com > 20077419401162.rar > snake.cpp


#include "stdafx.h" 
#include "snake.h" 
#include  
#include"LoadBmpFile.h" 
snake::snake(point * Snake_Point,int Point_Num) 
{ 
	this->Snake_Point = Snake_Point ; 
	this->Point_Num   = Point_Num   ; 
	this->Pre_Snake_Point = NULL; 
	Termination_Flag  = FALSE; 
	ShowPointFlag = TRUE; 
} 
 
void snake::DrawPoints(HDC hdc) 
{ 
	int Index = 0; 
	HPEN hPen; 
	hPen = CreatePen(PS_SOLID,2, RGB(255,0,0));   
	SelectObject(hdc,hPen); 
	point temp; 
 
	for(;Index < this->Point_Num;Index++) 
	{ 
		temp = this->ReadPoint(Index); 
		SetPixel(hdc,temp.x,temp.y,RGB(255,0,255)); 
 
		MoveToEx(hdc,this->ReadPoint(Index).x,this->ReadPoint(Index).y,NULL); 
		LineTo	(hdc,this->ReadPoint((Index+1)%this->Point_Num).x,this->ReadPoint((Index+1)%this->Point_Num).y); 
 
	} 
 
	DeleteObject(hPen); 
} 
 
void snake::StartTimer(HWND hWnd) 
{ 
	SetTimer(hWnd,SNAKE_TIMER,100,NULL); 
} 
 
void snake::SnakeAlgorithm() 
{ 
	Termination_Flag = FALSE; 
	point temp,SnakePoint; 
	No_Of_Mov = 0; 
/* 
	while(Termination_Flag == FALSE) 
	{ 
		No_Of_Mov = 0; 
		for(int i = 0;iPoint_Num;i++) 
		{ 
			temp = this->MinEnergyPoint(i); 
			SnakePoint = this->ReadPoint(i); 
			if(SnakePoint.x!=temp.x && SnakePoint.y!=temp.y) 
			{ 
				this->WritePoint(temp,i); 
				No_Of_Mov ++; 
			} 
		} 
		if(No_Of_Mov < this->Point_Num*0.05)//ThresHold_Of_Mov 
			Termination_Flag = TRUE; 
	} 
*/	 
StorePoints(); 
 
		for(int i = 0;iPoint_Num;i++) 
		{ 
			temp = this->MinEnergyPoint(i); 
		/*	temp = this->MovePoint(i); 
			temp.x = this->ReadPoint(i).x + temp.x; 
			temp.y = this->ReadPoint(i).y + temp.y; 
		*/ 
			SnakePoint = this->ReadPoint(i); 
			if(SnakePoint.x!=temp.x && SnakePoint.y!=temp.y) 
			{ 
				No_Of_Mov++; 
				this->WritePoint(temp,i); 
			} 
		} 
} 
double snake::Energy1(int No_Of_Point,point OffSet)//mid 
{ 
	//relatively Coordinator 
	double ix,iy; 
	static double _ix,_iy,i_x,i_y; 
 
	ix = this->Pre_Snake_Point[No_Of_Point].x+OffSet.x; 
	iy = this->Pre_Snake_Point[No_Of_Point].y+OffSet.y; 
 
	i_x= this->Pre_Snake_Point[(No_Of_Point+1)%this->Point_Num].x; 
	i_y= this->Pre_Snake_Point[(No_Of_Point+1)%this->Point_Num].y; 
 
	_ix= this->Pre_Snake_Point[(No_Of_Point-1+this->Point_Num)%this->Point_Num].x; 
	_iy= this->Pre_Snake_Point[(No_Of_Point-1+this->Point_Num)%this->Point_Num].y; 
 
	double Result1; 
	Result1 = 0.5*((2*ix - _ix - i_x)*(2*ix - _ix - i_x) + (2*iy - _iy - i_y)*(2*iy - _iy - i_y)) 
		 /((ix-_ix)*(ix-_ix)+(iy-_iy)*(iy-_iy)+(ix-i_x)*(ix-i_x)+(iy-i_y)*(iy-i_y)); 
	return Result1; 
} 
double snake::Energy2(int No_Of_Point,point OffSet)//power 
{ 
//	Result2 是蛇的力量 
	return GetScore(MovePoint(No_Of_Point),OffSet); 
} 
 
double snake::Energy3(int No_Of_Point,point OffSet)//averDis 
{ 
	static int StaticNo = -1; 
	//relatively Coordinator 
	static float _ix,_iy,i_x,i_y; 
	static double Dis; 
	float  ix,iy; 
	float  TempIx,TempIy; 
	static float MaxDis,MinDis; 
 
	ix = this->Pre_Snake_Point[No_Of_Point].x; 
	iy = this->Pre_Snake_Point[No_Of_Point].y; 
 
	if(StaticNo != No_Of_Point) 
	{ 
		StaticNo = No_Of_Point; 
 
		i_x= this->Pre_Snake_Point[(No_Of_Point+1)%this->Point_Num].x; 
		i_y= this->Pre_Snake_Point[(No_Of_Point+1)%this->Point_Num].y; 
 
		_ix= this->Pre_Snake_Point[(No_Of_Point-1+this->Point_Num)%this->Point_Num].x; 
		_iy= this->Pre_Snake_Point[(No_Of_Point-1+this->Point_Num)%this->Point_Num].y; 
 
	////////////////////Average Distance 
		if(No_Of_Point ==0) 
		{ 
			Dis = 0; 
			for(int i=0;iPoint_Num;i++) 
			{ 
				Dis += ( 
					(this->Pre_Snake_Point[(i+1)%this->Point_Num].x-this->Pre_Snake_Point[i].x)* 
					(this->Pre_Snake_Point[(i+1)%this->Point_Num].x-this->Pre_Snake_Point[i].x) 
					+ 
					(this->Pre_Snake_Point[(i+1)%this->Point_Num].y-this->Pre_Snake_Point[i].y)* 
					(this->Pre_Snake_Point[(i+1)%this->Point_Num].y-this->Pre_Snake_Point[i].y) 
					); 
			} 
			Dis /= (this->Point_Num); //Aver Dis 
		} 
 
		float TempDis; 
		MaxDis =-1; 
		MinDis =10000; 
		for(int i=0;i<9;i++) 
		{ 
			TempIx = ix-1 + i%3; 
			TempIy = iy-1 + i%3; 
			////Max,Min Dis 
			TempDis = fabs(Dis-(TempIx-i_x)*(TempIx-i_x)-(TempIy-i_y)*(TempIy-i_y)); 
				 
			if(TempDis>MaxDis) 
				MaxDis = TempDis; 
			if(TempDisPre_Snake_Point[No_Of_Point].x; 
	iy = this->Pre_Snake_Point[No_Of_Point].y; 
 
	static float _ix,_iy,i_x,i_y; 
	static float MaxCurv=-1; 
	if(StaticNo != No_Of_Point) 
	{ 
		StaticNo = No_Of_Point; 
 
		i_x= this->Pre_Snake_Point[(No_Of_Point+1)%this->Point_Num].x; 
		i_y= this->Pre_Snake_Point[(No_Of_Point+1)%this->Point_Num].y; 
 
		_ix= this->Pre_Snake_Point[(No_Of_Point-1+this->Point_Num)%this->Point_Num].x; 
		_iy= this->Pre_Snake_Point[(No_Of_Point-1+this->Point_Num)%this->Point_Num].y; 
		 
		float TempCurv; 
 
		MaxCurv =-1; 
 
		for(int i=0;i<9;i++) 
		{ 
			TempIx = ix-1 + i%3; 
			TempIy = iy-1 + i%3; 
			///////////Max ,Min Curv 
			//i1 : (_ix-TempIx,_iy-TempIy) 
			//i2 : (i_x-Tempix,i_y-TempIy) 
			//i1+i2 (_ix+i_x-2*TempIx,_iy+i_y-2*TempIy) 
			//|i1+i2|^2 : x^2+y^2 
			TempCurv = (_ix+i_x-2*TempIx)*(_ix+i_x-2*TempIx)+(_iy+i_y-2*TempIy)*(_iy+i_y-2*TempIy); 
			if(TempCurv>MaxCurv) 
				MaxCurv = TempCurv; 
		} 
	} 
 
	TempIx = ix + OffSet.x; 
	TempIy = iy + OffSet.y; 
 
return ((_ix+i_x-2*TempIx)*(_ix+i_x-2*TempIx)+(_iy+i_y-2*TempIy)*(_iy+i_y-2*TempIy))/MaxCurv; 
} 
float snake::InternalEnergy(int No_Of_Point,point OffSet) 
{ 
	float Lamida1 = 0;//Lamida * midPoint 
	float Lamida2 = 0;//蛇power 
	float Lamida3 = 0;//平均距离 
	float Lamida4 = 0;//curv 
	 
	Lamida1 = 0;//Lamida * midPoint 
	Lamida2 = 0.6;//蛇power 
	Lamida3 = 0.2;//平均距离 
	Lamida4 = 0.2;//curv 
	 
	//debug 
//	Lamida2 = 1; 
//	static float Direction_X,Direction_Y; 
 
//	ix = this->Pre_Snake_Point[No_Of_Point].x + OffSet.x; 
//	iy = this->Pre_Snake_Point[No_Of_Point].y + OffSet.y; 
 
	//法向量 与 试探向量的 点积 
//	Result2 = k*(Direction_X *OffSet.x + Direction_Y *OffSet.y)/(Direction_X*Direction_X+Direction_Y*Direction_Y) 
//		*(OffSet.x*OffSet.x + OffSet.y*OffSet.y); 
//	return Lamida* Result1 + Lamida3*Result3 + Lamida2* Result2 + Lamida4*Result4; 
return Lamida1*this->Energy1(No_Of_Point,OffSet)+ Lamida2*this->Energy2(No_Of_Point,OffSet)+ Lamida3* this->Energy3(No_Of_Point,OffSet)+ Lamida4*this->Energy4(No_Of_Point,OffSet); 
} 
 
float snake::ExternalEnergy(int No_Of_Point,point OffSet) 
{ 
	float Img_Energy; 
	point temp; 
    LPSTR   lpPtr; 
	temp = this->Snake_Point[No_Of_Point]; 
 
	temp.x += OffSet.x; 
	temp.y += OffSet.y; 
	/////////////// 
	if(temp.x>0  
	   &&temp.xImg_Width 
	   &&temp.y>0 
	   &&temp.yImg_Height 
	   ) 
	{ 
		lpPtr =	(char *)this->Img_Energy + \ 
			this->Img_Height*this->Img_Width-((int)temp.y+1)*this->Img_Width + (int)temp.x; 
		////////////// 
		Img_Energy = (unsigned char)*(lpPtr); 
	} 
	else Img_Energy = 255; 
	Img_Energy /= 255; 
	return Img_Energy; 
} 
 
point snake::MinEnergyPoint(int No_Of_Point) 
{ 
	float MinEnergy = 1000000,Energy,MaxEnergy=-1000; 
	point MinPoint,OffSet; 
 
	float i_x,i_y,_ix,_iy; 
	float Direction_X,Direction_Y; 
	this->Coefficient = 0.7;//internal 
/* 
	i_x= this->Pre_Snake_Point[(No_Of_Point+1)%this->Point_Num].x; 
	i_y= this->Pre_Snake_Point[(No_Of_Point+1)%this->Point_Num].y; 
 
	_ix= this->Pre_Snake_Point[(No_Of_Point-1+this->Point_Num)%this->Point_Num].x; 
	_iy= this->Pre_Snake_Point[(No_Of_Point-1+this->Point_Num)%this->Point_Num].y; 
 
	Direction_X = i_x - _ix; 
	Direction_Y = i_y - _iy; 
	Direction_X = -1*Direction_Y; 
	Direction_Y = i_x - _ix; 
	float Length = sqrt(Direction_X*Direction_X + Direction_Y*Direction_Y); 
	if(Length!=0) 
	{ 
		Direction_X /= Length; 
		Direction_Y /= Length; 
	} 
 
	for(int i=-1;i<2;i++) 
		for(int j=-1;j<2;j++) 
		{ 
			Energy = (i*Direction_X + j*Direction_Y)/(i*i+j*j)*(Direction_X*Direction_X+Direction_Y*Direction_Y); 
			if(Energy>MaxEnergy) 
			{ 
				MaxEnergy = Energy; 
				OffSet.x = i; 
				OffSet.y = j; 
			} 
		} 
//(0.4+this->ExternalEnergy(No_Of_Point,OffSet))/(1+this->InternalEnergy(No_Of_Point,OffSet)+this->ExternalEnergy(No_Of_Point,OffSet)); 
/*			Energy = this->Coefficient*this->InternalEnergy(No_Of_Point,OffSet)+(1-this->Coefficient)*(this->ExternalEnergy(No_Of_Point,OffSet)); 
			if(EnergyCoefficient*this->InternalEnergy(No_Of_Point,OffSet)+(1-this->Coefficient)*(this->ExternalEnergy(No_Of_Point,OffSet)); 
			if(EnergyCoefficient*this->InternalEnergy(No_Of_Point,OffSet)+(1-this->Coefficient)*(this->ExternalEnergy(No_Of_Point,OffSet)); 
			if(EnergyCoefficient*this->InternalEnergy(No_Of_Point,OffSet)+(1-this->Coefficient)*(this->ExternalEnergy(No_Of_Point,OffSet)); 
	if(Energy == MinEnergy) 
		MinPoint = OffSet; 
	OffSet = MinPoint; 
	MinPoint.x = this->ReadPoint(No_Of_Point).x + OffSet.x; 
	MinPoint.y = this->ReadPoint(No_Of_Point).y + OffSet.y; 
 
	return MinPoint; //absolutely position 
} 
point snake::MovePoint(int Index) 
{ 
	int ix,iy; 
	int _ix,_iy; 
	int ix_,iy_; 
	float Dx,Dy; 
	float Energy,MaxEnergy=-1; 
	int i,j; 
	point OffSet; 
	point Opposite; 
	OffSet.x=0; 
	OffSet.y=0; 
if(i=this->ExternalEnergy(Index,OffSet)<0.392) 
{ 
	ix = this->Pre_Snake_Point[Index].x; 
	iy = this->Pre_Snake_Point[Index].y; 
	ix_= this->Pre_Snake_Point[(Index+1)%this->Point_Num].x; 
	iy_= this->Pre_Snake_Point[(Index+1)%this->Point_Num].y; 
	_ix= this->Pre_Snake_Point[(Index-1+this->Point_Num)%this->Point_Num].x; 
	_iy= this->Pre_Snake_Point[(Index-1+this->Point_Num)%this->Point_Num].y; 
	 
	Dx = _ix-ix + ix_-ix; 
	Dy = _iy-iy + iy_-iy; 
//  反向 
	point i1,i2; 
	float i1len,i2len; 
	i1.x = _ix-ix; i1.y =_iy-iy; 
	i2.x = ix_-ix; i2.y =iy_-iy;  
	Opposite.x = i1.x+i2.x; 
	Opposite.y = i1.y+i2.y; 
	i1len = fabs(sqrt(i1.x*i1.x + i1.y*i1.y)); 
	i2len = fabs(sqrt(i2.x*i2.x + i2.y*i2.y)); 
	i1.x /= -1*i1len; i1.y /= -1*i1len; //方向 
	i2.x /= -1*i2len; i2.y /= -1*i2len; 
 
	i1.x = i1.x*i2len; i1.y = i1.y*i2len; 
	i2.x = i2.x*i1len; i2.y = i2.y*i1len; 
 
	Dx = i1.x+i2.x; 
	Dy = i1.y+i2.y; 
// 
	float Direction_X ,Direction_Y; 
	Direction_X = ix_ - _ix; 
	Direction_Y = iy_ - _iy; 
	Direction_X = -1*Direction_Y; 
	Direction_Y = ix_ - _ix; 
 
	if((Direction_X*Dx+Direction_Y*Dy)<0)//反向>0) 
	{ 
	for(i=-1;i<2;i++) 
		for(j=-1;j<2;j++) 
		{ 
			Energy = i*Dx+j*Dy; 
			if(Energy>MaxEnergy) 
			{ 
				MaxEnergy = Energy; 
				OffSet.x =i; 
				OffSet.y =j; 
			} 
		} 
	} 
	else 
	{ 
		MaxEnergy = -1; 
	 for(i=-1;i<2;i++) 
		for(j=-1;j<2;j++) 
		{ 
			Energy = i*Opposite.x +j*Opposite.y; 
			if(Energy>MaxEnergy) 
			{ 
				MaxEnergy = Energy; 
				OffSet.x =i; 
				OffSet.y =j; 
			} 
		} 
	} 
} 
 
/* 
	OffSet.x = this->ReadPoint(Index).x + OffSet.x; 
	OffSet.y = this->ReadPoint(Index).y + OffSet.y; 
*/ 
/////////////////////////debug 
/* 
	MaxEnergy = -1; 
	Dx = ix_-_ix; 
	Dy = iy_-_iy; 
	Dx = -1*Dy; 
	Dy = ix_-_ix; 
 
	for(i=-1;i<2;i++) 
		for(j=-1;j<2;j++) 
		{ 
			Energy = i*Dx + j*Dy; 
			Energy = -1*Energy; 
			if(Energy>MaxEnergy) 
			{ 
				MaxEnergy = Energy; 
				OffSet.x =i; 
				OffSet.y =j; 
			} 
		} 
*/ 
///////////////////////// 
	return OffSet; 
} 
float snake::GetScore(point ShouldMove,point NowOffSet) 
{ 
	return sqrt((ShouldMove.x - NowOffSet.x)*(ShouldMove.x - NowOffSet.x)+ 
		(ShouldMove.y - NowOffSet.y)*(ShouldMove.y - NowOffSet.y) ) / 2*sqrt(2); 
} 
void snake::PointToImg(class load_bmp_file &Bmp_File) 
{ 
       DWORD                 OffBits,BufSize,LineBytes; 
 
       LPSTR                   lpPtr; 
 
	   LPBITMAPINFOHEADER    lpImgData; 
 
	   char Energy; 
 
       OffBits=Bmp_File.bf.bfOffBits-sizeof(BITMAPFILEHEADER); 
 
	   LineBytes =(DWORD)WIDTHBYTES(Bmp_File.bi.biWidth*Bmp_File.bi.biBitCount); 
 
       BufSize=OffBits+Bmp_File.bi.biHeight*LineBytes; 
 
	   lpImgData=(LPBITMAPINFOHEADER)GlobalLock(Bmp_File.hImgData); 
 
	   this->Img_Width  = LineBytes; 
	   this->Img_Height = Bmp_File.bi.biHeight; 
	   if(this->Img_Energy!=NULL) 
		   delete []this->Img_Energy; 
	   this->Img_Energy = new char [this->Img_Width*this->Img_Height]; 
/////////// 
       lpPtr=(char *)lpImgData+OffBits; 
       memcpy(this->Img_Energy,lpPtr,BufSize-OffBits); 
/////////	    
       GlobalUnlock(Bmp_File.hImgData); 
} 
 
point snake::ReadPoint(int Index) 
{ 
	point tem; 
		tem.x = this->Snake_Point[Index].x+(float)(Window_Width/2-this->Img_Width/2); 
 
		tem.y = this->Snake_Point[Index].y+(float)(Window_Height/2-this->Img_Height/2); 
	return tem; 
} 
void snake::WritePoint(point temp,int Index) 
{ 
	this->Snake_Point[Index].x = temp.x-(float)(Window_Width/2-this->Img_Width/2); 
	this->Snake_Point[Index].y = temp.y-(float)(Window_Height/2-this->Img_Height/2); 
} 
 
void snake::SetPoints(int Num_Of_Points) 
{ 
	float Radius,CentreX,CentreY,Angle; 
	this->Point_Num = Num_Of_Points; 
	this->Snake_Point = new point[Num_Of_Points]; 
//	Radius = this->Img_HeightImg_Width?this->Img_Height/2:this->Img_Width/2; 
//  扩张的圆 
	Radius = 20; 
	Radius --; 
//	CentreX = this->Img_Width/2; 
//	CentreY = this->Img_Height/2; 
	Angle  = 3.1415*2/Num_Of_Points; 
	for(int i=0;iSnake_Point[i].x = this->Center.x+Radius*cos(i*Angle); 
		this->Snake_Point[i].y = this->Center.y+Radius*sin(i*Angle); 
	} 
} 
void snake::StorePoints() 
{ 
	static int Pre_Point_Num = 0; 
 
	if(Pre_Snake_Point == NULL) 
	{ 
		Pre_Point_Num = Point_Num; 
		Pre_Snake_Point = new point[Point_Num]; 
	} 
	else 
	{ 
		if(Pre_Point_Num!=Point_Num) 
		{ 
			delete [] Pre_Snake_Point; 
			Pre_Point_Num = Point_Num; 
			Pre_Snake_Point = new point[Point_Num]; 
		} 
	} 
	for(int i=0;iReadPoint(0).x-Center.x; 
	temp.y = this->ReadPoint(0).y-Center.y; 
	Len *= temp.x*temp.x+temp.y*temp.y; 
	OffSet.x =OffSet.y =0; 
	for(i=1;iPoint_Num;i++) 
	{ 
		temp.x =this->ReadPoint(i).x-Center.x; 
		temp.y =this->ReadPoint(i).y-Center.y; 
		Len *= temp.x*temp.x+temp.y*temp.y; 
	} 
 
	float MinEnergy,Energy; 
	MinEnergy = 10; 
	int j; 
	 for(i=-1;i<2;i++) 
		for(j=-1;j<2;j++) 
		{ 
			Energy = i*temp.x +j*temp.y; 
			if(Energy>MaxEnergy) 
			{ 
				MaxEnergy = Energy; 
				OffSet.x =i; 
				OffSet.y =j; 
			} 
		} 
	Center.x += OffSet.x; 
	Center.y += OffSet.y; 
} 
*/ 
}