1 /*--------------------------------------------------------------------------*/
2 /* ALBERTA: an Adaptive multi Level finite element toolbox using */
3 /* Bisectioning refinement and Error control by Residual */
4 /* Techniques for scientific Applications */
5 /* */
6 /* file: graphXO.c */
7 /* */
8 /* */
9 /* description: simple graphical routines */
10 /* */
11 /*--------------------------------------------------------------------------*/
12 /* */
13 /* authors: Alfred Schmidt */
14 /* Zentrum fuer Technomathematik */
15 /* Fachbereich 3 Mathematik/Informatik */
16 /* Universitaet Bremen */
17 /* Bibliothekstr. 2 */
18 /* D-28359 Bremen, Germany */
19 /* */
20 /* Kunibert G. Siebert */
21 /* Institut fuer Mathematik */
22 /* Universitaet Augsburg */
23 /* Universitaetsstr. 14 */
24 /* D-86159 Augsburg, Germany */
25 /* */
26 /* http://www.mathematik.uni-freiburg.de/IAM/ALBERTA */
27 /* */
28 /* (c) by A. Schmidt and K.G. Siebert (1996-2003) */
29 /* */
30 /*--------------------------------------------------------------------------*/
31
32 #ifdef HAVE_CONFIG_H
33 # include "config.h"
34 #endif
35
36 #include "alberta.h"
37
38 #include <GL/glx.h>
39 #include <GL/gl.h>
40 #include <unistd.h>
41
42 /*---8<---------------------------------------------------------------------*/
43 /*--- standard colors ---*/
44 /*--------------------------------------------------------------------->8---*/
45
46 const GRAPH_RGBCOLOR rgb_black = {0.0,0.0,0.0};
47 const GRAPH_RGBCOLOR rgb_white = {1.0,1.0,1.0};
48 const GRAPH_RGBCOLOR rgb_red = {1.0,0.0,0.0};
49 const GRAPH_RGBCOLOR rgb_green = {0.0,1.0,0.0};
50 const GRAPH_RGBCOLOR rgb_blue = {0.0,0.0,1.0};
51 const GRAPH_RGBCOLOR rgb_yellow = {1.0,1.0,0.0};
52 const GRAPH_RGBCOLOR rgb_magenta = {1.0,0.0,1.0};
53 const GRAPH_RGBCOLOR rgb_cyan = {0.0,1.0,1.0};
54 const GRAPH_RGBCOLOR rgb_grey50 = {0.5,0.5,0.5};
55
56 const GRAPH_RGBCOLOR rgb_albert = {0.433,0.781,0.969};
57 const GRAPH_RGBCOLOR rgb_alberta = {0.000,0.391,0.605};
58
59
60 struct ogl_window
61 {
62 Display *dpy;
63 Window win;
64 GLXContext context;
65 unsigned int width, height;
66 float xmin[MAX(2,DIM_MAX)];
67 float xmax[MAX(2,DIM_MAX)];
68 float diam[MAX(2,DIM_MAX)];
69 Bool doubleBuffered;
70 };
71 typedef struct ogl_window OGL_WINDOW;
72
73 #if DIM_OF_WORLD < 3
74 static Bool opengl_available = True;
75 #endif
76
77 /****************************************************************************/
78
79 #if DIM_OF_WORLD < 3
WaitForNotify(Display * d,XEvent * e,char * arg)80 static Bool WaitForNotify(Display *d, XEvent *e, char *arg)
81 {
82 return (e->type == MapNotify) && (e->xmap.window == (Window)arg);
83 }
84 #endif
85
86 /****************************************************************************/
87
88 #if DIM_OF_WORLD < 3
OGL_set_std_window(OGL_WINDOW * ogl_win)89 static Bool OGL_set_std_window(OGL_WINDOW *ogl_win)
90 {
91 Bool res = false;
92
93 if (ogl_win) {
94
95 res = glXMakeCurrent(ogl_win->dpy, ogl_win->win, ogl_win->context);
96
97 glViewport(0, 0, ogl_win->width, ogl_win->height);
98
99 glMatrixMode(GL_PROJECTION);
100 glLoadIdentity();
101 glMatrixMode(GL_MODELVIEW);
102 glLoadIdentity();
103 glOrtho(ogl_win->xmin[0], ogl_win->xmax[0],
104 ogl_win->xmin[1], ogl_win->xmax[1],
105 -1.0, 1.0);
106 }
107 return res;
108 }
109
110 #define OGL_FLUSH(ogl)\
111 if ((ogl)->doubleBuffered)glXSwapBuffers((ogl)->dpy, ogl->win);else glFlush()
112
113 static int open_info = 0;
114
findVisual(Display * dpy,int screen,Bool * doubleBuffered)115 static XVisualInfo *findVisual(Display *dpy, int screen, Bool *doubleBuffered)
116 {
117 /*
118 * Find a GLX Visual to use.
119 * Order of preference
120 * 24 bit mono double buffered
121 * 24 bit single buffered
122 * any depth double buffered
123 * any depth single buffered
124 */
125 int dblBuf24[] = { GLX_RGBA, GLX_DOUBLEBUFFER,
126 GLX_RED_SIZE, 8, GLX_GREEN_SIZE, 8, GLX_BLUE_SIZE, 8, None };
127 int snglBuf24[] = { GLX_RGBA,
128 GLX_RED_SIZE, 8, GLX_GREEN_SIZE, 8, GLX_BLUE_SIZE, 8, None };
129 int dblBuf[] = { GLX_RGBA, GLX_DOUBLEBUFFER, None };
130 int snglBuf[] = { GLX_RGBA, None };
131
132 XVisualInfo *vi = NULL;
133
134 if ((vi = glXChooseVisual(dpy, screen, dblBuf24)))
135 {
136 INFO(open_info,2,"Using dblBuf24\n");
137 *doubleBuffered = True;
138 return(vi);
139 }
140
141 if ((vi = glXChooseVisual(dpy, screen, snglBuf24)))
142 {
143 *doubleBuffered = False;
144 INFO(open_info,2,"Using snglBuf24\n");
145 return(vi);
146 }
147
148 if ((vi = glXChooseVisual(dpy, screen, dblBuf)))
149 {
150 *doubleBuffered = True;
151 INFO(open_info,2,"Using dblBuf\n");
152 return(vi);
153 }
154
155 if ((vi = glXChooseVisual(dpy, screen, snglBuf)))
156 {
157 INFO(open_info,2,"Using snglBuf\n");
158 *doubleBuffered = False;
159 return(vi);
160 }
161
162 WARNING("can't find visual\n");
163 return(NULL);
164 }
165
createWindow(Display * dpy,int screen,XVisualInfo * vi,const char * name,const char * geom)166 static Window createWindow(Display *dpy, int screen, XVisualInfo *vi,
167 const char *name, const char *geom)
168 {
169 XSetWindowAttributes attributes;
170 unsigned long valuemask = 0;
171 Window root = RootWindow(dpy, screen);
172 Atom delete_window_atom = XInternAtom(dpy, "WM_DELETE_WINDOW", 0);
173 Window window;
174 XSizeHints size_hints;
175 XEvent event;
176 int status;
177 const char *default_geom = "300x300+0+0";
178
179 attributes.colormap = XCreateColormap(dpy, root, vi->visual, AllocNone);
180 if (!attributes.colormap)
181 {
182 WARNING("no color map\n");
183 return(0);
184 }
185 valuemask = CWColormap;
186 valuemask = CWColormap|CWBorderPixel|CWBackPixel;
187
188 size_hints.flags = PResizeInc | PMinSize ;
189 size_hints.width_inc = 1;
190 size_hints.height_inc = 1;
191 size_hints.min_width = 10;
192 size_hints.min_height = 10;
193
194 if (!geom) geom = default_geom;
195
196 status = XGeometry(dpy, vi->screen, (char *) geom, (char *) default_geom,
197 2, 1, 1, 0, 0, &(size_hints.x), &(size_hints.y),
198 &(size_hints.width), &(size_hints.height));
199 if (status & (XValue|YValue))
200 {
201 size_hints.flags |= USPosition;
202 size_hints.flags &= ~PPosition;
203 }
204 if (status & (WidthValue|HeightValue))
205 {
206 size_hints.flags |= USSize;
207 size_hints.flags &= ~PSize;
208 }
209
210 if (size_hints.flags & USSize)
211 {
212 size_hints.flags |= PAspect;
213 size_hints.min_aspect.x = size_hints.width;
214 size_hints.min_aspect.y = size_hints.height;
215 size_hints.max_aspect.x = size_hints.width;
216 size_hints.max_aspect.y = size_hints.height;
217 }
218
219 attributes.border_pixel = 0;
220 attributes.background_pixel = 0;
221 attributes.event_mask = StructureNotifyMask;
222 window = XCreateWindow(dpy, root, size_hints.x, size_hints.y,
223 size_hints.width, size_hints.height, 0, vi->depth,
224 InputOutput, vi->visual, valuemask, &attributes);
225
226 if (!window)
227 {
228 WARNING("couldn't create a window\n");
229 return(0);
230 }
231
232 XSetStandardProperties(dpy, window, name, name, None, NULL, 0, &size_hints);
233 XSelectInput(dpy, window, ExposureMask|StructureNotifyMask);
234
235 XMapWindow(dpy, window);
236
237 XSetWMProtocols(dpy, window, &delete_window_atom, 1);
238 XIfEvent(dpy, &event, WaitForNotify, (char*) window);
239 XStoreName(dpy, window, name);
240
241 return(window);
242 }
243
OGL_create_window(const char * name,const char * geometry)244 static OGL_WINDOW *OGL_create_window(const char *name, const char *geometry)
245 {
246 FUNCNAME("OGL_create_window");
247 Display *dpy;
248 int screen;
249 Window window, root;
250 int dummy;
251 Bool doubleBuffered;
252 XVisualInfo *vi;
253 GLXContext context;
254 unsigned int bwidth, depth;
255 int x, y;
256 OGL_WINDOW * ogl_win;
257
258 if (!(dpy = XOpenDisplay(NULL)))
259 {
260 WARNING("can't open X display\n");
261 return (NULL);
262 }
263 screen = DefaultScreen(dpy);
264
265 if (!(opengl_available = glXQueryExtension(dpy, &dummy, &dummy)))
266 {
267 WARNING("server doesn't support GLX Extension\n");
268 return (NULL);
269 }
270
271 if (!(vi = findVisual(dpy, screen, &doubleBuffered)))
272 return(NULL);
273
274 if (!(window = createWindow(dpy, screen, vi, name, geometry)))
275 return(NULL);
276
277 context = glXCreateContext(dpy, vi, NULL, GL_TRUE);
278
279 XFree(vi);
280
281 if (context == NULL)
282 {
283 WARNING("can't create context\n");
284 return(NULL);
285 }
286
287 if (!glXMakeCurrent(dpy, window, context))
288 {
289 WARNING("glXMakeCurrent failed\n");
290 return (NULL);
291 }
292
293 ogl_win = MEM_ALLOC(1, OGL_WINDOW);
294 ogl_win->dpy = dpy;
295 ogl_win->win = window;
296 ogl_win->context = context;
297 ogl_win->doubleBuffered = doubleBuffered;
298
299 XGetGeometry(dpy, window, &root, &x, &y,
300 &ogl_win->width, &ogl_win->height,
301 &bwidth, &depth);
302
303 return(ogl_win);
304 }
305
306 /****************************************************************************/
307
OGL_destroy_window(OGL_WINDOW * ogl_win)308 static void OGL_destroy_window(OGL_WINDOW *ogl_win)
309 {
310 /* FUNCNAME("OGL_destroy_window"); re-enable when MSG() is used here ... */
311
312 if (!ogl_win) return;
313
314 glXDestroyContext(ogl_win->dpy, ogl_win->context);
315
316 XDestroyWindow(ogl_win->dpy, ogl_win->win);
317 XFlush(ogl_win->dpy);
318
319 MEM_FREE(ogl_win, 1, OGL_WINDOW);
320 }
321
322 /****************************************************************************/
323
OGL_clear_window(OGL_WINDOW * ogl_win,const GRAPH_RGBCOLOR c)324 static void OGL_clear_window(OGL_WINDOW *ogl_win, const GRAPH_RGBCOLOR c)
325 {
326 FUNCNAME("OGL_clear_window");
327
328 Window root;
329 unsigned int w, h, depth, bwidth;
330 int x, y;
331
332 if (!ogl_win) {
333 MSG("no OGL_WINDOW\n");
334 return;
335 }
336
337 OGL_set_std_window(ogl_win);
338
339 /* Has the window size changed? */
340 XGetGeometry(ogl_win->dpy, ogl_win->win,
341 &root, &x, &y, &w, &h, &bwidth, &depth);
342
343 if (w != ogl_win->width || h != ogl_win->height){
344 ogl_win->width = w;
345 ogl_win->height = h;
346 XResizeWindow(ogl_win->dpy, ogl_win->win, w, h);
347 }
348
349 glXMakeCurrent(ogl_win->dpy, ogl_win->win, ogl_win->context);
350
351 glViewport(0, 0, w, h);
352
353 glMatrixMode(GL_PROJECTION);
354 glLoadIdentity();
355 glMatrixMode(GL_MODELVIEW);
356 glLoadIdentity();
357 glOrtho(ogl_win->xmin[0], ogl_win->xmax[0],
358 ogl_win->xmin[1], ogl_win->xmax[1],
359 -1.0, 1.0);
360
361 if (c)
362 glClearColor(c[0], c[1], c[2], 1.0);
363 else
364 glClearColor(1.0, 1.0, 1.0, 1.0);
365
366 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
367 OGL_FLUSH(ogl_win);
368 }
369 #endif
370
371 /****************************************************************************/
372
373 /****************************************************************************/
374 /* Common graphic routines available to the user */
375 /****************************************************************************/
376
377 #if DIM_OF_WORLD == 1
378 #include "graphXO_1d.c"
379 #endif
380 #if DIM_OF_WORLD == 2
381 #include "graphXO_2d.c"
382 #endif
383
graph_open_window(const char * title,const char * geometry,REAL * world,MESH * mesh)384 GRAPH_WINDOW graph_open_window(const char *title, const char *geometry,
385 REAL *world, MESH *mesh)
386 {
387 FUNCNAME("graph_open_window");
388
389 switch(mesh->dim) {
390 #if DIM_OF_WORLD == 1
391 case 1:
392 return graph_open_window_1d(title, geometry, world, mesh);
393 #endif
394 #if DIM_OF_WORLD == 2
395 case 2:
396 return graph_open_window_2d(title, geometry, world, mesh);
397 #endif
398 case 3:
399 ERROR("Not implemented for dim == 3!\n");
400 return 0;
401 default:
402 ERROR_EXIT("Illegal mesh->dim: must equal DIM_OF_WORLD\n");
403 }
404
405 return 0;
406 }
407
408
graph_close_window(GRAPH_WINDOW win)409 void graph_close_window(GRAPH_WINDOW win)
410 {
411 #if DIM_OF_WORLD==1
412 graph_close_window_1d(win);
413 #elif DIM_OF_WORLD==2
414 graph_close_window_2d(win);
415 #else
416 ERROR("Not implemented for dim == 3!\n");
417 #endif
418 return;
419 }
420
421
graph_clear_window(GRAPH_WINDOW win,const GRAPH_RGBCOLOR c)422 void graph_clear_window(GRAPH_WINDOW win, const GRAPH_RGBCOLOR c)
423 {
424 #if DIM_OF_WORLD==1
425 graph_clear_window_1d(win, c);
426 #elif DIM_OF_WORLD==2
427 graph_clear_window_2d(win, c);
428 #else
429 ERROR("Not implemented for dim == 3!\n");
430 #endif
431 return;
432 }
433
434
graph_mesh(GRAPH_WINDOW win,MESH * mesh,const GRAPH_RGBCOLOR c,FLAGS flag)435 void graph_mesh(GRAPH_WINDOW win, MESH *mesh, const GRAPH_RGBCOLOR c,
436 FLAGS flag)
437 {
438 FUNCNAME("graph_mesh");
439
440 switch(mesh->dim) {
441 #if DIM_OF_WORLD == 1
442 case 1:
443 if(DIM_OF_WORLD != 1) {
444 ERROR("dim must equal DIM_OF_WORLD == %d!\n", DIM_OF_WORLD);
445 return;
446 }
447 graph_mesh_1d(win, mesh, c, flag);
448 break;
449 #endif
450 #if DIM_OF_WORLD == 2
451 case 2:
452 if(DIM_OF_WORLD != 2) {
453 ERROR("dim must equal DIM_OF_WORLD == %d!\n", DIM_OF_WORLD);
454 return;
455 }
456 graph_mesh_2d(win, mesh, c, flag);
457 break;
458 #endif
459 case 3:
460 ERROR("Not implemented for dim == 3!\n");
461 return;
462 default:
463 ERROR_EXIT("Illegal dim!\n");
464 }
465 }
466
graph_drv(GRAPH_WINDOW win,const DOF_REAL_VEC * u,REAL min,REAL max,int refine)467 void graph_drv(GRAPH_WINDOW win, const DOF_REAL_VEC *u,
468 REAL min, REAL max, int refine)
469 {
470 FUNCNAME("graph_drv");
471
472 TEST_EXIT(u && u->fe_space && u->fe_space->admin && u->fe_space->admin->mesh,
473 "no vec or fe_space or admin or mesh!\n");
474
475 switch(u->fe_space->admin->mesh->dim) {
476 #if DIM_OF_WORLD == 1
477 case 1:
478 if(DIM_OF_WORLD != 1) {
479 ERROR("dim must equal DIM_OF_WORLD == %d!\n", DIM_OF_WORLD);
480 return;
481 }
482 graph_drv_1d(win, u, min, max, refine, NULL);
483 break;
484 #endif
485 #if DIM_OF_WORLD == 2
486 case 2:
487 if(DIM_OF_WORLD != 2) {
488 ERROR("dim must equal DIM_OF_WORLD == %d!\n", DIM_OF_WORLD);
489 return;
490 }
491 graph_drv_2d(win, u, min, max, refine);
492 break;
493 #endif
494 case 3:
495 ERROR("Not implemented for dim == 3!\n");
496 return;
497 default:
498 ERROR_EXIT("Illegal dim!\n");
499 }
500 }
501
graph_drv_d(GRAPH_WINDOW win,const DOF_REAL_D_VEC * ud,REAL min,REAL max,int refine)502 void graph_drv_d(GRAPH_WINDOW win, const DOF_REAL_D_VEC *ud,
503 REAL min, REAL max, int refine)
504 {
505 FUNCNAME("graph_drv_d");
506
507 TEST_EXIT(ud && ud->fe_space && ud->fe_space->admin && ud->fe_space->admin->mesh,
508 "no vec or fe_space or admin or mesh!\n");
509
510 switch(ud->fe_space->admin->mesh->dim) {
511 #if DIM_OF_WORLD == 1
512 case 1:
513 if(DIM_OF_WORLD != 1) {
514 ERROR("dim must equal DIM_OF_WORLD == %d!\n", DIM_OF_WORLD);
515 return;
516 }
517 graph_drv_d_1d(win, ud, min, max, refine, NULL);
518 break;
519 #endif
520 #if DIM_OF_WORLD ==2
521 case 2:
522 if(DIM_OF_WORLD != 2) {
523 ERROR("dim must equal DIM_OF_WORLD == %d!\n", DIM_OF_WORLD);
524 return;
525 }
526 graph_drv_d_2d(win, ud, min, max, refine);
527 break;
528 #endif
529 case 3:
530 ERROR("Not implemented for dim == 3!\n");
531 return;
532 default:
533 ERROR_EXIT("Illegal dim!\n");
534 }
535 }
536
graph_el_est(GRAPH_WINDOW win,MESH * mesh,REAL (* get_est)(EL *),REAL min,REAL max)537 void graph_el_est(GRAPH_WINDOW win, MESH *mesh, REAL (*get_est)(EL *),
538 REAL min, REAL max)
539 {
540 FUNCNAME("graph_drv_d");
541
542 if(!mesh) {
543 ERROR("No mesh given!\n");
544 return;
545 }
546
547 switch(mesh->dim) {
548 #if DIM_OF_WORLD == 1
549 case 1:
550 if(DIM_OF_WORLD != 1) {
551 ERROR("dim must equal DIM_OF_WORLD == %d!\n", DIM_OF_WORLD);
552 return;
553 }
554 graph_el_est_1d(win, mesh, get_est, min, max, NULL);
555 break;
556 #endif
557 #if DIM_OF_WORLD == 2
558 case 2:
559 if(DIM_OF_WORLD != 2) {
560 ERROR("dim must equal DIM_OF_WORLD == %d!\n", DIM_OF_WORLD);
561 return;
562 }
563 graph_el_est_2d(win, mesh, get_est, min, max);
564 break;
565 #endif
566 case 3:
567 ERROR("Not implemented for dim == 3!\n");
568 return;
569 default:
570 ERROR_EXIT("Illegal dim!\n");
571 }
572 }
573
574 /****************************************************************************/
575
graph_point(GRAPH_WINDOW win,const REAL p0[2],const GRAPH_RGBCOLOR c,float ps)576 void graph_point(GRAPH_WINDOW win, const REAL p0[2], const GRAPH_RGBCOLOR c,
577 float ps)
578 {
579 #if DIM_OF_WORLD >= 3
580 FUNCNAME("graph_point");
581
582 ERROR("Not implemented for dim == 3!\n");
583 #else
584 OGL_WINDOW *ogl_win = (OGL_WINDOW *)win;
585
586 OGL_set_std_window(ogl_win);
587
588 glColor3fv(c ? c : rgb_black);
589 glPointSize(ps > 0 ? ps : 1.0);
590
591 glBegin(GL_POINTS);
592 glVertex2d(p0[0], p0[1]);
593 glEnd();
594
595 OGL_FLUSH(ogl_win);
596 #endif
597 return;
598 }
599
600
graph_points(GRAPH_WINDOW win,int np,REAL (* p)[2],const GRAPH_RGBCOLOR c,float ps)601 void graph_points(GRAPH_WINDOW win, int np, REAL (*p)[2],
602 const GRAPH_RGBCOLOR c, float ps)
603 {
604 #if DIM_OF_WORLD >= 3
605 FUNCNAME("graph_points");
606
607 ERROR("Not implemented for dim == 3!\n");
608 #else
609 int i;
610 OGL_WINDOW *ogl_win = (OGL_WINDOW *)win;
611
612 OGL_set_std_window(ogl_win);
613
614 glColor3fv(c ? c : rgb_black);
615 glPointSize(ps > 0 ? ps : 1.0);
616
617 glBegin(GL_POINTS);
618 for (i = 0; i < np; i++)
619 glVertex2d(p[i][0], p[i][1]);
620
621 glEnd();
622
623 OGL_FLUSH(ogl_win);
624 #endif
625
626 return;
627 }
628
629 /****************************************************************************/
630
graph_line(GRAPH_WINDOW win,const REAL p0[2],const REAL p1[2],const GRAPH_RGBCOLOR c,float lw)631 void graph_line(GRAPH_WINDOW win, const REAL p0[2], const REAL p1[2],
632 const GRAPH_RGBCOLOR c, float lw)
633 {
634 #if DIM_OF_WORLD >= 3
635 FUNCNAME("graph_line");
636
637 ERROR("Not implemented for dim == 3!\n");
638 #else
639 float xy[2];
640 int j;
641 OGL_WINDOW *ogl_win = (OGL_WINDOW *)win;
642
643 OGL_set_std_window(ogl_win);
644
645 glColor3fv(c ? c : rgb_black);
646 glLineWidth(lw > 0 ? lw : 1.0);
647
648 glBegin(GL_LINE_STRIP);
649 for (j=0; j<2; j++) xy[j] = p0[j];
650 glVertex2fv(xy);
651 for (j=0; j<2; j++) xy[j] = p1[j];
652 glVertex2fv(xy);
653 glEnd();
654
655 OGL_FLUSH(ogl_win);
656 #endif
657
658 return;
659 }
660