~jeko-ios-software/openracing/trackgen2

« back to all changes in this revision

Viewing changes to easymesh.cpp

  • Committer: Jean-Christophe Hoelt
  • Date: 2009-02-20 11:16:27 UTC
  • Revision ID: jeko@ios-software.com-20090220111627-y95675cby1q72v20
Initial import

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/************************************************************************************************
 
2
 
 
3
    file                 : easymesh.cpp
 
4
    author               : Bojan NICENO 
 
5
    Original Location    : http://www-dinma.univ.trieste.it/~nirftc/research/easymesh/easymesh.html
 
6
    modified             : Eric Espie (eric.espie@torcs.org)
 
7
    copyright            : Bojan NICENO & Eric Espie (parts)
 
8
    version              : $Id: easymesh.cpp,v 1.11 2005/06/30 22:23:45 berniw Exp $
 
9
 
 
10
 ************************************************************************************************/
 
11
 
 
12
 
 
13
#include <math.h>
 
14
#include <stdio.h>
 
15
#include <stdlib.h>
 
16
#include <cstring>
 
17
 
 
18
#include <tgf.h>
 
19
#include <track.h>
 
20
#include <robottools.h>
 
21
 
 
22
#include "trackgen.h"
 
23
#include "elevation.h"
 
24
#include "easymesh.h"
 
25
#include "objects.h"
 
26
#include "relief.h"
 
27
#include "ac3d.h"
 
28
#include "easymesh.h"
 
29
 
 
30
 
 
31
static tdble    Margin;
 
32
static tdble    ExtHeight;
 
33
static tdble    GridStep;
 
34
static tdble    TrackStep;
 
35
static char     buf[1024];
 
36
static const char       *TexName;
 
37
static tdble    TexSize;
 
38
static tdble    TexRand;
 
39
 
 
40
#ifndef max
 
41
#define max(a,b)  (((a) > (b)) ? (a) : (b))
 
42
#endif
 
43
#ifndef min
 
44
#define min(a,b)  (((a) < (b)) ? (a) : (b))
 
45
#endif
 
46
#ifndef PI
 
47
#define PI    3.14159265359
 
48
#endif
 
49
 
 
50
#define SMALL 1e-10
 
51
#define GREAT 1e+10
 
52
 
 
53
#define ON      0 
 
54
#define OFF    -1       /* element is switched off */
 
55
#define WAIT   -2       /* node is waiting (it is a corner node) */
 
56
#define A       3
 
57
#define D       4
 
58
#define W       5
 
59
 
 
60
#define MAX_NODES 15000
 
61
 
 
62
/*-----------------------------+
 
63
|  definitions for the chains  |
 
64
+-----------------------------*/
 
65
#define CLOSED 0
 
66
#define OPEN   1
 
67
#define INSIDE 2
 
68
 
 
69
 
 
70
struct ele
 
71
{
 
72
    int i,  j,  k;
 
73
    int ei, ej, ek;
 
74
    int si, sj, sk;
 
75
 
 
76
    int mark;             /* is it off (ON or OFF) */
 
77
    int state;            /* is it (D)one, (A)ctive or (W)aiting */
 
78
    int material;
 
79
 
 
80
    double xv, yv, xin, yin, R, r, Det;
 
81
 
 
82
    int new_numb;         /* used for renumeration */
 
83
}
 
84
elem[MAX_NODES*2];
 
85
 
 
86
 
 
87
struct sid
 
88
{
 
89
    int ea, eb;           /* left and right element */
 
90
    int a, b, c, d;       /* left, right, start and end point */
 
91
 
 
92
    int mark;             /* is it off, is on the boundary */
 
93
 
 
94
    double s;
 
95
 
 
96
    int new_numb;         /* used for renumeration */
 
97
}
 
98
side[MAX_NODES*3];
 
99
 
 
100
 
 
101
struct nod node[MAX_NODES], *point;
 
102
 
 
103
 
 
104
struct seg *segment;
 
105
 
 
106
struct chai
 
107
{
 
108
    int s0, s1, type;
 
109
} *chain;
 
110
 
 
111
 
 
112
int Ne, Nn, Ns, Nc, Fl;             /* number of: elements, nodes, sides */
 
113
int ugly;                       /* mora li biti globalna ??? */
 
114
 
 
115
double xmax, xmin, ymax, ymin;
 
116
 
 
117
struct vtx
 
118
{
 
119
    double      x;
 
120
    double      y;
 
121
    double      z;
 
122
};
 
123
 
 
124
struct ref
 
125
{
 
126
    int         vtxidx;
 
127
    double      u;
 
128
    double      v;
 
129
};
 
130
 
 
131
 
 
132
struct surf
 
133
{
 
134
    struct ref  ref[3];
 
135
};
 
136
 
 
137
 
 
138
struct group
 
139
{
 
140
    int         nbvtx;
 
141
    int         maxvtx;
 
142
    struct vtx  *vertices;
 
143
    
 
144
    int         nbsurf;
 
145
    int         maxsurf;
 
146
    struct surf *surfaces;
 
147
};
 
148
 
 
149
#define SURF_INCR       100
 
150
#define VTX_INCR        100
 
151
 
 
152
static struct group     *Groups;
 
153
static int              ActiveGroups;
 
154
static float            GroupSize;
 
155
static float            XGroupOffset;
 
156
static float            YGroupOffset;
 
157
static int              XGroupNb;
 
158
static int              GroupNb;
 
159
 
 
160
 
 
161
void swap_side(int s);
 
162
 
 
163
 
 
164
/*=========================================================================*/
 
165
double area(struct nod *na, struct nod *nb, struct nod *nc)
 
166
{
 
167
    return 0.5 * (((*nb).x - (*na).x) * ((*nc).y - (*na).y) 
 
168
                  - ((*nb).y - (*na).y) * ((*nc).x - (*na).x));
 
169
}
 
170
/*-------------------------------------------------------------------------*/
 
171
 
 
172
 
 
173
/*=========================================================================*/
 
174
double dist(struct nod *na, struct nod *nb)
 
175
{
 
176
    return sqrt(((*nb).x-(*na).x)*((*nb).x-(*na).x)
 
177
                + ((*nb).y-(*na).y)*((*nb).y-(*na).y) );
 
178
}
 
179
/*-------------------------------------------------------------------------*/
 
180
 
 
181
 
 
182
/*=========================================================================*/
 
183
int in_elem(struct nod *n)
 
184
{
 
185
    int e;
 
186
 
 
187
    for (e = 0; e < Ne; e++) {   /* This must search through all elements ?? */
 
188
        if (area(n, &node[elem[e].i], &node[elem[e].j]) >= 0.0
 
189
            && area(n, &node[elem[e].j], &node[elem[e].k]) >= 0.0
 
190
            && area(n, &node[elem[e].k], &node[elem[e].i]) >= 0.0) {
 
191
            break; 
 
192
        }
 
193
    }
 
194
    return e;
 
195
}
 
196
/*-in_elem-----------------------------------------------------------------*/
 
197
 
 
198
 
 
199
/*=========================================================================*/
 
200
void bowyer(int n, int spac)
 
201
{
 
202
    int e, s, swap;
 
203
    struct nod vor;
 
204
 
 
205
    do { 
 
206
        swap = 0;
 
207
        for (s = 0; s < Ns; s++) {
 
208
            if (side[s].mark == 0) {
 
209
                if (side[s].a == n) {
 
210
                    e = side[s].eb; 
 
211
                    if (e != OFF) {
 
212
                        vor.x = elem[e].xv; 
 
213
                        vor.y=  elem[e].yv;
 
214
                        if (dist(&vor, &node[n]) < elem[e].R) {
 
215
                            swap_side(s);
 
216
                            swap=1;
 
217
                        }
 
218
                    }
 
219
                } else {
 
220
                    if (side[s].b == n) {
 
221
                        e = side[s].ea;
 
222
                        if (e != OFF) {
 
223
                            vor.x = elem[e].xv; 
 
224
                            vor.y = elem[e].yv;
 
225
                            if (dist(&vor, &node[n]) < elem[e].R) {
 
226
                                swap_side(s);
 
227
                                swap=1;
 
228
                            }
 
229
                        }
 
230
                    }
 
231
                }
 
232
            }
 
233
        }
 
234
    } while (swap == 1);
 
235
 
 
236
}
 
237
/*-bowyer------------------------------------------------------------------*/
 
238
 
 
239
 
 
240
/*=========================================================================*/
 
241
/*---------------------------------------------------+
 
242
|  This function calculates radii of inscribed and   |
 
243
|  circumscribed circle for a given element (int e)  |
 
244
+---------------------------------------------------*/
 
245
void circles(int e)
 
246
{
 
247
    double x, y, xi, yi, xj, yj, xk, yk, xij, yij, xjk, yjk, num, den;
 
248
    double si, sj, sk, O;
 
249
 
 
250
    xi = node[elem[e].i].x;
 
251
    yi = node[elem[e].i].y;
 
252
    xj = node[elem[e].j].x;
 
253
    yj = node[elem[e].j].y;
 
254
    xk = node[elem[e].k].x;
 
255
    yk = node[elem[e].k].y;
 
256
   
 
257
    xij = 0.5 * (xi + xj);
 
258
    yij = 0.5 * (yi + yj);
 
259
    xjk = 0.5 * (xj + xk);
 
260
    yjk = 0.5 * (yj + yk);
 
261
 
 
262
    num = (xij - xjk) * (xj - xi) + (yij - yjk) * (yj - yi);
 
263
    den = (xj - xi) * (yk - yj) - (xk - xj) * (yj - yi);
 
264
 
 
265
    if (den > 0) {
 
266
        elem[e].xv = x = xjk + num / den * (yk - yj);
 
267
        elem[e].yv = y = yjk - num / den * (xk - xj);
 
268
        elem[e].R  = sqrt((xi - x) * (xi - x) + (yi - y) * (yi - y));
 
269
    }
 
270
    
 
271
 
 
272
    si = side[elem[e].si].s;
 
273
    sj = side[elem[e].sj].s;
 
274
    sk = side[elem[e].sk].s;
 
275
    O = si + sj + sk;
 
276
    elem[e].Det = xi * (yj - yk) - xj * (yi - yk) + xk * (yi - yj);
 
277
 
 
278
    elem[e].xin = (xi * si + xj * sj + xk * sk ) / O;
 
279
    elem[e].yin = (yi * si + yj * sj + yk * sk ) / O;
 
280
 
 
281
    elem[e].r   = elem[e].Det / O;
 
282
}
 
283
/*-circles-----------------------------------------------------------------*/
 
284
 
 
285
 
 
286
/*=========================================================================*/
 
287
/*----------------------------------------------------------------+
 
288
|  This function calculates the value of the spacing function in  |
 
289
|  a new node 'n' which is inserted in element 'e' by a linear    |
 
290
|  approximation from the values of the spacing function in the   |
 
291
|  elements nodes.                                                |
 
292
+----------------------------------------------------------------*/
 
293
void spacing(int e, int n)
 
294
{
 
295
    double dxji, dxki, dyji, dyki, dx_i, dy_i, det, a, b;
 
296
 
 
297
    dxji = node[elem[e].j].x - node[elem[e].i].x;
 
298
    dyji = node[elem[e].j].y - node[elem[e].i].y;
 
299
    dxki = node[elem[e].k].x - node[elem[e].i].x;
 
300
    dyki = node[elem[e].k].y - node[elem[e].i].y;
 
301
    dx_i = node[n].x - node[elem[e].i].x;
 
302
    dy_i = node[n].y - node[elem[e].i].y;
 
303
 
 
304
    det = dxji*dyki - dxki*dyji;
 
305
 
 
306
    a = (+dyki * dx_i - dxki * dy_i) / det;
 
307
    b = (-dyji * dx_i + dxji * dy_i) / det;
 
308
 
 
309
    node[n].F = node[elem[e].i].F + 
 
310
        a * (node[elem[e].j].F - node[elem[e].i].F) +
 
311
        b * (node[elem[e].k].F - node[elem[e].i].F);
 
312
}
 
313
/*-spacing-----------------------------------------------------------------*/
 
314
 
 
315
 
 
316
/*=========================================================================*/
 
317
int insert_node(double x, double y, double z, int spac,
 
318
                int prev_n, int prev_s_mark, int mark, int next_s_mark, int next_n)
 
