]> git.mxchange.org Git - flightgear.git/blob - AssemTris/assemtris.c
Fixed a bug in the handling of exclude files which was causing
[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(1);
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
376     offset_lon = offset_lat = 0.0;
377
378     while ( fgets(line, 250, fp) != NULL ) {
379         if ( strncmp(line, "gdn ", 4) == 0 ) {
380             sscanf(line, "gdn %lf %lf %lf\n", &n[0], &n[1], &n[2]);
381
382             if ( ! is_extra_node(n) ) {
383                 nodes[nodecount][0] = n[0] + offset_lon;
384                 nodes[nodecount][1] = n[1] + offset_lat;
385                 nodes[nodecount][2] = n[2];
386
387                 /*
388                   printf("read_nodes(%d) %.2f %.2f %.2f %s", nodecount, 
389                       nodes[nodecount][0], nodes[nodecount][1], 
390                       nodes[nodecount][2], line);
391                       */
392
393                 nodecount++;
394             } else {
395                 printf("found extra node %.2f %.2f %.2f\n", n[0], n[1], n[2]);
396             }
397         }
398     }
399 }
400
401
402 /* load in nodes from the various split and shared pieces to
403  * reconstruct a tile */
404 void build_node_list(char *basename, char *basepath) {
405     char exfile[256];
406     FILE *ne, *nw, *se, *sw, *north, *south, *east, *west, *body;
407
408     // load extra nodes if they exist
409     strcpy(exfile, basename);
410     strcat(exfile, ".node.ex");
411     read_extra_nodes(exfile);
412
413     ne = my_open(basename, basepath, ".ne");
414     read_nodes(ne, OFFSET_LON, OFFSET_LAT);
415     fclose(ne);
416
417     nw = my_open(basename, basepath, ".nw");
418     read_nodes(nw, -1.0 * OFFSET_LON, OFFSET_LAT);
419     fclose(nw);
420
421     se = my_open(basename, basepath, ".se");
422     read_nodes(se, OFFSET_LON, -1.0 * OFFSET_LAT);
423     fclose(se);
424
425     sw = my_open(basename, basepath, ".sw");
426     read_nodes(sw, -1.0 * OFFSET_LON, -1.0 * OFFSET_LAT);
427     fclose(sw);
428
429     north = my_open(basename, basepath, ".north");
430     read_nodes(north, 0.0, OFFSET_LAT);
431     fclose(north);
432
433     south = my_open(basename, basepath, ".south");
434     read_nodes(south, 0.0, -1.0 * OFFSET_LAT);
435     fclose(south);
436
437     east = my_open(basename, basepath, ".east");
438     read_nodes(east, OFFSET_LON, 0.0);
439     fclose(east);
440
441     west = my_open(basename, basepath, ".west");
442     read_nodes(west, -1.0 * OFFSET_LON, 0.0);
443     fclose(west);
444
445     body = my_open(basename, basepath, ".body");
446     read_nodes(body, 0.0, 0.0);
447     fclose(body);
448 }
449
450
451 /* dump in WaveFront .obj format */
452 void dump_nodes(char *basename) {
453     char file[256];
454     FILE *fd;
455     int i;
456
457     /* generate output file name */
458     strcpy(file, basename);
459     // len = strlen(file);
460     // file[len-2] = '\0';
461     strcat(file, ".node");
462     
463     /* dump vertices */
464     printf("Creating node file:  %s\n", file);
465     printf("  writing vertices in .node format.\n");
466     fd = fopen(file, "w");
467
468     fprintf(fd, "%d 2 1 0\n", excount + nodecount);
469
470     // now write out extra node data
471     for ( i = 1; i <= excount; i++ ) {
472         fprintf(fd, "%d %.2f %.2f %.2f 0\n", 
473                 i, exnodes[i][0], exnodes[i][1], exnodes[i][2]);
474     }
475
476     /* now write out actual node data */
477     for ( i = 0; i < nodecount; i++ ) {
478         fprintf(fd, "%d %.2f %.2f %.2f 0\n", excount + i + 1,
479                nodes[i][0], nodes[i][1], nodes[i][2]);
480     }
481
482     fclose(fd);
483 }
484
485
486 int main(int argc, char **argv) {
487     char basename[256], basepath[256], temp[256];
488     long int tmp_index;
489     int len;
490
491     // derive base name
492     strcpy(basename, argv[1]);
493     len = strlen(basename);
494
495     /* find the base path of the file */
496     extract_path(basename, basepath);
497     extract_path(basepath, basepath);
498     extract_path(basepath, basepath);
499     printf("%s\n", basepath);
500
501     /* find the index of the current file */
502     extract_file(basename, temp);
503     // len = strlen(temp);
504     // if ( len >= 2 ) {
505     //    temp[len-2] = '\0';
506     // }
507     tmp_index = atoi(temp);
508     printf("%ld\n", tmp_index);
509     fgBucketParseIndex(tmp_index, &my_index);
510
511     printf("bucket = %d %d %d %d\n", 
512            my_index.lon, my_index.lat, my_index.x, my_index.y);
513     /* generate the indexes of the neighbors */
514     fgBucketOffset(&my_index, &ne_index,  1,  1);
515     fgBucketOffset(&my_index, &nw_index, -1,  1);
516     fgBucketOffset(&my_index, &se_index,  1, -1);
517     fgBucketOffset(&my_index, &sw_index, -1, -1);
518
519     fgBucketOffset(&my_index, &north_index,  0,  1);
520     fgBucketOffset(&my_index, &south_index,  0, -1);
521     fgBucketOffset(&my_index, &east_index,  1,  0);
522     fgBucketOffset(&my_index, &west_index, -1,  0);
523
524     /*
525     printf("Corner indexes = %ld %ld %ld %ld\n", 
526            ne_index, nw_index, sw_index, se_index);
527     printf("Edge indexes = %ld %ld %ld %ld\n",
528            north_index, south_index, east_index, west_index);
529            */
530
531     /* load the input data files */
532     build_node_list(basename, basepath);
533
534     /* dump in WaveFront .obj format */
535     dump_nodes(basename);
536
537     return(0);
538 }
539
540
541 /* $Log$
542 /* Revision 1.12  1998/09/09 16:24:51  curt
543 /* Fixed a bug in the handling of exclude files which was causing
544 /*   a crash by calling fclose() on an invalid file handle.
545 /* Removed overlapping offsets.
546 /*
547  * Revision 1.11  1998/08/06 12:47:59  curt
548  * Removed overlap in tiles as a test.
549  *
550  * Revision 1.10  1998/07/21 04:34:20  curt
551  * Mods to handle extra nodes (i.e. preserve cutouts).
552  *
553  * Revision 1.9  1998/07/04 00:55:39  curt
554  * typedef'd struct fgBUCKET.
555  *
556  * Revision 1.8  1998/06/01 17:58:19  curt
557  * Added a slight border overlap to try to minimize pixel wide gaps between
558  * tiles due to round off error.  This is not a perfect solution, but helps.
559  *
560  * Revision 1.7  1998/04/14 02:26:00  curt
561  * Code reorganizations.  Added a Lib/ directory for more general libraries.
562  *
563  * Revision 1.6  1998/04/08 22:54:58  curt
564  * Adopted Gnu automake/autoconf system.
565  *
566  * Revision 1.5  1998/03/03 16:00:52  curt
567  * More c++ compile tweaks.
568  *
569  * Revision 1.4  1998/01/31 00:41:23  curt
570  * Made a few changes converting floats to doubles.
571  *
572  * Revision 1.3  1998/01/27 18:37:00  curt
573  * Lots of updates to get back in sync with changes made over in .../Src/
574  *
575  * Revision 1.2  1998/01/15 21:33:36  curt
576  * Assembling triangles and building a new .node file with the proper shared
577  * vertices now works.  Now we just have to use the shared normals and we'll
578  * be all set.
579  *
580  * Revision 1.1  1998/01/15 02:45:26  curt
581  * Initial revision.
582  *
583  */