⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 fractalview.cpp

📁 可以生成山、火焰、树与草等自然景物的实例
💻 CPP
📖 第 1 页 / 共 2 页
字号:
		rect.right =x0+50;
		rect.top=y0-50;
		OldBrush=m_pDC->SelectObject (&blkBrush);
		m_pDC->Rectangle (&rect);
		m_pDC->SelectObject (OldBrush);
		blkBrush.DeleteObject ();
	}
	
	//生成焰火升空阶段的画面
	//
	if(Level<=5)
	for(Num=0;Num<72;Num++)
	{
		xNew=1.0*Level/10*Particle[Num]*cos(5.0*Num*PI/180);
		yNew=1.0*Level/10*Particle[Num]*sin(5.0*Num*PI/180);
		x=x0+xNew;
		y=y0-yNew;
		PenSize=1+rand()%3;
		purplePen.CreatePen (PS_SOLID,PenSize,RGB(255,255,0));
		OldPen=m_pDC->SelectObject (&purplePen);
		m_pDC->MoveTo (x0,y0);
		m_pDC->LineTo (x,y);
		m_pDC->SelectObject (OldPen);
		purplePen.DeleteObject ();
	}
	
	//生成焰火在空中炸开阶段的画面
	//
	if(Level>=10&&Level<13)	
	for(Num=0;Num<500;Num++)
		{
			sx=rand()%2;
			sy=rand()%2;
			sd=rand()%10;
			xNew=rand()%50;
			yNew=rand()%50;

			if(sx)
				x=x0+xNew;
			else
				x=x0-xNew;
			if(sy)
				y=y0+yNew;
			else
				y=y0-yNew;

		Dis=(x-x0)*(x-x0)+(y-y0)*(y-y0);
		if(Dis>625&&Dis<2500||sd<=4)
			m_pDC->SetPixel (x,y,RGB(255,255,0));
		}
	
	//生成空中焰火逐渐熄灭阶段的画面
	//
	if(Level>11)	
	for(Num=0;Num<1200;Num++)
		{
			sx=rand()%2;
			sy=rand()%2;
			xNew=rand()%50;
			yNew=rand()%50;
			if(sx)
				x=x0+xNew;
			else
				x=x0-xNew;
			if(sy)
				y=y0+yNew;
			else
				y=y0-yNew;
			m_pDC->SetPixel (x,y,RGB(0,0,0));
		}
}

////////////////////////////////////////////////////
//焰火粒子属性指定函数:随机每个角度方向的粒子的大小
//
void CFractalView::InitSize(int size)
{
	int i;
	particle=0;
	srand((unsigned)time(NULL));
	for(i=0;i<72;i++)
	{
		Particle[i]=size+rand()%10;
	}

}