319
{
 
320
    int    i,j,k,e,ei,ej,ek, s,si,sj,sk;
 
321
    double sx, sy;
 
322
 
 
323
    Nn++;          /* one new node */
 
324
    //if ((Nn % 100) == 0) {
 
325
        printf("\r%d Nodes", Nn);
 
326
        fflush(stdout);
 
327
    //}
 
328
    
 
329
    if (Nn > MAX_NODES) {
 
330
        printf("\nResize MAX_NODES... > %d\n", MAX_NODES);
 
331
        exit(1);
 
332
    }
 
333
 
 
334
    if ((x < xmin) || (x > xmax) || (y < ymin) || (y > ymax)) {
 
335
        printf("\nDon't Insert %f %f\n", x, y);
 
336
        return 0;
 
337
/*      if (x < xmin) x = xmin; */
 
338
/*      if (x > xmax) x = xmax; */
 
339
/*      if (y < ymin) y = ymin; */
 
340
/*      if (y > ymax) y = ymax; */
 
341
    }
 
342
 
 
343
    node[Nn-1].x = x;
 
344
    node[Nn-1].y = y;
 
345
    node[Nn-1].z = z;
 
346
    node[Nn-1].mark = mark;
 
347
 
 
348
    /* find the element which contains new node */ 
 
349
    e = in_elem(&node[Nn-1]);
 
350
 
 
351
    /* calculate the spacing function in the new node */
 
352
    if(spac==ON) {
 
353
        spacing(e, Nn-1);
 
354
    }
 
355
    
 
356
    i  = elem[e].i;
 
357
    j  = elem[e].j;
 
358
    k  = elem[e].k;
 
359
    ei = elem[e].ei;
 
360
    ej = elem[e].ej;
 
361
    ek = elem[e].ek; 
 
362
    si = elem[e].si;
 
363
    sj = elem[e].sj;
 
364
    sk = elem[e].sk; 
 
365
 
 
366
    Ne += 2;
 
367
    Ns += 3;
 
368
 
 
369
    /*---------------+
 
370
    |  new elements  |
 
371
    +---------------*/ 
 
372
    elem[Ne-2].i = Nn - 1;
 
373
    elem[Ne-2].j = k;   
 
374
    elem[Ne-2].k = i;
 
375
    elem[Ne-1].i = Nn - 1; 
 
376
    elem[Ne-1].j = i; 
 
377
    elem[Ne-1].k = j; 
 
378
 
 
379
    elem[Ne-2].ei = ej;  
 
380
    elem[Ne-2].ej = Ne - 1;
 
381
    elem[Ne-2].ek = e;
 
382
    elem[Ne-1].ei = ek;  
 
383
    elem[Ne-1].ej = e; 
 
384
    elem[Ne-1].ek = Ne - 2;
 
385
 
 
386
    elem[Ne-2].si = sj;  
 
387
    elem[Ne-2].sj = Ns - 2;
 
388
    elem[Ne-2].sk = Ns - 3;
 
389
    elem[Ne-1].si = sk;  
 
390
    elem[Ne-1].sj = Ns - 1;
 
391
    elem[Ne-1].sk = Ns - 2;
 
392
 
 
393
    /*------------+ 
 
394
    |  new sides  |
 
395
    +------------*/ 
 
396
    side[Ns-3].c  = k; 
 
397
    side[Ns-3].d  = Nn - 1;     /* c-d */
 
398
    side[Ns-3].a  = j;  
 
399
    side[Ns-3].b  = i;        /* a-b */
 
400
    side[Ns-3].ea = e; 
 
401
    side[Ns-3].eb = Ne - 2;
 
402
 
 
403
    side[Ns-2].c  = i;  
 
404
    side[Ns-2].d  = Nn - 1;     /* c-d */
 
405
    side[Ns-2].a  = k;  
 
406
    side[Ns-2].b  = j;        /* a-b */
 
407
    side[Ns-2].ea = Ne - 2;
 
408
    side[Ns-2].eb = Ne - 1;
 
409
 
 
410
    side[Ns-1].c  = j;  
 
411
    side[Ns-1].d  = Nn - 1;     /* c-d */
 
412
    side[Ns-1].a  = i;  
 
413
    side[Ns-1].b  = k;        /* a-b */
 
414
    side[Ns-1].ea = Ne - 1;
 
415
    side[Ns-1].eb = e;       
 
416
 
 
417
    for (s = 1; s <= 3; s++) {
 
418
        sx = node[side[Ns-s].c].x - node[side[Ns-s].d].x;
 
419
        sy = node[side[Ns-s].c].y - node[side[Ns-s].d].y;
 
420
        side[Ns-s].s = sqrt(sx * sx + sy * sy);
 
421
    }
 
422
 
 
423
    elem[e].i  = Nn - 1;
 
424
    elem[e].ej = Ne - 2;
 
425
    elem[e].ek = Ne - 1;
 
426
    elem[e].sj = Ns - 3;
 
427
    elem[e].sk = Ns - 1;
 
428
 
 
429
    if (side[si].a == i) {
 
430
        side[si].a  = Nn - 1;
 
431
        side[si].ea = e;
 
432
    }
 
433
    if (side[si].b == i) {
 
434
        side[si].b  = Nn - 1;
 
435
        side[si].eb = e;
 
436
    }
 
437
 
 
438
    if (side[sj].a == j) {
 
439
        side[sj].a  = Nn - 1;
 
440
        side[sj].ea = Ne - 2;
 
441
    }
 
442
    if (side[sj].b == j) {
 
443
        side[sj].b  = Nn - 1;
 
444
        side[sj].eb = Ne - 2;
 
445
    }
 
446
 
 
447
    if (side[sk].a == k) {
 
448
        side[sk].a = Nn - 1;
 
449
        side[sk].ea = Ne - 1;
 
450
    } 
 
451
    if (side[sk].b == k) {
 
452
        side[sk].b = Nn - 1;
 
453
        side[sk].eb = Ne - 1;
 
454
    } 
 
455
 
 
456
    if (ej != -1) {
 
457
        if (elem[ej].ei == e) {
 
458
            elem[ej].ei = Ne - 2;
 
459
        }
 
460
        if (elem[ej].ej == e) {
 
461
            elem[ej].ej = Ne-2;
 
462
        }
 
463
        if (elem[ej].ek == e) {
 
464
            elem[ej].ek = Ne - 2;
 
465
        }
 
466
    }
 
467
 
 
468
    if (ek != -1) {
 
469
        if (elem[ek].ei == e) {
 
470
            elem[ek].ei = Ne - 1;
 
471
        }
 
472
        if (elem[ek].ej == e) {
 
473
            elem[ek].ej = Ne - 1;
 
474
        }
 
475
        if (elem[ek].ek == e) {
 
476
            elem[ek].ek = Ne - 1;
 
477
        }
 
478
    }
 
479
 
 
480
    /* Find circumenters for two new elements, 
 
481
       and for the one who's segment has changed */
 
482
    circles(e);
 
483
    circles(Ne - 2);
 
484
    circles(Ne - 1);
 
485
 
 
486
    bowyer(Nn - 1, spac);
 
487
 
 
488
    /*-------------------------------------------------+
 
489
    |  NEW ! Insert boundary conditions for the sides  |
 
490
    +-------------------------------------------------*/
 
491
    for (s = 3; s < Ns; s++) {
 
492
        if (side[s].c == prev_n && side[s].d == Nn - 1) {
 
493
            side[s].mark = prev_s_mark;
 
494
        }
 
495
        if (side[s].d == prev_n && side[s].c == Nn - 1) {
 
496
            side[s].mark = prev_s_mark;
 
497
        }
 
498
        if (side[s].c == next_n && side[s].d == Nn - 1) {
 
499
            side[s].mark = next_s_mark;
 
500
        }
 
501
        if (side[s].d == next_n && side[s].c == Nn - 1) {
 
502
            side[s].mark = next_s_mark;
 
503
        }
 
504
    }
 
505
 
 
506
    return e;
 
507
}
 
508
/*-insert_node-------------------------------------------------------------*/
 
509
 
 
510
 
 
511
/*=========================================================================*/
 
512
void swap_side(int s)
 
513
{
 
514
    int    a, b, c, d, ea, eb, eac = 0, ead = 0, ebc = 0, ebd = 0, sad = 0, sac = 0, sbc = 0, sbd = 0;
 
515
    double sx, sy;
 
516
 
 
517
    ea=side[s].ea; 
 
518
    eb=side[s].eb;
 
519
    a = side[s].a;
 
520
    b = side[s].b;
 
521
    c = side[s].c;
 
522
    d = side[s].d;
 
523
 
 
524
    if (elem[ea].ei == eb) {
 
525
        ead = elem[ea].ej;
 
526
        eac = elem[ea].ek; 
 
527
        sad = elem[ea].sj;
 
528
        sac = elem[ea].sk;
 
529
    }
 
530
 
 
531
    if (elem[ea].ej == eb) {
 
532
        ead = elem[ea].ek;
 
533
        eac = elem[ea].ei; 
 
534
        sad = elem[ea].sk;
 
535
        sac = elem[ea].si;
 
536
    }   
 
537
 
 
538
    if (elem[ea].ek == eb) {
 
539
        ead = elem[ea].ei;
 
540
        eac = elem[ea].ej;
 
541
        sad = elem[ea].si;
 
542
        sac = elem[ea].sj;
 
543
    }
 
544
 
 
545
    if (elem[eb].ei == ea) {
 
546
        ebc = elem[eb].ej;
 
547
        ebd = elem[eb].ek;
 
548
        sbc = elem[eb].sj;
 
549
        sbd = elem[eb].sk;
 
550
    }
 
551
 
 
552
    if (elem[eb].ej == ea) {
 
553
        ebc = elem[eb].ek;
 
554
        ebd = elem[eb].ei;
 
555
        sbc = elem[eb].sk; 
 
556
        sbd = elem[eb].si;
 
557
    }
 
558
 
 
559
    if (elem[eb].ek == ea) {
 
560
        ebc = elem[eb].ei;
 
561
        ebd = elem[eb].ej;
 
562
        sbc = elem[eb].si;
 
563
        sbd = elem[eb].sj;
 
564
    }
 
565
 
 
566
    elem[ea].i  = a;
 
567
    elem[ea].j  = b; 
 
568
    elem[ea].k  = d;  
 
569
    elem[ea].ei = ebd;
 
570
    elem[ea].ej = ead;
 
571
    elem[ea].ek = eb;  
 
572
    elem[ea].si = sbd;
 
573
    elem[ea].sj = sad;
 
574
    elem[ea].sk = s;  
 
575
  
 
576
    elem[eb].i  = a; 
 
577
    elem[eb].j  = c; 
 
578
    elem[eb].k  = b;  
 
579
    elem[eb].ei = ebc;
 
580
    elem[eb].ej = ea; 
 
581
    elem[eb].ek = eac;  
 
582
    elem[eb].si = sbc;
 
583
    elem[eb].sj = s;  
 
584
    elem[eb].sk = sac;  
 
585
 
 
586
    if (eac != -1) {
 
587
        if (elem[eac].ei == ea) {
 
588
            elem[eac].ei = eb;
 
589
        }
 
590
        if (elem[eac].ej == ea) {
 
591
            elem[eac].ej = eb;
 
592
        }
 
593
        if (elem[eac].ek == ea) {
 
594
            elem[eac].ek = eb; 
 
595
        }
 
596
    }
 
597
 
 
598
    if (ebd != -1) {
 
599
        if (elem[ebd].ei == eb) {
 
600
            elem[ebd].ei = ea;
 
601
        }
 
602
        if (elem[ebd].ej == eb) {
 
603
            elem[ebd].ej = ea;
 
604
        }
 
605
        if (elem[ebd].ek == eb) {
 
606
            elem[ebd].ek = ea; 
 
607
        }
 
608
    }
 
609
 
 
610
    if (side[sad].ea == ea) {
 
611
        side[sad].a = b;
 
612
    }
 
613
    if (side[sad].eb == ea) {
 
614
        side[sad].b = b;
 
615
    }
 
616
 
 
617
    if (side[sbc].ea == eb) {
 
618
        side[sbc].a = a;
 
619
    }
 
620
    if (side[sbc].eb == eb) {
 
621
        side[sbc].b = a;
 
622
    }
 
623
 
 
624
    if (side[sbd].ea == eb) {
 
625
        side[sbd].ea = ea;
 
626
        side[sbd].a = a;
 
627
    }
 
628
    if (side[sbd].eb == eb) {
 
629
        side[sbd].eb = ea;
 
630
        side[sbd].b = a;
 
631
    }
 
632
 
 
633
    if (a < b) {
 
634
        side[s].c  = a;
 
635
        side[s].d  = b;
 
636
        side[s].a  = d;
 
637
        side[s].b  = c;
 
638
        side[s].ea = ea;
 
639
        side[s].eb = eb;
 
640
    } else {
 
641
        side[s].c  = b;
 
642
        side[s].d  = a;
 
643
        side[s].a  = c;
 
644
        side[s].b  = d;
 
645
        side[s].ea = eb;
 
646
        side[s].eb = ea;
 
647
    }
 
648
 
 
649
    sx = node[side[s].c].x - node[side[s].d].x;
 
650
    sy = node[side[s].c].y - node[side[s].d].y;
 
651
    side[s].s = sqrt(sx * sx + sy * sy);
 
652
 
 
653
    if (side[sac].ea == ea) {
 
654
        side[sac].ea = eb;
 
655
        side[sac].a = b;
 
656
    }
 
657
    if (side[sac].eb == ea) {
 
658
        side[sac].eb = eb;
 
659
        side[sac].b = b;
 
660
    }
 
661
 
 
662
    if (side[sad].ea == ea) {
 
663
        side[sad].a = b;
 
664
    }
 
665
    if (side[sad].eb == ea) {
 
666
        side[sad].b = b;
 
667
    }
 
668
 
 
669
    if (side[sbc].ea == eb) {
 
670
        side[sbc].a = a;
 
671
    }
 
672
    if (side[sbc].eb == eb) {
 
673
        side[sbc].b = a;
 
674
    }
 
675
 
 
676
    if (side[sbd].ea == eb) {
 
677
        side[sbd].ea = ea;
 
678
        side[sbd].a = a;
 
679
    }
 
680
    if (side[sbd].eb == eb) {
 
681
        side[sbd].eb = ea;
 
682
        side[sbd].b = a;
 
683
    }
 
684
 
 
685
    circles(ea);
 
686
    circles(eb);
 
687
}
 
