1 /*****************************************************************************
2  *                                                                           *
3  *  Elmer, A Finite Element Software for Multiphysical Problems              *
4  *                                                                           *
5  *  Copyright 1st April 1995 - , CSC - IT Center for Science Ltd., Finland    *
6  *                                                                           *
7  *  This program is free software; you can redistribute it and/or            *
8  *  modify it under the terms of the GNU General Public License              *
9  *  as published by the Free Software Foundation; either version 2           *
10  *  of the License, or (at your option) any later version.                   *
11  *                                                                           *
12  *  This program is distributed in the hope that it will be useful,          *
13  *  but WITHOUT ANY WARRANTY; without even the implied warranty of           *
14  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the            *
15  *  GNU General Public License for more details.                             *
16  *                                                                           *
17  *  You should have received a copy of the GNU General Public License        *
18  *  along with this program (in file fem/GPL-2); if not, write to the        *
19  *  Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,         *
20  *  Boston, MA 02110-1301, USA.                                              *
21  *                                                                           *
22  *****************************************************************************/
23 
24 /*****************************************************************************
25  *                                                                           *
26  *  ElmerGUI glwidget                                                        *
27  *                                                                           *
28  *****************************************************************************
29  *                                                                           *
30  *  Authors: Mikko Lyly, Juha Ruokolainen and Peter R�back                   *
31  *  Email:   Juha.Ruokolainen@csc.fi                                         *
32  *  Web:     http://www.csc.fi/elmer                                         *
33  *  Address: CSC - IT Center for Science Ltd.                                 *
34  *           Keilaranta 14                                                   *
35  *           02101 Espoo, Finland                                            *
36  *                                                                           *
37  *  Original Date: 15 Mar 2008                                               *
38  *                                                                           *
39  *****************************************************************************/
40 
41 #include <QtGui>
42 #include <QtOpenGL>
43 #include <QWheelEvent>
44 #include <QKeyEvent>
45 #include <math.h>
46 #include <iostream>
47 #include <stdio.h>
48 #include "glwidget.h"
49 #include "mainwindow.h"
50 
51 using namespace std;
52 
53 #define MY_PI 3.14159265
54 #define ZSHIFT -5.0
55 
56 // Get qreal regardless of whether it's float or double
glGetQrealv(GLenum e,GLfloat * data)57 static inline void glGetQrealv(GLenum e, GLfloat* data) { glGetFloatv(e,data); }
glGetQrealv(GLenum e,GLdouble * data)58 static inline void glGetQrealv(GLenum e, GLdouble* data) { glGetDoublev(e,data); }
glMultMatrixq(const GLdouble * m)59 static inline void glMultMatrixq( const GLdouble *m ) { glMultMatrixd(m); }
glMultMatrixq(const GLfloat * m)60 static inline void glMultMatrixq( const GLfloat *m ) { glMultMatrixf(m); }
61 
list_t()62 list_t::list_t()
63 {
64   nature = PDE_UNKNOWN;
65   type = UNKNOWNLIST;
66   index = -1;
67   object = 0;
68   child = -1;
69   parent = -1;
70   selected = false;
71   visible = false;
72 }
73 
~list_t()74 list_t::~list_t()
75 {
76 }
77 
setNature(int n)78 void list_t::setNature(int n)
79 {
80   this->nature = n;
81 }
82 
getNature(void) const83 int list_t::getNature(void) const
84 {
85   return this->nature;
86 }
87 
setType(int n)88 void list_t::setType(int n)
89 {
90   this->type = n;
91 }
92 
getType(void) const93 int list_t::getType(void) const
94 {
95   return this->type;
96 }
97 
setIndex(int n)98 void list_t::setIndex(int n)
99 {
100   this->index = n;
101 }
102 
getIndex(void) const103 int list_t::getIndex(void) const
104 {
105   return this->index;
106 }
107 
setObject(GLuint n)108 void list_t::setObject(GLuint n)
109 {
110   this->object = n;
111 }
112 
getObject(void) const113 GLuint list_t::getObject(void) const
114 {
115   return this->object;
116 }
117 
setChild(int n)118 void list_t::setChild(int n)
119 {
120   this->child = n;
121 }
122 
getChild(void) const123 int list_t::getChild(void) const
124 {
125   return this->child;
126 }
127 
setParent(int n)128 void list_t::setParent(int n)
129 {
130   this->parent = n;
131 }
132 
getParent(void) const133 int list_t::getParent(void) const
134 {
135   return this->parent;
136 }
137 
setSelected(bool b)138 void list_t::setSelected(bool b)
139 {
140   this->selected = b;
141 }
142 
isSelected(void) const143 bool list_t::isSelected(void) const
144 {
145   return this->selected;
146 }
147 
setVisible(bool b)148 void list_t::setVisible(bool b)
149 {
150   this->visible = b;
151 }
152 
isVisible(void) const153 bool list_t::isVisible(void) const
154 {
155   return this->visible;
156 }
157 
158 // Construct glWidget...
159 //-----------------------------------------------------------------------------
GLWidget(QWidget * parent)160 GLWidget::GLWidget(QWidget *parent)
161   : QGLWidget(parent)
162 {
163   backgroundColor = Qt::white;
164   surfaceColor = Qt::cyan;
165   edgeColor = Qt::green;
166   surfaceMeshColor = Qt::black;
167   sharpEdgeColor = Qt::black;
168 
169   stateOrtho = false;
170   stateFlatShade = true;
171   stateDrawSurfaceMesh = true;
172   stateDrawVolumeMesh = false;
173   stateDrawSharpEdges = true;
174   stateDrawSurfaceElements = true;
175   stateDrawEdgeElements = true;
176   stateDrawCoordinates = false;
177   stateDrawSurfaceNumbers = false;
178   stateDrawEdgeNumbers = false;
179   stateDrawNodeNumbers = false;
180   stateDrawBoundaryIndex = false;
181   stateDrawBodyIndex = false;
182   stateBcColors = false;
183   stateBodyColors = false;
184 
185   currentlySelectedBody = -1;
186 
187   drawScale = 1.0;
188   drawTranslate[0] = 0.0;
189   drawTranslate[1] = 0.0;
190   drawTranslate[2] = 0.0;
191 
192   mesh = NULL;
193 
194   helpers = new Helpers;
195   meshutils = new Meshutils;
196 
197   ctrlPressed = false;
198   shiftPressed = false;
199   altPressed = false;
200 
201   // Coordinate axis:
202   quadric_axis = gluNewQuadric();
203 
204   // Background image:
205   stateUseBgImage = false;
206   stateStretchBgImage = false;
207   stateAlignRightBgImage = false;
208   bgImageFileName = "";
209   bgTexture = 0;
210   bgSizeX = 0;
211   bgSizeY = 0;
212 }
213 
214 
215 // dtor...
216 //-----------------------------------------------------------------------------
~GLWidget()217 GLWidget::~GLWidget()
218 {
219 }
220 
221 
222 // Min size hint...
223 //-----------------------------------------------------------------------------
minimumSizeHint() const224 QSize GLWidget::minimumSizeHint() const
225 {
226   return QSize(64, 64);
227 }
228 
229 
230 // Default size...
231 //-----------------------------------------------------------------------------
sizeHint() const232 QSize GLWidget::sizeHint() const
233 {
234   return QSize(720, 576);
235 }
236 
setMesh(mesh_t * m)237 void GLWidget::setMesh(mesh_t *m)
238 {
239   this->mesh = m;
240 }
241 
getMesh(void) const242 mesh_t* GLWidget::getMesh(void) const
243 {
244   return this->mesh;
245 }
246 
newMesh(void)247 void GLWidget::newMesh(void)
248 {
249   this->mesh = new mesh_t;
250 }
251 
deleteMesh(void)252 void GLWidget::deleteMesh(void)
253 {
254   delete this->mesh;
255 }
256 
hasMesh(void) const257 bool GLWidget::hasMesh(void) const
258 {
259   if(this->mesh)
260     return true;
261 
262   return false;
263 }
264 
265 // Init GL...
266 //-----------------------------------------------------------------------------
initializeGL()267 void GLWidget::initializeGL()
268 {
269   cout << "Initialize GL" << endl;
270   cout << "Vendor: " << glGetString(GL_VENDOR) << endl;
271   cout << "Renderer: " << glGetString(GL_RENDERER) << endl;
272   cout << "Version: " << glGetString(GL_VERSION) << endl;
273   cout.flush();
274 
275   static GLfloat light_ambient[]  = {0.2, 0.2, 0.2, 1.0};
276   static GLfloat light_diffuse[]  = {0.6, 0.6, 0.6, 1.0};
277   static GLfloat light_specular[] = {1.0, 1.0, 1.0, 1.0};
278   static GLfloat light_position[] = {0.0, 0.0, 5.0, 0.0};
279 
280   static GLfloat mat_ambient[]    = {0.2, 0.2, 0.2, 1.0};
281   static GLfloat mat_diffuse[]    = {1.0, 1.0, 1.0, 1.0};
282   static GLfloat mat_specular[]   = {0.9, 0.9, 0.9, 1.0};
283   static GLfloat high_shininess[] = {20.0};
284 
285   glMatrixMode(GL_MODELVIEW);
286   glLoadIdentity();
287 
288   glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, 1);
289   glLightModelf(GL_LIGHT_MODEL_LOCAL_VIEWER, 1.0);
290   glEnable(GL_LIGHTING);
291 
292   glLightModelf(GL_LIGHT_MODEL_LOCAL_VIEWER,1.0);
293   glLightfv(GL_LIGHT0, GL_AMBIENT, light_ambient);
294   glLightfv(GL_LIGHT0, GL_DIFFUSE, light_diffuse);
295   glLightfv(GL_LIGHT0, GL_SPECULAR, light_specular);
296   glLightfv(GL_LIGHT0, GL_POSITION, light_position);
297   glEnable(GL_LIGHT0);
298 
299   glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, mat_ambient);
300   glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mat_diffuse);
301   glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, mat_specular);
302   glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, high_shininess);
303   glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE);
304   glEnable(GL_COLOR_MATERIAL);
305 
306   glEnable(GL_DEPTH_TEST);
307   glDepthFunc(GL_LESS);
308   // glDepthRange(-10.0, 10.0);
309 
310   glShadeModel(GL_SMOOTH);
311   // glEnable(GL_LINE_SMOOTH);
312 
313   glEnable(GL_NORMALIZE);
314 
315   qglClearColor(backgroundColor);
316 
317   glEnable(GL_TEXTURE_2D);
318 }
319 
320 
321 
322 // Paint event...
323 //-----------------------------------------------------------------------------
paintGL()324 void GLWidget::paintGL()
325 {
326   float xabs[3], xrel[3];
327 
328   glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
329 
330   // Background image:
331   if(stateUseBgImage)
332     drawBgImage();
333 
334   // FE objects:
335   if(getLists() > 0) {
336 
337     for(int i = 0; i < getLists(); i++) {
338       list_t *l = getList(i);
339 
340       if(l->isVisible()) {
341 	glPushName(i);
342 
343 	if((l->getType() == SURFACEMESHLIST) && stateDrawSurfaceMesh) {
344 	  // translate slightly towards viewer
345 	  glMatrixMode(GL_PROJECTION);
346 	  glPushMatrix();
347 	  glTranslated(0, 0, 0.01);
348 	  glTranslated(0, 0, ZSHIFT);
349 	  glCallList(l->getObject());
350 	  glPopMatrix();
351 	  glMatrixMode(GL_MODELVIEW);
352 
353 	} else if((l->getType() == VOLUMEMESHLIST) && stateDrawVolumeMesh) {
354 	  // translate slightly towards viewer
355 	  glMatrixMode(GL_PROJECTION);
356 	  glPushMatrix();
357 	  glTranslated(0, 0, 0.01);
358 	  glTranslated(0, 0, ZSHIFT);
359 	  glCallList(l->getObject());
360 	  glPopMatrix();
361 	  glMatrixMode(GL_MODELVIEW);
362 
363 	} else if ((l->getType() == SHARPEDGELIST) && stateDrawSharpEdges) {
364 	  // translate slightly towards viewer
365 	  glMatrixMode(GL_PROJECTION);
366 	  glPushMatrix();
367 	  glTranslated(0, 0, 0.01);
368 	  glTranslated(0, 0, ZSHIFT);
369 	  glCallList(l->getObject());
370 	  glPopMatrix();
371 	  glMatrixMode(GL_MODELVIEW);
372 
373 	} else if((l->getType() == EDGELIST) && stateDrawEdgeElements ) {
374 	  // translate slightly towards viewer
375 	  glMatrixMode(GL_PROJECTION);
376 	  glPushMatrix();
377 	  glTranslated(0, 0, 0.02);
378 	  glTranslated(0, 0, ZSHIFT);
379 	  glCallList(l->getObject());
380 	  glPopMatrix();
381 	  glMatrixMode(GL_MODELVIEW);
382 
383 	} else if((l->getType() == SURFACELIST) && stateDrawSurfaceElements ) {
384 	  glMatrixMode(GL_PROJECTION);
385 	  glPushMatrix();
386 	  glTranslated(0, 0, ZSHIFT);
387 	  glCallList(l->getObject());
388 	  glPopMatrix();
389 	  glMatrixMode(GL_MODELVIEW);
390 
391 	} else {
392 	  glMatrixMode(GL_PROJECTION);
393 	  glPushMatrix();
394 	  glTranslated(0, 0, ZSHIFT);
395 	  glCallList(l->getObject());
396 	  glPopMatrix();
397 	  glMatrixMode(GL_MODELVIEW);
398 	}
399 
400 	glPopName();
401       }
402     }
403   }
404 
405   if(stateDrawCoordinates) {
406     // push a dummy name
407     glPushName(DUMMY_NAME);
408     drawCoordinates();
409     glPopName();
410   }
411 
412   if(mesh) {
413     if(stateDrawSurfaceNumbers) {
414       glMatrixMode(GL_PROJECTION);
415       glPushMatrix();
416       glTranslated(0, 0, ZSHIFT);
417       glTranslated(0, 0, 0.1);
418       glColor3d(0.5, 0, 0);
419 
420       for(int i=0; i < mesh->getSurfaces(); i++) {
421 	surface_t *surface = mesh->getSurface(i);
422 	int nodes = surface->getCode() / 100;
423 
424 	xabs[0] = xabs[1] = xabs[2] = 0.0;
425 
426 	for(int j = 0; j < nodes; j++) {
427 	  int ind = surface->getNodeIndex(j);
428 	  xabs[0] = xabs[0] + mesh->getNode(ind)->getX(0);
429 	  xabs[1] = xabs[1] + mesh->getNode(ind)->getX(1);
430 	  xabs[2] = xabs[2] + mesh->getNode(ind)->getX(2);
431 	}
432 
433 	xrel[0] = (xabs[0]/nodes - drawTranslate[0]) / drawScale;
434 	xrel[1] = (xabs[1]/nodes - drawTranslate[1]) / drawScale;
435 	xrel[2] = (xabs[2]/nodes - drawTranslate[2]) / drawScale;
436 
437 	renderText(xrel[0], xrel[1], xrel[2], QString::number(i+1) );
438       }
439 
440       glPopMatrix();
441       glMatrixMode(GL_MODELVIEW);
442     }
443 
444     if(stateDrawEdgeNumbers) {
445       glMatrixMode(GL_PROJECTION);
446       glPushMatrix();
447       glTranslated(0, 0, ZSHIFT);
448       glTranslated(0, 0, 0.1);
449       glColor3d(0.0, 0.5, 0);
450 
451       for(int i=0; i < mesh->getEdges(); i++) {
452 	edge_t *edge = mesh->getEdge(i);
453 	int nodes = edge->getCode() / 100;
454 
455 	xabs[0] = xabs[1] = xabs[2] = 0.0;
456 
457 	for(int j = 0; j < nodes; j++) {
458 	  int ind = edge->getNodeIndex(j);
459 	  xabs[0] = xabs[0] + mesh->getNode(ind)->getX(0);
460 	  xabs[1] = xabs[1] + mesh->getNode(ind)->getX(1);
461 	  xabs[2] = xabs[2] + mesh->getNode(ind)->getX(2);
462 	}
463 	xrel[0] = (xabs[0]/nodes - drawTranslate[0]) / drawScale;
464 	xrel[1] = (xabs[1]/nodes - drawTranslate[1]) / drawScale;
465 	xrel[2] = (xabs[2]/nodes - drawTranslate[2]) / drawScale;
466 
467 	renderText(xrel[0], xrel[1], xrel[2], QString::number(i+1) );
468       }
469 
470       glPopMatrix();
471       glMatrixMode(GL_MODELVIEW);
472     }
473 
474     if(stateDrawNodeNumbers) {
475       glMatrixMode(GL_PROJECTION);
476       glPushMatrix();
477       glTranslated(0, 0, ZSHIFT);
478       glTranslated(0, 0, 0.1);
479       glColor3d(0, 0, 0.5);
480 
481       for(int i = 0; i < mesh->getNodes(); i++) {
482 	xabs[0] = mesh->getNode(i)->getX(0);
483 	xabs[1] = mesh->getNode(i)->getX(1);
484 	xabs[2] = mesh->getNode(i)->getX(2);
485 
486 	xrel[0] = (xabs[0] - drawTranslate[0]) / drawScale;
487 	xrel[1] = (xabs[1] - drawTranslate[1]) / drawScale;
488 	xrel[2] = (xabs[2] - drawTranslate[2]) / drawScale;
489 
490 	renderText(xrel[0], xrel[1], xrel[2], QString::number(i+1) );
491       }
492 
493       glPopMatrix();
494       glMatrixMode(GL_MODELVIEW);
495     }
496 
497     if(stateDrawBoundaryIndex || stateDrawBodyIndex) {
498       glMatrixMode(GL_PROJECTION);
499       glPushMatrix();
500       glTranslated(0, 0, ZSHIFT);
501       glTranslated(0, 0, 0.1);
502       glColor3d(0.5, 0, 0);
503 
504       for(int i = 0; i < mesh->getEdges(); i++) {
505 	edge_t *edge = mesh->getEdge(i);
506 	int nodes = edge->getCode() / 100;
507 
508 	xabs[0] = xabs[1] = xabs[2] = 0.0;
509 
510 	for(int j = 0; j < nodes;j++) {
511 	  int ind = edge->getNodeIndex(j);
512 	  xabs[0] = xabs[0] + mesh->getNode(ind)->getX(0);
513 	  xabs[1] = xabs[1] + mesh->getNode(ind)->getX(1);
514 	  xabs[2] = xabs[2] + mesh->getNode(ind)->getX(2);
515 	}
516 
517 	xrel[0] = (xabs[0]/nodes - drawTranslate[0]) / drawScale;
518 	xrel[1] = (xabs[1]/nodes - drawTranslate[1]) / drawScale;
519 	xrel[2] = (xabs[2]/nodes - drawTranslate[2]) / drawScale;
520 
521 	if(stateDrawBoundaryIndex && (edge->getNature() == PDE_BOUNDARY))
522 	  renderText(xrel[0], xrel[1], xrel[2], QString::number(edge->getIndex()));
523 
524 	if(stateDrawBodyIndex && (edge->getNature() == PDE_BULK))
525 	  renderText(xrel[0], xrel[1], xrel[2], QString::number(edge->getIndex()));
526       }
527 
528       for(int i = 0; i < mesh->getSurfaces(); i++) {
529 	surface_t *surface = mesh->getSurface(i);
530 	int nodes = surface->getCode() / 100;
531 
532 	xabs[0] = xabs[1] = xabs[2] = 0.0;
533 
534 	for(int j = 0; j < nodes; j++) {
535 	  int ind = surface->getNodeIndex(j);
536 	  xabs[0] = xabs[0] + mesh->getNode(ind)->getX(0);
537 	  xabs[1] = xabs[1] + mesh->getNode(ind)->getX(1);
538 	  xabs[2] = xabs[2] + mesh->getNode(ind)->getX(2);
539 	}
540 
541 	xrel[0] = (xabs[0]/nodes - drawTranslate[0]) / drawScale;
542 	xrel[1] = (xabs[1]/nodes - drawTranslate[1]) / drawScale;
543 	xrel[2] = (xabs[2]/nodes - drawTranslate[2]) / drawScale;
544 
545 	if(stateDrawBoundaryIndex && (surface->getNature() == PDE_BOUNDARY))
546 	  renderText(xrel[0], xrel[1], xrel[2], QString::number(surface->getIndex()));
547 
548 	if(stateDrawBodyIndex && (surface->getNature() == PDE_BULK))
549 	  renderText(xrel[0], xrel[1], xrel[2], QString::number(surface->getIndex()));
550 
551 	// case 3d:
552 	if(stateDrawBodyIndex && (surface->getNature() == PDE_BOUNDARY)) {
553 	  for(int i = 0; i < surface->getElements(); i++) {
554 	    int j = surface->getElementIndex(i);
555 	    if(j >= 0) {
556 	      element_t *element = mesh->getElement(j);
557 	      renderText(xrel[0], xrel[1], xrel[2], QString::number(element->getIndex()));
558 	    }
559 	  }
560 	}
561 
562       }
563 
564       glPopMatrix();
565       glMatrixMode(GL_MODELVIEW);
566     }
567   }
568 }
569 
570 
571 // Change projection...
572 //-----------------------------------------------------------------------------
changeProjection()573 void GLWidget::changeProjection()
574 {
575   GLint viewport[4];
576   glGetIntegerv(GL_VIEWPORT, viewport);
577 
578   int width = viewport[2];
579   int height = viewport[3];
580   double top = 1.0;
581   double bottom = -1.0;
582   double left = -(double)width / (double)height;
583   double right = (double)width / (double)height;
584   double _near = -10.0;
585   double _far = 10.0;
586 
587   if(stateOrtho) {
588     glViewport(0, 0, (GLint)width, (GLint)height);
589     glMatrixMode(GL_PROJECTION);
590     glLoadIdentity();
591     glOrtho(left, right, bottom, top, _near, _far);
592     glMatrixMode(GL_MODELVIEW);
593   } else {
594     glViewport(0, 0, (GLint)width, (GLint)height);
595     glMatrixMode(GL_PROJECTION);
596     glLoadIdentity();
597     gluPerspective(54.0, (float)width/(float)height, 0.1, 10.0);
598     glMatrixMode(GL_MODELVIEW);
599   }
600 }
601 
602 // Resize window...
603 //-----------------------------------------------------------------------------
resizeGL(int width,int height)604 void GLWidget::resizeGL(int width, int height)
605 {
606   double top = 1.0;
607   double bottom = -1.0;
608   double left = -(double)width / (double)height;
609   double right = (double)width / (double)height;
610   double _near = -10.0;
611   double _far = 10.0;
612 
613   if(stateOrtho) {
614     glViewport(0, 0, (GLint)width, (GLint)height);
615     glMatrixMode(GL_PROJECTION);
616     glLoadIdentity();
617     glOrtho(left, right, bottom, top, _near, _far);
618     glMatrixMode(GL_MODELVIEW);
619   } else {
620     glViewport(0, 0, (GLint)width, (GLint)height);
621     glMatrixMode(GL_PROJECTION);
622     glLoadIdentity();
623     gluPerspective(45.0, (float)width/(float)height, 0.1, 10.0);
624     glMatrixMode(GL_MODELVIEW);
625   }
626 }
627 
628 
629 // Focus in event...
630 //-----------------------------------------------------------------------------
focusInEvent(QFocusEvent * event)631 void GLWidget::focusInEvent(QFocusEvent *event)
632 {
633   Q_UNUSED(event)
634 
635   // Should we check the key pressed status here?
636 }
637 
638 
639 // Key pressed...
640 //-----------------------------------------------------------------------------
keyPressEvent(QKeyEvent * event)641 void GLWidget::keyPressEvent(QKeyEvent *event)
642 {
643   if(event->key() == Qt::Key_Control)
644     ctrlPressed = true;
645 
646   if(event->key() == Qt::Key_Shift)
647     shiftPressed = true;
648 
649   if((event->key() == Qt::Key_Alt) || (event->key() == Qt::Key_AltGr))
650     altPressed = true;
651 
652   if(event->key() == Qt::Key_Escape)
653     emit(escPressed());
654 }
655 
656 
657 // Key released...
658 //-----------------------------------------------------------------------------
keyReleaseEvent(QKeyEvent * event)659 void GLWidget::keyReleaseEvent(QKeyEvent *event)
660 {
661   if(event->key() == Qt::Key_Control)
662     ctrlPressed = false;
663 
664   if(event->key() == Qt::Key_Shift)
665     shiftPressed = false;
666 
667   if(event->key() == Qt::Key_Alt)
668     altPressed = false;
669 }
670 
671 
672 
673 // Mouse button clicked...
674 //-----------------------------------------------------------------------------
mousePressEvent(QMouseEvent * event)675 void GLWidget::mousePressEvent(QMouseEvent *event)
676 {
677   lastPos = event->pos();
678   setFocus();  // for tracing keyboard events
679 }
680 
681 
682 
683 // Mouse wheel rotates...
684 //-----------------------------------------------------------------------------
wheelEvent(QWheelEvent * event)685 void GLWidget::wheelEvent(QWheelEvent *event)
686 {
687   double s = exp((double)(event->delta())*0.001);
688   glScaled(s, s, s);
689   updateGL();
690   lastPos = event->pos();
691   getMatrix();
692 }
693 
694 
695 
696 // Mouse moves...
697 //-----------------------------------------------------------------------------
mouseMoveEvent(QMouseEvent * event)698 void GLWidget::mouseMoveEvent(QMouseEvent *event)
699 {
700   GLint viewport[4];
701   glGetIntegerv(GL_VIEWPORT, viewport);
702 
703   int dx = event->x() - lastPos.x();
704   int dy = event->y() - lastPos.y();
705 
706   dy = -dy;
707 
708   if (((event->buttons() & Qt::LeftButton) &&
709        (event->buttons() & Qt::MidButton)) ) {
710 
711     // Scale:
712     double s = exp(dy*0.01);
713     glScaled(s, s, s);
714     updateGL();
715 
716   } else if (event->buttons() & Qt::LeftButton) {
717 
718     // Rotation:
719     double ax = -(double)dy;
720     double ay =  (double)dx;
721     double az = 0.0;
722 
723     double s = 180.0*sqrt(ax*ax+ay*ay+az*az)/(double)(viewport[3]+1);
724     double bx = invmatrix[0]*ax + invmatrix[4]*ay + invmatrix[8]*az;
725     double by = invmatrix[1]*ax + invmatrix[5]*ay + invmatrix[9]*az;
726     double bz = invmatrix[2]*ax + invmatrix[6]*ay + invmatrix[10]*az;
727     glRotated(s, bx, by, bz);
728     updateGL();
729 
730   } else if (event->buttons() & Qt::MidButton) {
731 
732     // Translation:
733     double s = 2.0/(double)(viewport[3]+1);
734     double ax = s*dx;
735     double ay = s*dy;
736     double az = 0.0;
737     glLoadIdentity();
738     glTranslated(ax, ay, az);
739     glMultMatrixq(matrix);
740     updateGL();
741   }
742 
743   lastPos = event->pos();
744   getMatrix();
745 }
746 
747 
748 
749 // Mouse button double clicked...
750 //-----------------------------------------------------------------------------
mouseDoubleClickEvent(QMouseEvent * event)751 void GLWidget::mouseDoubleClickEvent(QMouseEvent *event)
752 {
753   if(getLists() == 0)
754     return;
755 
756   static list_t dummylist;
757   static GLuint buffer[1024];
758   const int bufferSize = sizeof(buffer)/sizeof(GLuint);
759 
760   GLint viewport[4];
761   GLdouble projection[16];
762 
763   GLint hits;
764   GLint i, j;
765 
766   updateGL();
767 
768   glSelectBuffer(bufferSize, buffer);
769   glRenderMode(GL_SELECT);
770   glInitNames();
771 
772   glMatrixMode(GL_PROJECTION);
773   glPushMatrix();
774   glGetIntegerv(GL_VIEWPORT, viewport);
775   glGetDoublev(GL_PROJECTION_MATRIX, projection);
776   glLoadIdentity();
777 
778   GLdouble x = event->x();
779   GLdouble y = (double)viewport[3]-event->y()-1;
780 
781   GLdouble deltaX = 3.0;
782   GLdouble deltaY = 3.0;
783 
784   gluPickMatrix(x, y, deltaX, deltaY, viewport);
785   glMultMatrixd(projection);
786 
787   glMatrixMode(GL_MODELVIEW);
788 
789   updateGL();
790   // paintGL();
791 
792   hits = glRenderMode(GL_RENDER);
793 
794   bool badDriver = true;
795   GLuint smallestz = DUMMY_NAME;
796   GLuint nearest = DUMMY_NAME;
797 
798   if(hits != 0) {
799     for (i=0, j=0; i<hits; i++) {
800       GLuint minz = buffer[j+1];
801       GLuint resultz = buffer[j+3];
802 
803       badDriver = (badDriver && (minz == 0x80000000));
804 
805       if(minz < smallestz) {
806 	nearest = resultz;
807 	smallestz = minz;
808       }
809 
810       j += 3 + buffer[j];
811     }
812   }
813 
814   glMatrixMode(GL_PROJECTION);
815   glPopMatrix();
816   glMatrixMode(GL_MODELVIEW);
817 
818   if(badDriver) {
819     cerr << "Detected bad GL-context or broken graphics driver" << endl;
820     cerr.flush();
821     cout << "glRenderMode(GL_RENDER) produces bad z-values" << endl;
822     cout << "Unable to reliably select objects" << endl;
823     cout << "Vendor: " << glGetString(GL_VENDOR) << endl;
824     cout << "Renderer: " << glGetString(GL_RENDERER) << endl;
825     cout << "Version: " << glGetString(GL_VERSION) << endl;
826     cout.flush();
827   }
828 
829   // highlight the selected boundary:
830   if(nearest != DUMMY_NAME) {
831     list_t *l = getList(nearest);
832 
833     // skip sharp edge lists
834     if(l->getType() == SHARPEDGELIST)
835       return;
836 
837     // substitute surfacemeshlist with the parent surfacelist:
838     if(l->getType() == SURFACEMESHLIST)
839       l = getList(l->getParent());
840 
841     // if not ctrl pressed, rebuild all selected lists except this one:
842     if(!ctrlPressed) {
843       for(i = 0; i < getLists(); i++) {
844 	list_t *l2 = getList(i);
845 	if(l2->isSelected() && (l2->getIndex() != l->getIndex())) {
846 	  glDeleteLists(l2->getObject(), 1);
847 	  l2->setSelected(false);
848 	  if(l2->getType() == SURFACELIST) {
849             for( int j = 0; j < mesh->getSurfaces(); j++ ) {
850               surface_t *surf = mesh->getSurface(j);
851               if ( surf->getIndex() == l2->getIndex() )
852                 surf->setSelected(l2->isSelected());
853             }
854 	    l2->setObject(generateSurfaceList(l2->getIndex(), surfaceColor)); // cyan
855 	  } else if(l2->getType() == EDGELIST) {
856             for( int j=0; j < mesh->getEdges(); j++ ) {
857               edge_t *edge = mesh->getEdge(j);
858               if ( edge->getIndex() == l2->getIndex() )
859                 edge->setSelected(l2->isSelected());
860             }
861 	    l2->setObject(generateEdgeList(l2->getIndex(), edgeColor)); // green
862 	  }
863 	}
864       }
865     }
866 
867     // Toggle selection:
868     l->setSelected(!l->isSelected());
869 
870     glDeleteLists(l->getObject(), 1);
871 
872     // Highlight current selection:
873     if(l->getType() == SURFACELIST) {
874       if(l->isSelected()) {
875 	l->setObject(generateSurfaceList(l->getIndex(), Qt::red)); // red
876       } else {
877 	l->setObject(generateSurfaceList(l->getIndex(), surfaceColor)); // cyan
878       }
879 
880       for( int i=0; i<mesh->getSurfaces(); i++ ) {
881         surface_t *surf = mesh->getSurface(i);
882         if ( surf->getIndex() == l->getIndex() ) surf->setSelected(l->isSelected());
883       }
884 
885     } else if(l->getType() == EDGELIST) {
886       if(l->isSelected()) {
887 	l->setObject(generateEdgeList(l->getIndex(), Qt::red)); // red
888       } else {
889 	l->setObject(generateEdgeList(l->getIndex(), edgeColor)); // green
890       }
891       for( int i=0; i < mesh->getEdges(); i++ ) {
892         edge_t *edge = mesh->getEdge(i);
893         if ( edge->getIndex() == l->getIndex() ) edge->setSelected(l->isSelected());
894       }
895     }
896 
897     // body selection:
898     //----------------
899     currentlySelectedBody = -1;
900     if(shiftPressed || bodyEditActive) {
901 
902       // determine the max bulk index
903       int MAX_BULK_INDEX = -1;
904 
905       for(int i = 0; i < mesh->getElements(); i++) {
906 	element_t *elem = mesh->getElement(i);
907 	if(elem->getNature() != PDE_BULK)
908 	  break;
909 	if(elem->getIndex() > MAX_BULK_INDEX)
910 	  MAX_BULK_INDEX = elem->getIndex();
911       }
912 
913       for(int i = 0; i < mesh->getSurfaces(); i++) {
914 	surface_t *surf = mesh->getSurface(i);
915 	if(surf->getNature() != PDE_BULK)
916 	  break;
917 	if(surf->getIndex() > MAX_BULK_INDEX)
918 	  MAX_BULK_INDEX = surf->getIndex();
919       }
920 
921       for(int i = 0; i < mesh->getEdges(); i++) {
922 	edge_t *edge = mesh->getEdge(i);
923 	if(edge->getNature() != PDE_BULK)
924 	  break;
925 	if(edge->getIndex() > MAX_BULK_INDEX)
926 	  MAX_BULK_INDEX = edge->getIndex();
927       }
928 
929       MAX_BULK_INDEX++;
930       if(MAX_BULK_INDEX == 0) {
931 	cout << "Error in body selection: "
932 	  "There are no legal body indiced from which to choose" << endl;
933 	cout.flush();
934 	goto body_selection_finished;
935       }
936 
937       // allocate temp arrays:
938       bool *tmp1 = new bool[MAX_BULK_INDEX];
939       bool *tmp2 = new bool[MAX_BULK_INDEX];
940 
941       for(int i = 0; i < MAX_BULK_INDEX; i++) {
942 	tmp1[i] = true;
943 	tmp2[i] = false;
944       }
945 
946       // check if the selected lists uniquely determine a bulk body:
947       for(int i = 0; i < getLists(); i++) {
948 	list_t *l2 = getList(i);
949 
950 	if(l2->isSelected() && (l2->getNature() == PDE_BULK)) {
951 	  for(int j = 0; j < MAX_BULK_INDEX; j++) {
952 	    if(j != l2->getIndex())
953 	      tmp1[j] = false;
954 	  }
955 	}
956 
957 	if(l2->isSelected() && (l2->getNature() == PDE_BOUNDARY) &&
958 	   (l2->getType() == SURFACELIST)) {
959 	  for(int j = 0; j < mesh->getSurfaces(); j++) {
960 	    surface_t *surf = mesh->getSurface(j);
961 	    if(surf->getIndex() == l2->getIndex()) {
962 	      for(int k = 0; k < surf->getElements(); k++) {
963 		int l = surf->getElementIndex(k);
964 		if(l < 0)
965 		  break;
966 		element_t *elem = mesh->getElement(l);
967 		if((elem->getIndex() < 0) || (elem->getIndex() >= MAX_BULK_INDEX))
968 		  break;
969 		tmp2[elem->getIndex()] = true;
970 	      }
971 	      for(int k = 0; k < MAX_BULK_INDEX; k++) {
972 		tmp1[k] &= tmp2[k];
973 		tmp2[k] = false;
974 	      }
975 	    }
976 	  }
977 	}
978       }
979 
980       // array "tmp1" should contain only one entry with value "true"
981       int count = 0;
982       int found = -1;
983       for(int i = 0; i < MAX_BULK_INDEX; i++) {
984 	if( tmp1[i] ) {
985 	  count++;
986 	  found = i;
987 	}
988       }
989 
990       if((count == 1) && (found >= 0))
991 	currentlySelectedBody = found;
992 
993       delete [] tmp1;
994       delete [] tmp2;
995     }
996   body_selection_finished:
997 
998     // Emit result to mainwindow:
999     emit(signalBoundarySelected(l));
1000 
1001   } else {
1002 
1003     // Emit "nothing selected":
1004     dummylist.setNature(-1);
1005     dummylist.setType(-1);
1006     dummylist.setIndex(-1);
1007     emit(signalBoundarySelected(&dummylist));
1008 
1009   }
1010 
1011   updateGL();
1012 }
1013 
1014 
1015 
1016 // Get current matrix and its inverse...
1017 //-----------------------------------------------------------------------------
getMatrix()1018 void GLWidget::getMatrix()
1019 {
1020   glGetQrealv(GL_MODELVIEW_MATRIX, matrix);
1021   helpers->invertMatrix(matrix, invmatrix);
1022 }
1023 
1024 
1025 
1026 // Rebuild lists...
1027 //-----------------------------------------------------------------------------
rebuildLists()1028 void GLWidget::rebuildLists()
1029 {
1030   double *bb = mesh->boundingBox();
1031 
1032   drawTranslate[0] = bb[6]; // x-center
1033   drawTranslate[1] = bb[7]; // y-center
1034   drawTranslate[2] = bb[8]; // z-center
1035   drawScale = bb[9];        // scaling
1036 
1037   delete [] bb;
1038 
1039   if(getLists() > 0) {
1040     for(int i=0; i < getLists(); i++) {
1041       list_t *l = getList(i);
1042       glDeleteLists(l->getObject(), 1);
1043     }
1044   }
1045 
1046   makeLists();
1047 
1048   updateGL();
1049 }
1050 
1051 // Compose GL surface lists...
1052 //-----------------------------------------------------------------------------
rebuildSurfaceLists()1053 void GLWidget::rebuildSurfaceLists()
1054 {
1055   for( int i = 0; i < getLists(); i++ )
1056   {
1057     list_t *l = getList(i);
1058      if( l->getType() == SURFACELIST )
1059      {
1060        glDeleteLists( l->getObject(), 1 );
1061        if(l->isSelected()) {
1062  	 l->setObject(generateSurfaceList(l->getIndex(), Qt::red)); // red
1063        } else {
1064  	 l->setObject(generateSurfaceList(l->getIndex(), surfaceColor)); // cyan
1065        }
1066      }
1067   }
1068 }
1069 
1070 // Compose GL edge lists...
1071 //-----------------------------------------------------------------------------
rebuildEdgeLists()1072 void GLWidget::rebuildEdgeLists()
1073 {
1074   for( int i = 0; i < getLists(); i++ )
1075   {
1076     list_t *l = getList(i);
1077      if ( l->getType() == EDGELIST )
1078      {
1079        glDeleteLists( l->getObject(), 1 );
1080        if(l->isSelected()) {
1081  	 l->setObject(generateEdgeList(l->getIndex(), Qt::red)); // red
1082        } else {
1083  	 l->setObject(generateEdgeList(l->getIndex(), edgeColor)); // green
1084        }
1085      }
1086   }
1087 }
1088 
1089 
1090 
1091 // Compose GL object lists...
1092 //-----------------------------------------------------------------------------
makeLists()1093 GLuint GLWidget::makeLists()
1094 {
1095   int i;
1096   list_t *l;
1097 
1098   if((mesh == NULL) || mesh->isUndefined())
1099     return 0;
1100 
1101   // The rule for composing lists to display is the following:
1102   //---------------------------------------------------------------------------
1103   // - All surface elements with index >= 0 will be drawn - one list/index
1104   //   (list->type = SURFACELIST)
1105   // - For each surface element list, one auxiliary list will be drawn
1106   //   (list->type = SURFACEMESHLIST)
1107   // - All edge elements with index >= 0 will be drawn - one list/index
1108   //   (list->type = EDGELIST)
1109   // - All point elements with index >= 0 will be drawn - one list/index
1110   //   (list->type = POINTLIST)
1111   // - A list of sharp edges will always be drawn (even if it is empty)
1112   //---------------------------------------------------------------------------
1113 
1114   // Simultaneously, populate hash for mapping body & boundary incides:
1115   //--------------------------------------------------------------------
1116   boundaryMap.clear();
1117   bodyMap.clear();
1118   int boundaryCount = 0;
1119   int bodyCount = 0;
1120 
1121   // Scan volume elements to determine the number of material indices:
1122   //-------------------------------------------------------------------
1123   QMap<int, int> bodyNatures;
1124 
1125   for(i = 0; i < mesh->getElements(); i++) {
1126     element_t *element = mesh->getElement(i);
1127     int index = element->getIndex();
1128 
1129     if(index >= 0) {
1130       int nature = element->getNature();
1131 
1132       if(!bodyNatures.contains(index))
1133 	bodyNatures.insert(index, nature);
1134     }
1135   }
1136 
1137   QMapIterator<int, int> itrBody(bodyNatures);
1138   while (itrBody.hasNext()) {
1139     itrBody.next();
1140     int index = itrBody.key();
1141     int nature = itrBody.value();
1142 
1143     if(nature == PDE_BULK)
1144       bodyMap.insert(index, bodyCount++);
1145   }
1146 
1147   // Scan surface elements to determine the number of bcs. / mat. indices:
1148   //-----------------------------------------------------------------------
1149   int surface_bcs = 0;
1150 
1151   QMap<int, int> surfaceNatures;
1152 
1153   for(i = 0; i < mesh->getSurfaces(); i++) {
1154     surface_t *surface = mesh->getSurface(i);
1155     int index = surface->getIndex();
1156 
1157     if(index > 0) {
1158       int nature = surface->getNature();
1159 
1160       if(!surfaceNatures.contains(index))
1161 	surfaceNatures.insert(index, nature);
1162     }
1163   }
1164 
1165   QMapIterator<int, int> itrSurface(surfaceNatures);
1166   while (itrSurface.hasNext()) {
1167     itrSurface.next();
1168     int index = itrSurface.key();
1169     int nature = itrSurface.value();
1170 
1171     if(nature > 0) {
1172       surface_bcs++;
1173 
1174       if(nature == PDE_BULK)
1175 	bodyMap.insert(index, bodyCount++);
1176 
1177       if(nature == PDE_BOUNDARY)
1178 	boundaryMap.insert(index, boundaryCount++);
1179     }
1180   }
1181 
1182   cout << "Bcs/materials on surface elements: " << surface_bcs << endl;
1183   cout.flush();
1184 
1185   // Scan edge elements to determine the number of bcs. / mat. indices:
1186   //--------------------------------------------------------------------
1187   int edge_bcs = 0;
1188 
1189   QMap<int, int> edgeNatures;
1190 
1191   for(i = 0; i < mesh->getEdges(); i++) {
1192     edge_t *edge = mesh->getEdge(i);
1193     int index = edge->getIndex();
1194 
1195     if(index > 0) {
1196       int nature = edge->getNature();
1197 
1198       if(!edgeNatures.contains(index))
1199 	edgeNatures.insert(index, nature);
1200     }
1201   }
1202 
1203   QMapIterator<int, int> itrEdge(edgeNatures);
1204   while (itrEdge.hasNext()) {
1205     itrEdge.next();
1206     int index = itrEdge.key();
1207     int nature = itrEdge.value();
1208 
1209     if(nature > 0) {
1210       edge_bcs++;
1211 
1212       if(nature == PDE_BULK)
1213 	bodyMap.insert(index, bodyCount++);
1214 
1215       if(nature == PDE_BOUNDARY)
1216 	boundaryMap.insert(index, boundaryCount++);
1217     }
1218   }
1219 
1220   cout << "Bcs/materials on edge elements: " << edge_bcs << endl;
1221   cout.flush();
1222 
1223   // Scan point elements to determine the number of bcs. / mat. indices:
1224   //---------------------------------------------------------------------
1225   int point_bcs = 0;
1226 
1227   // TODO
1228 
1229   cout << "Bcs/materials on point elements: " << point_bcs << endl;
1230   cout.flush();
1231 
1232   // Generate lists:
1233   //---------------------------------------------------------------------
1234   for(i = 0; i < getLists(); i++)
1235     delete list.at(i);
1236 
1237   list.clear();
1238 
1239   cout << "Generating  lists to display" << endl;
1240   cout.flush();
1241 
1242   // Surface lists:
1243   //----------------
1244   for(i = 0; i < mesh->getSurfaces(); i++)
1245     mesh->getSurface(i)->setSelected(false);
1246 
1247   itrSurface.toFront();
1248   while (itrSurface.hasNext()) {
1249     itrSurface.next();
1250     int index = itrSurface.key();
1251     int nature = itrSurface.value();
1252 
1253     if(nature > 0) {
1254       l = new list_t;
1255       list.push_back(l);
1256 
1257       l->setNature(nature);
1258       l->setType(SURFACELIST);
1259       l->setIndex(index);
1260       l->setObject(generateSurfaceList(l->getIndex(), surfaceColor)); // cyan
1261       l->setChild(getLists());
1262       l->setParent(-1);
1263       l->setSelected(false);
1264       l->setVisible(stateDrawSurfaceElements);
1265 
1266       // edges of surface elements (just for visual):
1267       l = new list_t;
1268       list.push_back(l);
1269 
1270       l->setNature(PDE_UNKNOWN);
1271       l->setType(SURFACEMESHLIST);
1272       l->setIndex(index);
1273       l->setObject(generateSurfaceMeshList(l->getIndex(), surfaceMeshColor)); // black
1274       l->setChild(-1);
1275       l->setParent(getLists() - 2);
1276       l->setSelected(false);
1277       l->setVisible(stateDrawSurfaceMesh);
1278     }
1279   }
1280 
1281   // Edge lists (only PDE_BOUNDARY):
1282   //---------------------------------
1283   for(i = 0; i < mesh->getEdges(); i++)
1284     mesh->getEdge(i)->setSelected(false);
1285 
1286   itrEdge.toFront();
1287   while (itrEdge.hasNext()) {
1288     itrEdge.next();
1289     int index = itrEdge.key();
1290     int nature = itrEdge.value();
1291 
1292     if(nature > 0) {
1293       l = new list_t;
1294       list.push_back(l);
1295 
1296       l->setNature(nature);
1297       l->setType(EDGELIST);
1298       l->setIndex(index);
1299       l->setObject(generateEdgeList(l->getIndex(), edgeColor)); // green
1300       l->setChild(-1);
1301       l->setParent(-1);
1302       l->setSelected(false);
1303       l->setVisible(stateDrawEdgeElements);
1304     }
1305   }
1306 
1307   // Point lists: TODO
1308 
1309   // Sharp edges (just for visual):
1310   //--------------------------------
1311   l = new list_t;
1312   list.push_back(l);
1313 
1314   l->setNature(PDE_UNKNOWN);
1315   l->setType(SHARPEDGELIST);
1316   l->setIndex(-1);
1317   l->setObject(generateSharpEdgeList(sharpEdgeColor)); // black
1318   l->setChild(-1);
1319   l->setParent(-1);
1320   l->setSelected(false);
1321   l->setVisible(stateDrawSharpEdges);
1322 
1323   // Volume mesh (visual only):
1324   //----------------------------
1325   l = new list_t;
1326   list.push_back(l);
1327 
1328   l->setNature(PDE_UNKNOWN);
1329   l->setType(VOLUMEMESHLIST);
1330   l->setIndex(-1);
1331   l->setObject(generateVolumeMeshList(Qt::black)); // black
1332   l->setChild(-1);
1333   l->setParent(-1);
1334   l->setSelected(false);
1335   l->setVisible(stateDrawVolumeMesh);
1336 
1337   // Clean up:
1338   //-----------
1339   edgeNatures.clear();
1340   surfaceNatures.clear();
1341   bodyNatures.clear();
1342 
1343   updateGL();
1344   getMatrix();
1345 
1346   cout << "Generated " << getLists() << " lists" << endl;
1347   cout.flush();
1348 
1349   return getLists();
1350 }
1351 
1352 
1353 // Generate volume mesh list...
1354 //-----------------------------------------------------------------------------
generateVolumeMeshList(QColor qColor)1355 GLuint GLWidget::generateVolumeMeshList(QColor qColor)
1356 {
1357   static int tetmap[6][2] = {{0, 1}, {0, 2}, {0, 3},
1358 			     {1, 2}, {1, 3}, {2, 3}};
1359 
1360   static int wedgemap[9][2] = {{0, 1}, {1, 2}, {2, 0},
1361 			       {0, 3}, {1, 4}, {2, 5},
1362 			       {3, 4}, {4, 5}, {5, 3}};
1363 
1364 
1365   static int hexmap[12][2] = {{0, 1}, {1, 2}, {2, 3}, {3, 0},
1366 			      {0, 4}, {1, 5}, {2, 6}, {3, 7},
1367 			      {4, 5}, {5, 6}, {6, 7}, {7, 4}};
1368 
1369   double R = qColor.red() / 255.0;
1370   double G = qColor.green() / 255.0;
1371   double B = qColor.blue() / 255.0;
1372 
1373   GLuint current = glGenLists(1);
1374   glNewList(current, GL_COMPILE);
1375 
1376   glBegin(GL_LINES);
1377 
1378   for(int i = 0; i < mesh->getElements(); i++) {
1379     element_t *element = mesh->getElement(i);
1380 
1381     glColor3d(R, G, B);
1382 
1383     int nofEdges = 0;
1384     int *edgeMap = 0;
1385 
1386     switch((int)(element->getCode() / 100)) {
1387     case 5:
1388       nofEdges = 6;
1389       edgeMap = &tetmap[0][0];
1390       break;
1391     case 7:
1392       nofEdges = 9;
1393       edgeMap = &wedgemap[0][0];
1394       break;
1395     case 8:
1396       nofEdges = 12;
1397       edgeMap = &hexmap[0][0];
1398       break;
1399     }
1400 
1401     // draw edges:
1402     for(int j = 0; j < nofEdges; j++) {
1403       int p0 = *edgeMap++;
1404       int p1 = *edgeMap++;
1405 
1406       int q0 = element->getNodeIndex(p0);
1407       int q1 = element->getNodeIndex(p1);
1408 
1409       node_t *n0 = mesh->getNode(q0);
1410       node_t *n1 = mesh->getNode(q1);
1411 
1412       double x0 = ( n0->getX(0) - drawTranslate[0] ) / drawScale;
1413       double y0 = ( n0->getX(1) - drawTranslate[1] ) / drawScale;
1414       double z0 = ( n0->getX(2) - drawTranslate[2] ) / drawScale;
1415 
1416       double x1 = ( n1->getX(0) - drawTranslate[0] ) / drawScale;
1417       double y1 = ( n1->getX(1) - drawTranslate[1] ) / drawScale;
1418       double z1 = ( n1->getX(2) - drawTranslate[2] ) / drawScale;
1419 
1420       glVertex3d(x0, y0, z0);
1421       glVertex3d(x1, y1, z1);
1422     }
1423   }
1424 
1425   glEnd();
1426 
1427   glEndList();
1428 
1429   return current;
1430 }
1431 
1432 
1433 
1434 // Generate surface list...
1435 //-----------------------------------------------------------------------------
generateSurfaceList(int index,QColor qColor)1436 GLuint GLWidget::generateSurfaceList(int index, QColor qColor)
1437 {
1438   double x0[3], x1[3], x2[3], x3[3], u[3];
1439 
1440   double R = qColor.red() / 255.0;
1441   double G = qColor.green() / 255.0;
1442   double B = qColor.blue() / 255.0;
1443 
1444   GLuint current = glGenLists(1);
1445   glNewList(current, GL_COMPILE);
1446 
1447   // Draw triangles:
1448   //-----------------
1449   glBegin(GL_TRIANGLES);
1450 
1451   for(int i=0; i < mesh->getSurfaces(); i++) {
1452     surface_t *surface = mesh->getSurface(i);
1453 
1454     if((surface->getIndex() == index) && ((int)(surface->getCode() / 100) == 3)) {
1455 
1456       glColor3d(R, G, B);
1457 
1458       if(stateBcColors && (surface->getNature() == PDE_BOUNDARY)) {
1459         double c[3];
1460         indexColors(c, index);
1461         glColor3d(c[0], c[1], c[2]);
1462       }
1463 
1464       if(stateBodyColors) {
1465 	int bodyIndex = surface->getIndex();
1466 	if(surface->getNature() == PDE_BOUNDARY) {
1467 	  int parentIndex = surface->getElementIndex(0);
1468 	  element_t *parent = mesh->getElement(parentIndex);
1469 	  bodyIndex = parent->getIndex();
1470 	}
1471         double c[3];
1472         indexColors(c, bodyIndex);
1473         glColor3d(c[0], c[1], c[2]);
1474       }
1475 
1476       // change normal direction:
1477       changeNormalDirection(u, surface->getNormalVec());
1478       glNormal3dv(u);
1479 
1480       int n0 = surface->getNodeIndex(0);
1481       int n1 = surface->getNodeIndex(1);
1482       int n2 = surface->getNodeIndex(2);
1483 
1484       x0[0] = (mesh->getNode(n0)->getX(0) - drawTranslate[0]) / drawScale;
1485       x0[1] = (mesh->getNode(n0)->getX(1) - drawTranslate[1]) / drawScale;
1486       x0[2] = (mesh->getNode(n0)->getX(2) - drawTranslate[2]) / drawScale;
1487 
1488       x1[0] = (mesh->getNode(n1)->getX(0) - drawTranslate[0]) / drawScale;
1489       x1[1] = (mesh->getNode(n1)->getX(1) - drawTranslate[1]) / drawScale;
1490       x1[2] = (mesh->getNode(n1)->getX(2) - drawTranslate[2]) / drawScale;
1491 
1492       x2[0] = (mesh->getNode(n2)->getX(0) - drawTranslate[0]) / drawScale;
1493       x2[1] = (mesh->getNode(n2)->getX(1) - drawTranslate[1]) / drawScale;
1494       x2[2] = (mesh->getNode(n2)->getX(2) - drawTranslate[2]) / drawScale;
1495 
1496       changeNormalDirection(u, surface->getVertexNormalVec(0));
1497       if ( !stateFlatShade ) glNormal3dv(u);
1498       glVertex3dv(x0);
1499 
1500       changeNormalDirection(u, surface->getVertexNormalVec(1));
1501       if ( !stateFlatShade ) glNormal3dv(u);
1502       glVertex3dv(x1);
1503 
1504       changeNormalDirection(u, surface->getVertexNormalVec(2));
1505       if ( !stateFlatShade ) glNormal3dv(u);
1506       glVertex3dv(x2);
1507     }
1508   }
1509 
1510   glEnd();
1511 
1512   // Draw quads:
1513   //------------
1514   glBegin(GL_QUADS);
1515 
1516   for(int i=0; i < mesh->getSurfaces(); i++) {
1517     surface_t *surface = mesh->getSurface(i);
1518 
1519     if((surface->getIndex() == index) && ((int)(surface->getCode() / 100) == 4)) {
1520 
1521       glColor3d(R, G, B);
1522 
1523       if(stateBcColors && (surface->getNature() == PDE_BOUNDARY)) {
1524         double c[3];
1525         indexColors(c, index);
1526         glColor3d(c[0], c[1], c[2]);
1527       }
1528 
1529       if(stateBodyColors) {
1530 	int bodyIndex = surface->getIndex();
1531 	if(surface->getNature() == PDE_BOUNDARY) {
1532 	  int parentIndex = surface->getElementIndex(0);
1533 	  element_t *parent = mesh->getElement(parentIndex);
1534 	  bodyIndex = parent->getIndex();
1535 	}
1536         double c[3];
1537         indexColors(c, bodyIndex);
1538         glColor3d(c[0], c[1], c[2]);
1539       }
1540 
1541       // change normal direction:
1542       changeNormalDirection(u, surface->getNormalVec());
1543       glNormal3dv(u);
1544 
1545       int n0 = surface->getNodeIndex(0);
1546       int n1 = surface->getNodeIndex(1);
1547       int n2 = surface->getNodeIndex(2);
1548       int n3 = surface->getNodeIndex(3);
1549 
1550       x0[0] = (mesh->getNode(n0)->getX(0) - drawTranslate[0]) / drawScale;
1551       x0[1] = (mesh->getNode(n0)->getX(1) - drawTranslate[1]) / drawScale;
1552       x0[2] = (mesh->getNode(n0)->getX(2) - drawTranslate[2]) / drawScale;
1553 
1554       x1[0] = (mesh->getNode(n1)->getX(0) - drawTranslate[0]) / drawScale;
1555       x1[1] = (mesh->getNode(n1)->getX(1) - drawTranslate[1]) / drawScale;
1556       x1[2] = (mesh->getNode(n1)->getX(2) - drawTranslate[2]) / drawScale;
1557 
1558       x2[0] = (mesh->getNode(n2)->getX(0) - drawTranslate[0]) / drawScale;
1559       x2[1] = (mesh->getNode(n2)->getX(1) - drawTranslate[1]) / drawScale;
1560       x2[2] = (mesh->getNode(n2)->getX(2) - drawTranslate[2]) / drawScale;
1561 
1562       x3[0] = (mesh->getNode(n3)->getX(0) - drawTranslate[0]) / drawScale;
1563       x3[1] = (mesh->getNode(n3)->getX(1) - drawTranslate[1]) / drawScale;
1564       x3[2] = (mesh->getNode(n3)->getX(2) - drawTranslate[2]) / drawScale;
1565 
1566       changeNormalDirection(u, surface->getVertexNormalVec(0));
1567       if ( !stateFlatShade ) glNormal3dv(u);
1568       glVertex3dv(x0);
1569 
1570       changeNormalDirection(u, surface->getVertexNormalVec(1));
1571       if ( !stateFlatShade ) glNormal3dv(u);
1572       glVertex3dv(x1);
1573 
1574       changeNormalDirection(u, surface->getVertexNormalVec(2));
1575       if ( !stateFlatShade ) glNormal3dv(u);
1576       glVertex3dv(x2);
1577 
1578       changeNormalDirection(u, surface->getVertexNormalVec(3));
1579       if ( !stateFlatShade ) glNormal3dv(u);
1580       glVertex3dv(x3);
1581     }
1582   }
1583 
1584   glEnd();
1585   glEndList();
1586 
1587   return current;
1588 }
1589 
1590 
1591 
1592 // Generate surface edge list...
1593 //-----------------------------------------------------------------------------
generateSurfaceMeshList(int index,QColor qColor)1594 GLuint GLWidget::generateSurfaceMeshList(int index, QColor qColor)
1595 {
1596   double x0[3], x1[3], x2[3], x3[3];
1597 
1598   double R = qColor.red() / 255.0;
1599   double G = qColor.green() / 255.0;
1600   double B = qColor.blue() / 255.0;
1601 
1602   GLuint current = glGenLists(1);
1603   glNewList(current, GL_COMPILE);
1604 
1605   // Draw lines:
1606   //------------
1607   glLineWidth(1.0);
1608   glDisable(GL_LIGHTING);
1609   glColor3d(R, G, B);
1610   glBegin(GL_LINES);
1611 
1612   for(int i=0; i < mesh->getSurfaces(); i++) {
1613     surface_t *surface = mesh->getSurface(i);
1614 
1615     if((surface->getIndex() == index) && ((int)(surface->getCode() / 100) == 3)) {
1616       int n0 = surface->getNodeIndex(0);
1617       int n1 = surface->getNodeIndex(1);
1618       int n2 = surface->getNodeIndex(2);
1619 
1620       x0[0] = (mesh->getNode(n0)->getX(0) - drawTranslate[0]) / drawScale;
1621       x0[1] = (mesh->getNode(n0)->getX(1) - drawTranslate[1]) / drawScale;
1622       x0[2] = (mesh->getNode(n0)->getX(2) - drawTranslate[2]) / drawScale;
1623 
1624       x1[0] = (mesh->getNode(n1)->getX(0) - drawTranslate[0]) / drawScale;
1625       x1[1] = (mesh->getNode(n1)->getX(1) - drawTranslate[1]) / drawScale;
1626       x1[2] = (mesh->getNode(n1)->getX(2) - drawTranslate[2]) / drawScale;
1627 
1628       x2[0] = (mesh->getNode(n2)->getX(0) - drawTranslate[0]) / drawScale;
1629       x2[1] = (mesh->getNode(n2)->getX(1) - drawTranslate[1]) / drawScale;
1630       x2[2] = (mesh->getNode(n2)->getX(2) - drawTranslate[2]) / drawScale;
1631 
1632       glVertex3dv(x0);
1633       glVertex3dv(x1);
1634 
1635       glVertex3dv(x1);
1636       glVertex3dv(x2);
1637 
1638       glVertex3dv(x2);
1639       glVertex3dv(x0);
1640     }
1641   }
1642 
1643   for(int i=0; i < mesh->getSurfaces(); i++) {
1644     surface_t *surface = mesh->getSurface(i);
1645 
1646     if((surface->getIndex() == index) && ((int)(surface->getCode() / 100) == 4)) {
1647       int n0 = surface->getNodeIndex(0);
1648       int n1 = surface->getNodeIndex(1);
1649       int n2 = surface->getNodeIndex(2);
1650       int n3 = surface->getNodeIndex(3);
1651 
1652       x0[0] = (mesh->getNode(n0)->getX(0) - drawTranslate[0]) / drawScale;
1653       x0[1] = (mesh->getNode(n0)->getX(1) - drawTranslate[1]) / drawScale;
1654       x0[2] = (mesh->getNode(n0)->getX(2) - drawTranslate[2]) / drawScale;
1655 
1656       x1[0] = (mesh->getNode(n1)->getX(0) - drawTranslate[0]) / drawScale;
1657       x1[1] = (mesh->getNode(n1)->getX(1) - drawTranslate[1]) / drawScale;
1658       x1[2] = (mesh->getNode(n1)->getX(2) - drawTranslate[2]) / drawScale;
1659 
1660       x2[0] = (mesh->getNode(n2)->getX(0) - drawTranslate[0]) / drawScale;
1661       x2[1] = (mesh->getNode(n2)->getX(1) - drawTranslate[1]) / drawScale;
1662       x2[2] = (mesh->getNode(n2)->getX(2) - drawTranslate[2]) / drawScale;
1663 
1664       x3[0] = (mesh->getNode(n3)->getX(0) - drawTranslate[0]) / drawScale;
1665       x3[1] = (mesh->getNode(n3)->getX(1) - drawTranslate[1]) / drawScale;
1666       x3[2] = (mesh->getNode(n3)->getX(2) - drawTranslate[2]) / drawScale;
1667 
1668       glVertex3dv(x0);
1669       glVertex3dv(x1);
1670 
1671       glVertex3dv(x1);
1672       glVertex3dv(x2);
1673 
1674       glVertex3dv(x2);
1675       glVertex3dv(x3);
1676 
1677       glVertex3dv(x3);
1678       glVertex3dv(x0);
1679     }
1680   }
1681   glEnd();
1682 
1683   glEnable(GL_LIGHTING);
1684   glEndList();
1685 
1686   return current;
1687 }
1688 
1689 
1690 // Generate edge list...
1691 //-----------------------------------------------------------------------------
generateEdgeList(int index,QColor qColor)1692 GLuint GLWidget::generateEdgeList(int index, QColor qColor)
1693 {
1694   double x0[3], x1[3];
1695 
1696   double R = qColor.red() / 255.0;
1697   double G = qColor.green() / 255.0;
1698   double B = qColor.blue() / 255.0;
1699 
1700   GLuint current = glGenLists(1);
1701   glNewList(current, GL_COMPILE);
1702   glColor3d(R, G, B);
1703   glLineWidth(4.0);
1704   glDisable(GL_LIGHTING);
1705   glBegin(GL_LINES);
1706 
1707   for(int i=0; i < mesh->getEdges(); i++) {
1708     edge_t *edge = mesh->getEdge(i);
1709 
1710     if(edge->getIndex() == index) {
1711       int n0 = edge->getNodeIndex(0);
1712       int n1 = edge->getNodeIndex(1);
1713 
1714       x0[0] = (mesh->getNode(n0)->getX(0) - drawTranslate[0]) / drawScale;
1715       x0[1] = (mesh->getNode(n0)->getX(1) - drawTranslate[1]) / drawScale;
1716       x0[2] = (mesh->getNode(n0)->getX(2) - drawTranslate[2]) / drawScale;
1717 
1718       x1[0] = (mesh->getNode(n1)->getX(0) - drawTranslate[0]) / drawScale;
1719       x1[1] = (mesh->getNode(n1)->getX(1) - drawTranslate[1]) / drawScale;
1720       x1[2] = (mesh->getNode(n1)->getX(2) - drawTranslate[2]) / drawScale;
1721 
1722       glVertex3dv(x0);
1723       glVertex3dv(x1);
1724     }
1725   }
1726 
1727   glEnd();
1728 
1729   glEnable(GL_LIGHTING);
1730   glEndList();
1731 
1732   return current;
1733 }
1734 
1735 
1736 
1737 // Generate sharp edge list...
1738 //-----------------------------------------------------------------------------
generateSharpEdgeList(QColor qColor)1739 GLuint GLWidget::generateSharpEdgeList(QColor qColor)
1740 {
1741   double x0[3], x1[3];
1742 
1743   double R = qColor.red() / 255.0;
1744   double G = qColor.green() / 255.0;
1745   double B = qColor.blue() / 255.0;
1746 
1747   GLuint current = glGenLists(1);
1748   glNewList(current, GL_COMPILE);
1749 
1750   glColor3d(R, G, B);
1751   glLineWidth(1.0);
1752   glDisable(GL_LIGHTING);
1753   glBegin(GL_LINES);
1754 
1755   for(int i=0; i < mesh->getEdges(); i++) {
1756     edge_t *edge = mesh->getEdge(i);
1757 
1758     if(edge->isSharp()) {
1759       int n0 = edge->getNodeIndex(0);
1760       int n1 = edge->getNodeIndex(1);
1761 
1762       x0[0] = (mesh->getNode(n0)->getX(0) - drawTranslate[0]) / drawScale;
1763       x0[1] = (mesh->getNode(n0)->getX(1) - drawTranslate[1]) / drawScale;
1764       x0[2] = (mesh->getNode(n0)->getX(2) - drawTranslate[2]) / drawScale;
1765 
1766       x1[0] = (mesh->getNode(n1)->getX(0) - drawTranslate[0]) / drawScale;
1767       x1[1] = (mesh->getNode(n1)->getX(1) - drawTranslate[1]) / drawScale;
1768       x1[2] = (mesh->getNode(n1)->getX(2) - drawTranslate[2]) / drawScale;
1769 
1770       glVertex3dv(x0);
1771       glVertex3dv(x1);
1772     }
1773   }
1774 
1775   glEnd();
1776   glEnable(GL_LIGHTING);
1777   glEndList();
1778 
1779   return current;
1780 }
1781 
1782 
1783 // Draw coordinates:
1784 //-----------------------------------------------------------------------------
drawCoordinates()1785 void GLWidget::drawCoordinates()
1786 {
1787   glMatrixMode(GL_PROJECTION);
1788   glPushMatrix();
1789 
1790   // glTranslated(-0.8, -0.8, 5.0);
1791   glTranslated(-0.8, -0.8, ZSHIFT);
1792 
1793   glMatrixMode(GL_MODELVIEW);
1794 
1795   // z-axis
1796   glColor3d(0, 0, 1);
1797   gluCylinder(quadric_axis, 0.02, 0.0, 0.2, 8, 8);
1798   renderText(0.0, 0.0, 0.25, "Z");
1799 
1800   // x-axis
1801   glColor3d(1, 0, 0);
1802   glRotated(90, 0, 1, 0);
1803   gluCylinder(quadric_axis, 0.02, 0.0, 0.2, 8, 8);
1804   renderText(0.0, 0.0, 0.25, "X");
1805   glRotated(-90, 0, 1, 0);
1806 
1807   // y-axis
1808   glColor3d(0, 1, 0);
1809   glRotated(-90, 1, 0, 0);
1810   gluCylinder(quadric_axis, 0.02, 0.0, 0.2, 8, 8);
1811   renderText(0.0, 0.0, 0.25, "Y");
1812   glRotated(90, 1, 0, 0);
1813 
1814   glMatrixMode(GL_PROJECTION);
1815   glPopMatrix();
1816 
1817   glMatrixMode(GL_MODELVIEW);
1818 
1819   return;
1820 }
1821 
toggleCoordinates()1822 bool GLWidget::toggleCoordinates()
1823 {
1824   stateDrawCoordinates = !stateDrawCoordinates;
1825   updateGL();
1826   return stateDrawCoordinates;
1827 }
1828 
1829 // Draw background image...
1830 //-----------------------------------------------------------------------------
drawBgImage()1831 void GLWidget::drawBgImage()
1832 {
1833   GLint viewport[4];
1834 
1835   if(!bgTexture) {
1836 #if WITH_QT5
1837     cout << "Bind texture " << string(bgImageFileName.toLatin1()) << "... ";
1838 #else
1839     cout << "Bind texture " << string(bgImageFileName.toAscii()) << "... ";
1840 #endif
1841     QPixmap pixmap(bgImageFileName);
1842     bgSizeX = pixmap.width();
1843     bgSizeY = pixmap.height();
1844     bgTexture = bindTexture(pixmap, GL_TEXTURE_2D);
1845     cout << "done" << endl;
1846   }
1847 
1848   if(!bgTexture) {
1849     cout << "Failed to bind texture" << endl;
1850     stateUseBgImage = false;
1851     return;
1852   }
1853 
1854   glGetIntegerv(GL_VIEWPORT, viewport);
1855 
1856   double relativeSizeX = (double)viewport[2] / (double)viewport[3];
1857   double relativeSizeY = 1.0;
1858 
1859   double bgRelativeSizeX = (double)bgSizeX / (double)viewport[3];
1860   double bgRelativeSizeY = (double)bgSizeY / (double)viewport[3];
1861 
1862   double width = 1.0;
1863   double height = 1.0;
1864   double depth = 9.9;
1865   double xshift = 0.0;
1866   double yshift = 0.0;
1867 
1868   if(stateAlignRightBgImage) {
1869     width = bgRelativeSizeX;
1870     height = bgRelativeSizeY;
1871     xshift = relativeSizeX - bgRelativeSizeX;
1872     yshift = bgRelativeSizeY - relativeSizeY;
1873   }
1874 
1875   if(stateStretchBgImage) {
1876     width = (double)viewport[2] / (double)viewport[3];
1877     height = 1.0;
1878     xshift = 0.0;
1879     yshift = 0.0;
1880   }
1881 
1882   glDisable(GL_DEPTH_TEST);
1883   glPushMatrix();
1884   glLoadIdentity();
1885   glColor3d(1, 1, 1);
1886   glDisable(GL_LIGHTING);
1887   glEnable(GL_TEXTURE_2D);
1888   glBindTexture(GL_TEXTURE_2D, bgTexture);
1889 
1890   glBegin(GL_QUADS);
1891   glTexCoord2d(0, 0);
1892   glVertex3d(-width+xshift, -height+yshift, -depth);
1893   glTexCoord2d(1, 0);
1894   glVertex3d(+width+xshift, -height+yshift, -depth);
1895   glTexCoord2d(1, 1);
1896   glVertex3d(+width+xshift, +height+yshift, -depth);
1897   glTexCoord2d(0, 1);
1898   glVertex3d(-width+xshift, +height+yshift, -depth);
1899   glEnd();
1900 
1901   glDisable(GL_TEXTURE_2D);
1902   glEnable(GL_LIGHTING);
1903   glPopMatrix();
1904   glEnable(GL_DEPTH_TEST);
1905 }
1906 
1907 
1908 // Auxiliary function for changing the direction of a vector...
1909 //---------------------------------------------------------------------------
changeNormalDirection(double * u,double * v)1910 void GLWidget::changeNormalDirection(double *u, double *v)
1911 {
1912   u[0] = -v[0];
1913   u[1] = -v[1];
1914   u[2] = -v[2];
1915 }
1916 
getList(int i) const1917 list_t* GLWidget::getList(int i) const
1918 {
1919   return list.at(i);
1920 }
1921 
getLists() const1922 int GLWidget::getLists() const
1923 {
1924   return list.count();
1925 }
1926 
1927 // Set 'c' to an RGB color corresponding to index 'i'.
1928 // 'c' should be pre-allocated to a length of at least 3.
indexColors(double * c,int i)1929 void GLWidget::indexColors(double *c, int i)
1930 {
1931   c[0] = 0.5 + 0.5 * sin(1.0 * i);
1932   c[1] = 0.5 + 0.5 * cos(2.0 * i);
1933   c[2] = 0.5 + 0.5 * cos(3.0 * i);
1934 }
1935 
indexColors(int * c,int i)1936 void GLWidget::indexColors(int *c, int i)
1937 {
1938   double tmp[3];
1939 
1940   indexColors(tmp, i);
1941   for (int j = 0; j < 3; j++) c[j] = int(tmp[j]*255 + 0.5);
1942 }
1943