]> git.mxchange.org Git - flightgear.git/blob - AssemTris/assemtris.c
c6e4edeb77eec26ccaf20abaafa0c5c47272b479
[flightgear.git] / AssemTris / assemtris.c
1 /* splittris.c -- reassemble the pieces produced by splittris
2  *
3  * Written by Curtis Olson, started January 1998.
4  *
5  * Copyright (C) 1997  Curtis L. Olson  - curt@infoplane.com
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20  *
21  * $Id$
22  * (Log is kept at end of this file) */
23
24
25 #include <math.h>
26 #include <stdio.h>
27 #include <stdlib.h>   /* for atoi() */
28 #include <string.h>
29 #include <sys/stat.h> /* for stat() */
30 #include <unistd.h>   /* for stat() */
31
32 #include "assemtris.h"
33
34 #include <Include/fg_constants.h>
35 #include <Include/fg_types.h>
36 #include <Bucket/bucketutils.h>
37
38
39 /*
40 #define OFFSET_LON 0.1
41 #define OFFSET_LAT 0.1
42 */
43
44 #define OFFSET_LON 0.0
45 #define OFFSET_LAT 0.0
46
47 int nodecount = 0;
48 int excount = 0;
49
50 static double nodes[MAX_NODES][3];
51 static double exnodes[MAX_NODES][3];
52
53
54 fgBUCKET my_index;
55 fgBUCKET ne_index, nw_index, sw_index, se_index;
56 fgBUCKET north_index, south_index, east_index, west_index;
57
58
59 /* return the file base name ( foo/bar/file.ext = file.ext ) */
60 void extract_file(char *in, char *base) {
61     int len, i;
62
63     len = strlen(in);
64
65     i = len - 1;
66     while ( (i >= 0) && (in[i] != '/') ) {
67         i--;
68     }
69
70     in += (i + 1);
71     strcpy(base, in);
72 }
73
74
75 /* return the file path name ( foo/bar/file.ext = foo/bar ) */
76 void extract_path(char *in, char *base) {
77     int len, i;
78
79     len = strlen(in);
80     strcpy(base, in);
81
82     i = len - 1;
83     while ( (i >= 0) && (in[i] != '/') ) {
84         i--;
85     }
86
87     base[i] = '\0';
88 }
89
90
91 /* check to see if specified node is in the extra list */
92 int is_extra_node(double *n) {
93     int i;
94
95     for ( i = 1; i <= excount; i++ ) {
96         // we only check lon/lat in case the height got fooled with
97         // along the way
98         if ( (fabs(n[0] - exnodes[i][0]) < FG_EPSILON) &&
99              (fabs(n[1] - exnodes[i][1]) < FG_EPSILON) ) {
100             return(i);
101         }
102     }
103
104     return(0);
105 }
106
107 /* Read all the extra nodes.  These typically define inner areas to
108    exclude from triangulations.  There will be a .poly file that
109    refers to these by position number which assumes all the extra
110    nodes come first in the generated .node file. */
111 void read_extra_nodes(char *exfile) {
112     FILE *fd;
113     int i, junk1, junk2, junk3;
114
115     // load extra nodes if they exist
116     excount = 0;
117     if ( (fd = fopen(exfile, "r")) != NULL ) {
118         printf("Found and 'extra' node file = %s\n", exfile);
119         fscanf(fd, "%d %d %d %d", &excount, &junk1, &junk2, &junk3);
120
121         if ( excount > MAX_NODES - 1 ) {
122             printf("Error, too many 'extra' nodes, increase array size\n");
123             exit(-1);
124         } else {
125             printf("    Expecting %d 'extra' nodes\n", excount);
126         }
127
128         for ( i = 1; i <= excount; i++ ) {
129             fscanf(fd, "%d %lf %lf %lf\n", &junk1, 
130                    &exnodes[i][0], &exnodes[i][1], &exnodes[i][2]);
131             printf("(extra) %d %.2f %.2f %.2f\n", 
132                     i, exnodes[i][0], exnodes[i][1], exnodes[i][2]);
133         }
134         fclose(fd);
135     }
136 }
137
138
139 /* check if a file exists */
140 int file_exists(char *file) {
141     struct stat stat_buf;
142     int result;
143
144     printf("checking %s ... ", file);
145
146     result = stat(file, &stat_buf);
147
148     if ( result != 0 ) {
149         /* stat failed, no file */
150         printf("not found.\n");
151         return(0);
152     } else {
153         /* stat succeeded, file exists */
154         printf("exists.\n");
155         return(1);
156     }
157 }
158
159
160 /* check to see if a shared object exists */
161 int shared_object_exists(char *basepath, char *ext, char *file) {
162     char scene_path[256];
163     long int index;
164
165     if ( strcmp(ext, ".sw") == 0 ) {
166         fgBucketGenBasePath(&my_index, scene_path);
167         index = fgBucketGenIndex(&my_index);
168         sprintf(file, "%s/%s/%ld.1.sw", basepath, scene_path, index);
169         if ( file_exists(file) ) {
170             return(1);
171         }
172         fgBucketGenBasePath(&west_index, scene_path);
173         index = fgBucketGenIndex(&west_index);
174         sprintf(file, "%s/%s/%ld.1.se", basepath, scene_path, index);
175         if ( file_exists(file) ) {
176             return(1);
177         }
178         fgBucketGenBasePath(&sw_index, scene_path);
179         index = fgBucketGenIndex(&sw_index);
180         sprintf(file, "%s/%s/%ld.1.ne", basepath, scene_path, index);
181         if ( file_exists(file) ) {
182             return(1);
183         }
184         fgBucketGenBasePath(&south_index, scene_path);
185         index = fgBucketGenIndex(&south_index);
186         sprintf(file, "%s/%s/%ld.1.nw", basepath, scene_path, index);
187         if ( file_exists(file) ) {
188             return(1);
189         }
190     }
191
192     if ( strcmp(ext, ".se") == 0 ) {
193         fgBucketGenBasePath(&my_index, scene_path);
194         index = fgBucketGenIndex(&my_index);
195         sprintf(file, "%s/%s/%ld.1.se", basepath, scene_path, index);
196         if ( file_exists(file) ) {
197             return(1);
198         }
199         fgBucketGenBasePath(&east_index, scene_path);
200         index = fgBucketGenIndex(&east_index);
201         sprintf(file, "%s/%s/%ld.1.sw", basepath, scene_path, index);
202         if ( file_exists(file) ) {
203             return(1);
204         }
205         fgBucketGenBasePath(&se_index, scene_path);
206         index = fgBucketGenIndex(&se_index);
207         sprintf(file, "%s/%s/%ld.1.nw", basepath, scene_path, index);
208         if ( file_exists(file) ) {
209             return(1);
210         }
211         fgBucketGenBasePath(&south_index, scene_path);
212         index = fgBucketGenIndex(&south_index);
213         sprintf(file, "%s/%s/%ld.1.ne", basepath, scene_path, index);
214         if ( file_exists(file) ) {
215             return(1);
216         }
217     }
218
219     if ( strcmp(ext, ".ne") == 0 ) {
220         fgBucketGenBasePath(&my_index, scene_path);
221         index = fgBucketGenIndex(&my_index);
222         sprintf(file, "%s/%s/%ld.1.ne", basepath, scene_path, index);
223         if ( file_exists(file) ) {
224             return(1);
225         }
226         fgBucketGenBasePath(&east_index, scene_path);
227         index = fgBucketGenIndex(&east_index);
228         sprintf(file, "%s/%s/%ld.1.nw", basepath, scene_path, index);
229         if ( file_exists(file) ) {
230             return(1);
231         }
232         fgBucketGenBasePath(&ne_index, scene_path);
233         index = fgBucketGenIndex(&ne_index);
234         sprintf(file, "%s/%s/%ld.1.sw", basepath, scene_path, index);
235         if ( file_exists(file) ) {
236             return(1);
237         }
238         fgBucketGenBasePath(&north_index, scene_path);
239         index = fgBucketGenIndex(&north_index);
240         sprintf(file, "%s/%s/%ld.1.se", basepath, scene_path, index);
241         if ( file_exists(file) ) {
242             return(1);
243         }
244     }
245
246     if ( strcmp(ext, ".nw") == 0 ) {
247         fgBucketGenBasePath(&my_index, scene_path);
248         index = fgBucketGenIndex(&my_index);
249         sprintf(file, "%s/%s/%ld.1.nw", basepath, scene_path, index);
250         if ( file_exists(file) ) {
251             return(1);
252         }
253         fgBucketGenBasePath(&west_index, scene_path);
254         index = fgBucketGenIndex(&west_index);
255         sprintf(file, "%s/%s/%ld.1.ne", basepath, scene_path, index);
256         if ( file_exists(file) ) {
257             return(1);
258         }
259         fgBucketGenBasePath(&nw_index, scene_path);
260         index = fgBucketGenIndex(&nw_index);
261         sprintf(file, "%s/%s/%ld.1.se", basepath, scene_path, index);
262         if ( file_exists(file) ) {
263             return(1);
264         }
265         fgBucketGenBasePath(&north_index, scene_path);
266         index = fgBucketGenIndex(&north_index);
267         sprintf(file, "%s/%s/%ld.1.sw", basepath, scene_path, index);
268         if ( file_exists(file) ) {
269             return(1);
270         }
271     }
272
273     if ( strcmp(ext, ".south") == 0 ) {
274         fgBucketGenBasePath(&my_index, scene_path);
275         index = fgBucketGenIndex(&my_index);
276         sprintf(file, "%s/%s/%ld.1.south", basepath, scene_path, index);
277         if ( file_exists(file) ) {
278             return(1);
279         }
280         fgBucketGenBasePath(&south_index, scene_path);
281         index = fgBucketGenIndex(&south_index);
282         sprintf(file, "%s/%s/%ld.1.north", basepath, scene_path, index);
283         if ( file_exists(file) ) {
284             return(1);
285         }
286     }
287
288     if ( strcmp(ext, ".north") == 0 ) {
289         fgBucketGenBasePath(&my_index, scene_path);
290         index = fgBucketGenIndex(&my_index);
291         sprintf(file, "%s/%s/%ld.1.north", basepath, scene_path, index);
292         if ( file_exists(file) ) {
293             return(1);
294         }
295         fgBucketGenBasePath(&north_index, scene_path);
296         index = fgBucketGenIndex(&north_index);
297         sprintf(file, "%s/%s/%ld.1.south", basepath, scene_path, index);
298         if ( file_exists(file) ) {
299             return(1);
300         }
301     }
302
303     if ( strcmp(ext, ".west") == 0 ) {
304         fgBucketGenBasePath(&my_index, scene_path);
305         index = fgBucketGenIndex(&my_index);
306         sprintf(file, "%s/%s/%ld.1.west", basepath, scene_path, index);
307         if ( file_exists(file) ) {
308             return(1);
309         }
310         fgBucketGenBasePath(&west_index, scene_path);
311         index = fgBucketGenIndex(&west_index);
312         sprintf(file, "%s/%s/%ld.1.east", basepath, scene_path, index);
313         if ( file_exists(file) ) {
314             return(1);
315         }
316     }
317
318     if ( strcmp(ext, ".east") == 0 ) {
319         fgBucketGenBasePath(&my_index, scene_path);
320         index = fgBucketGenIndex(&my_index);
321         sprintf(file, "%s/%s/%ld.1.east", basepath, scene_path, index);
322         if ( file_exists(file) ) {
323             return(1);
324         }
325         fgBucketGenBasePath(&east_index, scene_path);
326         index = fgBucketGenIndex(&east_index);
327         sprintf(file, "%s/%s/%ld.1.west", basepath, scene_path, index);
328         if ( file_exists(file) ) {
329             return(1);
330         }
331     }
332
333     if ( strcmp(ext, ".body") == 0 ) {
334         fgBucketGenBasePath(&my_index, scene_path);
335         index = fgBucketGenIndex(&my_index);
336         sprintf(file, "%s/%s/%ld.1.body", basepath, scene_path, index);
337         if ( file_exists(file) ) {
338             return(1);
339         }
340     }
341
342     return(0);
343 }
344
345
346 /* my custom file opening routine ... don't open if a shared edge or
347  * vertex alread exists */
348 FILE *my_open(char *basename, char *basepath, char *ext) {
349     FILE *fp;
350     char filename[256];
351
352     /* check if a shared object already exists */
353     if ( shared_object_exists(basepath, ext, filename) ) {
354         /* not an actual file open error, but we've already got the
355          * shared edge, so we don't want to create another one */
356         fp = fopen(filename, "r");
357         printf("Opening %s\n", filename);
358         return(fp);
359     } else {
360         /* open the file */
361         printf("not opening\n");
362         return(NULL);
363     }
364 }
365
366
367 /* given a file pointer, read all the gdn (geodetic nodes from it.)
368    The specified offset values (in arcsec) are used to overlap the
369    edges of the tile slightly to cover gaps induced by floating point
370    precision problems.  1 arcsec == about 100 feet so 0.01 arcsec ==
371    about 1 foot */
372 void read_nodes(FILE *fp, double offset_lon, double offset_lat) {
373     double n[3];
374     char line[256];
375     int ex_index;
376
377     offset_lon = offset_lat = 0.0;
378
379     while ( fgets(line, 250, fp) != NULL ) {
380         if ( strncmp(line, "gdn ", 4) == 0 ) {
381             sscanf(line, "gdn %lf %lf %lf\n", &n[0], &n[1], &n[2]);
382
383             ex_index = is_extra_node(n);
384
385             if ( ex_index == 0 ) {
386                 // not an extra node
387                 nodes[nodecount][0] = n[0] + offset_lon;
388                 nodes[nodecount][1] = n[1] + offset_lat;
389                 nodes[nodecount][2] = n[2];
390
391                 /*
392                   printf("read_nodes(%d) %.2f %.2f %.2f %s", nodecount, 
393                       nodes[nodecount][0], nodes[nodecount][1], 
394                       nodes[nodecount][2], line);
395                       */
396
397                 nodecount++;
398             } else {
399                 // is an extra node
400                 printf("found extra node %.2f %.2f %.2f\n", n[0], n[1], n[2]);
401                 // preserve the DEM altitude for now
402                 exnodes[ex_index][2] = n[2];
403             }
404         }
405     }
406 }
407
408
409 /* load in nodes from the various split and shared pieces to
410  * reconstruct a tile */
411 void build_node_list(char *basename, char *basepath) {
412     char exfile[256];
413     FILE *ne, *nw, *se, *sw, *north, *south, *east, *west, *body;
414
415     // load extra nodes if they exist
416     strcpy(exfile, basename);
417     strcat(exfile, ".node.ex");
418     read_extra_nodes(exfile);
419
420     ne = my_open(basename, basepath, ".ne");
421     read_nodes(ne, OFFSET_LON, OFFSET_LAT);
422     fclose(ne);
423
424     nw = my_open(basename, basepath, ".nw");
425     read_nodes(nw, -1.0 * OFFSET_LON, OFFSET_LAT);
426     fclose(nw);
427
428     se = my_open(basename, basepath, ".se");
429     read_nodes(se, OFFSET_LON, -1.0 * OFFSET_LAT);
430     fclose(se);
431
432     sw = my_open(basename, basepath, ".sw");
433     read_nodes(sw, -1.0 * OFFSET_LON, -1.0 * OFFSET_LAT);
434     fclose(sw);
435
436     north = my_open(basename, basepath, ".north");
437     read_nodes(north, 0.0, OFFSET_LAT);
438     fclose(north);
439
440     south = my_open(basename, basepath, ".south");
441     read_nodes(south, 0.0, -1.0 * OFFSET_LAT);
442     fclose(south);
443
444     east = my_open(basename, basepath, ".east");
445     read_nodes(east, OFFSET_LON, 0.0);
446     fclose(east);
447
448     west = my_open(basename, basepath, ".west");
449     read_nodes(west, -1.0 * OFFSET_LON, 0.0);
450     fclose(west);
451
452     body = my_open(basename, basepath, ".body");
453     read_nodes(body, 0.0, 0.0);
454     fclose(body);
455 }
456
457
458 /* dump in WaveFront .obj format */
459 void dump_nodes(char *basename) {
460     char file[256];
461     FILE *fd;
462     int i;
463
464     /* generate output file name */
465     strcpy(file, basename);
466     // len = strlen(file);
467     // file[len-2] = '\0';
468     strcat(file, ".node");
469     
470     /* dump vertices */
471     printf("Creating node file:  %s\n", file);
472     printf("  writing vertices in .node format.\n");
473     fd = fopen(file, "w");
474
475     fprintf(fd, "%d 2 1 0\n", excount + nodecount);
476
477     // now write out extra node data
478     for ( i = 1; i <= excount; i++ ) {
479         fprintf(fd, "%d %.2f %.2f %.2f 0\n", 
480                 i, exnodes[i][0], exnodes[i][1], exnodes[i][2]);
481     }
482
483     /* now write out actual node data */
484     for ( i = 0; i < nodecount; i++ ) {
485         fprintf(fd, "%d %.2f %.2f %.2f 0\n", excount + i + 1,
486                nodes[i][0], nodes[i][1], nodes[i][2]);
487     }
488
489     fclose(fd);
490 }
491
492
493 int main(int argc, char **argv) {
494     char basename[256], basepath[256], temp[256];
495     long int tmp_index;
496     int len;
497
498     // derive base name
499     strcpy(basename, argv[1]);
500     len = strlen(basename);
501
502     /* find the base path of the file */
503     extract_path(basename, basepath);
504     extract_path(basepath, basepath);
505     extract_path(basepath, basepath);
506     printf("%s\n", basepath);
507
508     /* find the index of the current file */
509     extract_file(basename, temp);
510     // len = strlen(temp);
511     // if ( len >= 2 ) {
512     //    temp[len-2] = '\0';
513     // }
514     tmp_index = atoi(temp);
515     printf("%ld\n", tmp_index);
516     fgBucketParseIndex(tmp_index, &my_index);
517
518     printf("bucket = %d %d %d %d\n", 
519            my_index.lon, my_index.lat, my_index.x, my_index.y);
520     /* generate the indexes of the neighbors */
521     fgBucketOffset(&my_index, &ne_index,  1,  1);
522     fgBucketOffset(&my_index, &nw_index, -1,  1);
523     fgBucketOffset(&my_index, &se_index,  1, -1);
524     fgBucketOffset(&my_index, &sw_index, -1, -1);
525
526     fgBucketOffset(&my_index, &north_index,  0,  1);
527     fgBucketOffset(&my_index, &south_index,  0, -1);
528     fgBucketOffset(&my_index, &east_index,  1,  0);
529     fgBucketOffset(&my_index, &west_index, -1,  0);
530
531     /*
532     printf("Corner indexes = %ld %ld %ld %ld\n", 
533            ne_index, nw_index, sw_index, se_index);
534     printf("Edge indexes = %ld %ld %ld %ld\n",
535            north_index, south_index, east_index, west_index);
536            */
537
538     /* load the input data files */
539     build_node_list(basename, basepath);
540
541     /* dump in WaveFront .obj format */
542     dump_nodes(basename);
543
544     return(0);
545 }
546
547
548 /* $Log$
549 /* Revision 1.13  1998/09/21 20:56:30  curt
550 /* Changes to avoid setting airport area nodes back to their original
551 /* elevations if they have been changed.
552 /*
553  *
554  * Revision 1.12  1998/09/09 16:24:51  curt
555  * Fixed a bug in the handling of exclude files which was causing
556  *   a crash by calling fclose() on an invalid file handle.
557  * Removed overlapping offsets.
558  *
559  * Revision 1.11  1998/08/06 12:47:59  curt
560  * Removed overlap in tiles as a test.
561  *
562  * Revision 1.10  1998/07/21 04:34:20  curt
563  * Mods to handle extra nodes (i.e. preserve cutouts).
564  *
565  * Revision 1.9  1998/07/04 00:55:39  curt
566  * typedef'd struct fgBUCKET.
567  *
568  * Revision 1.8  1998/06/01 17:58:19  curt
569  * Added a slight border overlap to try to minimize pixel wide gaps between
570  * tiles due to round off error.  This is not a perfect solution, but helps.
571  *
572  * Revision 1.7  1998/04/14 02:26:00  curt
573  * Code reorganizations.  Added a Lib/ directory for more general libraries.
574  *
575  * Revision 1.6  1998/04/08 22:54:58  curt
576  * Adopted Gnu automake/autoconf system.
577  *
578  * Revision 1.5  1998/03/03 16:00:52  curt
579  * More c++ compile tweaks.
580  *
581  * Revision 1.4  1998/01/31 00:41:23  curt
582  * Made a few changes converting floats to doubles.
583  *
584  * Revision 1.3  1998/01/27 18:37:00  curt
585  * Lots of updates to get back in sync with changes made over in .../Src/
586  *
587  * Revision 1.2  1998/01/15 21:33:36  curt
588  * Assembling triangles and building a new .node file with the proper shared
589  * vertices now works.  Now we just have to use the shared normals and we'll
590  * be all set.
591  *
592  * Revision 1.1  1998/01/15 02:45:26  curt
593  * Initial revision.
594  *
595  */