688
/*-swap_side---------------------------------------------------------------*/
 
689
 
 
690
 
 
691
/*=========================================================================*/
 
692
void erase()
 
693
{
 
694
    int s, n, e;
 
695
 
 
696
    int a, b, c;
 
697
 
 
698
    /*--------------------------+
 
699
    |                           |
 
700
    |  Negative area check for  |
 
701
    |  elimination of elements  |
 
702
    |                           |
 
703
    +--------------------------*/
 
704
    for (e = 0; e < Ne; e++) {
 
705
        if ((node[elem[e].i].chain == node[elem[e].j].chain) &&
 
706
            (node[elem[e].j].chain == node[elem[e].k].chain) &&
 
707
            (chain[node[elem[e].i].chain].type == CLOSED)) {
 
708
            a = min(min(elem[e].i, elem[e].j), elem[e].k);
 
709
            c = max(max(elem[e].i, elem[e].j), elem[e].k);
 
710
            b = elem[e].i + elem[e].j + elem[e].k - a - c;
 
711
 
 
712
            if (a < 3) {
 
713
                elem[e].mark = OFF;
 
714
            } else {
 
715
                if (area(&node[a], &node[b], &node[c]) < 0.0) {
 
716
                    elem[e].mark = OFF;
 
717
                }
 
718
            }
 
719
        }
 
720
    }
 
721
    
 
722
 
 
723
    for (e = 0; e < Ne; e++) {
 
724
        if (elem[elem[e].ei].mark == OFF) {
 
725
            elem[e].ei = OFF;
 
726
        }
 
727
        if (elem[elem[e].ej].mark == OFF) {
 
728
            elem[e].ej = OFF;
 
729
        }
 
730
        if (elem[elem[e].ek].mark == OFF) {
 
731
            elem[e].ek = OFF;
 
732
        }
 
733
    }
 
734
 
 
735
    /*-----------------------+
 
736
    |                        |
 
737
    |  Elimination of sides  |
 
738
    |                        |
 
739
    +-----------------------*/
 
740
    for (s = 0; s < 3; s++) {
 
741
        side[s].mark = OFF;
 
742
    }   
 
743
 
 
744
    for (s = 3; s < Ns; s++) {
 
745
        if ((elem[side[s].ea].mark == OFF) && (elem[side[s].eb].mark == OFF)) {
 
746
            side[s].mark = OFF;
 
747
        }
 
748
    }
 
749
        
 
750
 
 
751
    for (s = 3; s < Ns; s++) {
 
752
        if (side[s].mark != OFF) {
 
753
            if (elem[side[s].ea].mark == OFF) {
 
754
                side[s].ea = OFF;
 
755
                side[s].a = OFF;
 
756
            }
 
757
            if (elem[side[s].eb].mark == OFF) {
 
758
                side[s].eb = OFF;
 
759
                side[s].b = OFF;
 
760
            }
 
761
        }
 
762
    }
 
763
        
 
764
 
 
765
    /*-----------------------+
 
766
    |                        |
 
767
    |  Elimination of nodes  |
 
768
    |                        |
 
769
    +-----------------------*/
 
770
    for (n = 0; n < 3; n++) {
 
771
        node[n].mark = OFF;
 
772
    }
 
773
        
 
774
 
 
775
}
 
776
/*-erase-------------------------------------------------------------------*/
 
777
 
 
778
 
 
779
/*=========================================================================*/
 
780
void diamond(void)
 
781
{
 
782
    int    ea, eb, eac = 0, ead = 0, ebc = 0, ebd = 0, s;
 
783
 
 
784
    for (s = 0; s < Ns; s++) {
 
785
        
 
786
        if (side[s].mark != OFF) {
 
787
            ea = side[s].ea;
 
788
            eb = side[s].eb;
 
789
 
 
790
            if (elem[ea].ei == eb) {
 
791
                ead = elem[ea].ej;
 
792
                eac = elem[ea].ek;
 
793
            }
 
794
            if (elem[ea].ej == eb) {
 
795
                ead = elem[ea].ek;
 
796
                eac = elem[ea].ei;
 
797
            }   
 
798
            if (elem[ea].ek == eb) {
 
799
                ead = elem[ea].ei;
 
800
                eac = elem[ea].ej;
 
801
            }
 
802
            if (elem[eb].ei == ea) {
 
803
                ebc = elem[eb].ej;
 
804
                ebd = elem[eb].ek;
 
805
            }
 
806
            if (elem[eb].ej == ea) {
 
807
                ebc = elem[eb].ek;
 
808
                ebd = elem[eb].ei;
 
809
            }
 
810
            if (elem[eb].ek == ea) {
 
811
                ebc = elem[eb].ei;
 
812
                ebd = elem[eb].ej;
 
813
            }
 
814
 
 
815
            if ((eac == OFF || elem[eac].state == D) &&
 
816
                (ebc == OFF || elem[ebc].state == D) &&
 
817
                (ead == OFF || elem[ead].state == D) &&
 
818
                (ebd == OFF || elem[ebd].state == D)) {
 
819
                elem[ea].state = D;
 
820
                elem[eb].state = D;
 
821
            }
 
822
        }
 
823
    }
 
824
    
 
825
}
 
826
/*-diamond-----------------------------------------------------------------*/
 
827
 
 
828
 
 
829
/*=========================================================================*/
 
830
void classify(void)
 
831
/*----------------------------------------------------------+
 
832
|  This function searches through all elements every time.  |
 
833
|  Some optimisation will definitely bee needed             |
 
834
|                                                           |
 
835
|  But it also must me noted, that this function defines    |
 
836
|  the strategy for insertion of new nodes                  |
 
837
|                                                           |
 
838
|  It's MUCH MUCH better when the ugliest element is found  |
 
839
|  as one with highest ratio of R/r !!! (before it was      |
 
840
|  element with greater R)                                  |
 
841
+----------------------------------------------------------*/
 
842
{
 
843
    int e, ei, ej, ek,si,sj,sk;
 
844
    double ratio = 0.7, F;
 
845
 
 
846
    ugly = OFF;
 
847
 
 
848
    for (e = 0; e < Ne; e++) {
 
849
        if (elem[e].mark != OFF) {
 
850
            ei = elem[e].ei;
 
851
            ej = elem[e].ej;
 
852
            ek = elem[e].ek;
 
853
 
 
854
            F = (node[elem[e].i].F + node[elem[e].j].F + node[elem[e].k].F) / 3.0;
 
855
 
 
856
            elem[e].state = W;
 
857
 
 
858
            /*--------------------------+
 
859
            |  0.577 is ideal triangle  |
 
860
            +--------------------------*/
 
861
            if (elem[e].R < 0.700*F) {
 
862
                elem[e].state = D; /* 0.0866; 0.07 */
 
863
            }
 
864
 
 
865
            /*------------------------+
 
866
            |  even this is possible  |
 
867
            +------------------------*/
 
868
            if (ei != OFF && ej != OFF && ek != OFF) {
 
869
                if (elem[ei].state == D && elem[ej].state == D && elem[ek].state == D) {
 
870
                    elem[e].state=D;
 
871
                }
 
872
            }
 
873
        }
 
874
    }
 
875
    
 
876
 
 
877
    /*--------------------------------------+
 
878
    |  Diamond check. Is it so important ?  |
 
879
    +--------------------------------------*/
 
880
    diamond();   
 
881
 
 
882
    /*------------------------------------------------+
 
883
    |  First part of the trick:                       |
 
884
    |    search through the elements on the boundary  |
 
885
    +------------------------------------------------*/
 
886
    for (e = 0; e < Ne; e++) {
 
887
        if (elem[e].mark != OFF && elem[e].state != D) {
 
888
            si = elem[e].si;
 
889
            sj = elem[e].sj;
 
890
            sk = elem[e].sk;
 
891
 
 
892
            if (side[si].mark != 0) {
 
893
                elem[e].state = A;
 
894
            }
 
895
            if (side[sj].mark != 0) {
 
896
                elem[e].state = A;
 
897
            }
 
898
            if (side[sk].mark != 0) {
 
899
                elem[e].state = A;
 
900
            }
 
901
 
 
902
            if (elem[e].state == A && elem[e].R / elem[e].r > ratio) {
 
903
                ratio = max(ratio, elem[e].R/elem[e].r);
 
904
                ugly = e;
 
905
            }
 
906
        }
 
907
    }
 
908
    
 
909
 
 
910
    /*-------------------------------------------------+
 
911
      |  Second part of the trick:                       |
 
912
      |    if non-acceptable element on the boundary is  |
 
913
      |    found, ignore the elements inside the domain  |
 
914
      +-------------------------------------------------*/
 
915
    if (ugly == OFF) {
 
916
        for (e = 0; e < Ne; e++) {
 
917
            if (elem[e].mark != OFF) {
 
918
                if (elem[e].state != D) {
 
919
                    ei = elem[e].ei;
 
920
                    ej = elem[e].ej;
 
921
                    ek = elem[e].ek;
 
922
 
 
923
                    if (ei != OFF) {
 
924
                        if (elem[ei].state == D) {
 
925
                            elem[e].state = A;
 
926
                        }
 
927
                    }
 
928
                    if (ej != OFF) {
 
929
                        if (elem[ej].state == D) {
 
930
                            elem[e].state = A;
 
931
                        }
 
932
                    }
 
933
                    if (ek != OFF) {
 
934
                        if (elem[ek].state == D) {
 
935
                            elem[e].state = A;
 
936
                        }
 
937
                    }
 
938
                    if (elem[e].state == A && elem[e].R/elem[e].r > ratio) {
 
939
                        ratio = max(ratio, elem[e].R / elem[e].r);
 
940
                        ugly = e;
 
941
                    }
 
942
                }
 
943
            }
 
944
        }
 
945
    }
 
946
}
 
947
/*-classify----------------------------------------------------------------*/
 
948
 
 
949
 
 
950
/*=========================================================================*/
 
951
/*---------------------------------------------------+
 
952
|  This function is very important.                  |
 
953
|  It determines the position of the inserted node.  |
 
954
+---------------------------------------------------*/
 
955
void new_node()
 
