Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
ElmerCSC
GitHub Repository: ElmerCSC/elmerfem
Path: blob/devel/matc/src/c3d.c
3196 views
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 library is free software; you can redistribute it and/or
8
* modify it under the terms of the GNU Lesser General Public
9
* License as published by the Free Software Foundation; either
10
* version 2.1 of the License, or (at your option) any later version.
11
*
12
* This library 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 GNU
15
* Lesser General Public License for more details.
16
*
17
* You should have received a copy of the GNU Lesser General Public
18
* License along with this library (in file ../LGPL-2.1); if not, write
19
* to the Free Software Foundation, Inc., 51 Franklin Street,
20
* Fifth Floor, Boston, MA 02110-1301 USA
21
*
22
*****************************************************************************/
23
24
/*******************************************************************************
25
*
26
* MATC surface display routines.
27
*
28
*******************************************************************************
29
*
30
* Author: Juha Ruokolainen
31
*
32
* Address: CSC - IT Center for Science Ltd.
33
* Keilaranta 14, P.O. BOX 405
34
* 02101 Espoo, Finland
35
* Tel. +358 0 457 2723
36
* Telefax: +358 0 457 2302
37
* EMail: [email protected]
38
*
39
* Date: 30 May 1996
40
*
41
* Modified by:
42
*
43
* Date of modification:
44
*
45
******************************************************************************/
46
/***********************************************************************
47
|
48
| Written ??-???-88 / JPR
49
| Last edited 16-FEB-89 / OP
50
|
51
* File: c3d
52
^
53
| USING THE C3D (preliminary)
54
|
55
| Full usage will be included later!
56
|
57
^**********************************************************************/
58
59
60
/*
61
* $Id: c3d.c,v 1.2 2005/05/27 12:26:14 vierinen Exp $
62
*
63
* $Log: c3d.c,v $
64
* Revision 1.2 2005/05/27 12:26:14 vierinen
65
* changed header install location
66
*
67
* Revision 1.1.1.1 2005/04/14 13:29:14 vierinen
68
* initial matc automake package
69
*
70
* Revision 1.2 1998/08/01 12:34:30 jpr
71
*
72
* Added Id, started Log.
73
*
74
*
75
*/
76
77
#include "elmer/matc.h"
78
79
#define C3D_MASK 9
80
#define C3D_HALFMASK (1 << (C3D_MASK - 1))
81
82
/***********************************************************************
83
Typedefinitions for panel tree
84
***********************************************************************/
85
struct node
86
{
87
int x, y, z, d;
88
};
89
90
struct element
91
{
92
struct node *node[4];
93
int d, z;
94
};
95
96
struct el_tree
97
{
98
struct el_tree *left, *right;
99
struct element *entry;
100
};
101
102
void C3D_Contour(double *, int, int);
103
void C3D_Levels(int);
104
105
void C3D_Show_Tri(int *, int *, int *d);
106
void C3D_Show_Elem(struct element *el);
107
void C3D_SelCol(int);
108
109
void C3D_Show_El_Tree(struct el_tree *head);
110
void C3D_Add_El_Tree(struct el_tree *head, struct el_tree *add);
111
112
void C3D_Pcalc(int, int, int, int, int, int, int *, int *, int *,int *);
113
void C3D_AreaFill(int, int, int *, int *);
114
115
VARIABLE *c3d_gc3d(VARIABLE *var)
116
{
117
C3D_Contour(MATR(var), NROW(var), NCOL(var));
118
return (VARIABLE *)NULL;
119
}
120
121
VARIABLE *c3d_gc3dlevels(VARIABLE *var)
122
{
123
C3D_Levels((int)*MATR(var));
124
return (VARIABLE *)NULL;
125
}
126
127
/***********************************************************************
128
Globals needed for C3D All start with the prefix c3d_
129
***********************************************************************/
130
static int c3d_clevels = 10,
131
c3d_perspective = FALSE;
132
#pragma omp threadprivate (c3d_clevels, c3d_perspective)
133
134
/***********************************************************************
135
void C3D_Contour(matrix, nr, nc) double *matrix; int nr, nc;
136
? Main function to be used.
137
| This function displays a matrix seen from the current C3D-viewpoint
138
| and with number of levels selected.
139
|
140
| NOTICE! CALL FROM FORTRAN:
141
|
142
| CALL C3D_Contour( a , %val( DIMY ) , %val( DIMX ) )
143
|
144
| The a should be of type double precision (or REAL*8 in VAX/VMS)
145
| and the dimensions are in reverse order
146
! No error messages are generated
147
& C3D...
148
***********************************************************************/
149
void C3D_Contour(double *matrix, int nr, int nc)
150
{
151
double xmin, xmax, ymin, ymax, dmin, dmax;
152
double x, y, z, d, xs, ys, zs;
153
154
struct el_tree *tr, *trb, *element_el_tree = NULL;
155
struct element *el, *elements = NULL;
156
struct node *nodes = NULL;
157
158
GMATRIX gm;
159
160
static GMATRIX ident =
161
{
162
1, 0, 0, 0,
163
0, 1, 0, 0,
164
0, 0, 1, 0,
165
0, 0, 0, 1
166
};
167
#pragma omp threadprivate (ident)
168
169
int i, j, k, n;
170
171
nodes = (struct node *)ALLOCMEM(nr * nc * sizeof(struct node));
172
173
xmin = ymin = dmin = 1.0e20;
174
xmax = ymax = dmax = -1.0e20;
175
176
for(i = 0, n = 0; i < nr; i++)
177
for(j = 0; j < nc; j++, n++) {
178
z = matrix[n]; dmin = min(dmin, z); dmax = max(dmax, z);
179
}
180
181
for(i = 0, n = 0; i < nr; i++)
182
for(j = 0; j < nc; j++, n++)
183
{
184
x = 2 * (double)i / (double)nr - 1;
185
y = 2 * (double)j / (double)nc - 1;
186
d = (matrix[n] - dmin) / (dmax - dmin);
187
z = 2 * d - 1;
188
gra_mtrans(x, y, z, &xs, &ys, &zs);
189
xs *= (1 << 20);
190
ys *= (1 << 20);
191
zs *= (1 << 20);
192
nodes[n].x = xs;
193
nodes[n].y = ys;
194
nodes[n].z = zs;
195
nodes[n].d = (c3d_clevels * d + 1) * (1 << C3D_MASK);
196
xmin = min(xmin, xs);
197
xmax = max(xmax, xs);
198
ymin = min(ymin, ys);
199
ymax = max(ymax, ys);
200
}
201
202
for(i = 0, n = 0; i < nr; i++)
203
for(j = 0; j < nc; j++, n++)
204
{
205
nodes[n].x = 4095 * (nodes[n].x-xmin) / (xmax-xmin);
206
nodes[n].y = 4095 * (nodes[n].y-ymin) / (ymax-ymin);
207
}
208
209
elements = (struct element *)
210
ALLOCMEM((nr - 1) * (nc - 1) * sizeof(struct element));
211
212
trb = (struct el_tree *)
213
ALLOCMEM((nr -1) * (nc - 1) * sizeof(struct el_tree));
214
215
for(i = 0, n = 0; i < nr - 1; i++)
216
for(j = 0; j < nc - 1; j++, n++) {
217
tr = &trb[n];
218
el = tr -> entry = &elements[n];
219
el -> node[0] = &nodes[nc*i + j];
220
el -> node[1] = &nodes[nc*(i+1) + j];
221
el -> node[2] = &nodes[nc*(i+1) + j + 1];
222
el -> node[3] = &nodes[nc*i + j + 1];
223
el -> d = 0; el -> z = 0;
224
for(k = 0; k < 4; k++) {
225
el -> d += el -> node[k] -> d;
226
el -> z += el -> node[k] -> z;
227
}
228
el -> d = (el -> d + 2) >> 2;
229
tr -> left = tr -> right = NULL;
230
if (element_el_tree == NULL)
231
element_el_tree = tr;
232
else
233
C3D_Add_El_Tree(element_el_tree, tr);
234
}
235
236
GRA_GETMATRIX(gm);
237
GRA_SETMATRIX(ident);
238
GRA_WINDOW(0.0,4096.0,0.0,4096.0,-1.0,1.0);
239
240
C3D_Show_El_Tree(element_el_tree);
241
242
if (gra_state.pratio>0)
243
GRA_PERSPECTIVE(gra_state.pratio);
244
GRA_SETMATRIX(gm);
245
GRA_FLUSH();
246
247
FREEMEM(elements);
248
FREEMEM(trb);
249
FREEMEM(nodes);
250
}
251
252
void C3D_Levels(int levels)
253
/***********************************************************************
254
| Set the number of colorlevels to be used in coloring
255
| use 0 for singlecolor hidden surface plot
256
! Number of levels must be between 0 - 13
257
^**********************************************************************/
258
{
259
if (levels >= 0)
260
c3d_clevels = levels;
261
else
262
error("C3D_Levels: level parameter negative, not changed.\n");
263
}
264
265
void C3D_Persp(int tf)
266
/***********************************************************************
267
| Use perspective or orthogonal transformation ?
268
! Number of levels must be between 0 - 13
269
^**********************************************************************/
270
{
271
c3d_perspective = tf;
272
}
273
274
void C3D_Add_El_Tree(struct el_tree *head, struct el_tree *add)
275
/***********************************************************************
276
| Add a single element into the current leaf of the element tree
277
| Only internal use
278
^**********************************************************************/
279
{
280
if (add -> entry -> z > head -> entry -> z) {
281
if (head -> left == NULL) {
282
head -> left = add;
283
}
284
else {
285
C3D_Add_El_Tree(head -> left, add);
286
}
287
}
288
else if (add -> entry -> z < head -> entry -> z) {
289
if (head -> right == NULL) {
290
head -> right = add;
291
}
292
else {
293
C3D_Add_El_Tree(head -> right, add);
294
}
295
}
296
else {
297
add -> left = head -> left;
298
head -> left = add;
299
}
300
}
301
302
void C3D_Show_El_Tree(struct el_tree *head)
303
/***********************************************************************
304
| Display the contents of the current leaf of the element tree
305
| Only internal use
306
^**********************************************************************/
307
{
308
if (head == NULL) return;
309
C3D_Show_El_Tree(head->left);
310
C3D_Show_Elem(head->entry);
311
C3D_Show_El_Tree(head->right);
312
}
313
314
void C3D_Free_El_Tree(struct el_tree *head)
315
/***********************************************************************
316
| Free the memory allocated to the current leaf of the element tree
317
| Only internal use
318
^**********************************************************************/
319
{
320
if (head == NULL) return;
321
C3D_Free_El_Tree(head->left);
322
C3D_Free_El_Tree(head->right);
323
FREEMEM(head);
324
}
325
326
int C3D_Convex_Test(int x[], int y[])
327
/***********************************************************************
328
| Test four-node polygon
329
| Only internal use
330
^**********************************************************************/
331
{
332
int a1, a2, at1, at2, amax, aind;
333
334
amax = abs(y[0]*(x[2]-x[1])+y[1]*(x[0]-x[2])+y[2]*(x[1]-x[0]));
335
aind = 3;
336
337
at1 = abs(y[2]*(x[0]-x[3])+y[3]*(x[2]-x[0])+y[0]*(x[3]-x[2]));
338
339
a1 = amax + at1;
340
341
if (at1 > amax) {
342
amax = at1; aind = 1;
343
}
344
345
at1 = abs(y[1]*(x[3]-x[2])+y[2]*(x[1]-x[3])+y[3]*(x[2]-x[1]));
346
347
if (at1 > amax) {
348
amax = at1; aind = 0;
349
}
350
351
at2 = abs(y[3]*(x[1]-x[0])+y[0]*(x[3]-x[1])+y[1]*(x[0]-x[3]));
352
353
if (at2 > amax) {
354
aind = 2;
355
}
356
357
a2 = at1 + at2;
358
359
if (a1 == a2) return -1;
360
361
return aind;
362
}
363
364
void C3D_Show_Elem(struct element *el)
365
/***********************************************************************
366
| Display a single element by coloring and transformation
367
| Only internal use
368
^**********************************************************************/
369
{
370
int x[5], y[5], z[5], zz, xp, yp;
371
int xi[5], yi[5], i;
372
int d[5], zp, col[3];
373
374
Point p[5];
375
376
for(i = 0; i != 4; i++)
377
{
378
x[i] = el -> node[i] -> x;
379
y[i] = el -> node[i] -> y;
380
d[i] = el -> node[i] -> d;
381
}
382
383
if ((d[0]>>C3D_MASK) == (d[1]>>C3D_MASK) &&
384
(d[0]>>C3D_MASK) == (d[2]>>C3D_MASK) &&
385
(d[0]>>C3D_MASK) == (d[3]>>C3D_MASK))
386
{
387
C3D_SelCol(d[0]>>C3D_MASK);
388
C3D_AreaFill(4, TRUE, x, y);
389
return;
390
}
391
392
switch(C3D_Convex_Test(x,y))
393
{
394
case 0:
395
C3D_Show_Tri(x, y, d);
396
xi[0] = x[2]; xi[1] = x[3]; xi[2] = x[0];
397
yi[0] = y[2]; yi[1] = y[3]; yi[2] = y[0];
398
col[0] = d[2]; col[1] = d[3]; col[2] = d[0];
399
C3D_Show_Tri(xi, yi, col);
400
break;
401
402
case 1:
403
C3D_Show_Tri(&x[1], &y[1], &d[1]);
404
xi[0] = x[0]; xi[1] = x[1]; xi[2] = x[3];
405
yi[0] = y[0]; yi[1] = y[1]; yi[2] = y[3];
406
col[0] = d[0]; col[1] = d[1]; col[2] = d[3];
407
C3D_Show_Tri(xi, yi, col);
408
break;
409
410
case 2:
411
C3D_Show_Tri(x, y, d);
412
xi[0] = x[2]; xi[1] = x[3]; xi[2] = x[0];
413
yi[0] = y[2]; yi[1] = y[3]; yi[2] = y[0];
414
col[0] = d[2]; col[1] = d[3]; col[2] = d[0];
415
C3D_Show_Tri(xi, yi, col);
416
break;
417
418
case 3:
419
C3D_Show_Tri(&x[1], &y[1], &d[1]);
420
xi[0] = x[0]; xi[1] = x[1]; xi[2] = x[3];
421
yi[0] = y[0]; yi[1] = y[1]; yi[2] = y[3];
422
col[0] = d[0]; col[1] = d[1]; col[2] = d[3];
423
C3D_Show_Tri(xi, yi, col);
424
break;
425
426
default:
427
xp = 0; yp = 0;
428
for(i = 0; i != 4; i++)
429
{
430
xp += x[i]; yp += y[i];
431
}
432
xp = (xp + 2) >> 2; yp = (yp + 2) >> 2;
433
zp = el -> d;
434
435
xi[0] = x[0]; xi[1] = x[1]; xi[2] = xp;
436
yi[0] = y[0]; yi[1] = y[1]; yi[2] = yp;
437
col[0] = d[0]; col[1] = d[1]; col[2] = zp;
438
C3D_Show_Tri(xi, yi, col);
439
440
xi[0] = x[1]; xi[1] = x[2];
441
yi[0] = y[1]; yi[1] = y[2];
442
col[0] = d[1]; col[1] = d[2];
443
C3D_Show_Tri(xi, yi, col);
444
445
xi[0] = x[2]; xi[1] = x[3];
446
yi[0] = y[2]; yi[1] = y[3];
447
col[0] = d[2]; col[1] = d[3];
448
C3D_Show_Tri(xi, yi, col);
449
450
xi[0] = x[3]; xi[1] = x[0];
451
yi[0] = y[3]; yi[1] = y[0];
452
col[0] = d[3]; col[1] = d[0];
453
C3D_Show_Tri(xi, yi, col);
454
break;
455
}
456
457
p[0].x = (int)(x[0]+0.5); p[0].y = (int)(y[0]+0.5); p[0].z = 0.0;
458
p[1].x = (int)(x[1]+0.5); p[1].y = (int)(y[1]+0.5); p[1].z = 0.0;
459
p[2].x = (int)(x[2]+0.5); p[2].y = (int)(y[2]+0.5); p[2].z = 0.0;
460
p[3].x = (int)(x[3]+0.5); p[3].y = (int)(y[3]+0.5); p[3].z = 0.0;
461
p[4].x = (int)(x[0]+0.5); p[4].y = (int)(y[0]+0.5); p[4].z = 0.0;
462
GRA_COLOR(1);
463
GRA_POLYLINE(5, p);
464
}
465
466
void C3D_Show_Tri(int x[3], int y[3], int d[3])
467
/***********************************************************************
468
| Only internal use
469
^**********************************************************************/
470
{
471
int xx[128], yy[128], dd[128], px[7], py[7];
472
int i, j, k, n = 0;
473
474
if ((d[0] >> C3D_MASK) == (d[1] >> C3D_MASK) &&
475
(d[0] >> C3D_MASK) == (d[2] >> C3D_MASK))
476
{
477
C3D_SelCol(d[0] >> C3D_MASK);
478
C3D_AreaFill(3, FALSE, x, y);
479
return;
480
}
481
482
C3D_Pcalc(x[0],y[0],d[0],x[1],y[1],d[1],&i,&xx[n],&yy[n],&dd[n]); n += i;
483
C3D_Pcalc(x[1],y[1],d[1],x[2],y[2],d[2],&i,&xx[n],&yy[n],&dd[n]); n += i;
484
C3D_Pcalc(x[2],y[2],d[2],x[0],y[0],d[0],&i,&xx[n],&yy[n],&dd[n]); n += i;
485
486
for(i = 0; i < 2; i++)
487
{
488
xx[n+i] = xx[i];
489
yy[n+i] = yy[i];
490
dd[n+i] = dd[i];
491
}
492
493
for(i = 0, k = 0; i < n - 2; k = 0, i++)
494
{
495
px[k] = xx[i]; py[k++] = yy[i];
496
px[k] = xx[i+1]; py[k++] = yy[i+1];
497
498
if (dd[i] == dd[i+1]) {
499
i++; px[k] = xx[i+1]; py[k++] = yy[i+1];
500
}
501
502
for(j = n - 1; j > i; j--) {
503
if (dd[i] == dd[j]) {
504
if (dd[j-1] == dd[j]) {
505
px[k] = xx[j-1]; py[k++] = yy[j-1];
506
}
507
px[k] = xx[j]; py[k++] = yy[j];
508
px[k] = xx[j+1]; py[k++] = yy[j+1];
509
if (dd[j] == dd[j+1]) {
510
j++; px[k] = xx[j+1]; py[k++] = yy[j+1];
511
}
512
break;
513
}
514
}
515
516
if (k > 2) {
517
C3D_SelCol(dd[i]);
518
C3D_AreaFill(k, FALSE, px, py);
519
}
520
521
}
522
}
523
524
void C3D_Pcalc(int x0, int y0, int d0, int x1, int y1, int d1,
525
int *n, int xx[], int yy[], int dd[])
526
/***********************************************************************
527
| Only internal use
528
^**********************************************************************/
529
{
530
int x, y, deltax, deltay, deltad;
531
int i, d, ds;
532
533
*n = abs((d1 >> C3D_MASK) - (d0 >> C3D_MASK));
534
535
xx[0] = x0; yy[0] = y0; dd[0] = d0 >> C3D_MASK;
536
(*n)++;
537
538
if (*n != 1) {
539
540
deltad = (d1 >= d0 ? 1 : (-1));
541
ds = d0 & ((1 << C3D_MASK)-1);
542
543
if (d1 > d0) {
544
ds = (1 << C3D_MASK) - ds;
545
}
546
547
d = abs(d1 - d0);
548
549
if (x1 > x0) {
550
deltax = ((x1 - x0) << (C3D_MASK << 1)) / d;
551
deltax >>= C3D_MASK;
552
x = x0 + ((ds * deltax + C3D_HALFMASK) >> C3D_MASK);
553
}
554
else {
555
deltax = ((x0 - x1) << (C3D_MASK << 1)) / d;
556
deltax >>= C3D_MASK;
557
x = x0 - ((ds * deltax + C3D_HALFMASK) >> C3D_MASK);
558
deltax = -deltax;
559
}
560
561
if (y1 > y0) {
562
deltay = ((y1 - y0) << (C3D_MASK << 1)) / d;
563
deltay >>= C3D_MASK;
564
y = y0 + ((ds * deltay + C3D_HALFMASK) >> C3D_MASK);
565
}
566
else {
567
deltay = ((y0 - y1) << (C3D_MASK << 1)) / d;
568
deltay >>= C3D_MASK;
569
y = y0 - ((ds * deltay + C3D_HALFMASK) >> C3D_MASK);
570
deltay = -deltay;
571
}
572
573
for(i = 1; i != *n; i++) {
574
dd[i] = dd[i-1] + deltad;
575
xx[i] = x; yy[i] = y;
576
x = x + deltax; y = y + deltay;
577
}
578
}
579
}
580
581
void C3D_SelCol(int col)
582
/***********************************************************************
583
| Only internal use
584
^**********************************************************************/
585
{
586
GRA_COLOR(++col);
587
}
588
589
void C3D_AreaFill(int n, int border, int x[], int y[])
590
/***********************************************************************
591
| Only internal use
592
^**********************************************************************/
593
{
594
int i, j;
595
Point p[8];
596
597
while(n > 0 && x[n-1] == x[0] && y[n-1] == y[0]) n--;
598
599
for(i = 0; i < n; i++) {
600
p[i].x = (int)(x[i]+0.5); p[i].y = (int)(y[i]+0.5); p[i].z = 0.0;
601
}
602
603
for(i = 0; i < n - 1; i++)
604
if (p[i].x == p[i+1].x && p[i].y == p[i+1].y) {
605
for(j = i + 1; j < n - 1; j++) {
606
p[j].x = p[j+1].x; p[j].y = p[j+1].y;
607
}
608
n--;
609
}
610
611
if (n > 2) {
612
GRA_AREAFILL(n, p);
613
if (border)
614
{
615
p[n].x = p[0].x;
616
p[n].y = p[0].y;
617
p[n].z = 0;
618
GRA_COLOR(1);
619
GRA_POLYLINE(n+1, p);
620
}
621
}
622
}
623
624