void CFractalView::OnTimer(UINT nIDEvent) 
{
	//对焰火的燃放阶段进行定时与计数
	DrawParticle(200,200,10,particle,TRUE);
	particle++;
	particle=particle>20?0:particle;
	CView::OnTimer(nIDEvent);
}
///////////////////////////////////////////////////////////////////////////////////
//树叶绘制函数:根据几何解释和树叶的模型(叶轮廓多边形)数据,绘制一片树叶
//
void CFractalView::DrawLeaf(double angle, float xratio, float yratio, int x0, int y0)
{
	POINT Temp[10];
	int x,y;
	int iIndex;
	double Dis,radian; 
	CBrush GreenBrush,*OldBrush;
	CPen GreenPen,*OldPen;
    
	//按比例缩放叶面大小
	//
	for(iIndex=0;iIndex<10;iIndex++)
	{
		Temp[iIndex].x=xratio*leaf[iIndex].x;
		Temp[iIndex].y=yratio*leaf[iIndex].y;
	}

	//计算旋转以后的叶面模型顶点坐标
	//
	for(iIndex=0;iIndex<10;iIndex++)
	{
		Dis=sqrt(Temp[iIndex].x*Temp[iIndex].x+Temp[iIndex].y*Temp[iIndex].y);
		radian=angle*PI/180+atan2(Temp[iIndex].y,Temp[iIndex].x);
		Temp[iIndex].x=x0+Dis*cos(radian);
		Temp[iIndex].y=y0-Dis*sin(radian);
	}

	//创建画笔与画刷
	//
	GreenPen.CreatePen (PS_SOLID,1,RGB(25,200,25));
	GreenBrush.CreateSolidBrush (RGB(0,255,0));
	OldPen=m_pDC->SelectObject (&GreenPen);
	OldBrush=m_pDC->SelectObject (&GreenBrush);

	//按填充多边形的方式画叶面
	//
	m_pDC->Polygon (Temp,8);

	//通过画线画叶茎
	//
	m_pDC->MoveTo (Temp[1]);
	m_pDC->LineTo (Temp[8]);
	m_pDC->LineTo (Temp[7]);
	m_pDC->MoveTo (Temp[2]);
	m_pDC->LineTo (Temp[9]);
	m_pDC->LineTo (Temp[6]);
	m_pDC->MoveTo (Temp[0]);
	m_pDC->LineTo (Temp[4]);

    //释放创建的画笔与画刷对象
	//
	m_pDC->SelectObject (OldPen);
	m_pDC->SelectObject (OldBrush);
	GreenPen.DeleteObject ();
	GreenBrush.DeleteObject ();


}

///////////////////////////////////////////////////////////////////////////////////
//树枝绘制函数:根据几何解释和树枝的模型(枝轮廓多边形)数据,绘制一段树枝
//
void CFractalView::DrawTwig(double angle, float xratio, float yratio, int x0, int y0,POINT *InOut,bool delta)
{
	POINT Temp[4];
	int x,y;
	int iIndex;
	double Dis,radian; 
	CBrush GreenBrush,*OldBrush;
	CPen GreenPen,*OldPen;
    
	//按比例缩放枝干大小
	//
	for(iIndex=0;iIndex<4;iIndex++)
	{
		Temp[iIndex].x=xratio*twig[iIndex].x;
		Temp[iIndex].y=yratio*twig[iIndex].y;
	}

    //计算旋转以后的树枝模型顶点坐标
	//
	for(iIndex=0;iIndex<4;iIndex++)
	{
		Dis=sqrt(Temp[iIndex].x*Temp[iIndex].x+Temp[iIndex].y*Temp[iIndex].y);
		radian=angle*PI/180+atan2(Temp[iIndex].y,Temp[iIndex].x);
		Temp[iIndex].x=x0+Dis*cos(radian);
		Temp[iIndex].y=y0-Dis*sin(radian);
	}

	//将树枝末端直线段输出以便为后续绘制进行定位
	//
	if(delta)
	{
		Temp[1].x =InOut[0].x;
		Temp[1].y =InOut[0].y;
		Temp[2].x =InOut[1].x;
		Temp[2].y =InOut[1].y;
	}

	//创建画笔与画刷
	//
	GreenPen.CreatePen (PS_SOLID,1,RGB(128,0,64));
	GreenBrush.CreateSolidBrush (RGB(255,210,233));
	OldPen=m_pDC->SelectObject (&GreenPen);
	OldBrush=m_pDC->SelectObject (&GreenBrush);

	//按填充多边形的方式画树枝
	//
	m_pDC->Polygon (Temp,4);
	
	//释放创建的画笔与画刷对象
	//
	m_pDC->SelectObject (OldPen);
	m_pDC->SelectObject (OldBrush);
	GreenPen.DeleteObject ();
	GreenBrush.DeleteObject ();

	//输出树枝末端直线段
	InOut[0].x=Temp[0].x;
	InOut[0].y=Temp[0].y;
	InOut[1].x=Temp[3].x;
	InOut[1].y=Temp[3].y;

}

////////////////////////////////////////////////////////////////////
//树造型函数:按指定的细分步数(参数level指定)利用正规文法模型生成
//树或者草(参数grass决定)
//
void CFractalView::CreateTree(TREENODE **Tree, int level,bool grass)
{
	int iWill;
	TREENODE *pCurr,*pNext,*pNew;
	TREENODE *pA;
	TREENODE *pB2,*pB3,*pB4,*pB5,*pB6,*pB7,*pB8,*pB9;
	
	//删除已有结构
	//
	if(Tree[0])
	{
		DeleteTree(Tree);
		TreeLevel=0;
	}
	
	InitTree();
	level=level<0?0:level;
	level=level>10?10:level;

    
	if(level>TreeLevel)
	{
		for(iWill=0;iWill<=level-TreeLevel;iWill++)
		{
			//一个细分步
			//
			pCurr=Tree[0];
			while(pCurr)
			{
				//生成过程体现正规文法的产生式规则
				//
				pNext=pCurr->Next ;

				//A->AA:对于字符A,重新生成一个A节点并插入
				//前一个A节点后面,而得到AA
				//
				if(pCurr->Value=='A')
				{
					pA= new _TREENODE;
					if(pA==NULL)
					{
						MessageBox( "不能获取所需要的内存", _T(""),MB_OK );
						exit(0);
					}
					pA->Value ='A';
					pA->Next =pNext;
				}

				//对于字符B,分别按树或草结构生成A[B]AA(B)或
				//A[B]BB(B)系列字符节点并取代B节点
				//
				if(pCurr->Value=='B')
				{
					pCurr->Value ='A';
					pB2= new _TREENODE;
					pB3= new _TREENODE;
					pB4= new _TREENODE;
					pB5= new _TREENODE;
					pB6= new _TREENODE;
					pB7= new _TREENODE;
					pB8= new _TREENODE;
					pB9= new _TREENODE;
					if(!pB2||!pB3||!pB4||!pB5||!pB6||!pB7||!pB8||!pB9)
					{
						MessageBox( "不能获取所需要的内存", _T(""),MB_OK );
						exit(0);
					}
					pCurr->Next =pB2;
					
					pB2->Value ='[';
					pB2->Next=pB3;
					
					pB3->Value ='B';
					pB3->Next=pB4;

					pB4->Value =']';
					pB4->Next=pB5;

					if(grass)
						pB5->Value ='B'; //草
					else
						pB5->Value ='A'; //树
					pB5->Next=pB6;
					
					if(grass)
						pB6->Value ='B'; //草
					else
						pB6->Value ='A'; //树
					pB6->Next=pB7;

					pB7->Value ='(';
					pB7->Next=pB8;

					pB8->Value ='B';
					pB8->Next=pB9;

					pB9->Value =')';
					pB9->Next=pNext;
				}
				pCurr=pNext;
			}
		}
	}

	TreeLevel=level;
}

///////////////////////////////////////////////////////////
//树初始化函数:根据初始数据创建一个树的基本拓扑结构
//
void CFractalView::InitTree()
{
	int iIndex;
	TREENODE *pCurr,*pTemp;
	for(iIndex=0;iIndex<5;iIndex++)
	{
		pCurr= new _TREENODE;
		if(pCurr==NULL)
		{
			MessageBox( "不能获取所需要的内存", _T(""),MB_OK );
			exit(0);
		}
		pCurr->Value =tree[iIndex];
		pCurr->Next =NULL;
		if(!iIndex)
			Tree[0]=pCurr;
		else
			pTemp->Next =pCurr;	
		pTemp=pCurr;
	}

	TreeLevel=0;
}

////////////////////////////////////////////////////////
//压栈函数:将节点存入栈顶
//
void CFractalView::Push(STACKNODE **pStack,STACKNODE sn)
{
	STACKNODE *pCurr;

	pCurr= new _STACKNODE;
	if(pCurr==NULL)
	{
		MessageBox( "不能获取所需要的内存", _T(""),MB_OK );
		exit(0);
	}
	pCurr->angle =sn.angle ;
	pCurr->p1 =sn.p1 ;
	pCurr->p2 =sn.p2;
	pCurr->Next =pStack[0];
	pStack[0]=pCurr;
}