956
{
 
957
    int    s=OFF, n = 0;
 
958
    double xM, yM, zM, p, q, qx, qy, rhoM, rho_M, d;
 
959
 
 
960
    struct nod Ca;
 
961
 
 
962
    /*-------------------------------------------------------------------------+
 
963
      |  It's obvious that elements which are near the boundary, will come into  |
 
964
      |  play first.                                                             |
 
965
      |                                                                          |
 
966
      |  However, some attention has to be payed for the case when two accepted  |
 
967
      |  elements surround the ugly one                                          |
 
968
      |                                                                          |
 
969
      |  What if new points falls outside the domain                             |
 
970
      +-------------------------------------------------------------------------*/
 
971
    if ((elem[ugly].ei != OFF) &&  (elem[elem[ugly].ei].state == D)) {
 
972
        s = elem[ugly].si;
 
973
        n = elem[ugly].i;
 
974
    }
 
975
    if ((elem[ugly].ej != OFF) && (elem[elem[ugly].ej].state == D)) {
 
976
        s = elem[ugly].sj;
 
977
        n = elem[ugly].j;
 
978
    }
 
979
    if ((elem[ugly].ek != OFF) && (elem[elem[ugly].ek].state == D)) {
 
980
        s = elem[ugly].sk;
 
981
        n = elem[ugly].k;
 
982
    }
 
983
    if ((elem[ugly].si != OFF) && (side[elem[ugly].si].mark > 0)) {
 
984
        s = elem[ugly].si;
 
985
        n = elem[ugly].i;
 
986
    }
 
987
    if ((elem[ugly].sj != OFF) && (side[elem[ugly].sj].mark > 0)) {
 
988
        s = elem[ugly].sj;
 
989
        n = elem[ugly].j;
 
990
    }
 
991
    if ((elem[ugly].sk != OFF) && (side[elem[ugly].sk].mark > 0)) {
 
992
        s = elem[ugly].sk;
 
993
        n = elem[ugly].k;
 
994
    }
 
995
    if (s == OFF) {
 
996
        return;
 
997
    }
 
998
    
 
999
 
 
1000
    xM  = 0.5 * (node[side[s].c].x + node[side[s].d].x);
 
1001
    yM  = 0.5 * (node[side[s].c].y + node[side[s].d].y);
 
1002
    zM  = 0.5 * (node[side[s].c].z + node[side[s].d].z);
 
1003
 
 
1004
    Ca.x = elem[ugly].xv;
 
1005
    Ca.y = elem[ugly].yv;
 
1006
 
 
1007
    p  = 0.5 * side[s].s;    /* not checked */
 
1008
 
 
1009
    qx = Ca.x - xM;
 
1010
    qy = Ca.y - yM;
 
1011
    q  = sqrt(qx * qx + qy * qy);
 
1012
 
 
1013
    rhoM = 0.577 * 0.5 *(node[side[s].c].F + node[side[s].d].F);
 
1014
 
 
1015
    rho_M = min(max(rhoM, p), 0.5 * (p * p + q * q) / q);
 
1016
 
 
1017
    if (rho_M < p) {
 
1018
        d = rho_M;
 
1019
    } else {
 
1020
        d = rho_M + sqrt(rho_M * rho_M - p * p); 
 
1021
    }
 
1022
 
 
1023
    /*---------------------------------------------------------------------+
 
1024
    |  The following line check can the new point fall outside the domain. |
 
1025
    |  However, I can't remember how it works, but I believe that it is    |
 
1026
    |  still a weak point of the code, particulary when there are lines    |
 
1027
    |  inside the domain                                                   |
 
1028
    +---------------------------------------------------------------------*/
 
1029
 
 
1030
    if (area(&node[side[s].c], &node[side[s].d], &Ca) *
 
1031
        area(&node[side[s].c], &node[side[s].d], &node[n]) > 0.0 ) {
 
1032
        insert_node(xM + d * qx  / q,  yM + d * qy / q, zM, ON, OFF, 0, 0, 0, OFF);
 
1033
    }
 
1034
    return;
 
1035
}
 
1036
/*-new_node----------------------------------------------------------------*/
 
1037
 
 
1038
 
 
1039
/*=========================================================================*/
 
1040
void neighbours() 
 
1041
/*--------------------------------------------------------------+
 
1042
|  Counting the elements which surround each node.              |
 
1043
|  It is important for the two functions: 'relax' and 'smooth'  |
 
1044
+--------------------------------------------------------------*/
 
1045
 
1046
    int s;
 
1047
 
 
1048
    for (s = 0; s < Ns; s++) {
 
1049
        if (side[s].mark == 0) {
 
1050
            if (node[side[s].c].mark == 0) {
 
1051
                node[side[s].c].Nne++;
 
1052
            }
 
1053
        }
 
1054
        if (node[side[s].d].mark == 0) {
 
1055
            node[side[s].d].Nne++;
 
1056
        }
 
1057
        
 
1058
    }
 
1059
}
 
1060
/*-neighbours--------------------------------------------------------------*/
 
1061
 
 
1062
 
 
1063
/*=========================================================================*/
 
1064
void materials()
 
1065
{
 
1066
    int e, c, mater = 0, over;
 
1067
    int ei, ej, ek, si, sj, sk;
 
1068
 
 
1069
    for (e = 0; e < Ne; e++) {
 
1070
        if (elem[e].mark != OFF) {
 
1071
            elem[e].material = OFF;
 
1072
        }
 
1073
    }
 
1074
    
 
1075
 
 
1076
    for (c = 0; c < Nc; c++) {
 
1077
        if (point[c].inserted == 0) {
 
1078
            elem[in_elem(&point[c])].material = point[c].mark;
 
1079
            mater = ON;
 
1080
        }
 
1081
    }
 
1082
 
 
1083
    if (mater == ON) {
 
1084
        for(;;) {      
 
1085
            over = ON;
 
1086
            for (e = 0; e < Ne; e++) {
 
1087
                if (elem[e].mark != OFF && elem[e].material == OFF) {
 
1088
                    ei = elem[e].ei;
 
1089
                    ej = elem[e].ej;
 
1090
                    ek = elem[e].ek;
 
1091
 
 
1092
                    si = elem[e].si;
 
1093
                    sj = elem[e].sj;
 
1094
                    sk = elem[e].sk;
 
1095
 
 
1096
                    if (ei != OFF) {
 
1097
                        if (elem[ei].material != OFF && side[si].mark == 0) {
 
1098
                            elem[e].material = elem[ei].material;
 
1099
                            over = OFF;
 
1100
                        }
 
1101
                    }
 
1102
                                
 
1103
 
 
1104
                    if (ej != OFF) {
 
1105
                        if (elem[ej].material != OFF && side[sj].mark == 0) {
 
1106
                            elem[e].material = elem[ej].material;
 
1107
                            over = OFF;
 
1108
                        }
 
1109
                    }
 
1110
                                
 
1111
 
 
1112
                    if (ek != OFF) {
 
1113
                        if (elem[ek].material != OFF && side[sk].mark == 0) {
 
1114
                            elem[e].material = elem[ek].material;
 
1115
                            over = OFF;
 
1116
                        }
 
1117
                    }
 
1118
                }
 
1119
            }
 
1120
            if (over == ON) {
 
1121
                break;
 
1122
            }
 
1123
        } /* for(iter) */
 
1124
    }
 
1125
}
 
1126
/*-materials---------------------------------------------------------------*/
 
1127
 
 
1128
 
 
1129
/*=========================================================================*/
 
1130
void relax()
 
1131
{
 
1132
    int s, T, E;
 
1133
 
 
1134
    for (T = 6; T >= 3; T--) {
 
1135
        for (s = 0; s < Ns; s++) {
 
1136
            if (side[s].mark == 0) {
 
1137
                if ((node[side[s].a].mark == 0) &&
 
1138
                    (node[side[s].b].mark == 0) &&
 
1139
                    (node[side[s].c].mark == 0) &&
 
1140
                    (node[side[s].d].mark == 0)) {
 
1141
                    E = node[side[s].c].Nne + node[side[s].d].Nne 
 
1142
                        - node[side[s].a].Nne - node[side[s].b].Nne;
 
1143
 
 
1144
                    if (E == T) {
 
1145
                        node[side[s].a].Nne++;
 
1146
                        node[side[s].b].Nne++; 
 
1147
                        node[side[s].c].Nne--;
 
1148
                        node[side[s].d].Nne--;  
 
1149
                        swap_side(s);
 
1150
                    }
 
1151
                }
 
1152
            }
 
1153
        }
 
1154
    }
 
1155
}
 
1156
/*-relax-------------------------------------------------------------------*/
 
1157
 
 
1158
 
 
1159
/*=========================================================================*/
 
1160
int smooth()
 
1161
{
 
1162
    int it, s, n, e;
 
1163
 
 
1164
    for (it = 0; it < 10; it++) {    
 
1165
        for (s = 0; s < Ns; s++) {
 
1166
                if (side[s].mark == 0) {
 
1167
                    if (node[side[s].c].mark == 0) {
 
1168
                        node[side[s].c].sumx += node[side[s].d].x;
 
1169
                        node[side[s].c].sumy += node[side[s].d].y;
 
1170
                    }
 
1171
                    if (node[side[s].d].mark == 0) {
 
1172
                        node[side[s].d].sumx += node[side[s].c].x;
 
1173
                        node[side[s].d].sumy += node[side[s].c].y;
 
1174
                    }
 
1175
                }
 
1176
        }
 
1177
        for (n = 0; n < Nn; n++) {
 
1178
            if(node[n].mark == 0) {
 
1179
                node[n].x = node[n].sumx/node[n].Nne;
 
1180
                node[n].y = node[n].sumy/node[n].Nne;
 
1181
                node[n].sumx = 0.0;
 
1182
                node[n].sumy = 0.0;
 
1183
            }
 
1184
        }
 
1185
    }
 
1186
 
 
1187
    for (e = 0; e < Ne; e++) {
 
1188
        if (elem[e].mark != OFF) {
 
1189
            circles(e);
 
1190
        }
 
1191
    }
 
1192
 
 
1193
    return 0;
 
1194
}
 
1195
/*-smooth------------------------------------------------------------------*/
 
1196
 
 
1197
 
 
1198
/*=========================================================================*/
 
1199
void renum()
 
