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