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