1200
{
 
1201
    int n, s, e, c, d, i, j, k;
 
1202
    int new_elem=0, new_node=0, new_side=0, next_e, next_s, lowest;
 
1203
 
 
1204
    for (n = 0; n < Nn; n++) {
 
1205
        node[n].new_numb = OFF;
 
1206
    }
 
1207
    for (e = 0; e < Ne; e++) {
 
1208
        elem[e].new_numb = OFF;
 
1209
    }
 
1210
    for (s = 0; s < Ns; s++) {
 
1211
        side[s].new_numb = OFF;
 
1212
    }
 
1213
 
 
1214
    /*-------------------------------+
 
1215
    |  Searching the first element.  |
 
1216
    |  It is the first which is ON   |
 
1217
    +-------------------------------*/
 
1218
    for (e = 0; e < Ne; e++) {
 
1219
        if (elem[e].mark != OFF) {
 
1220
            break;
 
1221
        }
 
1222
    }
 
1223
 
 
1224
    /*----------------------------------------------------------+
 
1225
    |  Assigning numbers 0 and 1 to the nodes of first element  |
 
1226
    +----------------------------------------------------------*/
 
1227
    node[elem[e].i].new_numb = new_node;
 
1228
    new_node++;
 
1229
    node[elem[e].j].new_numb = new_node;
 
1230
    new_node++;
 
1231
 
 
1232
    /*%%%%%%%%%%%%%%%%%%%%%%%%%
 
1233
    %                         %
 
1234
    %  Renumeration of nodes  %
 
1235
    %                         % 
 
1236
    %%%%%%%%%%%%%%%%%%%%%%%%%*/
 
1237
    printf("\nRenum Nodes, ");
 
1238
    fflush(stdout);
 
1239
    do {
 
1240
        lowest = Nn + Nn;
 
1241
        next_e = OFF;
 
1242
 
 
1243
        for (e = 0; e < Ne; e++) {
 
1244
            if (elem[e].mark != OFF && elem[e].new_numb == OFF) {
 
1245
                i = node[elem[e].i].new_numb;
 
1246
                j = node[elem[e].j].new_numb;
 
1247
                k = node[elem[e].k].new_numb;
 
1248
 
 
1249
                if (i + j + k + 2 == abs(i) + abs(j) + abs(k)) {
 
1250
                    if ((i == OFF) && (j + k) < lowest) {
 
1251
                        next_e = e;
 
1252
                        lowest = j + k;
 
1253
                    }
 
1254
                    if ((j == OFF) && (i + k) < lowest) {
 
1255
                        next_e = e;
 
1256
                        lowest = i + k;
 
1257
                    }
 
1258
                    if ((k == OFF) && (i + j) < lowest) {
 
1259
                        next_e = e;
 
1260
                        lowest = i + j;
 
1261
                    }
 
1262
                }
 
1263
            }
 
1264
        }
 
1265
            
 
1266
 
 
1267
        if (next_e != OFF) {
 
1268
            i = node[elem[next_e].i].new_numb;
 
1269
            j = node[elem[next_e].j].new_numb;
 
1270
            k = node[elem[next_e].k].new_numb;
 
1271
 
 
1272
            /*----------------------------------+
 
1273
            |  Assign a new number to the node  |
 
1274
            +----------------------------------*/
 
1275
            if (i == OFF) {
 
1276
                node[elem[next_e].i].new_numb = new_node;
 
1277
                new_node++;
 
1278
            }
 
1279
            if (j == OFF) {
 
1280
                node[elem[next_e].j].new_numb = new_node;
 
1281
                new_node++;
 
1282
            }
 
1283
            if (k == OFF) {
 
1284
                node[elem[next_e].k].new_numb = new_node;
 
1285
                new_node++;
 
1286
            }
 
1287
        }
 
1288
    } while (next_e != OFF);
 
1289
 
 
1290
    /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
1291
    %                             %
 
1292
    %  Renumeration of triangles  %
 
1293
    %                             %
 
1294
    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
 
1295
    printf("Triangles, ");
 
1296
    fflush(stdout);
 
1297
    do {
 
1298
        lowest = Nn + Nn + Nn;
 
1299
        next_e = OFF;
 
1300
 
 
1301
        for (e = 0; e < Ne; e++) {
 
1302
            if (elem[e].mark != OFF && elem[e].new_numb == OFF) {
 
1303
                i = node[elem[e].i].new_numb;
 
1304
                j = node[elem[e].j].new_numb;
 
1305
                k = node[elem[e].k].new_numb;
 
1306
 
 
1307
                if ((i + j + k) < lowest) {
 
1308
                    next_e = e;
 
1309
                    lowest = i + j + k;
 
1310
                }
 
1311
            }
 
1312
        }
 
1313
 
 
1314
        if (next_e != OFF) {
 
1315
            elem[next_e].new_numb = new_elem;
 
1316
            new_elem++;
 
1317
        }
 
1318
    } while (next_e != OFF);
 
1319
 
 
1320
 
 
1321
 
 
1322
    /*%%%%%%%%%%%%%%%%%%%%%%%%%
 
1323
    %                         %
 
1324
    %  Renumeration of sides  %
 
1325
    %                         %
 
1326
    %%%%%%%%%%%%%%%%%%%%%%%%%*/
 
1327
    printf("Sides");
 
1328
    fflush(stdout);
 
1329
    do {
 
1330
        lowest = Nn + Nn;
 
1331
        next_s = OFF;
 
1332
 
 
1333
        for (s = 0; s < Ns; s++) {
 
1334
            if (side[s].mark != OFF && side[s].new_numb == OFF) {
 
1335
                c = node[side[s].c].new_numb;
 
1336
                d = node[side[s].d].new_numb;
 
1337
 
 
1338
                if ((c + d) < lowest) {
 
1339
                    lowest = c + d;
 
1340
                    next_s = s;
 
1341
                }
 
1342
            }
 
1343
        }
 
1344
 
 
1345
        if (next_s != OFF) {
 
1346
            side[next_s].new_numb = new_side;
 
1347
            new_side++;
 
1348
        }
 
1349
    } while (next_s != OFF);
 
1350
    printf("\n");
 
1351
}
 
1352
/*-renum-------------------------------------------------------------------*/
 
1353
 
 
1354
 
 
1355
 
 
1356
/*=========================================================================*/
 
1357
int load(void)
 
1358
{
 
1359
    int  c, n, s, M = 0, chains;
 
1360
    double xt, yt, gab;
 
1361
    int m;
 
1362
    double xO, yO, zO, xN, yN, zN, L, Lx, Ly, Lz, dLm, ddL = 0, L_tot;
 
1363
    int *inserted;
 
1364
 
 
1365
    memset(elem, 0, sizeof(elem));
 
1366
    memset(side, 0, sizeof(side));
 
1367
    memset(node, 0, sizeof(node));
 
1368
    
 
1369
    xmax = -GREAT;
 
1370
    xmin = +GREAT;
 
1371
    ymax = -GREAT;
 
1372
    ymin = +GREAT;
 
1373
 
 
1374
    printf("Segments = %d\n", Fl);
 
1375
 
 
1376
    inserted = (int *)calloc(Nc, sizeof(int)); 
 
1377
    chain   = (struct chai *)calloc(Fl + 1, sizeof(struct chai)); /* approximation */
 
1378
 
 
1379
    for (n = 0; n < Nc; n++) {
 
1380
        xmax = max(xmax, point[n].x);
 
1381
        ymax = max(ymax, point[n].y);
 
1382
        xmin = min(xmin, point[n].x);
 
1383
        ymin = min(ymin, point[n].y);
 
1384
    }
 
1385
 
 
1386
    printf("xmin = %f   ymin = %f\n", xmin, ymin);
 
1387
    printf("xmax = %f   ymax = %f\n", xmax, ymax);
 
1388
    
 
1389
 
 
1390
    /*----------------------+
 
1391
      counting the chains
 
1392
     +----------------------*/
 
1393
    chains = 0;
 
1394
    chain[chains].s0 = 0;
 
1395
    for (s = 0; s < Fl; s++) {
 
1396
        point[segment[s].n0].inserted++;
 
1397
        point[segment[s].n1].inserted++;
 
1398
 
 
1399
        segment[s].chain = chains;
 
1400
 
 
1401
        if (segment[s].n1 != segment[s+1].n0) {
 
1402
            chain[chains].s1 = s;
 
1403
            chains++;
 
1404
            chain[chains].s0 = s+1;
 
1405
        }
 
1406
    }
 
1407
 
 
1408
    printf("Chains = %d\n", chains);
 
1409
 
 
1410
    /*-------------------------------------+
 
1411
      counting the nodes on each segment
 
1412
     +-------------------------------------*/
 
1413
    for (s = 0; s < Fl; s++) {
 
1414
        xO = point[segment[s].n0].x;
 
1415
        yO = point[segment[s].n0].y;
 
1416
        xN = point[segment[s].n1].x;
 
1417
        yN = point[segment[s].n1].y;
 
1418
 
 
1419
        Lx = (xN - xO);
 
1420
        Ly = (yN - yO);
 
1421
        L  = sqrt(Lx * Lx + Ly * Ly);
 
1422
 
 
1423
        if ((point[segment[s].n0].F + point[segment[s].n1].F > L ) &&
 
1424
            (segment[s].n0 != segment[s].n1)) {
 
1425
            point[segment[s].n0].F = min(point[segment[s].n0].F,L);
 
1426
            point[segment[s].n1].F = min(point[segment[s].n1].F,L);
 
1427
        }
 
1428
    }
 
1429
 
 
1430
    /*-------------------------------------+
 
1431
      counting the nodes on each segment
 
1432
     +-------------------------------------*/
 
1433
    for (s = 0; s < Fl; s++) {
 
1434
        xO = point[segment[s].n0].x;
 
1435
        yO = point[segment[s].n0].y;
 
1436
        xN = point[segment[s].n1].x;
 
1437
        yN = point[segment[s].n1].y; 
 
1438
 
 
1439
        Lx = (xN - xO);
 
1440
        Ly = (yN - yO);
 
1441
        L  = sqrt(Lx * Lx + Ly * Ly);
 
1442
 
 
1443
        if (point[segment[s].n1].F + point[segment[s].n0].F <= L) {
 
1444
            dLm = 0.5 * (point[segment[s].n0].F + point[segment[s].n1].F);
 
1445
            segment[s].N = (int)ceil(L / dLm);
 
1446
        } else {
 
1447
            segment[s].N = 1;
 
1448
        }
 
1449
    }
 
1450
 
 
1451
 
 
1452
    for (n = 0; n < chains; n++) {
 
1453
        if (segment[chain[n].s0].n0 == segment[chain[n].s1].n1) {
 
1454
            chain[n].type = CLOSED;
 
1455
        }
 
1456
 
 
1457
        if (segment[chain[n].s0].n0 != segment[chain[n].s1].n1) {
 
1458
            chain[n].type = OPEN;
 
1459
        }
 
1460
 
 
1461
        if ((point[segment[chain[n].s0].n0].inserted == 1) &&
 
1462
            (point[segment[chain[n].s1].n1].inserted == 1)) {
 
1463
            chain[n].type = INSIDE;
 
1464
        }
 
1465
    }
 
1466
 
 
1467
    /*------------+
 
1468
    |             |
 
1469
    |  Inserting  |
 
1470
    |             |
 
1471
    +------------*/
 
1472
    xt = 0.5 * (xmax + xmin);
 
1473
    yt = 0.5 * (ymax + ymin);
 
1474
 
 
1475
    gab = max((xmax - xmin), (ymax - ymin));
 
1476
 
 
1477
    Nn = 3;
 
1478
    node[2].x = xt;
 
1479
    node[2].y = yt + 2.8 * gab;
 
1480
    node[2].z = point[0].z;
 
1481
 
 
1482
    node[0].x = xt - 2.0 * gab;
 
1483
    node[0].y = yt - 1.4 * gab;
 
1484
    node[0].z = point[0].z;
 
1485
 
 
1486
    node[1].x = xt + 2.0 * gab;
 
1487
    node[1].y = yt - 1.4 * gab;
 
1488
    node[1].z = point[0].z;
 
1489
 
 
1490
    node[2].inserted = 2;
 
1491
    node[1].inserted = 2;
 
1492
    node[0].inserted = 2;
 
1493
 
 
1494
    node[2].next = 1;
 
1495
    node[1].next = 0;
 
1496
    node[0].next = 2;
 
1497
 
 
1498
    Ne = 1;
 
1499
    elem[0].i  = 0;
 
1500
    elem[0].j  = 1;
 
1501
    elem[0].k  = 2;
 
1502
    elem[0].ei = -1;
 
1503
    elem[0].ej = -1;
 
1504
    elem[0].ek = -1;
 
1505
    elem[0].si = 1;
 
1506
    elem[0].sj = 2;
 
1507
    elem[0].sk = 0;
 
1508
 
 
1509
    Ns = 3;
 
1510
    side[0].c  = 0;
 
1511
    side[0].d  = 1;
 
1512
    side[0].a  = 2;
 
1513
    side[0].b  = -1;
 
1514
 
 
1515
    side[1].c  = 1;
 
1516
    side[1].d  = 2;
 
1517
    side[1].a  = 0;
 
1518
    side[1].b  = -1;
 
1519
 
 
1520
    side[2].c  = 0;
 
1521
    side[2].d  = 2;
 
1522
    side[2].a  = -1;
 
1523
    side[2].b  = 1;
 
1524
 
 
1525
    side[0].ea =  0;
 
1526
    side[0].eb = -1;
 
1527
 
 
1528
    side[1].ea =  0;
 
1529
    side[1].eb = -1;
 
1530
 
 
1531
    side[2].ea = -1;
 
1532
    side[2].eb = 0;
 
1533
 
 
1534
 
 
1535
    for (n = 0; n < Nc; n++) {
 
1536
        point[n].new_numb = OFF;
 
1537
    }
 
1538
    
 
1539
 
 
1540
    for (c = 0; c < chains; c++) {
 
1541
        for (s = chain[c].s0; s <= chain[c].s1; s++) {
 
1542
            xO = point[segment[s].n0].x;
 
1543
            yO = point[segment[s].n0].y;
 
1544
            zO = point[segment[s].n0].z;
 
1545
            xN = point[segment[s].n1].x;
 
1546
            yN = point[segment[s].n1].y; 
 
1547
            zN = point[segment[s].n1].z;
 
1548
 
 
1549
            /*===============
 
1550
            *  first point  *
 
1551
             ===============*/
 
1552
            if (point[segment[s].n0].new_numb == OFF ) {
 
1553
                if (s == chain[c].s0) { /*  first segment in the chain */
 
1554
                    insert_node(xO, yO, zO, OFF,
 
1555
                                OFF, OFF, point[segment[s].n0].mark, OFF, OFF);
 
1556
                } else {
 
1557
                    if (s == chain[c].s1 && segment[s].N == 1) {
 
1558
                        insert_node(xO, yO, zO, OFF,
 
1559
                                    Nn-1, segment[s-1].mark,
 
1560
                                    point[segment[s].n0].mark,
 
1561
                                    segment[s].mark, point[segment[chain[c].s0].n0].new_numb);
 
1562
                    } else {
 
1563
                        insert_node(xO, yO, zO, OFF,
 
1564
                                    Nn-1, segment[s-1].mark, point[segment[s].n0].mark, OFF, OFF);
 
1565
                    }
 
1566
                }
 
1567
 
 
1568
                node[Nn-1].next     = Nn;     /* Nn-1 is index of inserted node */
 
1569
                node[Nn-1].chain    = segment[s].chain;
 
1570
                node[Nn-1].F        = point[segment[s].n0].F;
 
1571
                point[segment[s].n0].new_numb = Nn-1;
 
1572
            }
 
1573
 
 
1574
            Lx = (xN - xO);
 
1575
            Ly = (yN - yO);
 
1576
            Lz = (zN - zO);
 
1577
            L  = sqrt(Lx * Lx + Ly * Ly);
 
1578
            dLm=L/segment[s].N;
 
1579
 
 
1580
            if (point[segment[s].n0].F + point[segment[s].n1].F <= L) { 
 
1581
                if (point[segment[s].n0].F > point[segment[s].n1].F) {
 
1582
                    M = -segment[s].N / 2;
 
1583
                    ddL = (point[segment[s].n1].F-dLm) / M;
 
1584
                } else {
 
1585
                    M = +segment[s].N / 2;
 
1586
                    ddL = (dLm - point[segment[s].n0].F) / M;
 
1587
                }
 
1588
            }
 
1589
 
 
1590
            /*=================
 
1591
             *  middle points  *
 
1592
             =================*/
 
1593
            L_tot = 0;
 
1594
            if (point[segment[s].n0].F + point[segment[s].n1].F <= L) {
 
1595
                for (m = 1; m < abs(segment[s].N); m++) {
 
1596
                    L_tot += (dLm - M * ddL);
 
1597
  
 
1598
                    if (point[segment[s].n0].F > point[segment[s].n1].F) {
 
1599
                        M++;
 
1600
                        if (M == 0 && segment[s].N % 2 == 0) {
 
1601
                            M++;
 
1602
                        }
 
1603
                    } else {
 
1604
                        M--;
 
1605
                        if (M == 0 && segment[s].N % 2 == 0) {
 
1606
                            M--;
 
1607
                        }
 
1608
                    }
 
1609
 
 
1610
                    if (s == chain[c].s1 && m == (abs(segment[s].N) - 1)) {
 
1611
                        insert_node(xO + Lx / L * L_tot, yO + Ly / L * L_tot, zO + Lz / L * L_tot, OFF,
 
1612
                                    Nn - 1, segment[s].mark, segment[s].mark, segment[s].mark, point[segment[s].n1].new_numb);
 
1613
                        node[Nn - 1].next = Nn;
 
1614
                    } else {
 
1615
                        if(m == 1) {
 
1616
                            insert_node(xO + Lx / L * L_tot, yO + Ly / L * L_tot, zO + Lz / L * L_tot, OFF,
 
1617
                                        point[segment[s].n0].new_numb, segment[s].mark, segment[s].mark, OFF, OFF);
 
1618
                            node[Nn - 1].next = Nn;
 
1619
                        } else {
 
1620
                            insert_node(xO + Lx / L * L_tot, yO + Ly / L * L_tot, zO + Lz / L * L_tot, OFF,
 
1621
                                        Nn - 1, segment[s].mark, segment[s].mark, OFF, OFF);
 
1622
                            node[Nn - 1].next = Nn;
 
1623
                        }
 
1624
                    }
 
1625
                            
 
1626
 
 
1627
                    node[Nn - 1].chain    = segment[s].chain;
 
1628
                    node[Nn - 1].F        = 0.5 * (node[Nn - 2].F + (dLm-M * ddL));
 
1629
                }
 
1630
            }
 
1631
 
 
1632
            /*==============
 
1633
             *  last point  * -> just for the inside chains
 
1634
             ==============*/
 
1635
            if ((point[segment[s].n1].new_numb == OFF) && (s==chain[c].s1)) {
 
1636
                insert_node(xN, yN, zN, OFF,
 
1637
                            Nn - 1, segment[s].mark, point[segment[s].n1].mark, OFF, OFF);
 
1638
                node[Nn - 1].next     = OFF;
 
1639
                node[Nn - 1].chain    = segment[s].chain;
 
1640
                node[Nn - 1].F        = point[segment[s].n1].F;
 
1641
            }
 
1642
 
 
1643
            if (chain[c].type == CLOSED && s == chain[c].s1) {
 
1644
                node[Nn - 1].next = point[segment[chain[c].s0].n0].new_numb;
 
1645
            } 
 
1646
 
 
1647
            if (chain[c].type == OPEN && s == chain[c].s1) {
 
1648
                node[Nn-1].next = OFF;
 
1649
            }
 
1650
                    
 
1651
        }
 
1652
    }
 
1653
    
 
1654
    free(segment);
 
1655
    free(inserted);
 
1656
 
 
1657
    return 0;
 
1658
}
 
