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