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) {
376 offset_lon = offset_lat = 0.0;
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]);
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];
388 printf("read_nodes(%d) %.2f %.2f %.2f %s", nodecount,
389 nodes[nodecount][0], nodes[nodecount][1],
390 nodes[nodecount][2], line);
395 printf("found extra node %.2f %.2f %.2f\n", n[0], n[1], n[2]);
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) {
406 FILE *ne, *nw, *se, *sw, *north, *south, *east, *west, *body;
408 // load extra nodes if they exist
409 strcpy(exfile, basename);
410 strcat(exfile, ".node.ex");
411 read_extra_nodes(exfile);
413 ne = my_open(basename, basepath, ".ne");
414 read_nodes(ne, OFFSET_LON, OFFSET_LAT);
417 nw = my_open(basename, basepath, ".nw");
418 read_nodes(nw, -1.0 * OFFSET_LON, OFFSET_LAT);
421 se = my_open(basename, basepath, ".se");
422 read_nodes(se, OFFSET_LON, -1.0 * OFFSET_LAT);
425 sw = my_open(basename, basepath, ".sw");
426 read_nodes(sw, -1.0 * OFFSET_LON, -1.0 * OFFSET_LAT);
429 north = my_open(basename, basepath, ".north");
430 read_nodes(north, 0.0, OFFSET_LAT);
433 south = my_open(basename, basepath, ".south");
434 read_nodes(south, 0.0, -1.0 * OFFSET_LAT);
437 east = my_open(basename, basepath, ".east");
438 read_nodes(east, OFFSET_LON, 0.0);
441 west = my_open(basename, basepath, ".west");
442 read_nodes(west, -1.0 * OFFSET_LON, 0.0);
445 body = my_open(basename, basepath, ".body");
446 read_nodes(body, 0.0, 0.0);
451 /* dump in WaveFront .obj format */
452 void dump_nodes(char *basename) {
457 /* generate output file name */
458 strcpy(file, basename);
459 // len = strlen(file);
460 // file[len-2] = '\0';
461 strcat(file, ".node");
464 printf("Creating node file: %s\n", file);
465 printf(" writing vertices in .node format.\n");
466 fd = fopen(file, "w");
468 fprintf(fd, "%d 2 1 0\n", excount + nodecount);
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]);
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]);
486 int main(int argc, char **argv) {
487 char basename[256], basepath[256], temp[256];
492 strcpy(basename, argv[1]);
493 len = strlen(basename);
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);
501 /* find the index of the current file */
502 extract_file(basename, temp);
503 // len = strlen(temp);
505 // temp[len-2] = '\0';
507 tmp_index = atoi(temp);
508 printf("%ld\n", tmp_index);
509 fgBucketParseIndex(tmp_index, &my_index);
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);
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);
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);
531 /* load the input data files */
532 build_node_list(basename, basepath);
534 /* dump in WaveFront .obj format */
535 dump_nodes(basename);
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.
547 * Revision 1.11 1998/08/06 12:47:59 curt
548 * Removed overlap in tiles as a test.
550 * Revision 1.10 1998/07/21 04:34:20 curt
551 * Mods to handle extra nodes (i.e. preserve cutouts).
553 * Revision 1.9 1998/07/04 00:55:39 curt
554 * typedef'd struct fgBUCKET.
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.
560 * Revision 1.7 1998/04/14 02:26:00 curt
561 * Code reorganizations. Added a Lib/ directory for more general libraries.
563 * Revision 1.6 1998/04/08 22:54:58 curt
564 * Adopted Gnu automake/autoconf system.
566 * Revision 1.5 1998/03/03 16:00:52 curt
567 * More c++ compile tweaks.
569 * Revision 1.4 1998/01/31 00:41:23 curt
570 * Made a few changes converting floats to doubles.
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/
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
580 * Revision 1.1 1998/01/15 02:45:26 curt