1659
/*-load--------------------------------------------------------------------*/
 
1660
 
 
1661
static int
 
1662
insert_node_in_group(struct nod *nod, struct group *group)
 
1663
{
 
1664
    int         i;
 
1665
 
 
1666
    /* find if node is already present in this group */
 
1667
    for (i = 0; i < group->nbvtx; i++) {
 
1668
        if ((group->vertices[i].x == nod->x) &&
 
1669
            (group->vertices[i].y == nod->y) &&
 
1670
            (group->vertices[i].z == nod->z)) {
 
1671
            return i;
 
1672
        }
 
1673
    }
 
1674
    /* insert new node */
 
1675
    if (group->nbvtx == group->maxvtx) {
 
1676
        group->maxvtx += VTX_INCR;
 
1677
        group->vertices = (struct vtx   *)realloc(group->vertices, group->maxvtx * sizeof (struct vtx));
 
1678
    }
 
1679
    group->vertices[group->nbvtx].x = nod->x;
 
1680
    group->vertices[group->nbvtx].y = nod->y;
 
1681
    group->vertices[group->nbvtx].z = nod->z;
 
1682
    group->nbvtx++;
 
1683
    return (group->nbvtx - 1);
 
1684
}
 
1685
 
 
1686
static void
 
1687
insert_elem_in_group(struct ele *elem, struct nod *nods)
 
1688
{
 
1689
    int                 grIdx;
 
1690
    double              xmean, ymean;
 
1691
    struct group        *curGrp;
 
1692
    struct surf         *curSurf;
 
1693
 
 
1694
    xmean = (nods[elem->i].x + nods[elem->j].x + nods[elem->k].x) / 3.0;
 
1695
    ymean = (nods[elem->i].y + nods[elem->j].y + nods[elem->k].y) / 3.0;
 
1696
 
 
1697
    grIdx = (int)((xmean - XGroupOffset) / GroupSize) + 
 
1698
        XGroupNb * (int)((ymean - YGroupOffset) / GroupSize);
 
1699
    
 
1700
    curGrp = &(Groups[grIdx]);
 
1701
    
 
1702
    /* insert the surface */
 
1703
    if (curGrp->nbsurf == curGrp->maxsurf) {
 
1704
        if (curGrp->nbsurf == 0) {
 
1705
            ActiveGroups++;
 
1706
        }
 
1707
        curGrp->maxsurf += SURF_INCR;
 
1708
        curGrp->surfaces = (struct surf *)realloc(curGrp->surfaces, curGrp->maxsurf * sizeof (struct surf));
 
1709
    }
 
1710
    curSurf = &(curGrp->surfaces[curGrp->nbsurf++]);
 
1711
 
 
1712
    curSurf->ref[0].u = nods[elem->i].x / TexSize; // + (TexRand * rand()/(RAND_MAX+1.0));
 
1713
    curSurf->ref[0].v = nods[elem->i].y / TexSize; // + (TexRand * rand()/(RAND_MAX+1.0));
 
1714
    curSurf->ref[1].u = nods[elem->j].x / TexSize; // + (TexRand * rand()/(RAND_MAX+1.0));
 
1715
    curSurf->ref[1].v = nods[elem->j].y / TexSize; // + (TexRand * rand()/(RAND_MAX+1.0));
 
1716
    curSurf->ref[2].u = nods[elem->k].x / TexSize; // + (TexRand * rand()/(RAND_MAX+1.0));
 
1717
    curSurf->ref[2].v = nods[elem->k].y / TexSize; // + (TexRand * rand()/(RAND_MAX+1.0));
 
1718
    
 
1719
    curSurf->ref[0].vtxidx = insert_node_in_group(&(nods[elem->i]), curGrp);
 
1720
    curSurf->ref[1].vtxidx = insert_node_in_group(&(nods[elem->j]), curGrp);
 
1721
    curSurf->ref[2].vtxidx = insert_node_in_group(&(nods[elem->k]), curGrp);
 
1722
}
 
1723
 
 
1724
static void
 
1725
groups(void)
 
1726
{
 
1727
    int  e, s, n, r_Nn=0, r_Ns=0, r_Ne=0;
 
1728
 
 
1729
    struct nod *r_node;
 
1730
    struct ele *r_elem;
 
1731
    struct sid *r_side;
 
1732
 
 
1733
    r_node = (struct nod *)calloc(Nn, sizeof(struct nod));
 
1734
    r_elem = (struct ele *)calloc(Ne, sizeof(struct ele));
 
1735
    r_side = (struct sid *)calloc(Ns, sizeof(struct sid));
 
1736
    if (r_side == NULL) {
 
1737
        fprintf(stderr, "Sorry, cannot allocate enough memory !\n");
 
1738
        return ;
 
1739
    }
 
1740
 
 
1741
    for (n = 0; n < Nn; n++) {
 
1742
        if (node[n].mark != OFF && node[n].new_numb != OFF) {
 
1743
            r_Nn++;
 
1744
            r_node[node[n].new_numb].x    = node[n].x;
 
1745
            r_node[node[n].new_numb].y    = node[n].y;
 
1746
            if ((node[n].mark == 0) || (node[n].mark == 100000)) {
 
1747
                r_node[node[n].new_numb].z = GetElevation(node[n].x, node[n].y, node[n].z);
 
1748
            } else {
 
1749
                r_node[node[n].new_numb].z = node[n].z;
 
1750
            }
 
1751
            r_node[node[n].new_numb].mark = node[n].mark;
 
1752
        }
 
1753
    }
 
1754
 
 
1755
 
 
1756
    for (e = 0; e < Ne; e++) {
 
1757
        if (elem[e].mark != OFF && elem[e].new_numb != OFF) {
 
1758
            r_Ne++;
 
1759
            r_elem[elem[e].new_numb].i  = node[elem[e].i].new_numb;
 
1760
            r_elem[elem[e].new_numb].j  = node[elem[e].j].new_numb;
 
1761
            r_elem[elem[e].new_numb].k  = node[elem[e].k].new_numb;
 
1762
            r_elem[elem[e].new_numb].si = side[elem[e].si].new_numb;
 
1763
            r_elem[elem[e].new_numb].sj = side[elem[e].sj].new_numb;
 
1764
            r_elem[elem[e].new_numb].sk = side[elem[e].sk].new_numb;
 
1765
            r_elem[elem[e].new_numb].xv = elem[e].xv;
 
1766
            r_elem[elem[e].new_numb].yv = elem[e].yv;
 
1767
            r_elem[elem[e].new_numb].material = elem[e].material;
 
1768
 
 
1769
            if (elem[e].ei != -1)
 
1770
                r_elem[elem[e].new_numb].ei = elem[elem[e].ei].new_numb;
 
1771
            else
 
1772
                r_elem[elem[e].new_numb].ei = -1;
 
1773
 
 
1774
            if (elem[e].ej != -1)
 
1775
                r_elem[elem[e].new_numb].ej = elem[elem[e].ej].new_numb;
 
1776
            else
 
1777
                r_elem[elem[e].new_numb].ej = -1;
 
1778
 
 
1779
            if (elem[e].ek != -1)
 
1780
                r_elem[elem[e].new_numb].ek = elem[elem[e].ek].new_numb;
 
1781
            else
 
1782
                r_elem[elem[e].new_numb].ek = -1;
 
1783
        }
 
1784
    }
 
1785
 
 
1786
 
 
1787
    for (s = 0; s < Ns; s++) {
 
1788
        if (side[s].mark != OFF && side[s].new_numb != OFF) {
 
1789
            r_Ns++;
 
1790
            r_side[side[s].new_numb].c    = node[side[s].c].new_numb;
 
1791
            r_side[side[s].new_numb].d    = node[side[s].d].new_numb;
 
1792
            r_side[side[s].new_numb].mark = side[s].mark;
 
1793
 
 
1794
            if (side[s].a != OFF) {
 
1795
                r_side[side[s].new_numb].a  = node[side[s].a].new_numb;
 
1796
                r_side[side[s].new_numb].ea = elem[side[s].ea].new_numb;
 
1797
            } else {
 
1798
                r_side[side[s].new_numb].a  = OFF;
 
1799
                r_side[side[s].new_numb].ea = OFF;
 
1800
            }
 
1801
 
 
1802
            if (side[s].b != OFF) {
 
1803
                r_side[side[s].new_numb].b  = node[side[s].b].new_numb;
 
1804
                r_side[side[s].new_numb].eb = elem[side[s].eb].new_numb;
 
1805
            } else {
 
1806
                r_side[side[s].new_numb].b  = OFF;
 
1807
                r_side[side[s].new_numb].eb = OFF;
 
1808
            }
 
1809
        }
 
1810
    }
 
1811
 
 
1812
    for (e = 0; e < r_Ne; e++) {
 
1813
        insert_elem_in_group(&(r_elem[e]), r_node);
 
1814
    }
 
1815
}
 
