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>
42 static double nodes[MAX_NODES][3];
43 static double exnodes[MAX_NODES][3];
47 fgBUCKET ne_index, nw_index, sw_index, se_index;
48 fgBUCKET north_index, south_index, east_index, west_index;
51 /* return the file base name ( foo/bar/file.ext = file.ext ) */
52 void extract_file(char *in, char *base) {
58 while ( (i >= 0) && (in[i] != '/') ) {
67 /* return the file path name ( foo/bar/file.ext = foo/bar ) */
68 void extract_path(char *in, char *base) {
75 while ( (i >= 0) && (in[i] != '/') ) {
83 /* check to see if specified node is in the extra list */
84 int is_extra_node(double *n) {
87 for ( i = 1; i <= excount; i++ ) {
88 // we only check lon/lat in case the height got fooled with
90 if ( (fabs(n[0] - exnodes[i][0]) < FG_EPSILON) &&
91 (fabs(n[1] - exnodes[i][1]) < FG_EPSILON) ) {
99 /* Read all the extra nodes. These typically define inner areas to
100 exclude from triangulations. There will be a .poly file that
101 refers to these by position number which assumes all the extra
102 nodes come first in the generated .node file. */
103 void read_extra_nodes(char *exfile) {
105 int i, junk1, junk2, junk3;
107 // load extra nodes if they exist
109 if ( (fd = fopen(exfile, "r")) != NULL ) {
110 printf("Found and 'extra' node file = %s\n", exfile);
111 fscanf(fd, "%d %d %d %d", &excount, &junk1, &junk2, &junk3);
113 if ( excount > MAX_NODES - 1 ) {
114 printf("Error, too many 'extra' nodes, increase array size\n");
117 printf(" Expecting %d 'extra' nodes\n", excount);
120 for ( i = 1; i <= excount; i++ ) {
121 fscanf(fd, "%d %lf %lf %lf\n", &junk1,
122 &exnodes[i][0], &exnodes[i][1], &exnodes[i][2]);
123 printf("(extra) %d %.2f %.2f %.2f\n",
124 i, exnodes[i][0], exnodes[i][1], exnodes[i][2]);
131 /* check if a file exists */
132 int file_exists(char *file) {
133 struct stat stat_buf;
136 printf("checking %s ... ", file);
138 result = stat(file, &stat_buf);
141 /* stat failed, no file */
142 printf("not found.\n");
145 /* stat succeeded, file exists */
152 /* check to see if a shared object exists */
153 int shared_object_exists(char *basepath, char *ext, char *file) {
154 char scene_path[256];
157 if ( strcmp(ext, ".sw") == 0 ) {
158 fgBucketGenBasePath(&my_index, scene_path);
159 index = fgBucketGenIndex(&my_index);
160 sprintf(file, "%s/%s/%ld.1.sw", basepath, scene_path, index);
161 if ( file_exists(file) ) {
164 fgBucketGenBasePath(&west_index, scene_path);
165 index = fgBucketGenIndex(&west_index);
166 sprintf(file, "%s/%s/%ld.1.se", basepath, scene_path, index);
167 if ( file_exists(file) ) {
170 fgBucketGenBasePath(&sw_index, scene_path);
171 index = fgBucketGenIndex(&sw_index);
172 sprintf(file, "%s/%s/%ld.1.ne", basepath, scene_path, index);
173 if ( file_exists(file) ) {
176 fgBucketGenBasePath(&south_index, scene_path);
177 index = fgBucketGenIndex(&south_index);
178 sprintf(file, "%s/%s/%ld.1.nw", basepath, scene_path, index);
179 if ( file_exists(file) ) {
184 if ( strcmp(ext, ".se") == 0 ) {
185 fgBucketGenBasePath(&my_index, scene_path);
186 index = fgBucketGenIndex(&my_index);
187 sprintf(file, "%s/%s/%ld.1.se", basepath, scene_path, index);
188 if ( file_exists(file) ) {
191 fgBucketGenBasePath(&east_index, scene_path);
192 index = fgBucketGenIndex(&east_index);
193 sprintf(file, "%s/%s/%ld.1.sw", basepath, scene_path, index);
194 if ( file_exists(file) ) {
197 fgBucketGenBasePath(&se_index, scene_path);
198 index = fgBucketGenIndex(&se_index);
199 sprintf(file, "%s/%s/%ld.1.nw", basepath, scene_path, index);
200 if ( file_exists(file) ) {
203 fgBucketGenBasePath(&south_index, scene_path);
204 index = fgBucketGenIndex(&south_index);
205 sprintf(file, "%s/%s/%ld.1.ne", basepath, scene_path, index);
206 if ( file_exists(file) ) {
211 if ( strcmp(ext, ".ne") == 0 ) {
212 fgBucketGenBasePath(&my_index, scene_path);
213 index = fgBucketGenIndex(&my_index);
214 sprintf(file, "%s/%s/%ld.1.ne", basepath, scene_path, index);
215 if ( file_exists(file) ) {
218 fgBucketGenBasePath(&east_index, scene_path);
219 index = fgBucketGenIndex(&east_index);
220 sprintf(file, "%s/%s/%ld.1.nw", basepath, scene_path, index);
221 if ( file_exists(file) ) {
224 fgBucketGenBasePath(&ne_index, scene_path);
225 index = fgBucketGenIndex(&ne_index);
226 sprintf(file, "%s/%s/%ld.1.sw", basepath, scene_path, index);
227 if ( file_exists(file) ) {
230 fgBucketGenBasePath(&north_index, scene_path);
231 index = fgBucketGenIndex(&north_index);
232 sprintf(file, "%s/%s/%ld.1.se", basepath, scene_path, index);
233 if ( file_exists(file) ) {
238 if ( strcmp(ext, ".nw") == 0 ) {
239 fgBucketGenBasePath(&my_index, scene_path);
240 index = fgBucketGenIndex(&my_index);
241 sprintf(file, "%s/%s/%ld.1.nw", basepath, scene_path, index);
242 if ( file_exists(file) ) {
245 fgBucketGenBasePath(&west_index, scene_path);
246 index = fgBucketGenIndex(&west_index);
247 sprintf(file, "%s/%s/%ld.1.ne", basepath, scene_path, index);
248 if ( file_exists(file) ) {
251 fgBucketGenBasePath(&nw_index, scene_path);
252 index = fgBucketGenIndex(&nw_index);
253 sprintf(file, "%s/%s/%ld.1.se", basepath, scene_path, index);
254 if ( file_exists(file) ) {
257 fgBucketGenBasePath(&north_index, scene_path);
258 index = fgBucketGenIndex(&north_index);
259 sprintf(file, "%s/%s/%ld.1.sw", basepath, scene_path, index);
260 if ( file_exists(file) ) {
265 if ( strcmp(ext, ".south") == 0 ) {
266 fgBucketGenBasePath(&my_index, scene_path);
267 index = fgBucketGenIndex(&my_index);
268 sprintf(file, "%s/%s/%ld.1.south", basepath, scene_path, index);
269 if ( file_exists(file) ) {
272 fgBucketGenBasePath(&south_index, scene_path);
273 index = fgBucketGenIndex(&south_index);
274 sprintf(file, "%s/%s/%ld.1.north", basepath, scene_path, index);
275 if ( file_exists(file) ) {
280 if ( strcmp(ext, ".north") == 0 ) {
281 fgBucketGenBasePath(&my_index, scene_path);
282 index = fgBucketGenIndex(&my_index);
283 sprintf(file, "%s/%s/%ld.1.north", basepath, scene_path, index);
284 if ( file_exists(file) ) {
287 fgBucketGenBasePath(&north_index, scene_path);
288 index = fgBucketGenIndex(&north_index);
289 sprintf(file, "%s/%s/%ld.1.south", basepath, scene_path, index);
290 if ( file_exists(file) ) {
295 if ( strcmp(ext, ".west") == 0 ) {
296 fgBucketGenBasePath(&my_index, scene_path);
297 index = fgBucketGenIndex(&my_index);
298 sprintf(file, "%s/%s/%ld.1.west", basepath, scene_path, index);
299 if ( file_exists(file) ) {
302 fgBucketGenBasePath(&west_index, scene_path);
303 index = fgBucketGenIndex(&west_index);
304 sprintf(file, "%s/%s/%ld.1.east", basepath, scene_path, index);
305 if ( file_exists(file) ) {
310 if ( strcmp(ext, ".east") == 0 ) {
311 fgBucketGenBasePath(&my_index, scene_path);
312 index = fgBucketGenIndex(&my_index);
313 sprintf(file, "%s/%s/%ld.1.east", basepath, scene_path, index);
314 if ( file_exists(file) ) {
317 fgBucketGenBasePath(&east_index, scene_path);
318 index = fgBucketGenIndex(&east_index);
319 sprintf(file, "%s/%s/%ld.1.west", basepath, scene_path, index);
320 if ( file_exists(file) ) {
325 if ( strcmp(ext, ".body") == 0 ) {
326 fgBucketGenBasePath(&my_index, scene_path);
327 index = fgBucketGenIndex(&my_index);
328 sprintf(file, "%s/%s/%ld.1.body", basepath, scene_path, index);
329 if ( file_exists(file) ) {
338 /* my custom file opening routine ... don't open if a shared edge or
339 * vertex alread exists */
340 FILE *my_open(char *basename, char *basepath, char *ext) {
344 /* check if a shared object already exists */
345 if ( shared_object_exists(basepath, ext, filename) ) {
346 /* not an actual file open error, but we've already got the
347 * shared edge, so we don't want to create another one */
348 fp = fopen(filename, "r");
349 printf("Opening %s\n", filename);
353 printf("not opening\n");
359 /* given a file pointer, read all the gdn (geodetic nodes from it.)
360 The specified offset values (in arcsec) are used to overlap the
361 edges of the tile slightly to cover gaps induced by floating point
362 precision problems. 1 arcsec == about 100 feet so 0.01 arcsec ==
364 void read_nodes(FILE *fp, double offset_lon, double offset_lat) {
368 while ( fgets(line, 250, fp) != NULL ) {
369 if ( strncmp(line, "gdn ", 4) == 0 ) {
370 sscanf(line, "gdn %lf %lf %lf\n", &n[0], &n[1], &n[2]);
372 if ( ! is_extra_node(n) ) {
373 nodes[nodecount][0] = n[0] + offset_lon;
374 nodes[nodecount][1] = n[1] + offset_lat;
375 nodes[nodecount][2] = n[2];
378 printf("read_nodes(%d) %.2f %.2f %.2f %s", nodecount,
379 nodes[nodecount][0], nodes[nodecount][1],
380 nodes[nodecount][2], line);
385 printf("found extra node %.2f %.2f %.2f\n", n[0], n[1], n[2]);
392 /* load in nodes from the various split and shared pieces to
393 * reconstruct a tile */
394 void build_node_list(char *basename, char *basepath) {
396 FILE *ne, *nw, *se, *sw, *north, *south, *east, *west, *body;
398 // load extra nodes if they exist
399 strcpy(exfile, basename);
400 strcat(exfile, ".node.ex");
401 read_extra_nodes(exfile);
403 ne = my_open(basename, basepath, ".ne");
404 read_nodes(ne, 0.1, 0.1);
407 nw = my_open(basename, basepath, ".nw");
408 read_nodes(nw, -0.1, 0.1);
411 se = my_open(basename, basepath, ".se");
412 read_nodes(se, 0.1, -0.1);
415 sw = my_open(basename, basepath, ".sw");
416 read_nodes(sw, -0.1, -0.1);
419 north = my_open(basename, basepath, ".north");
420 read_nodes(north, 0.0, 0.1);
423 south = my_open(basename, basepath, ".south");
424 read_nodes(south, 0.0, -0.1);
427 east = my_open(basename, basepath, ".east");
428 read_nodes(east, 0.1, 0.0);
431 west = my_open(basename, basepath, ".west");
432 read_nodes(west, -0.1, 0.0);
435 body = my_open(basename, basepath, ".body");
436 read_nodes(body, 0.0, 0.0);
441 /* dump in WaveFront .obj format */
442 void dump_nodes(char *basename) {
447 /* generate output file name */
448 strcpy(file, basename);
449 // len = strlen(file);
450 // file[len-2] = '\0';
451 strcat(file, ".node");
454 printf("Creating node file: %s\n", file);
455 printf(" writing vertices in .node format.\n");
456 fd = fopen(file, "w");
458 fprintf(fd, "%d 2 1 0\n", excount + nodecount);
460 // now write out extra node data
461 for ( i = 1; i <= excount; i++ ) {
462 fprintf(fd, "%d %.2f %.2f %.2f 0\n",
463 i, exnodes[i][0], exnodes[i][1], exnodes[i][2]);
466 /* now write out actual node data */
467 for ( i = 0; i < nodecount; i++ ) {
468 fprintf(fd, "%d %.2f %.2f %.2f 0\n", excount + i + 1,
469 nodes[i][0], nodes[i][1], nodes[i][2]);
476 int main(int argc, char **argv) {
477 char basename[256], basepath[256], temp[256];
482 strcpy(basename, argv[1]);
483 len = strlen(basename);
485 /* find the base path of the file */
486 extract_path(basename, basepath);
487 extract_path(basepath, basepath);
488 extract_path(basepath, basepath);
489 printf("%s\n", basepath);
491 /* find the index of the current file */
492 extract_file(basename, temp);
493 // len = strlen(temp);
495 // temp[len-2] = '\0';
497 tmp_index = atoi(temp);
498 printf("%ld\n", tmp_index);
499 fgBucketParseIndex(tmp_index, &my_index);
501 printf("bucket = %d %d %d %d\n",
502 my_index.lon, my_index.lat, my_index.x, my_index.y);
503 /* generate the indexes of the neighbors */
504 fgBucketOffset(&my_index, &ne_index, 1, 1);
505 fgBucketOffset(&my_index, &nw_index, -1, 1);
506 fgBucketOffset(&my_index, &se_index, 1, -1);
507 fgBucketOffset(&my_index, &sw_index, -1, -1);
509 fgBucketOffset(&my_index, &north_index, 0, 1);
510 fgBucketOffset(&my_index, &south_index, 0, -1);
511 fgBucketOffset(&my_index, &east_index, 1, 0);
512 fgBucketOffset(&my_index, &west_index, -1, 0);
515 printf("Corner indexes = %ld %ld %ld %ld\n",
516 ne_index, nw_index, sw_index, se_index);
517 printf("Edge indexes = %ld %ld %ld %ld\n",
518 north_index, south_index, east_index, west_index);
521 /* load the input data files */
522 build_node_list(basename, basepath);
524 /* dump in WaveFront .obj format */
525 dump_nodes(basename);
532 /* Revision 1.10 1998/07/21 04:34:20 curt
533 /* Mods to handle extra nodes (i.e. preserve cutouts).
535 * Revision 1.9 1998/07/04 00:55:39 curt
536 * typedef'd struct fgBUCKET.
538 * Revision 1.8 1998/06/01 17:58:19 curt
539 * Added a slight border overlap to try to minimize pixel wide gaps between
540 * tiles due to round off error. This is not a perfect solution, but helps.
542 * Revision 1.7 1998/04/14 02:26:00 curt
543 * Code reorganizations. Added a Lib/ directory for more general libraries.
545 * Revision 1.6 1998/04/08 22:54:58 curt
546 * Adopted Gnu automake/autoconf system.
548 * Revision 1.5 1998/03/03 16:00:52 curt
549 * More c++ compile tweaks.
551 * Revision 1.4 1998/01/31 00:41:23 curt
552 * Made a few changes converting floats to doubles.
554 * Revision 1.3 1998/01/27 18:37:00 curt
555 * Lots of updates to get back in sync with changes made over in .../Src/
557 * Revision 1.2 1998/01/15 21:33:36 curt
558 * Assembling triangles and building a new .node file with the proper shared
559 * vertices now works. Now we just have to use the shared normals and we'll
562 * Revision 1.1 1998/01/15 02:45:26 curt