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