1816
/*-groups--------------------------------------------------------------------*/
 
1817
 
 
1818
 
 
1819
static void
 
1820
draw_ac(FILE *ac_file, const char *name)
 
1821
{
 
1822
    int                 i, j, k;
 
1823
    struct group        *curGrp;
 
1824
 
 
1825
    Ac3dGroup(ac_file, name, ActiveGroups);
 
1826
 
 
1827
    for (i = 0; i < GroupNb; i++) {
 
1828
        curGrp = &(Groups[i]);
 
1829
        if (curGrp->nbsurf == 0) {
 
1830
            continue;
 
1831
        }
 
1832
        
 
1833
        fprintf(ac_file, "OBJECT poly\n");
 
1834
        fprintf(ac_file, "name \"%s%d\"\n", name, i);
 
1835
        fprintf(ac_file, "texture \"%s\"\n", TexName);
 
1836
        fprintf(ac_file, "numvert %d\n", curGrp->nbvtx);
 
1837
        for (j = 0; j < curGrp->nbvtx; j++) {
 
1838
            fprintf(ac_file, "%g %g %g\n", curGrp->vertices[j].x, curGrp->vertices[j].z, -curGrp->vertices[j].y);
 
1839
        }
 
1840
        fprintf(ac_file, "numsurf %d\n", curGrp->nbsurf);
 
1841
        for (j = 0; j < curGrp->nbsurf; j++) {
 
1842
            fprintf(ac_file, "SURF 0x30\n");
 
1843
            fprintf(ac_file, "mat 0\n");
 
1844
            fprintf(ac_file, "refs 3\n");
 
1845
            for (k = 0; k < 3; k++) {
 
1846
                fprintf(ac_file, "%d %f %f\n", curGrp->surfaces[j].ref[k].vtxidx, curGrp->surfaces[j].ref[k].u, curGrp->surfaces[j].ref[k].v);
 
1847
            }
 
1848
        }
 
1849
        fprintf(ac_file, "kids 0\n");
 
1850
    }
 
1851
    
 
1852
}
 
1853
/*-draw_ac--------------------------------------------------------------------*/
 
1854
 
 
1855
 
 
1856
 
 
1857
 
 
1858
static void
 
1859
generate_mesh(void)
 
1860
{
 
1861
    int         Nn0;
 
1862
    
 
1863
    printf("Load Chains\n");
 
1864
    load();
 
1865
    erase();
 
1866
    classify();
 
1867
    
 
1868
    do {
 
1869
        Nn0 = Nn;
 
1870
        new_node();
 
1871
        classify();
 
1872
        if (Nn > (MAX_NODES / 2 - 2)) {
 
1873
            break;
 
1874
        }
 
1875
        if (Nn == Nn0) {
 
1876
            break;
 
1877
        }
 
1878
    } while (ugly != OFF);
 
1879
 
 
1880
    neighbours();
 
1881
    relax();
 
1882
    smooth();
 
1883
    renum();
 
1884
    fflush(stdout);
 
1885
    materials();
 
1886
    groups();
 
1887
}
 
1888
 
 
1889
 
 
1890
static int
 
1891
GetTrackOrientation(tTrack *track)
 
1892
{
 
1893
    tTrackSeg   *seg;
 
1894
    int         i;
 
1895
    tdble       ang = 0;
 
1896
 
 
1897
    for (i = 0, seg = track->seg->next; i < track->nseg; i++, seg = seg->next) {
 
1898
        switch (seg->type) {
 
1899
        case TR_STR:
 
1900
            break;
 
1901
        case TR_LFT:
 
1902
            ang += seg->arc;
 
1903
            break;
 
1904
        case TR_RGT:
 
1905
            ang -= seg->arc;
 
1906
            break;
 
1907
        }
 
1908
    }
 
1909
    if (ang > 0) {
 
1910
        return ANTICLOCKWISE;
 
1911
    }
 
1912
    return CLOCKWISE;
 
1913
}
 
1914
 
 
1915
 
 
1916
#define ADD_POINT(_x,_y,_z,_F,_mark)                    \
 
1917
do {                                                    \
 
1918
    point[nbvert].x = _x;                               \
 
1919
    point[nbvert].y = _y;                               \
 
1920
    point[nbvert].z = _z;                               \
 
1921
    point[nbvert].F = _F;                               \
 
1922
    point[nbvert].mark = _mark;                         \
 
1923
    nbvert++;                                           \
 
1924
    if (nbvert == maxVert) {                            \
 
1925
        maxVert *= 2;                                   \
 
1926
        point = (struct nod*)realloc(point, maxVert);   \
 
1927
        memset(&point[nbvert], 0, maxVert / 2);         \
 
1928
    }                                                   \
 
1929
} while (0)
 
1930
 
 
1931
/** Generate the terrain mesh.
 
1932
    @param      rightside       1 if use the right side
 
1933
                                0 if use the left side
 
1934
    @param      reverse         1 if reverse the points order
 
1935
                                0 if keep the track order
 
1936
    @param      exterior        1 if it is the exterior
 
1937
                                0 if it is the interior
 
1938
    @param      
 
1939
    @return     None.
 
1940
*/
 
1941
static void
 
1942
GenerateMesh(tTrack *Track, int rightside, int reverse, int exterior)
 
