// pdnmeshView.cpp : implementation of the CPdnmeshView class // /* pdnmesh - a 2D finite element solver Copyright (C) 2001-2005 Sarod Yatawatta This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA $Id: pdnmeshView.cpp,v 1.5 2005/02/16 13:16:15 sarod Exp $ */ #include "stdafx.h" #include "winpdnmesh.h" #include "pdnmeshDoc.h" #include "pdnmeshView.h" #include "model.h" #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif ///////////////////////////////////////////////////////////////////////////// // CPdnmeshView IMPLEMENT_DYNCREATE(CPdnmeshView, CView) BEGIN_MESSAGE_MAP(CPdnmeshView, CView) //{{AFX_MSG_MAP(CPdnmeshView) ON_WM_CREATE() ON_WM_DESTROY() ON_WM_ERASEBKGND() ON_WM_SIZE() ON_WM_MOUSEMOVE() ON_COMMAND(VID_DRAW_CFILL, OnDrawCfill) ON_COMMAND(VID_DRAW_CONTOUR, OnDrawContour) ON_COMMAND(VID_DRAW_GRAD, OnDrawGrad) ON_COMMAND(VID_DRAW_MESH, OnDrawMesh) ON_WM_LBUTTONDOWN() ON_COMMAND(ZID_ZOOM_ALL, OnZoomAll) ON_COMMAND(ZID_ZOOM_BACK, OnZoomBack) ON_COMMAND(ZID_ZOOM_START, OnZoomStart) ON_COMMAND(VID_NEXT_EIGENMODE, OnNextEigenmode) ON_COMMAND(SID_SOLVE, OnSolve) //}}AFX_MSG_MAP END_MESSAGE_MAP() ///////////////////////////////////////////////////////////////////////////// // CPdnmeshView construction/destruction CPdnmeshView::CPdnmeshView() { // TODO: add construction code here } CPdnmeshView::~CPdnmeshView() { } BOOL CPdnmeshView::PreCreateWindow(CREATESTRUCT& cs) { // TODO: Modify the Window class or styles here by modifying // the CREATESTRUCT cs cs.style |=WS_CLIPCHILDREN|WS_CLIPSIBLINGS|CS_OWNDC; //set default size cs.cx=800; cs.cy=200; return CView::PreCreateWindow(cs); } ///////////////////////////////////////////////////////////////////////////// // CPdnmeshView drawing void CPdnmeshView::OnDraw(CDC* pDC) { CPdnmeshDoc* pDoc = GetDocument(); ASSERT_VALID(pDoc); // TODO: add draw code for native data here CPaintDC dc(this); HWND hWnd =GetSafeHwnd(); HDC hDC=::GetDC(hWnd); wglMakeCurrent(hDC,m_hglrc); DrawGLScene(); //draw routine of view // call draw of doc pDoc->draw(); //if (doubleBuffered ) SwapBuffers(m_hgldc); //else //glFlush(); //wglMakeCurrent( NULL, NULL ); //ValidateRect(NULL); } ///////////////////////////////////////////////////////////////////////////// // CPdnmeshView diagnostics #ifdef _DEBUG void CPdnmeshView::AssertValid() const { CView::AssertValid(); } void CPdnmeshView::Dump(CDumpContext& dc) const { CView::Dump(dc); } CPdnmeshDoc* CPdnmeshView::GetDocument() // non-debug version is inline { ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CPdnmeshDoc))); return (CPdnmeshDoc*)m_pDocument; } #endif //_DEBUG ///////////////////////////////////////////////////////////////////////////// // CPdnmeshView message handlers int CPdnmeshView::OnCreate(LPCREATESTRUCT lpCreateStruct) { if (CView::OnCreate(lpCreateStruct) == -1) return -1; // TODO: Add your specialized creation code here m_hgldc=::GetDC(m_hWnd); if(!SetPixelformat(m_hgldc)) { ::MessageBox(::GetFocus(),"SetPixelformat Failed!","Error",MB_OK); return -1; } m_hglrc=wglCreateContext(m_hgldc); int i=wglMakeCurrent(m_hgldc,m_hglrc); InitGL(); return 0; } void CPdnmeshView::OnDestroy() { CView::OnDestroy(); // TODO: Add your message handler code here if (wglGetCurrentContext() !=NULL) wglMakeCurrent(NULL,NULL); if(m_hglrc!=NULL) { wglDeleteContext(m_hglrc); m_hglrc=NULL; } } BOOL CPdnmeshView::OnEraseBkgnd(CDC* pDC) { // TODO: Add your message handler code here and/or call default //return CView::OnEraseBkgnd(pDC); return TRUE; } void CPdnmeshView::OnSize(UINT nType, int cx, int cy) { CView::OnSize(nType, cx, cy); // TODO: Add your message handler code here theApp.p_w=cx; theApp.p_h=cy; ReSizeGLScene((int)cx,(int)cy); } //Utility functions BOOL CPdnmeshView::SetPixelformat(HDC hdc) { PIXELFORMATDESCRIPTOR *ppfd; int pixelformat; PIXELFORMATDESCRIPTOR pfd={ sizeof(PIXELFORMATDESCRIPTOR), //size of pfd 1, //version PFD_DRAW_TO_WINDOW| //support window PFD_SUPPORT_OPENGL| //support OpenGL PFD_GENERIC_FORMAT| PFD_DOUBLEBUFFER, //flags PFD_TYPE_RGBA, //type RGBA 32, //colour depth in bits 0, 0, 0, 0, 0, 0, //(r,g,b) bits 8, //no alpha buffer 0, //shift bit ignored 8, //no accumulation buffer 0,0,0,0, //accum bits ignored 64, //32 bit z buffer 8, //no stencil buffer 8, // no auxiliary buffer PFD_MAIN_PLANE, //main layer 0, //reserved 0,0,0 //layer masks ignored }; ppfd=&pfd; if((pixelformat=ChoosePixelFormat(hdc,ppfd))==0) { ::MessageBox(NULL,"ChoosePixelFormat Failed","Error",MB_OK); return FALSE; } if(SetPixelFormat(hdc,pixelformat,ppfd)==FALSE) { ::MessageBox(NULL,"SetPixelFormat Failed","Error",MB_OK); return FALSE; } return TRUE; } //Get GL info void CPdnmeshView::GetGLInfo() { CString w; w="OpenGL Information\n\nWho: "; w+=::glGetString(GL_VENDOR); w+="\nWhich: "; w+=::glGetString(GL_RENDERER); w+="\nVersion: "; w+=::glGetString(GL_VERSION); w+="\nExtensions: "; w+=::glGetString(GL_EXTENSIONS); ::AfxMessageBox(w,MB_ICONINFORMATION); } //resize and initialize void CPdnmeshView::ReSizeGLScene(int width, int height) { if(height==0) { height=1; } glViewport(0,0,width,height); glMatrixMode(GL_PROJECTION); glLoadIdentity(); //gluPerspective(45.0f,(float)width/(float)height,0.1f,100.f); gluOrtho2D(-1,1,-1,1); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); } int CPdnmeshView::InitGL(void) { glShadeModel(GL_SMOOTH); glClearColor(0.0f,0.0f,0.0f,0.5f); glClearDepth(1.0f); glEnable(GL_DEPTH_TEST); glDepthFunc(GL_LEQUAL); glHint(GL_PERSPECTIVE_CORRECTION_HINT,GL_NICEST); return TRUE; } int CPdnmeshView::DrawGLScene(void) { glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); return TRUE; } void CPdnmeshView::OnMouseMove(UINT nFlags, CPoint point) { GLdouble c_mat[16]; // TODO: Add your message handler code here and/or call default //Update current (x,y) double xx,yy; xx=2*(double)point.x/(double)theApp.p_w-1.0; yy=-2*(double)point.y/(double)theApp.p_h+1.0; //zoom window glGetDoublev(GL_MODELVIEW_MATRIX,c_mat); if (mouse_responce_flag==MENU_ZOOM_END) { zoom_x2=((xx-c_mat[12])/c_mat[0]); zoom_y2=((yy-c_mat[13])/c_mat[5]); Invalidate(); } //global coordinates theApp.p_x=((xx-c_mat[12])/c_mat[0])*g_xscale-g_xoff;; theApp.p_y=((yy-c_mat[13])/c_mat[5])*g_yscale-g_yoff; CView::OnMouseMove(nFlags, point); } void CPdnmeshView::OnDrawCfill() { // TODO: Add your command handler code here plot_fill=(plot_fill?0:1); Invalidate(); } void CPdnmeshView::OnDrawContour() { // TODO: Add your command handler code here plot_cont=(plot_cont?0:1); Invalidate(); } void CPdnmeshView::OnDrawGrad() { // TODO: Add your command handler code here plot_grad=(plot_grad?0:1); Invalidate(); } void CPdnmeshView::OnDrawMesh() { // TODO: Add your command handler code here plot_mesh=(plot_mesh?0:1); Invalidate(); } void CPdnmeshView::OnLButtonDown(UINT nFlags, CPoint point) { // TODO: Add your message handler code here and/or call default if(mouse_responce_flag==MENU_ZOOM_START){ double xx,yy; GLdouble c_mat[16]; xx=2*(double)point.x/(double)theApp.p_w-1.0; yy=-2*(double)point.y/(double)theApp.p_h+1.0; //convert to world coordinates glGetDoublev(GL_MODELVIEW_MATRIX,c_mat); zoom_x1=(float)((xx-c_mat[12])/c_mat[0]); zoom_y1=(float)((yy-c_mat[13])/c_mat[5]); //eliminate previous zoom window zoom_x2=zoom_x1; zoom_y1=zoom_y1; mouse_responce_flag=MENU_ZOOM_END; } else if (mouse_responce_flag==MENU_ZOOM_END) { double xx,yy; GLdouble c_mat[16]; xx=2*(double)point.x/(double)theApp.p_w-1.0; yy=-2*(double)point.y/(double)theApp.p_h+1.0; //convert to world coordinates glGetDoublev(GL_MODELVIEW_MATRIX,c_mat); zoom_x2=(float)((xx-c_mat[12])/c_mat[0]); zoom_y2=(float)((yy-c_mat[13])/c_mat[5]); //do the zoom if (zoom_x1!=zoom_x2) { /* first arrange points in zoom window */ if ( zoom_x1 > zoom_x2 ) { double temp=zoom_x1; zoom_x1=zoom_x2; zoom_x2=temp; } if ( zoom_y1 < zoom_y2 ) { double temp=zoom_y1; zoom_y1=zoom_y2; zoom_y2=temp; } /* now keep same aspect ratio as the figure */ zoom_y2=-(double) theApp.p_h/(double)theApp.p_w*(zoom_x2-zoom_x1)+zoom_y1; /* preserve the current matrix on the stack */ glPushMatrix(); /* first zoom all */ glLoadIdentity(); /* then do the real zoom */ glScalef((float)(-2.0/(zoom_x1-zoom_x2)),(float)(2.0/(zoom_y1-zoom_y2)),1.0); glTranslatef((float)(-0.5*(zoom_x1+zoom_x2)),(float)(-0.5*(zoom_y1+zoom_y2)),0); /* redisplay */ Invalidate(); } mouse_responce_flag=MENU_ZOOM_START; } CView::OnLButtonDown(nFlags, point); } void CPdnmeshView::OnZoomAll() { // TODO: Add your command handler code here glLoadIdentity(); mouse_responce_flag=MENU_0; //stop zooming Invalidate(); } void CPdnmeshView::OnZoomBack() { // TODO: Add your command handler code here glPopMatrix(); Invalidate(); } void CPdnmeshView::OnZoomStart() { // TODO: Add your command handler code here mouse_responce_flag=(mouse_responce_flag==MENU_ZOOM_START?MENU_ZOOM_END:MENU_ZOOM_START); Invalidate(); } void CPdnmeshView::OnNextEigenmode() { // TODO: Add your command handler code here /* switch to next eigenmode */ if (solve_equation== POISSON || solve_equation == POISSON_SPARSE ) { current_plotting_contour=0; } else if (solve_equation == HELMHOLTZ ) { current_plotting_contour++; if ( current_plotting_contour >=degree_of_freedom ) current_plotting_contour=0; } else if ((solve_equation == HELMHOLTZ_INHOMO) || (solve_equation == HELMHOLTZ_FREQ) || (solve_equation == HELMHOLTZ_BETA)) { current_plotting_contour++; if ( current_plotting_contour >=3*degree_of_freedom ) current_plotting_contour=0; } Invalidate(); } void CPdnmeshView::OnSolve() { CFrameWnd *pMainFrame = static_cast(AfxGetMainWnd()); if (pMainFrame) { CStatusBar *pStatusBar = static_cast(pMainFrame->GetMessageBar()); if (pStatusBar) { pStatusBar->SetPaneText(1, "Solving Problem.."); } } // TODO: Add your command handler code here CPdnmeshDoc* pDoc = GetDocument(); ASSERT_VALID(pDoc); if(pDoc->model !=NULL) pDoc->model->Solve(); Invalidate(); if (pMainFrame) { CStatusBar *pStatusBar = static_cast(pMainFrame->GetMessageBar()); if (pStatusBar) { pStatusBar->SetPaneText(1, "Solving Problem..Done."); } } }