source: git/src/new3dout.c @ 1b71c05

RELEASE/1.0
Last change on this file since 1b71c05 was 1b71c05, checked in by Olly Betts <olly@…>, 14 years ago

src/: Update FSF address in (C) notices in source files.

git-svn-id: file:///home/survex-svn/survex/branches/1.0@3463 4b37db11-9a0c-4f06-9ece-9ab7cdaee568

  • Property mode set to 100644
File size: 10.1 KB
RevLine 
[421b7d2]1/* new3dout.c
[647407d]2 * .3dx writing routines
[bd1913f]3 * Copyright (C) 2000, 2001 Phil Underwood
[2dfd768]4 * Copyright (C) 2001, 2002, 2003 Olly Betts
[647407d]5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
[1b71c05]18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
[647407d]19 */
20
21#include <config.h>
[3d441da]22#include "cavern.h"
[b4e3e7d]23
[ef3c9e2]24#ifdef CHASM3DX
[b4e3e7d]25
[3d441da]26#include <stdio.h>
27#include <math.h>
28
29#include "3ddefs.h"
[570df0c0]30#include "debug.h"
[fa42426]31#include "filename.h"
[b4e3e7d]32
[647407d]33twig *rhizome, *limb;
[8a01812]34char *firstfilename, *startingdir;
35int fUseNewFormat = 0;
[bd1913f]36
[b4e3e7d]37static enum {
38   IMG_NONE = 0,
39   IMG_FILENOTFOUND = /*Couldn't open data file `%s'*/24,
40   IMG_OUTOFMEMORY  = /*Out of memory %.0s*/38,
41   IMG_DIRECTORY    = /*Filename `%s' refers to directory*/44,
42   IMG_CANTOPENOUT  = /*Failed to open output file `%s'*/47,
43   IMG_BADFORMAT    = /*Bad 3d image file `%s'*/106
44} img_errno = IMG_NONE;
45
[bd1913f]46/* put counted string */
47static int
48fputcs(const char *s, FILE *fh)
49{
50   int len = strlen(s);
[23f7ea7]51   /* if the label is empty or > 255 chars. store 0 in the length byte
52    * followed by a 32 bit length value */
53   if (len == 0 || len > 255) {
54      if (putc(0, fh) == EOF) return EOF;
[fe8e80e]55      put32((INT32_T)len, fh);
[23f7ea7]56      if (ferror(fh)) return EOF;
57   } else {
58      if (putc((unsigned char)len, fh) == EOF) return EOF;
59   }
[bd1913f]60   return fputs(s, fh);
61}
62
[23f7ea7]63/* length on disk of counted string */
64static unsigned int
65cslen(const char *s)
66{
67   int len = strlen(s);
68   /* if the label is empty or > 255 chars. store 0 in the length byte
69    * followed by a 32 bit length value */
70   if (len == 0 || len > 255) return len + 5;
71   return len + 1;
72}
73
[bd1913f]74static char *basesource;
[8a01812]75static int statcount = 1; /* this is the total number of things added */
[647407d]76
[bd1913f]77static int
78scount(twig *twiglet)
79{
[570df0c0]80  twig *lib;
81
[bd1913f]82  if (twiglet->from) return 1;
[647407d]83
[4c07c51]84  SVX_ASSERT(twiglet->to);
[421b7d2]85
[570df0c0]86  lib = twiglet->down;
87  twiglet->count = 0;
88  while (lib->right) {
89    lib = lib->right;
90    twiglet->count += scount(lib);
[647407d]91  }
[570df0c0]92  return (twiglet->count ? 1 : 0);
[647407d]93}
94
[2dfd768]95static void
96cave_write_title(const char *title, img *p_img)
[647407d]97{
[2dfd768]98   putc(TITLE_3D, p_img->fh);
99   fputcs(title, p_img->fh);
[647407d]100}
101
[0dee66c]102static int
[2dfd768]103cave_write_pos(img * p_img, pos *pid, prefix *pre)
[647407d]104{
[0dee66c]105   if (pid->id == 0) {
106      const char *tag;
107      unsigned int len;
108      pid->id = (INT32_T)statcount;
109      tag = pre->ident;
110      len = cslen(tag) + 12 + 4;
111      /* storage station name, 12 for data, 4 for id */
[2dfd768]112      putc(STATION_3D, p_img->fh);
[0dee66c]113      if (len == 0 || len > 255) {
[2dfd768]114         if (putc(0, p_img->fh) == EOF) return EOF;
115         put32((INT32_T)len, p_img->fh);
116         if (ferror(p_img->fh)) return EOF;
[0dee66c]117      } else {
[2dfd768]118         if (putc((unsigned char)len, p_img->fh) == EOF) return EOF;
[0dee66c]119      }
[2dfd768]120      put32((INT32_T)statcount, p_img->fh); /* station ID */
121      put32((INT32_T)(pid->p[0] * 100.0), p_img->fh); /* X in cm */
122      put32((INT32_T)(pid->p[1] * 100.0), p_img->fh); /* Y */
123      put32((INT32_T)(pid->p[2] * 100.0), p_img->fh); /* Z */
124      fputcs(tag, p_img->fh);
[0dee66c]125      statcount++;
126   } else {
127      /* we've already put this in the file, so just a link is needed */
[2dfd768]128      putc(STATLINK_3D, p_img->fh);
129      putc(0x04, p_img->fh);
130      put32((INT32_T)pid->id, p_img->fh);
[0dee66c]131   }
132   return 0;
[647407d]133}
134
[bd1913f]135img *
136cave_open_write(const char *fnm, const char *title)
[647407d]137{
[2dfd768]138   img *p_img;
[647407d]139   if (fDirectory(fnm)) {
[b4e3e7d]140      img_errno = IMG_DIRECTORY;
[647407d]141      return NULL;
142   }
143
[2dfd768]144   p_img = (img *)xosmalloc(ossizeof(img));
145   if (p_img == NULL) {
[b4e3e7d]146      img_errno = IMG_OUTOFMEMORY;
[647407d]147      return NULL;
148   }
149
[2dfd768]150   p_img->fh = fopen(fnm, "wb");
151   if (!p_img->fh) {
152      osfree(p_img);
[b4e3e7d]153      img_errno = IMG_CANTOPENOUT;
[647407d]154      return NULL;
155   }
[2dfd768]156   fputs("SVX3d", p_img->fh);
157   putc(0x00, p_img->fh); /* Major version 0 */
158   putc(0x0A, p_img->fh); /* Minor version 10*/
159   put32(0, p_img->fh); /* dummy number for num of stations: fill later */
160   cave_write_title(title, p_img);
161   return p_img;
[647407d]162}
163
[bd1913f]164int
165cave_error(void)
[647407d]166{
[b4e3e7d]167   return img_errno;
[647407d]168}
169
[2dfd768]170static void
171cave_write_source(img * p_img, const char *source)
[647407d]172{
173  /* create a relative path, given an absolute dir, and an absolute file */
174  /* part 1. find where they differ */
[eed2283]175  char *allocated_source = NULL;
176  /* is it an absolute? */
177  if (!fAbsoluteFnm(source)) {
178    allocated_source = use_path(startingdir, source);
179    source = allocated_source;
180  }
181
182  /* strip source down to just a file name... */
183  if (strncmp(source, basesource, strlen(basesource)) != 0) {
184    printf("Warning: source links may not work\n");
185  } else {
186    source = source + strlen(basesource);
[647407d]187  }
[2dfd768]188  putc(SOURCE_3D, p_img->fh);
189  fputcs(source, p_img->fh);
[eed2283]190  osfree(allocated_source);
[647407d]191}
192
[bd1913f]193static void
[2dfd768]194save3d(img *p_img, twig *sticky)
[647407d]195{
[23f7ea7]196  unsigned int ltag;
197  unsigned int stubcount;
[eb18f4d]198  double err, length, offset;
[647407d]199  twig *twiglet;
[bd1913f]200  for (twiglet = sticky->right; twiglet; twiglet = twiglet->right) {
201    if (twiglet->from) {
202      if (!twiglet->to) { /* fixed point */
[2dfd768]203        cave_write_pos(p_img, twiglet->from->pos, twiglet->from);
[bd1913f]204      } else { /*leg */
205        /* calculate an average percentage error, based on %age change of polars */
206        /* offset is how far the _to_ point is from where we thought it would be */
207        offset = hypot(twiglet->to->pos->p[2] - (twiglet->from->pos->p[2] +
208                                                 twiglet->delta[2]),
209                       hypot(twiglet->to->pos->p[0] - (twiglet->from->pos->p[0] +
210                                                       twiglet->delta[0]),
211                             twiglet->to->pos->p[1] - (twiglet->from->pos->p[1] +
212                                                       twiglet->delta[1])));
213        /* length is our reconstituted expected length */
214        length = hypot(hypot(twiglet->delta[0], twiglet->delta[1]),
215                       twiglet->delta[2]);
[647407d]216#ifdef DEBUG
[bd1913f]217        if (strcmp(twiglet->from->ident, "86") == 0)
218          printf("deltas... %g %g %g length %g offset %g",
219                 twiglet->delta[0], twiglet->delta[1], twiglet->delta[2],
220                 length, offset);
[647407d]221#endif
[bd1913f]222        if (fabs(length) < 0.01) {
[49f28ab]223          err = 0; /* What is the error for a leg with zero length?
[421b7d2]224                    * Phil -  he say none. */
[bd1913f]225        } else {
[eb18f4d]226          err = 10000.0 * offset / length;
[647407d]227        }
[2dfd768]228        putc(LEG_3D, p_img->fh);
229        put16((INT16_T)0x02, p_img->fh);
230        putc(0x04, p_img->fh);
231        put32((INT32_T)err, p_img->fh); /* output error in %*100 */
232        cave_write_pos(p_img, twiglet->from->pos, twiglet->from);
233        cave_write_pos(p_img, twiglet->to->pos, twiglet->to);
[bd1913f]234      }
235    } else {
236      if (twiglet->count) {
[2dfd768]237        putc(BRANCH_3D, p_img->fh);
[bd1913f]238        /* number of records  - legs + values */
239        stubcount = 0;
240        if (twiglet->source) stubcount++;
241        if (twiglet->drawings) stubcount++;
242        if (twiglet->instruments) stubcount++;
243        if (twiglet->tape) stubcount++;
244        if (twiglet->date) stubcount++;
245        stubcount += twiglet->count;
[23f7ea7]246        if (stubcount > 32767) {
[2dfd768]247          put16(0, p_img->fh);
248          put32(stubcount, p_img->fh);
[23f7ea7]249        } else {
[2dfd768]250          put16((unsigned short)stubcount, p_img->fh);
[23f7ea7]251        }
252        ltag = cslen(twiglet->to->ident);
[b60659c]253        if (ltag <= 255) {
[2dfd768]254          putc((unsigned char)ltag, p_img->fh);
[23f7ea7]255        } else {
[2dfd768]256          putc(0, p_img->fh);
257          put32(ltag, p_img->fh);
[23f7ea7]258        }
[2dfd768]259        fputcs(twiglet->to->ident, p_img->fh);
260        if (twiglet->source) cave_write_source(p_img, twiglet->source);
[bd1913f]261        if (twiglet->date) {
[2dfd768]262          putc(DATE_3D, p_img->fh);
263          fputcs(twiglet->date, p_img->fh);
[bd1913f]264        }
265        if (twiglet->drawings) {
[2dfd768]266          putc(DRAWINGS_3D, p_img->fh);
267          fputcs(twiglet->drawings, p_img->fh);
[bd1913f]268        }
269        if (twiglet->instruments) {
[2dfd768]270          putc(INSTRUMENTS_3D, p_img->fh);
271          fputcs(twiglet->instruments, p_img->fh);
[647407d]272        }
[bd1913f]273        if (twiglet->tape) {
[2dfd768]274          putc(TAPE_3D, p_img->fh);
275          fputcs(twiglet->tape, p_img->fh);
[bd1913f]276        }
[2dfd768]277        save3d(p_img, twiglet->down);
[647407d]278      }
279    }
[bd1913f]280  }
[647407d]281}
[8a01812]282
283static void
[2dfd768]284cave_write_base_source(img *p_img)
[647407d]285{
[bd1913f]286  char *temp;
[647407d]287  /* is it an absolute? */
288  if (fAbsoluteFnm(firstfilename)) {
289    basesource = path_from_fnm(firstfilename);
290  } else {
291    temp = use_path(startingdir,firstfilename);
[bd1913f]292    basesource = path_from_fnm(temp);
293    osfree(temp);
[647407d]294  }
295
[bd1913f]296#if 0
[6359834]297  /* remove any ./../. etcs but not today */
[bd1913f]298  temp = osstrdup(basesource);
299  realpath(temp, basesource);
300#endif
301
[2dfd768]302  putc(BASE_SOURCE_3D, p_img->fh);
303  fputcs(basesource, p_img->fh);
[647407d]304
[bd1913f]305  /* get the actual file name */
306  temp = leaf_from_fnm(firstfilename);
[2dfd768]307  putc(BASE_FILE_3D, p_img->fh);
308  fputcs(temp, p_img->fh);
[bd1913f]309  osfree(temp);
[647407d]310}
311
[6f185e5]312int
[2dfd768]313cave_close(img *p_img)
[647407d]314{
[6f185e5]315   int result = 1;
[bd1913f]316   /* let's do the twiglet traverse! */
317   twig *twiglet = rhizome->down;
[2dfd768]318   cave_write_base_source(p_img);
[bd1913f]319   scount(rhizome);
[2dfd768]320   save3d(p_img, twiglet);
321   if (p_img->fh) {
[7ffc24a]322      /* Write end of data marker */
[2dfd768]323      putc(END_3D, p_img->fh);
[647407d]324      /* and finally write how many stations there are */
[2dfd768]325      fseek(p_img->fh, 7L, SEEK_SET);
326      put32((INT32_T)statcount, p_img->fh);
327      if (ferror(p_img->fh)) result = 0;
328      if (fclose(p_img->fh) == EOF) result = 0;
[647407d]329   }
[2dfd768]330   osfree(p_img);
[6f185e5]331   return result;
[647407d]332}
333
[bd1913f]334void
335create_twig(prefix *pre, const char *fname)
336{
[647407d]337  twig *twiglet;
338  twig *lib;
[3bcbcb2]339  lib = get_twig(pre->up); /* get the active twig for parent's prefix */
[647407d]340  twiglet = osnew(twig);
341  twiglet->from = NULL;
342  twiglet->to = pre;
343  twiglet->sourceval=0; /* lowest priority */
344  pre->twig_link = twiglet; /* connect both ways */
345  twiglet->right = NULL;
[bd1913f]346  twiglet->drawings = twiglet->date = twiglet->tape = twiglet->instruments
347     = NULL;
[647407d]348  twiglet->source = osstrdup(fname);
349  if (lib) {
[bd1913f]350    twiglet->count = lib->count + 1;
351    /* ie we are changing the global attachment update...*/
352    if (lib == limb) limb = twiglet;
[647407d]353    lib->right = twiglet;
354    twiglet->up = lib->up;
355  } else {
356    twiglet->up = NULL;
357  }
358  lib = twiglet;
359  twiglet = osnew(twig);
360  twiglet->to = twiglet->from = NULL;
361  twiglet->up = lib;
362  twiglet->sourceval = 0;
[bd1913f]363  twiglet->drawings = twiglet->source = twiglet->instruments
364     = twiglet->date = twiglet->tape = NULL;
[647407d]365  twiglet->down = twiglet->right = NULL;
366  twiglet->count=0;
367  lib->down = twiglet;
368}
369
[bd1913f]370twig *
371get_twig(prefix *pre)
372{
373   twig *temp;
374   if (pre && pre->twig_link) {
375     temp = pre->twig_link->down;
376     if (temp) while (temp->right) temp = temp->right;
377     return temp;
378   }
379   return NULL;
[647407d]380}
[b4e3e7d]381
[647407d]382#endif
Note: See TracBrowser for help on using the repository browser.