1 // pdnmeshView.cpp : implementation of the CPdnmeshView class
2 //
3 /*  pdnmesh - a 2D finite element solver
4     Copyright (C) 2001-2005 Sarod Yatawatta <sarod@users.sf.net>
5   This program is free software; you can redistribute it and/or modify
6   it under the terms of the GNU General Public License as published by
7   the Free Software Foundation; either version 2 of the License, or
8   (at your option) any later version.
9 
10   This program is distributed in the hope that it will be useful,
11   but WITHOUT ANY WARRANTY; without even the implied warranty of
12   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13   GNU General Public License for more details.
14 
15   You should have received a copy of the GNU General Public License
16   along with this program; if not, write to the Free Software
17   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18   $Id: pdnmeshView.cpp,v 1.5 2005/02/16 13:16:15 sarod Exp $
19 */
20 #include "stdafx.h"
21 #include "winpdnmesh.h"
22 
23 #include "pdnmeshDoc.h"
24 #include "pdnmeshView.h"
25 #include "model.h"
26 
27 #ifdef _DEBUG
28 #define new DEBUG_NEW
29 #undef THIS_FILE
30 static char THIS_FILE[] = __FILE__;
31 #endif
32 
33 /////////////////////////////////////////////////////////////////////////////
34 // CPdnmeshView
35 
IMPLEMENT_DYNCREATE(CPdnmeshView,CView)36 IMPLEMENT_DYNCREATE(CPdnmeshView, CView)
37 
38 BEGIN_MESSAGE_MAP(CPdnmeshView, CView)
39 	//{{AFX_MSG_MAP(CPdnmeshView)
40 	ON_WM_CREATE()
41 	ON_WM_DESTROY()
42 	ON_WM_ERASEBKGND()
43 	ON_WM_SIZE()
44 	ON_WM_MOUSEMOVE()
45 	ON_COMMAND(VID_DRAW_CFILL, OnDrawCfill)
46 	ON_COMMAND(VID_DRAW_CONTOUR, OnDrawContour)
47 	ON_COMMAND(VID_DRAW_GRAD, OnDrawGrad)
48 	ON_COMMAND(VID_DRAW_MESH, OnDrawMesh)
49 	ON_WM_LBUTTONDOWN()
50 	ON_COMMAND(ZID_ZOOM_ALL, OnZoomAll)
51 	ON_COMMAND(ZID_ZOOM_BACK, OnZoomBack)
52 	ON_COMMAND(ZID_ZOOM_START, OnZoomStart)
53 	ON_COMMAND(VID_NEXT_EIGENMODE, OnNextEigenmode)
54 	ON_COMMAND(SID_SOLVE, OnSolve)
55 	//}}AFX_MSG_MAP
56 END_MESSAGE_MAP()
57 
58 /////////////////////////////////////////////////////////////////////////////
59 // CPdnmeshView construction/destruction
60 
61 CPdnmeshView::CPdnmeshView()
62 {
63 	// TODO: add construction code here
64 
65 }
66 
~CPdnmeshView()67 CPdnmeshView::~CPdnmeshView()
68 {
69 }
70 
PreCreateWindow(CREATESTRUCT & cs)71 BOOL CPdnmeshView::PreCreateWindow(CREATESTRUCT& cs)
72 {
73 	// TODO: Modify the Window class or styles here by modifying
74 	//  the CREATESTRUCT cs
75 
76   cs.style |=WS_CLIPCHILDREN|WS_CLIPSIBLINGS|CS_OWNDC;
77   //set default size
78   cs.cx=800;
79   cs.cy=200;
80 	return CView::PreCreateWindow(cs);
81 }
82 
83 /////////////////////////////////////////////////////////////////////////////
84 // CPdnmeshView drawing
85 
OnDraw(CDC * pDC)86 void CPdnmeshView::OnDraw(CDC* pDC)
87 {
88 	CPdnmeshDoc* pDoc = GetDocument();
89 	ASSERT_VALID(pDoc);
90 	// TODO: add draw code for native data here
91 
92   CPaintDC dc(this);
93   HWND hWnd =GetSafeHwnd();
94   HDC hDC=::GetDC(hWnd);
95   wglMakeCurrent(hDC,m_hglrc);
96   DrawGLScene(); //draw routine of view
97   // call draw of doc
98   pDoc->draw();
99   //if (doubleBuffered )
100    SwapBuffers(m_hgldc);
101   //else
102    //glFlush();
103 
104   //wglMakeCurrent( NULL, NULL );
105 
106   //ValidateRect(NULL);
107 
108 }
109 
110 
111 /////////////////////////////////////////////////////////////////////////////
112 // CPdnmeshView diagnostics
113 
114 #ifdef _DEBUG
AssertValid() const115 void CPdnmeshView::AssertValid() const
116 {
117 	CView::AssertValid();
118 }
119 
Dump(CDumpContext & dc) const120 void CPdnmeshView::Dump(CDumpContext& dc) const
121 {
122 	CView::Dump(dc);
123 }
124 
GetDocument()125 CPdnmeshDoc* CPdnmeshView::GetDocument() // non-debug version is inline
126 {
127 	ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CPdnmeshDoc)));
128 	return (CPdnmeshDoc*)m_pDocument;
129 }
130 #endif //_DEBUG
131 
132 /////////////////////////////////////////////////////////////////////////////
133 // CPdnmeshView message handlers
OnCreate(LPCREATESTRUCT lpCreateStruct)134 int CPdnmeshView::OnCreate(LPCREATESTRUCT lpCreateStruct)
135 {
136 	if (CView::OnCreate(lpCreateStruct) == -1)
137 		return -1;
138 
139 	// TODO: Add your specialized creation code here
140   m_hgldc=::GetDC(m_hWnd);
141 
142   if(!SetPixelformat(m_hgldc)) {
143    ::MessageBox(::GetFocus(),"SetPixelformat Failed!","Error",MB_OK);
144    return -1;
145   }
146   m_hglrc=wglCreateContext(m_hgldc);
147   int i=wglMakeCurrent(m_hgldc,m_hglrc);
148 
149   InitGL();
150 	return 0;
151 }
152 
OnDestroy()153 void CPdnmeshView::OnDestroy()
154 {
155 	CView::OnDestroy();
156 
157 	// TODO: Add your message handler code here
158   if (wglGetCurrentContext() !=NULL)
159    wglMakeCurrent(NULL,NULL);
160 
161   if(m_hglrc!=NULL)  {
162    wglDeleteContext(m_hglrc);
163    m_hglrc=NULL;
164   }
165 
166 }
167 
OnEraseBkgnd(CDC * pDC)168 BOOL CPdnmeshView::OnEraseBkgnd(CDC* pDC)
169 {
170 	// TODO: Add your message handler code here and/or call default
171 
172 	//return CView::OnEraseBkgnd(pDC);
173   return TRUE;
174 }
175 
OnSize(UINT nType,int cx,int cy)176 void CPdnmeshView::OnSize(UINT nType, int cx, int cy)
177 {
178 	CView::OnSize(nType, cx, cy);
179 
180 	// TODO: Add your message handler code here
181 
182   theApp.p_w=cx;
183   theApp.p_h=cy;
184   ReSizeGLScene((int)cx,(int)cy);
185 
186 }
187 
188 
189 
190 //Utility functions
SetPixelformat(HDC hdc)191 BOOL CPdnmeshView::SetPixelformat(HDC hdc)
192 {
193  PIXELFORMATDESCRIPTOR *ppfd;
194  int pixelformat;
195 
196  PIXELFORMATDESCRIPTOR pfd={
197 	sizeof(PIXELFORMATDESCRIPTOR), //size of pfd
198 	1, //version
199 	PFD_DRAW_TO_WINDOW| //support window
200 	PFD_SUPPORT_OPENGL| //support OpenGL
201 	PFD_GENERIC_FORMAT|
202 	PFD_DOUBLEBUFFER, //flags
203   PFD_TYPE_RGBA, //type RGBA
204 	32, //colour depth in bits
205 	0, 0, 0, 0, 0, 0, //(r,g,b) bits
206 	8, //no alpha buffer
207 	0, //shift bit ignored
208 	8, //no accumulation buffer
209 	0,0,0,0, //accum bits ignored
210 	64, //32 bit z buffer
211 	8, //no stencil buffer
212 	8, // no auxiliary buffer
213 	PFD_MAIN_PLANE, //main layer
214 	0, //reserved
215 	0,0,0 //layer masks ignored
216  };
217 
218  ppfd=&pfd;
219 
220  if((pixelformat=ChoosePixelFormat(hdc,ppfd))==0) {
221 	::MessageBox(NULL,"ChoosePixelFormat Failed","Error",MB_OK);
222   return FALSE;
223  }
224  if(SetPixelFormat(hdc,pixelformat,ppfd)==FALSE) {
225   ::MessageBox(NULL,"SetPixelFormat Failed","Error",MB_OK);
226   return FALSE;
227  }
228  return TRUE;
229 }
230 
231 
232 //Get GL info
GetGLInfo()233 void CPdnmeshView::GetGLInfo()
234 {
235  CString w;
236  w="OpenGL Information\n\nWho: ";
237  w+=::glGetString(GL_VENDOR);
238  w+="\nWhich: ";
239  w+=::glGetString(GL_RENDERER);
240  w+="\nVersion: ";
241  w+=::glGetString(GL_VERSION);
242  w+="\nExtensions: ";
243  w+=::glGetString(GL_EXTENSIONS);
244  ::AfxMessageBox(w,MB_ICONINFORMATION);
245 }
246 
247 //resize and initialize
ReSizeGLScene(int width,int height)248 void CPdnmeshView::ReSizeGLScene(int width, int height)
249 {
250  if(height==0) {
251   height=1;
252  }
253  glViewport(0,0,width,height);
254  glMatrixMode(GL_PROJECTION);
255  glLoadIdentity();
256 
257  //gluPerspective(45.0f,(float)width/(float)height,0.1f,100.f);
258  gluOrtho2D(-1,1,-1,1);
259  glMatrixMode(GL_MODELVIEW);
260  glLoadIdentity();
261 }
262 
InitGL(void)263 int CPdnmeshView::InitGL(void)
264 {
265  glShadeModel(GL_SMOOTH);
266  glClearColor(0.0f,0.0f,0.0f,0.5f);
267  glClearDepth(1.0f);
268  glEnable(GL_DEPTH_TEST);
269  glDepthFunc(GL_LEQUAL);
270  glHint(GL_PERSPECTIVE_CORRECTION_HINT,GL_NICEST);
271  return TRUE;
272 }
273 
DrawGLScene(void)274 int CPdnmeshView::DrawGLScene(void)
275 {
276  glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
277  return TRUE;
278 }
279 
OnMouseMove(UINT nFlags,CPoint point)280 void CPdnmeshView::OnMouseMove(UINT nFlags, CPoint point)
281 {
282   GLdouble c_mat[16];
283 	// TODO: Add your message handler code here and/or call default
284 
285  //Update current (x,y)
286   double xx,yy;
287   xx=2*(double)point.x/(double)theApp.p_w-1.0;
288   yy=-2*(double)point.y/(double)theApp.p_h+1.0;
289   //zoom window
290   glGetDoublev(GL_MODELVIEW_MATRIX,c_mat);
291   if (mouse_responce_flag==MENU_ZOOM_END) {
292     zoom_x2=((xx-c_mat[12])/c_mat[0]);
293     zoom_y2=((yy-c_mat[13])/c_mat[5]);
294     Invalidate();
295   }
296   //global coordinates
297   theApp.p_x=((xx-c_mat[12])/c_mat[0])*g_xscale-g_xoff;;
298   theApp.p_y=((yy-c_mat[13])/c_mat[5])*g_yscale-g_yoff;
299 	CView::OnMouseMove(nFlags, point);
300 }
301 
OnDrawCfill()302 void CPdnmeshView::OnDrawCfill()
303 {
304 	// TODO: Add your command handler code here
305   plot_fill=(plot_fill?0:1);
306   Invalidate();
307 }
308 
OnDrawContour()309 void CPdnmeshView::OnDrawContour()
310 {
311 	// TODO: Add your command handler code here
312 	plot_cont=(plot_cont?0:1);
313   Invalidate();
314 }
315 
OnDrawGrad()316 void CPdnmeshView::OnDrawGrad()
317 {
318 	// TODO: Add your command handler code here
319 	plot_grad=(plot_grad?0:1);
320   Invalidate();
321 }
322 
OnDrawMesh()323 void CPdnmeshView::OnDrawMesh()
324 {
325 	// TODO: Add your command handler code here
326 	plot_mesh=(plot_mesh?0:1);
327   Invalidate();
328 }
329 
OnLButtonDown(UINT nFlags,CPoint point)330 void CPdnmeshView::OnLButtonDown(UINT nFlags, CPoint point)
331 {
332 	// TODO: Add your message handler code here and/or call default
333   if(mouse_responce_flag==MENU_ZOOM_START){
334   double xx,yy;
335   GLdouble c_mat[16];
336   xx=2*(double)point.x/(double)theApp.p_w-1.0;
337   yy=-2*(double)point.y/(double)theApp.p_h+1.0;
338   //convert to world coordinates
339   glGetDoublev(GL_MODELVIEW_MATRIX,c_mat);
340   zoom_x1=(float)((xx-c_mat[12])/c_mat[0]);
341   zoom_y1=(float)((yy-c_mat[13])/c_mat[5]);
342   //eliminate previous zoom window
343   zoom_x2=zoom_x1; zoom_y1=zoom_y1;
344   mouse_responce_flag=MENU_ZOOM_END;
345   } else if (mouse_responce_flag==MENU_ZOOM_END) {
346   double xx,yy;
347   GLdouble c_mat[16];
348   xx=2*(double)point.x/(double)theApp.p_w-1.0;
349   yy=-2*(double)point.y/(double)theApp.p_h+1.0;
350   //convert to world coordinates
351   glGetDoublev(GL_MODELVIEW_MATRIX,c_mat);
352   zoom_x2=(float)((xx-c_mat[12])/c_mat[0]);
353   zoom_y2=(float)((yy-c_mat[13])/c_mat[5]);
354   //do the zoom
355   if (zoom_x1!=zoom_x2) {
356       /* first arrange points in zoom window */
357     if ( zoom_x1 > zoom_x2 ) {
358             double temp=zoom_x1;
359             zoom_x1=zoom_x2;
360             zoom_x2=temp;
361     }
362     if ( zoom_y1 < zoom_y2 ) {
363             double temp=zoom_y1;
364             zoom_y1=zoom_y2;
365             zoom_y2=temp;
366     }
367      /* now keep same aspect ratio as the figure */
368     zoom_y2=-(double) theApp.p_h/(double)theApp.p_w*(zoom_x2-zoom_x1)+zoom_y1;
369       /* preserve the current matrix on the stack */
370        glPushMatrix();
371        /* first zoom all */
372        glLoadIdentity();
373     /* then do the real zoom */
374     glScalef((float)(-2.0/(zoom_x1-zoom_x2)),(float)(2.0/(zoom_y1-zoom_y2)),1.0);
375     glTranslatef((float)(-0.5*(zoom_x1+zoom_x2)),(float)(-0.5*(zoom_y1+zoom_y2)),0);
376    /* redisplay */
377    Invalidate();
378  }
379    mouse_responce_flag=MENU_ZOOM_START;
380 
381   }
382 	CView::OnLButtonDown(nFlags, point);
383 }
384 
OnZoomAll()385 void CPdnmeshView::OnZoomAll()
386 {
387 	// TODO: Add your command handler code here
388   glLoadIdentity();
389   mouse_responce_flag=MENU_0; //stop zooming
390   Invalidate();
391 }
392 
OnZoomBack()393 void CPdnmeshView::OnZoomBack()
394 {
395 	// TODO: Add your command handler code here
396   glPopMatrix();
397   Invalidate();
398 }
399 
OnZoomStart()400 void CPdnmeshView::OnZoomStart()
401 {
402 	// TODO: Add your command handler code here
403 	mouse_responce_flag=(mouse_responce_flag==MENU_ZOOM_START?MENU_ZOOM_END:MENU_ZOOM_START);
404   Invalidate();
405 }
406 
OnNextEigenmode()407 void CPdnmeshView::OnNextEigenmode()
408 {
409 	// TODO: Add your command handler code here
410 	/* switch to next eigenmode */
411   if (solve_equation== POISSON || solve_equation == POISSON_SPARSE ) {
412    current_plotting_contour=0;
413   } else if (solve_equation == HELMHOLTZ ) {
414    current_plotting_contour++;
415   if ( current_plotting_contour >=degree_of_freedom )
416    current_plotting_contour=0;
417   } else if ((solve_equation == HELMHOLTZ_INHOMO)
418      || (solve_equation == HELMHOLTZ_FREQ)
419      || (solve_equation == HELMHOLTZ_BETA)) {
420    current_plotting_contour++;
421   if ( current_plotting_contour >=3*degree_of_freedom )
422    current_plotting_contour=0;
423   }
424   Invalidate();
425 }
426 
OnSolve()427 void CPdnmeshView::OnSolve()
428 {
429    CFrameWnd *pMainFrame = static_cast<CFrameWnd *>(AfxGetMainWnd());
430    if (pMainFrame) {
431     CStatusBar *pStatusBar = static_cast<CStatusBar *>(pMainFrame->GetMessageBar());
432     if (pStatusBar) {
433         pStatusBar->SetPaneText(1, "Solving Problem..");
434     }
435    }
436 
437 	// TODO: Add your command handler code here
438 	CPdnmeshDoc* pDoc = GetDocument();
439 	ASSERT_VALID(pDoc);
440 	if(pDoc->model !=NULL)
441 	 pDoc->model->Solve();
442 	Invalidate();
443     if (pMainFrame) {
444     CStatusBar *pStatusBar = static_cast<CStatusBar *>(pMainFrame->GetMessageBar());
445     if (pStatusBar) {
446         pStatusBar->SetPaneText(1, "Solving Problem..Done.");
447     }
448    }
449 
450 }
451