////////////////////////////////////////////////////////
//出栈函数:删除并栈顶节点
//
STACKNODE *  CFractalView::Pop()
{
	STACKNODE *pCurr;
	
	pCurr=Stack[0];
	if(pCurr)
		Stack[0]=pCurr->Next ;
	return pCurr;
}


/////////////////////////////////////////////////////////
//树显示函数:遍历树的拓扑结构链表,进行几何解释并显示解
//释内容
//
void CFractalView::DrawTree(TREENODE **Tree,int x0,int y0)
{
	TREENODE *pCurr;
	STACKNODE *pStack,*pLastA,sn,LastA;
	POINT Connection[2];
	bool delta;
	float xratio,yratio;
	float deltaAngle;
	bool Kept;
	int xNew0,yNew0;
	int Direction;

	delta=FALSE;
	Kept=TRUE;
	pLastA=NULL;
	Direction=0;

	pCurr=Tree[0];
	while(pCurr)
	{
		switch(pCurr->Value)
		{
		
		//将A解释成树枝
		//
		case 'A':
			//单独处理首段树枝的情况
			//
			if(!pLastA)
			{
				xratio=0.4;
				yratio=0.5;
				xNew0=x0;
				yNew0=y0;
				deltaAngle=0;
				delta=FALSE;
				pLastA=&LastA;
			}
			else
			{
				//计算树枝的大小和角度并将树枝接在前一段树枝上
			    //
				xNew0=(pLastA->p1.x+pLastA->p2.x)>>1;
				yNew0=(pLastA->p1.y+pLastA->p2.y)>>1;
				xratio=0.5*abs(pLastA->p2.x-pLastA->p1.x)/twig[2].x;
				yratio=0.5;
				Connection[0].x=pLastA->p1.x;
				Connection[0].y=pLastA->p1.y;
				Connection[1].x=pLastA->p2.x;
				Connection[1].y=pLastA->p2.y;
				delta=TRUE;
				switch(Direction)
				{
				case 0://主干
					deltaAngle=0;
					break;
				case -1://左枝
					if(!Kept)
						deltaAngle=pLastA->angle +15;
					else
						deltaAngle=pLastA->angle;
					break;
				case 1://由枝
					if(!Kept)
						deltaAngle=pLastA->angle -15;
					else
						deltaAngle=pLastA->angle;				
					break;
				}
			}
			
			DrawTwig(deltaAngle,xratio,yratio,xNew0,yNew0,Connection,delta);				
			
			//为简化后续使用保存当前信息
			//
			pLastA->angle=deltaAngle ;
			pLastA->Direction =Direction;
			pLastA->p1.x =Connection[0].x;
			pLastA->p1.y =Connection[0].y;
			pLastA->p2.x =Connection[1].x;
			pLastA->p2.y =Connection[1].y;
			pLastA->zoom =xratio;
			Kept=TRUE;
			break;
		
		//将B解释成叶片
		//
		case 'B':
			xratio=0.3;
			yratio=xratio;
			
			if(Direction==-1)//左叶片
			{
				xNew0=pLastA->p1.x;
				yNew0=pLastA->p1 .y;
				if(!Kept)
						deltaAngle=pLastA->angle +15;
					else
						deltaAngle=pLastA->angle;
			}
			else   //右叶片
			{
				xNew0=pLastA->p2.x;
				yNew0=pLastA->p2 .y;
				if(!Kept)
						deltaAngle=pLastA->angle -15;
					else
						deltaAngle=pLastA->angle;
			}

			DrawLeaf(deltaAngle,xratio,yratio,xNew0,yNew0);
			
			Kept=TRUE;
			break;
		
		//[解释为后续树枝或叶在当前角度上向左偏
		//
		case '[':
			//保存当前树枝的位置与角度等信息
			//
			sn.angle =pLastA->angle ;
			sn.p1 =pLastA->p1 ;
			sn.p2=pLastA->p2 ;
			sn.Direction =pLastA->Direction ;
			Push(Stack,sn);
			Direction=-1;
			Kept=FALSE;
			break;
		
		//]解释为左偏结束要回到分叉位置
        //
		case ']':
			//恢复到分叉位置
			//
			pLastA=Pop();
			Direction=pLastA->Direction ;
			break;

		//(解释为后续树枝或叶在当前角度上向右偏
		//
		case '(':
			sn.angle =pLastA->angle ;
			sn.p1 =pLastA->p1 ;
			sn.p2=pLastA->p2 ;
			sn.Direction =pLastA->Direction ;
			Push(Stack,sn);
			Direction=1;
			Kept=FALSE;
			break;
		
		//)解释为右偏结束要回到分叉位置
        //
		case ')':
			pLastA=Pop();
			Direction=pLastA->Direction ;
		}
		pCurr=pCurr->Next ;
	}
}

