📄 buildgrid.cpp
字号:
/*****************************************************************************
学习有限元课课程时做的一个作业,划分画等边三角为小四边形网格
可以作为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 + -