1 /* splittris.c -- reassemble the pieces produced by splittris
3 * Written by Curtis Olson, started January 1998.
5 * Copyright (C) 1997 Curtis L. Olson - curt@infoplane.com
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.
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.
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.
22 * (Log is kept at end of this file) */
27 #include <stdlib.h> /* for atoi() */
29 #include <sys/stat.h> /* for stat() */
30 #include <unistd.h> /* for stat() */
32 #include "assemtris.h"
34 #include <Include/fg_constants.h>
35 #include <Include/fg_types.h>
36 #include <Bucket/bucketutils.h>
40 #define OFFSET_LON 0.1
41 #define OFFSET_LAT 0.1
44 #define OFFSET_LON 0.0
45 #define OFFSET_LAT 0.0
50 static double nodes[MAX_NODES][3];
51 static double exnodes[MAX_NODES][3];
55 fgBUCKET ne_index, nw_index, sw_index, se_index;
56 fgBUCKET north_index, south_index, east_index, west_index;
59 /* return the file base name ( foo/bar/file.ext = file.ext ) */
60 void extract_file(char *in, char *base) {
66 while ( (i >= 0) && (in[i] != '/') ) {
75 /* return the file path name ( foo/bar/file.ext = foo/bar ) */
76 void extract_path(char *in, char *base) {
83 while ( (i >= 0) && (in[i] != '/') ) {
91 /* check to see if specified node is in the extra list */
92 int is_extra_node(double *n) {
95 for ( i = 1; i <= excount; i++ ) {
96 // we only check lon/lat in case the height got fooled with
98 if ( (fabs(n[0] - exnodes[i][0]) < FG_EPSILON) &&
99 (fabs(n[1] - exnodes[i][1]) < FG_EPSILON) ) {
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) {
113 int i, junk1, junk2, junk3;
115 // load extra nodes if they exist
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);
121 if ( excount > MAX_NODES - 1 ) {
122 printf("Error, too many 'extra' nodes, increase array size\n");
125 printf(" Expecting %d 'extra' nodes\n", excount);
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]);
139 /* check if a file exists */
140 int file_exists(char *file) {
141 struct stat stat_buf;
144 printf("checking %s ... ", file);
146 result = stat(file, &stat_buf);
149 /* stat failed, no file */
150 printf("not found.\n");
153 /* stat succeeded, file exists */
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];
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) ) {
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) ) {
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) ) {
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) ) {
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) ) {
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) ) {
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) ) {
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) ) {
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) ) {
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) ) {
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) ) {
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) ) {
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) ) {
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) ) {
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) ) {
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) ) {
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) ) {
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) ) {
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) ) {
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) ) {
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) ) {
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) ) {
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) ) {
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) ) {
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) ) {
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) {
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);
361 printf("not opening\n");
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 ==
372 void read_nodes(FILE *fp, double offset_lon, double offset_lat) {
377 offset_lon = offset_lat = 0.0;
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]);
383 ex_index = is_extra_node(n);
385 if ( ex_index == 0 ) {
387 nodes[nodecount][0] = n[0] + offset_lon;
388 nodes[nodecount][1] = n[1] + offset_lat;
389 nodes[nodecount][2] = n[2];
392 printf("read_nodes(%d) %.2f %.2f %.2f %s", nodecount,
393 nodes[nodecount][0], nodes[nodecount][1],
394 nodes[nodecount][2], line);
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];
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) {
413 FILE *ne, *nw, *se, *sw, *north, *south, *east, *west, *body;
415 // load extra nodes if they exist
416 strcpy(exfile, basename);
417 strcat(exfile, ".node.ex");
418 read_extra_nodes(exfile);
420 ne = my_open(basename, basepath, ".ne");
421 read_nodes(ne, OFFSET_LON, OFFSET_LAT);
424 nw = my_open(basename, basepath, ".nw");
425 read_nodes(nw, -1.0 * OFFSET_LON, OFFSET_LAT);
428 se = my_open(basename, basepath, ".se");
429 read_nodes(se, OFFSET_LON, -1.0 * OFFSET_LAT);
432 sw = my_open(basename, basepath, ".sw");
433 read_nodes(sw, -1.0 * OFFSET_LON, -1.0 * OFFSET_LAT);
436 north = my_open(basename, basepath, ".north");
437 read_nodes(north, 0.0, OFFSET_LAT);
440 south = my_open(basename, basepath, ".south");
441 read_nodes(south, 0.0, -1.0 * OFFSET_LAT);
444 east = my_open(basename, basepath, ".east");
445 read_nodes(east, OFFSET_LON, 0.0);
448 west = my_open(basename, basepath, ".west");
449 read_nodes(west, -1.0 * OFFSET_LON, 0.0);
452 body = my_open(basename, basepath, ".body");
453 read_nodes(body, 0.0, 0.0);
458 /* dump in WaveFront .obj format */
459 void dump_nodes(char *basename) {
464 /* generate output file name */
465 strcpy(file, basename);
466 // len = strlen(file);
467 // file[len-2] = '\0';
468 strcat(file, ".node");
471 printf("Creating node file: %s\n", file);
472 printf(" writing vertices in .node format.\n");
473 fd = fopen(file, "w");
475 fprintf(fd, "%d 2 1 0\n", excount + nodecount);
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]);
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]);
493 int main(int argc, char **argv) {
494 char basename[256], basepath[256], temp[256];
499 strcpy(basename, argv[1]);
500 len = strlen(basename);
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);
508 /* find the index of the current file */
509 extract_file(basename, temp);
510 // len = strlen(temp);
512 // temp[len-2] = '\0';
514 tmp_index = atoi(temp);
515 printf("%ld\n", tmp_index);
516 fgBucketParseIndex(tmp_index, &my_index);
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);
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);
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);
538 /* load the input data files */
539 build_node_list(basename, basepath);
541 /* dump in WaveFront .obj format */
542 dump_nodes(basename);
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.
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.
559 * Revision 1.11 1998/08/06 12:47:59 curt
560 * Removed overlap in tiles as a test.
562 * Revision 1.10 1998/07/21 04:34:20 curt
563 * Mods to handle extra nodes (i.e. preserve cutouts).
565 * Revision 1.9 1998/07/04 00:55:39 curt
566 * typedef'd struct fgBUCKET.
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.
572 * Revision 1.7 1998/04/14 02:26:00 curt
573 * Code reorganizations. Added a Lib/ directory for more general libraries.
575 * Revision 1.6 1998/04/08 22:54:58 curt
576 * Adopted Gnu automake/autoconf system.
578 * Revision 1.5 1998/03/03 16:00:52 curt
579 * More c++ compile tweaks.
581 * Revision 1.4 1998/01/31 00:41:23 curt
582 * Made a few changes converting floats to doubles.
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/
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
592 * Revision 1.1 1998/01/15 02:45:26 curt