/////////////////////////////////////////////
//树结构删除函数:删除树结构链表的所有节点
//
void CFractalView::DeleteTree(TREENODE **Tree)
{
	TREENODE *pCurr,*pTemp;

	pCurr=Tree[0];
	pTemp=pCurr->Next ;
	while(pCurr)
	{
		delete pCurr;
		pCurr=pTemp;
		if(pTemp)
			pTemp=pTemp->Next ;
	}
	Tree[0]=NULL;
}

/////////////////////////////////////////
//生成草命令函数:启动生成并显示草的过程
//
void CFractalView::OnbtnGrass() 
{
	opStatus=4;
	ClrScr();
}

////////////////////////////////////////////
//生成山峦命令函数:启动生成并显示山峦的过程
//
void CFractalView::OnbtnHill() 
{
	opStatus=1;
	ClrScr();
}

////////////////////////////////////////////
//生成焰火命令函数:启动生成并显示焰火的过程
//
void CFractalView::OnbtnSkyrocket() 
{
	opStatus=2;
	ClrScr();
}

/////////////////////////////////////////
//生成树命令函数:启动生成并显示树的过程
//
void CFractalView::OnbtnTree() 
{
	opStatus=3;
	ClrScr();
}

//////////////////////////////////////////////////
//顶点删除函数:删除顶点(三角形)链表中的全部节点
//
void CFractalView::DeleteVertices(VERTEX **pLink)
{
	VERTEX *pCurr,*pTemp;
 
 	pCurr=pLink[0];
 	pTemp=pCurr->Next;
 	while(pCurr)
 	{
 		delete pCurr;
 		pCurr=pTemp;
 		if(pTemp)
			pTemp=pTemp->Next; 
 	};
 	pLink[0]=NULL;
}

/////////////////////////////////
//清屏函数:清除显示导致重画屏幕
//
void CFractalView::ClrScr()
{
	RECT rect;
	int i,j;

	GetClientRect(&rect);
	InvalidateRect(&rect,TRUE);
}

//////////////////////////////////////////////////////////
//景物创建与显示执行函数:根据景物的类型调用相关函数创建并
//显示相应景物
//
void CFractalView::Draw()
{
	switch(opStatus)
	{
	case 1:KillTimer(1);         //山峦
		CreateHill(5);
		DrawHill(Hill);
		break;
	case 2:SetTimer(1,250,NULL); //焰火
		break;
	case 3:                      //树
		KillTimer(1);
		CreateTree(Tree,5,FALSE);
		DrawTree(Tree,350,400);
		break;
	case 4:                      //草
		KillTimer(1);
		CreateTree(Tree,4,TRUE);
		DrawTree(Tree,350,350);
		break;
	default:;                    //初始情况
		break;
	}
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -