📄 snake.cpp
字号:
#include "stdafx.h"
#include "snake.h"
#include <math.h>
#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;i<this->Point_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;i<this->Point_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;i<this->Point_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(TempDis<MinDis)
MinDis = TempDis;
}
}
TempIx = ix + OffSet.x;
TempIy = iy + OffSet.y;
return (fabs(Dis-(TempIx-i_x)*(TempIx-i_x)-(TempIy-i_y)*(TempIy-i_y))-MinDis)/(MaxDis-MinDis);
}
double snake::Energy4(int No_Of_Point,point OffSet)//curvature
{
static int StaticNo = -1;
//relatively Coordinator
float ix,iy;
float TempIx,TempIy;
ix = this->Pre_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.x<this->Img_Width
&&temp.y>0
&&temp.y<this->Img_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(Energy<MinEnergy)
{
MinEnergy = Energy;
MinPoint = OffSet;
}
OffSet.x = 0;
OffSet.y = 0;
Energy = this->Coefficient*this->InternalEnergy(No_Of_Point,OffSet)+(1-this->Coefficient)*(this->ExternalEnergy(No_Of_Point,OffSet));
if(Energy<MinEnergy)
{
MinEnergy = Energy;
MinPoint = OffSet;
}
*/
for(int i=-1;i<2;i++)
for(int j=-1;j<2;j++)
{
OffSet.x=i;OffSet.y=j;
Energy = this->Coefficient*this->InternalEnergy(No_Of_Point,OffSet)+(1-this->Coefficient)*(this->ExternalEnergy(No_Of_Point,OffSet));
if(Energy<MinEnergy)
{
MinEnergy = Energy;
MinPoint = OffSet;
}
}
//Centre
OffSet.x = OffSet.y =0;
Energy = this->Coefficient*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_Height<this->Img_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;i<Num_Of_Points;i++)
{
this->Snake_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;i<Point_Num;i++)
{
Pre_Snake_Point[i].x=Snake_Point[i].x;
Pre_Snake_Point[i].y=Snake_Point[i].y;
}
}
void snake::AdjustCenter(point & Center)
{
/* int i;
point temp,OffSet;
temp.x = temp.y =2;
double Len =1;//总乘积
while((temp.x *temp.x+temp.y*temp.y)<3)
{
Len = 1;
temp.x = this->ReadPoint(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;i<this->Point_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;
}
*/
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -