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

📄 buildgrid.cpp

📁 等边三角形有限元网格生成程序
💻 CPP
📖 第 1 页 / 共 2 页
字号:

/*****************************************************************************
 学习有限元课课程时做的一个作业,划分画等边三角为小四边形网格
 可以作为SDK开发小型的Windows程序的良好例子。
 控件创建、画图、文件对话框、窗口位图保存等技巧可供初学者参考。
 有问题请联系tohjs@163.com
				胡金山@2003.5		空军工程大学工程学院
*****************************************************************************/

#include <windows.h>
#include <stdio.h>
#include <math.h>
#include <string>

#define PI (3.1415926535897932384626433832795)
//============================================================================
struct Pt{						//点数据
	double x,y;
};
struct ENode{					//单元结点结构体
	double x,y;					//单元结点坐标
	int num;					//单元结点在总体区域划分中的编号
	ENode& ENode::operator =(const Pt& rhs) 
	{			
		x=rhs.x;				//此操作符直接将点数据赋值给节点变量
		y=rhs.y;
		return *this;
	}
};
struct EQuad{					//四边形单元结构体
	ENode nd[4];				//存储相对应的总体结点号
	int num;					//单元在总体区域划分中的编号
	EQuad::EQuad()				//构造函数用来初始化节点数据
	{
		for(int i=0;i<4;i++)
		{	
			nd[i].x=0;
			nd[i].y=0;
		}
	}
};
//-----------------------------------------------------------------------
//全局变量
int N;							//三角形每边分2*N单元,共3*N*N单元,且有3*N*N+3*N+1节点
const Pt pt1={60.0,435.0};		//三角形的三个顶点
const Pt pt2={560.0,435.0};
const Pt pt3={310.0,2.0};
std::string StrMsg;
EQuad* pEQ;
//-----------------------------------------------------------------------
// Square() 求平方
// 参数: [I]双精度型变量x
// 返回: x的平方值
//-----------------------------------------------------------------------
double Square(double x)
{
	return x*x;
}
//-----------------------------------------------------------------------
// LineIntersect() 两直线求交点
// 参数: [I]构成两相交直线的四点
// 返回: 交点
//-----------------------------------------------------------------------
Pt GetLineIntersect(Pt& pt1,Pt& pt2,Pt& pt3,Pt& pt4)
{
	Pt pt;
	pt.x=( (pt4.y-pt3.y)*(pt2.x-pt1.x)*pt3.x -(pt2.y-pt1.y)*(pt4.x-pt3.x)*pt1.x +
			(pt2.x-pt1.x)*(pt4.x-pt3.x)*pt1.y-(pt2.x-pt1.x)*(pt4.x-pt3.x)*pt3.y
		 )
		 / ( (pt4.y-pt3.y)*(pt2.x-pt1.x) - (pt2.y-pt1.y)*(pt4.x-pt3.x) );
	if(pt2.x-pt1.x==0)
		pt.y=(pt.x-pt3.x)* (pt4.y-pt3.y)/(pt4.x-pt3.x)  +pt3.y;
	else
		pt.y=(pt.x-pt1.x)* (pt2.y-pt1.y)/(pt2.x-pt1.x)  +pt1.y;
	return pt;
}
//-----------------------------------------------------------------------
// DivideLine() 直线均分n份,求各分割点
// 参数: [I]构成直线的两点,整数数n
//		 [O]用来保存分割点的数组pt[n+1],包括两端点
// 返回: 无
//-----------------------------------------------------------------------
void DivideLine(Pt& pt1,Pt& pt2,int n,Pt pt[])
{
	for(int i=1;i<n;i++)
	{
		pt[i].x=pt1.x+ (pt2.x-pt1.x)*i/n;
		pt[i].y=pt1.y+ (pt2.y-pt1.y)*i/n;
	}
	pt[0]=pt1;
	pt[n]=pt2;
	return;
}
//-----------------------------------------------------------------------
// BuildGrid() 生成网格
// 参数: [I]等边三角形三个顶点,四边形单元数组指针
//		 [O]四边形单元数组内容保存生成的网格数据
// 返回: 无
//
// 三角形每边分2*N单元,计算可得共3*N*N单元,且有3*N*N+3*N+1节点,即N*N+N*(N+1)+(N+1)^2
//-----------------------------------------------------------------------
void BuildGrid(Pt pt1,Pt pt2,Pt pt3,EQuad pE[])
{
	int i;
	Pt center,ptTemp;
	center.x=(pt1.x+pt2.x+pt3.x)/3;
	center.y=(pt1.y+pt2.y+pt3.y)/3;
	Pt* ptL1=new Pt[N+1];
	Pt* ptL3=new Pt[N+1];
	Pt* ptL2=new Pt[N+1];
	Pt* ptL4=new Pt[N+1];
	EQuad* pETmp=new EQuad[N*N];

	//---------第一个大四边形-----------------------
	ptTemp.x=(pt1.x+pt2.x)/2;		//取四边形边上的节点
	ptTemp.y=(pt1.y+pt2.y)/2;
	DivideLine(pt1,ptTemp,N,ptL1);
	DivideLine(ptTemp,center,N,ptL2);

	ptTemp.x=(pt1.x+pt3.x)/2;
	ptTemp.y=(pt1.y+pt3.y)/2;
	DivideLine(pt1,ptTemp,N,ptL4);
	DivideLine(ptTemp,center,N,ptL3);

	for(i=0;i<N*N;i++)						
	{
		pE[i].num=i;
		pE[i].nd[0].num=i+i/N;
		pE[i].nd[1].num=i+i/N+1;
		pE[i].nd[2].num=i+i/N+N+2;
		pE[i].nd[3].num=i+i/N+N+1;
		
		pE[i].nd[0]=GetLineIntersect(ptL1[i%N],ptL3[i%N], ptL2[i/N],ptL4[i/N]);
		pE[i].nd[1]=GetLineIntersect(ptL1[i%N+1],ptL3[i%N+1], ptL2[i/N],ptL4[i/N]);
		pE[i].nd[2]=GetLineIntersect(ptL1[i%N+1],ptL3[i%N+1], ptL2[i/N+1],ptL4[i/N+1]);
		pE[i].nd[3]=GetLineIntersect(ptL1[i%N],ptL3[i%N], ptL2[i/N+1],ptL4[i/N+1]);
	}
	//---------第二个大四边形-----------------------
	ptTemp.x=(pt2.x+pt3.x)/2;		//取四边形边上的节点
	ptTemp.y=(pt2.y+pt3.y)/2;
	DivideLine(pt2,ptTemp,N,ptL1);
	DivideLine(ptTemp,center,N,ptL2);

	ptTemp.x=(pt2.x+pt1.x)/2;
	ptTemp.y=(pt2.y+pt1.y)/2;
	DivideLine(pt2,ptTemp,N,ptL4);
	DivideLine(ptTemp,center,N,ptL3);

	for(i=0;i<N*N;i++)					
	{
		pE[i+N*N].num=i +(N+1)*(N+1);
		pE[i+N*N].nd[0].num=i+i/N +(N+1)*(N+1);
		pE[i+N*N].nd[1].num=i+i/N+1 +(N+1)*(N+1);
		pE[i+N*N].nd[2].num=i+i/N+N+2 +(N+1)*(N+1);
		pE[i+N*N].nd[3].num=i+i/N+N+1 +(N+1)*(N+1);
		
		pE[i+N*N].nd[0]=GetLineIntersect(ptL1[i%N],ptL3[i%N], ptL2[i/N],ptL4[i/N]);
		pE[i+N*N].nd[1]=GetLineIntersect(ptL1[i%N+1],ptL3[i%N+1], ptL2[i/N],ptL4[i/N]);
		pE[i+N*N].nd[2]=GetLineIntersect(ptL1[i%N+1],ptL3[i%N+1], ptL2[i/N+1],ptL4[i/N+1]);
		pE[i+N*N].nd[3]=GetLineIntersect(ptL1[i%N],ptL3[i%N], ptL2[i/N+1],ptL4[i/N+1]);
	}
	
	for(i=2*N*N-N;i<2*N*N;i++)		//在与第一个大四边形交线上的情况
	{
		pE[i].nd[2].num=pE[(1+i%N)*N-1].nd[2].num;
		pE[i].nd[3].num=pE[(1+i%N)*N-1].nd[1].num;
	}
	//------------第三个大四边形--------------------
	ptTemp.x=(pt3.x+pt1.x)/2;		//取四边形边上的节点
	ptTemp.y=(pt3.y+pt1.y)/2;
	DivideLine(pt3,ptTemp,N,ptL1);
	DivideLine(ptTemp,center,N,ptL2);

	ptTemp.x=(pt3.x+pt2.x)/2;
	ptTemp.y=(pt3.y+pt2.y)/2;
	DivideLine(pt3,ptTemp,N,ptL4);
	DivideLine(ptTemp,center,N,ptL3);

	for(i=0;i<N*N;i++)					
	{
		pE[i+2*N*N].num=i +2*N*N;
		pE[i+2*N*N].nd[0].num=i + (N+1)*(N+1)+(N+1)*N;
		pE[i+2*N*N].nd[1].num=i+1 + (N+1)*(N+1)+(N+1)*N;
		pE[i+2*N*N].nd[2].num=i+N+1 + (N+1)*(N+1)+(N+1)*N;
		pE[i+2*N*N].nd[3].num=i+N + (N+1)*(N+1)+(N+1)*N;

		pE[i+2*N*N].nd[0]=GetLineIntersect(ptL1[i%N],ptL3[i%N], ptL2[i/N],ptL4[i/N]);
		pE[i+2*N*N].nd[1]=GetLineIntersect(ptL1[i%N+1],ptL3[i%N+1], ptL2[i/N],ptL4[i/N]);
		pE[i+2*N*N].nd[2]=GetLineIntersect(ptL1[i%N+1],ptL3[i%N+1], ptL2[i/N+1],ptL4[i/N+1]);
		pE[i+2*N*N].nd[3]=GetLineIntersect(ptL1[i%N],ptL3[i%N], ptL2[i/N+1],ptL4[i/N+1]);
	}
	for(i=3*N*N-N;i<3*N*N;i++)			//在与第二个大四边形的交线上的情况
	{
		pE[i].nd[2].num=pE[N*N+(1+i%N)*N-1].nd[2].num;
		pE[i].nd[3].num=pE[N*N+(1+i%N)*N-1].nd[1].num;
	}
	for(i=2*N*N+N-1;i<=3*N*N-1;)		//在与第一个大四边形的交线上的情况
	{
		pE[i].nd[1].num=pE[ N*(N-1)+(i-N*N*2+1)/N-1 ].nd[3].num;
		pE[i].nd[2].num=pE[ N*(N-1)+(i-N*N*2+1)/N-1 ].nd[2].num;
		i+=N;
	}
	delete []pETmp;
	delete []ptL1;	delete []ptL2;
	delete []ptL3;	delete []ptL4;
	return;
}

//-----------------------------------------------------------------------
// GetSaveFileDlg() 显示保存文件通用对话框
// 参数: [I]父窗口句柄hwnd
//		 [O]文件全路径名保存字符串
// 返回: 成功或确定返回非零值,失败或取消返回零
//-----------------------------------------------------------------------
int GetSaveFileDlg (HWND hwnd,PTSTR szFileName,TCHAR szFilter[])
{
	static OPENFILENAME ofn;
	ofn.lStructSize			= sizeof (OPENFILENAME) ;
	ofn.hwndOwner			= hwnd ;
	ofn.hInstance			= NULL ;
	ofn.lpstrFilter			= szFilter ;
	ofn.lpstrCustomFilter	= NULL ;
	ofn.nMaxCustFilter		= 0 ;
	ofn.nFilterIndex		= 0 ;
	ofn.lpstrFile			= NULL ;          // Set in Open and Close functions
	ofn.nMaxFile			= MAX_PATH ;
	ofn.lpstrFileTitle		= NULL ;          // Set in Open and Close functions
	ofn.nMaxFileTitle		= MAX_PATH ;
	ofn.lpstrInitialDir		= NULL ;
	ofn.lpstrTitle			= NULL ;
	ofn.Flags				= 0 ;             // Set in Open and Close functions
	ofn.nFileOffset			= 0 ;
	ofn.nFileExtension		= 0 ;
	ofn.lpstrDefExt			= TEXT ("txt") ;
	ofn.lCustData			= 0L ;
	ofn.lpfnHook			= NULL ;
	ofn.lpTemplateName		= NULL ;
	ofn.lpstrFile			= szFileName ;

	return GetSaveFileName (&ofn);
}
//============================================================================

#define BTN_BUILD_GRID	1001
#define BTN_SAVEGRIDMSG	1002
#define BTN_SAVEBMP		1003
#define BTN_EXIT		1004
#define ID_EDIT_OUTPUT	1005
#define ID_EDIT_N		1006
#define ID_DRAWBOX		1007
//============================================================================

LRESULT CALLBACK WndProc(HWND,UINT,WPARAM,LPARAM);

BOOL WriteWindowToDIB(LPTSTR szFile, HWND hwnd);
//============================================================================
int WINAPI WinMain(	HINSTANCE hInstance,HINSTANCE hPrevInst, LPSTR lpszCmdLine,	int	nCmdShow)
{
	HWND hwnd ;
	MSG Msg ;
	WNDCLASS wndclass ;
	char lpszClassName[] = "窗口";		
	char lpszTitle[]= "有限元网格生成程序 -- 胡金山@空军工程大学";	
	
	wndclass.style			= 0;					
	wndclass.lpfnWndProc	= WndProc ;	
	wndclass.cbClsExtra		= 0 ;		
	wndclass.cbWndExtra		= 0 ;			
	wndclass.hInstance		= hInstance ;	
	wndclass.hIcon			= LoadIcon( NULL, IDI_APPLICATION) ;
	wndclass.hCursor		= LoadCursor( NULL, IDC_ARROW) ;
	wndclass.hbrBackground	= (HBRUSH)GetStockObject(WHITE_BRUSH) ;
	wndclass.lpszMenuName	= NULL ;	
	wndclass.lpszClassName	= lpszClassName ;
	
	if( !RegisterClass( &wndclass))	
		return FALSE ;
	
	hwnd=CreateWindow(lpszClassName,lpszTitle,			
		WS_OVERLAPPEDWINDOW,//WS_DLGFRAME,
		(GetSystemMetrics (SM_CXSCREEN) )	/ 6,
        (GetSystemMetrics (SM_CYSCREEN) )	/ 100,
		(GetSystemMetrics (SM_CXSCREEN) )*5 / 8,
        (GetSystemMetrics (SM_CYSCREEN) )*5 / 6,	
		NULL,				
		NULL,				
		hInstance,			
		NULL) ;			
	ShowWindow( hwnd, nCmdShow) ;
	UpdateWindow(hwnd);
	while( GetMessage(&Msg, NULL, 0, 0))
	{
		TranslateMessage( &Msg) ;
		DispatchMessage( &Msg) ;
	}
	return Msg.wParam;				
}

LRESULT CALLBACK WndProc(HWND hwnd,UINT message,WPARAM  wParam,	LPARAM  lParam)
{
	HDC hdc;
	PAINTSTRUCT ps;
	static HWND hwndDrawBox ;
	static HWND hwndEditOutput ;
	static HWND hwndEditN ;
	static HPEN hP;
	static int   cxChar, cyChar ;	
	int x0=0,y0=0;
	int i,j;
	char str[256];		//临时字符串
	FILE* wfp;			//文件指针
	static EQuad* pEQ;
	static TCHAR szFileName[MAX_PATH];
	switch(message)
	{
	case WM_CREATE:
		pEQ=NULL;
		cxChar = LOWORD (GetDialogBaseUnits ());
        cyChar = HIWORD (GetDialogBaseUnits ());
		hP=CreatePen(PS_SOLID,1,RGB(0x70,0x70,0xcf));
		hwndDrawBox = CreateWindow (TEXT ("static"),
					TEXT ("DrawBox"),
                          WS_CHILD | WS_VISIBLE|COLOR_BTNHIGHLIGHT,
                          cxChar*0, cxChar*0 ,75 * cxChar, 28 * cyChar,
                     hwnd, (HMENU)ID_DRAWBOX,((LPCREATESTRUCT) lParam)->hInstance, NULL) ;
		//ShowWindow (hwndDrawBox, SW_SHOW) ;

		CreateWindow (TEXT("button"),TEXT("生成网格"),WS_CHILD | WS_VISIBLE|BS_PUSHBUTTON,
                     cxChar*32, cyChar * 32,20 * cxChar, 2 * cyChar,
                     hwnd, (HMENU)BTN_BUILD_GRID,((LPCREATESTRUCT) lParam)->hInstance, NULL) ;

		CreateWindow (TEXT("button"),TEXT("网格保存到位图..."),WS_CHILD | WS_VISIBLE|BS_PUSHBUTTON,
                     cxChar*56, cyChar * 32,20 * cxChar, 2 * cyChar,
                     hwnd, (HMENU)BTN_SAVEBMP,((LPCREATESTRUCT) lParam)->hInstance, NULL) ;

		CreateWindow (TEXT("button"),TEXT("退出"),WS_CHILD | WS_VISIBLE|BS_PUSHBUTTON,
                     cxChar*56, cyChar *35,20 * cxChar, 2 * cyChar,
                     hwnd, (HMENU)BTN_EXIT,((LPCREATESTRUCT) lParam)->hInstance, NULL) ;
		CreateWindow (TEXT("button"),TEXT("网格详细信息保存..."),WS_CHILD | WS_VISIBLE|BS_PUSHBUTTON,
                     cxChar*32, cyChar *35,20 * cxChar, 2 * cyChar,
                     hwnd, (HMENU)BTN_SAVEGRIDMSG,((LPCREATESTRUCT) lParam)->hInstance, NULL) ;
		hwndEditOutput	= CreateWindow (TEXT ("edit"), NULL,
                         WS_CHILD | WS_VISIBLE | WS_VSCROLL|
                         WS_BORDER | ES_LEFT | ES_MULTILINE |ES_READONLY|
                         ES_AUTOHSCROLL | ES_AUTOVSCROLL,
                         2*cxChar, cyChar * (1 + 2 * 1)+410,25 * cxChar, 9 * cyChar,
						 hwnd, (HMENU) ID_EDIT_OUTPUT,
                         ((LPCREATESTRUCT) lParam) -> hInstance, NULL) ;
		hwndEditN		= CreateWindow (TEXT ("edit"), NULL,
                         WS_CHILD | WS_VISIBLE |WS_BORDER | ES_CENTER |
						 ES_AUTOHSCROLL | ES_AUTOVSCROLL,
                         20, 110,8 * cxChar, 5*cyChar/4,
						 hwnd, (HMENU) ID_EDIT_N,
                         ((LPCREATESTRUCT) lParam) -> hInstance, NULL) ;
		SetWindowText(hwndEditOutput,"网格单元和节点信息显示");
		SetWindowText(hwndEditN,"5");
		pEQ=NULL;
		break;

⌨️ 快捷键说明

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