1943
{
 
1944
    int         startNeeded;
 
1945
    int         i, j, nbvert, maxVert;
 
1946
    tdble       ts, step, anz;
 
1947
    tTrackSeg   *seg;
 
1948
    tTrackSeg   *mseg;
 
1949
    tTrkLocPos  trkpos;
 
1950
    tdble       x, y;
 
1951
    tdble       radiusr, radiusl;
 
1952
    struct nod  *point2;
 
1953
    int         nb_relief_vtx, nb_relief_seg;
 
1954
 
 
1955
    printf("GenerateMesh: ");
 
1956
    if (rightside) {
 
1957
        printf("right, ");
 
1958
    } else {
 
1959
        printf("left, ");
 
1960
    }
 
1961
    if (reverse) {
 
1962
        printf("reverse order, ");
 
1963
    } else {
 
1964
        printf("normal order, ");
 
1965
    }
 
1966
    if (exterior) {
 
1967
        printf("exterior\n");
 
1968
    } else {
 
1969
        printf("interior\n");
 
1970
    }
 
1971
 
 
1972
    CountRelief(1 - exterior, &nb_relief_vtx, &nb_relief_seg);
 
1973
 
 
1974
    printf("Relief: %d vtx, %d seg\n", nb_relief_vtx, nb_relief_seg);
 
1975
    
 
1976
    /* Estimation of the number of points */
 
1977
    maxVert = ((int)(Track->length) + nb_relief_vtx) * sizeof(struct nod);
 
1978
    point = (struct nod*)calloc(1, maxVert);
 
1979
    
 
1980
    if (rightside) {
 
1981
        nbvert = 0;
 
1982
 
 
1983
        if (exterior && !reverse && UseBorder) {
 
1984
            ADD_POINT(-Margin, -Margin, ExtHeight, GridStep, 100000);
 
1985
            ADD_POINT(Track->max.x + Margin, -Margin, ExtHeight, GridStep, 100000);
 
1986
            ADD_POINT(Track->max.x + Margin, Track->max.y + Margin, ExtHeight, GridStep, 100000);
 
1987
            ADD_POINT(-Margin, Track->max.y + Margin, ExtHeight, GridStep, 100000);
 
1988
        }
 
1989
 
 
1990
        /* Right side */
 
1991
        startNeeded = 1;
 
1992
        for (i = 0, mseg = Track->seg->next; i < Track->nseg; i++, mseg = mseg->next) {
 
1993
            if (mseg->rside != NULL) {
 
1994
                seg = mseg->rside;
 
1995
                if (seg->rside != NULL) {
 
1996
                    seg = seg->rside;
 
1997
                }
 
1998
            } else {
 
1999
                seg = mseg;
 
2000
            }
 
2001
            if (startNeeded) {
 
2002
                ADD_POINT(seg->vertex[TR_SR].x, seg->vertex[TR_SR].y, seg->vertex[TR_SR].z, GridStep, i+1);
 
2003
            }
 
2004
            switch (seg->type) {
 
2005
            case TR_STR:
 
2006
                ts = TrackStep;
 
2007
                trkpos.seg = seg;
 
2008
                while (ts < seg->length) {
 
2009
                    trkpos.toStart = ts;
 
2010
                    trkpos.toRight = 0;
 
2011
                    RtTrackLocal2Global(&trkpos, &x, &y, TR_TORIGHT);
 
2012
                    ADD_POINT(x, y, RtTrackHeightL(&trkpos), GridStep, i+1);
 
2013
                    ts += TrackStep;
 
2014
                }
 
2015
                break;
 
2016
            case TR_LFT:
 
2017
                step = TrackStep / (mseg->radiusr);
 
2018
                anz = seg->angle[TR_ZS] + step;
 
2019
                ts = step;
 
2020
                radiusr = seg->radiusr;
 
2021
                trkpos.seg = seg;
 
2022
                trkpos.toRight = 0;
 
2023
                while (anz < seg->angle[TR_ZE]) {
 
2024
                    trkpos.toStart = ts;
 
2025
                    /* right */
 
2026
                    RtTrackLocal2Global(&trkpos, &x, &y, TR_TORIGHT);
 
2027
                    ADD_POINT(x, y, RtTrackHeightL(&trkpos), GridStep, i+1);
 
2028
                    ts += step;
 
2029
                    anz += step;
 
2030
                }
 
2031
                break;
 
2032
            case TR_RGT:
 
2033
                step = TrackStep / (mseg->radiusl);
 
2034
                anz = seg->angle[TR_ZS] - step;
 
2035
                ts = step;
 
2036
                radiusr = seg->radiusr;
 
2037
                trkpos.seg = seg;
 
2038
                trkpos.toRight = 0;
 
2039
                while (anz > seg->angle[TR_ZE]) {
 
2040
                    trkpos.toStart = ts;
 
2041
                    /* right */
 
2042
                    RtTrackLocal2Global(&trkpos, &x, &y, TR_TORIGHT);
 
2043
                    ADD_POINT(x, y, RtTrackHeightL(&trkpos), GridStep, i+1);
 
2044
                    ts += step;
 
2045
                    anz -= step;
 
2046
                }
 
2047
                break;
 
2048
            }
 
2049
            if (i != (Track->nseg - 1)) {
 
2050
                ADD_POINT(seg->vertex[TR_ER].x, seg->vertex[TR_ER].y, seg->vertex[TR_ER].z, GridStep, i+1);
 
2051
                startNeeded = 0;
 
2052
            }
 
2053
        }
 
2054
 
 
2055
        if (exterior && reverse && UseBorder) {
 
2056
            ADD_POINT(-Margin,Track->max.y + Margin, ExtHeight, GridStep, 100000);
 
2057
            ADD_POINT(Track->max.x + Margin, Track->max.y + Margin, ExtHeight, GridStep, 100000);
 
2058
            ADD_POINT(Track->max.x + Margin, -Margin, ExtHeight, GridStep, 100000);
 
2059
            ADD_POINT(-Margin, -Margin, ExtHeight, GridStep, 100000);
 
2060
        }
 
2061
 
 
2062
    } else {
 
2063
        nbvert = 0;
 
2064
 
 
2065
        if (exterior && !reverse && UseBorder) {
 
2066
            ADD_POINT(-Margin, -Margin, ExtHeight, GridStep, 100000);
 
2067
            ADD_POINT(Track->max.x + Margin, -Margin, ExtHeight, GridStep, 100000);
 
2068
            ADD_POINT(Track->max.x + Margin, Track->max.y + Margin, ExtHeight, GridStep, 100000);
 
2069
            ADD_POINT(-Margin, Track->max.y + Margin, ExtHeight, GridStep, 100000);
 
2070
        }
 
2071
 
 
2072
        /* Left Side */
 
2073
        startNeeded = 1;
 
2074
        for (i = 0, mseg = Track->seg->next; i < Track->nseg; i++, mseg = mseg->next) {
 
2075
            if (mseg->lside) {
 
2076
                seg = mseg->lside;
 
2077
                if (seg->lside) {
 
2078
                    seg = seg->lside;
 
2079
                }
 
2080
            } else {
 
2081
                seg = mseg;
 
2082
            }
 
2083
            if (startNeeded) {
 
2084
                ADD_POINT(seg->vertex[TR_SL].x, seg->vertex[TR_SL].y, seg->vertex[TR_SL].z, GridStep, i+1);
 
2085
            }
 
2086
            
 
2087
            switch (seg->type) {
 
2088
            case TR_STR:
 
2089
                ts = TrackStep;
 
2090
                trkpos.seg = seg;
 
2091
                while (ts < seg->length) {
 
2092
                    trkpos.toStart = ts;
 
2093
                    trkpos.toRight = RtTrackGetWidth(seg, ts);
 
2094
                    RtTrackLocal2Global(&trkpos, &x, &y, TR_TORIGHT);
 
2095
                    ADD_POINT(x, y, RtTrackHeightL(&trkpos), GridStep, i+1);
 
2096
                    ts += TrackStep;
 
2097
                }
 
2098
                break;
 
2099
            case TR_LFT:
 
2100
                step = TrackStep / (mseg->radiusr);
 
2101
                anz = seg->angle[TR_ZS] + step;
 
2102
                ts = step;
 
2103
                radiusl = seg->radiusl;
 
2104
                trkpos.seg = seg;
 
2105
                while (anz < seg->angle[TR_ZE]) {
 
2106
                    trkpos.toStart = ts;
 
2107
                    trkpos.toRight = RtTrackGetWidth(seg, ts);
 
2108
                    RtTrackLocal2Global(&trkpos, &x, &y, TR_TORIGHT);
 
2109
                    /* left */
 
2110
                    ADD_POINT(x, y, RtTrackHeightL(&trkpos), GridStep, i+1);
 
2111
                    ts += step;
 
2112
                    anz += step;
 
2113
                }
 
2114
                break;
 
2115
            case TR_RGT:
 
2116
                step = TrackStep / (mseg->radiusl);
 
2117
                anz = seg->angle[TR_ZS] - step;
 
2118
                ts = step;
 
2119
                radiusl = seg->radiusl;
 
2120
                trkpos.seg = seg;
 
2121
                while (anz > seg->angle[TR_ZE]) {
 
2122
                    trkpos.toStart = ts;
 
2123
                    trkpos.toRight = RtTrackGetWidth(seg, ts);
 
2124
                    RtTrackLocal2Global(&trkpos, &x, &y, TR_TORIGHT);
 
2125
                    /* left */
 
2126
                    ADD_POINT(x, y, RtTrackHeightL(&trkpos), GridStep, i+1);
 
2127
                    ts += step;
 
2128
                    anz -= step;
 
2129
                }
 
2130
                break;
 
2131
            }
 
2132
            if (i != (Track->nseg - 1)) {
 
2133
                ADD_POINT(seg->vertex[TR_EL].x, seg->vertex[TR_EL].y, seg->vertex[TR_EL].z, GridStep, i+1);
 
2134
                startNeeded = 0;
 
2135
            }
 
2136
        }
 
2137
 
 
2138
        if (exterior && reverse && UseBorder) {
 
2139
            ADD_POINT(-Margin, Track->max.y + Margin, ExtHeight, GridStep, 100000);
 
2140
            ADD_POINT(Track->max.x + Margin, Track->max.y + Margin, ExtHeight, GridStep, 100000);
 
2141
            ADD_POINT(Track->max.x + Margin, -Margin, ExtHeight, GridStep, 100000);
 
2142
            ADD_POINT(-Margin, -Margin, ExtHeight, GridStep, 100000);
 
2143
        }
 
2144
    }
 
2145
 
 
2146
    Nc = nbvert;
 
2147
    segment = (struct seg *)calloc(Nc + 1 + nb_relief_seg, sizeof(struct seg));
 
2148
    segment[Nc].n0 = -1;
 
2149
    segment[Nc].n1 = -1;
 
2150
 
 
2151
    if (reverse){
 
2152
        /* reverse order */
 
2153
        point2 = (struct nod*)calloc(Nc + 1 + nb_relief_vtx, sizeof(struct nod));
 
2154
        for (i = 0; i < Nc; i++) {
 
2155
            memcpy(&(point2[i]), &(point[Nc-i-1]), sizeof(struct nod));
 
2156
        }
 
2157
        free(point);
 
2158
        point = point2;
 
2159
    }
 
2160
 
 
2161
    Fl = 0;
 
2162
    if (exterior && !UseBorder) {
 
2163
        GenRelief(0);
 
2164
    }
 
2165
    if (exterior && UseBorder) {
 
2166
        segment[0].n0 = 0;
 
2167
        segment[0].n1 = 1;
 
2168
        segment[0].mark = 100000;
 
2169
        segment[1].n0 = 1;
 
2170
        segment[1].n1 = 2;
 
2171
        segment[1].mark = 100000;
 
2172
        segment[2].n0 = 2;
 
2173
        segment[2].n1 = 3;
 
2174
        segment[2].mark = 100000;
 
2175
        segment[3].n0 = 3;
 
2176
        segment[3].n1 = 0;
 
2177
        segment[3].mark = 100000;
 
2178
 
 
2179
        i = 0;
 
2180
        j = 0;
 
2181
        do {
 
2182
            segment[j+4].n0 = i+4;
 
2183
            i = (i + 1) % (Nc - 4);
 
2184
            segment[j+4].n1 = i+4;
 
2185
            segment[j+4].mark = 2;
 
2186
            j++;
 
2187
        } while (i != 0);
 
2188
        
 
2189
    } else {
 
2190
        i = 0;
 
2191
        j = Fl;
 
2192
        do {
 
2193
            segment[j].n0 = i;
 
2194
            i = (i + 1) % nbvert;
 
2195
            segment[j].n1 = i;
 
2196
            segment[j].mark = 1;
 
2197
            j++;
 
2198
        } while (i != 0);
 
2199
        Fl = j;
 
2200
    }
 
2201
    if (exterior) {
 
2202
        if (UseBorder) {
 
2203
            Fl = Nc;
 
2204
            GenRelief(0);
 
2205
        }
 
2206
    } else {
 
2207
        Fl = Nc;
 
2208
        GenRelief(1);
 
2209
    }
 
2210
    segment[Fl].n0 = -1;
 
2211
    segment[Fl].n1 = -1;
 
2212
    generate_mesh();
 
2213
}
 
2214
 
 
2215
 
 
2216
void
 
2217
GenerateTerrain(tTrack *track, void *TrackHandle, char *outfile, FILE *AllFd, int noElevation)
 
2218
{
 
2219
    const char  *FileName;
 
2220
    const char  *mat;
 
2221
    FILE        *curFd = NULL;
 
2222
 
 
2223
    TrackStep = GfParmGetNum(TrackHandle, TRK_SECT_TERRAIN, TRK_ATT_TSTEP, NULL, 10.0);
 
2224
    GfOut("Track step: %.2f\n", TrackStep);
 
2225
    Margin    = GfParmGetNum(TrackHandle, TRK_SECT_TERRAIN, TRK_ATT_BMARGIN, NULL, 100.0);
 
2226
    GridStep  = GfParmGetNum(TrackHandle, TRK_SECT_TERRAIN, TRK_ATT_BSTEP, NULL, 10.0);
 
2227
    ExtHeight = GfParmGetNum(TrackHandle, TRK_SECT_TERRAIN, TRK_ATT_BHEIGHT, NULL, 0.0);
 
2228
    GfOut("Border margin: %.2f    step: %.2f    height: %.2f\n", Margin, GridStep, ExtHeight);
 
2229
    
 
2230
    GroupSize = GfParmGetNum(TrackHandle, TRK_SECT_TERRAIN, TRK_ATT_GRPSZ, NULL, 100.0);
 
2231
    XGroupOffset = track->min.x - Margin;
 
2232
    YGroupOffset = track->min.y - Margin;
 
2233
 
 
2234
    XGroupNb = (int)((track->max.x + Margin - (track->min.x - Margin)) / GroupSize) + 1;
 
2235
    
 
2236
    GroupNb = XGroupNb * ((int)((track->max.y + Margin - (track->min.y - Margin)) / GroupSize) + 1);
 
2237
    
 
2238
    Groups = (struct group *)calloc(GroupNb, sizeof (struct group));
 
2239
    ActiveGroups = 0;
 
2240
    
 
2241
    
 
2242
 
 
2243
    mat = GfParmGetStr(TrackHandle, TRK_SECT_TERRAIN, TRK_ATT_SURF, "grass");
 
2244
    if (track->version < 4) {
 
2245
        sprintf(buf, "%s/%s/%s", TRK_SECT_SURFACES, TRK_LST_SURF, mat);
 
2246
    } else {
 
2247
        sprintf(buf, "%s/%s", TRK_SECT_SURFACES, mat);
 
2248
    }
 
2249
    TexName = GfParmGetStr(TrackHandle, buf, TRK_ATT_TEXTURE, "grass.rgb");
 
2250
    TexSize = GfParmGetNum(TrackHandle, buf, TRK_ATT_TEXSIZE, (char*)NULL, 20.0);
 
2251
    TexRand = GfParmGetNum(TrackHandle, buf, TRK_ATT_SURFRAND, (char*)NULL, TexSize / 10.0);
 
2252
 
 
2253
    FileName = GfParmGetStr(TrackHandle, TRK_SECT_TERRAIN, TRK_ATT_RELIEF, NULL);
 
2254
    if (FileName) {
 
2255
        sprintf(buf, "tracks/%s/%s/%s", track->category, track->internalname, FileName);
 
2256
        LoadRelief(TrackHandle, buf);
 
2257
    }
 
2258
    if (noElevation == -1) {
 
2259
        FileName = GfParmGetStr(TrackHandle, TRK_SECT_TERRAIN, TRK_ATT_ELEVATION, NULL);
 
2260
        if (FileName) {
 
2261
            sprintf(buf, "tracks/%s/%s/%s", track->category, track->internalname, FileName);
 
2262
            LoadElevation(track, TrackHandle, buf);
 
2263
        }
 
2264
    }
 
2265
    
 
2266
        if (outfile) {
 
2267
                // Attempt to fix AC3D (the application) segfault on opening the msh file.
 
2268
                //curFd = Ac3dOpen(outfile, 2);
 
2269
                curFd = Ac3dOpen(outfile, 1);
 
2270
        }
 
2271
 
 
2272
    if (GetTrackOrientation(track) == CLOCKWISE) {
 
2273
 
 
2274
        GenerateMesh(track, 1 /* right */, 1 /* reverse */, 0 /* interior */);
 
2275
        GenerateMesh(track, 0 /* left */,  0 /* normal */,  1 /* exterior */);
 
2276
        if (curFd) {
 
2277
            draw_ac(curFd, "TERR");
 
2278
        }
 
2279
        if (AllFd) {
 
2280
            draw_ac(AllFd, "TERR");
 
2281
        }
 
2282
    } else {
 
2283
        GenerateMesh(track, 0 /* left */,  0 /* normal */,  0 /* interior */);
 
2284
        GenerateMesh(track, 1 /* right */, 1 /* reverse */, 1 /* exterior */);
 
2285
        if (curFd) {
 
2286
            draw_ac(curFd, "TERR");
 
2287
        }
 
2288
        if (AllFd) {
 
2289
            draw_ac(AllFd, "TERR");
 
2290
        }
 
2291
    }
 
2292
    if (curFd) {
 
2293
        Ac3dClose(curFd);
 
2294
    }
 
2295
    
 
2296
}