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
Line 
1/* new3dout.c
2 * .3dx writing routines
3 * Copyright (C) 2000, 2001 Phil Underwood
4 * Copyright (C) 2001, 2002, 2003 Olly Betts
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
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
19 */
20
21#include <config.h>
22#include "cavern.h"
23
24#ifdef CHASM3DX
25
26#include <stdio.h>
27#include <math.h>
28
29#include "3ddefs.h"
30#include "debug.h"
31#include "filename.h"
32
33twig *rhizome, *limb;
34char *firstfilename, *startingdir;
35int fUseNewFormat = 0;
36
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
46/* put counted string */
47static int
48fputcs(const char *s, FILE *fh)
49{
50   int len = strlen(s);
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;
55      put32((INT32_T)len, fh);
56      if (ferror(fh)) return EOF;
57   } else {
58      if (putc((unsigned char)len, fh) == EOF) return EOF;
59   }
60   return fputs(s, fh);
61}
62
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
74static char *basesource;
75static int statcount = 1; /* this is the total number of things added */
76
77static int
78scount(twig *twiglet)
79{
80  twig *lib;
81
82  if (twiglet->from) return 1;
83
84  SVX_ASSERT(twiglet->to);
85
86  lib = twiglet->down;
87  twiglet->count = 0;
88  while (lib->right) {
89    lib = lib->right;
90    twiglet->count += scount(lib);
91  }
92  return (twiglet->count ? 1 : 0);
93}
94
95static void
96cave_write_title(const char *title, img *p_img)
97{
98   putc(TITLE_3D, p_img->fh);
99   fputcs(title, p_img->fh);
100}
101
102static int
103cave_write_pos(img * p_img, pos *pid, prefix *pre)
104{
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 */
112      putc(STATION_3D, p_img->fh);
113      if (len == 0 || len > 255) {
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;
117      } else {
118         if (putc((unsigned char)len, p_img->fh) == EOF) return EOF;
119      }
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);
125      statcount++;
126   } else {
127      /* we've already put this in the file, so just a link is needed */
128      putc(STATLINK_3D, p_img->fh);
129      putc(0x04, p_img->fh);
130      put32((INT32_T)pid->id, p_img->fh);
131   }
132   return 0;
133}
134
135img *
136cave_open_write(const char *fnm, const char *title)
137{
138   img *p_img;
139   if (fDirectory(fnm)) {
140      img_errno = IMG_DIRECTORY;
141      return NULL;
142   }
143
144   p_img = (img *)xosmalloc(ossizeof(img));
145   if (p_img == NULL) {
146      img_errno = IMG_OUTOFMEMORY;
147      return NULL;
148   }
149
150   p_img->fh = fopen(fnm, "wb");
151   if (!p_img->fh) {
152      osfree(p_img);
153      img_errno = IMG_CANTOPENOUT;
154      return NULL;
155   }
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;
162}
163
164int
165cave_error(void)
166{
167   return img_errno;
168}
169
170static void
171cave_write_source(img * p_img, const char *source)
172{
173  /* create a relative path, given an absolute dir, and an absolute file */
174  /* part 1. find where they differ */
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);
187  }
188  putc(SOURCE_3D, p_img->fh);
189  fputcs(source, p_img->fh);
190  osfree(allocated_source);
191}
192
193static void
194save3d(img *p_img, twig *sticky)
195{
196  unsigned int ltag;
197  unsigned int stubcount;
198  double err, length, offset;
199  twig *twiglet;
200  for (twiglet = sticky->right; twiglet; twiglet = twiglet->right) {
201    if (twiglet->from) {
202      if (!twiglet->to) { /* fixed point */
203        cave_write_pos(p_img, twiglet->from->pos, twiglet->from);
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]);
216#ifdef DEBUG
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);
221#endif
222        if (fabs(length) < 0.01) {
223          err = 0; /* What is the error for a leg with zero length?
224                    * Phil -  he say none. */
225        } else {
226          err = 10000.0 * offset / length;
227        }
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);
234      }
235    } else {
236      if (twiglet->count) {
237        putc(BRANCH_3D, p_img->fh);
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;
246        if (stubcount > 32767) {
247          put16(0, p_img->fh);
248          put32(stubcount, p_img->fh);
249        } else {
250          put16((unsigned short)stubcount, p_img->fh);
251        }
252        ltag = cslen(twiglet->to->ident);
253        if (ltag <= 255) {
254          putc((unsigned char)ltag, p_img->fh);
255        } else {
256          putc(0, p_img->fh);
257          put32(ltag, p_img->fh);
258        }
259        fputcs(twiglet->to->ident, p_img->fh);
260        if (twiglet->source) cave_write_source(p_img, twiglet->source);
261        if (twiglet->date) {
262          putc(DATE_3D, p_img->fh);
263          fputcs(twiglet->date, p_img->fh);
264        }
265        if (twiglet->drawings) {
266          putc(DRAWINGS_3D, p_img->fh);
267          fputcs(twiglet->drawings, p_img->fh);
268        }
269        if (twiglet->instruments) {
270          putc(INSTRUMENTS_3D, p_img->fh);
271          fputcs(twiglet->instruments, p_img->fh);
272        }
273        if (twiglet->tape) {
274          putc(TAPE_3D, p_img->fh);
275          fputcs(twiglet->tape, p_img->fh);
276        }
277        save3d(p_img, twiglet->down);
278      }
279    }
280  }
281}
282
283static void
284cave_write_base_source(img *p_img)
285{
286  char *temp;
287  /* is it an absolute? */
288  if (fAbsoluteFnm(firstfilename)) {
289    basesource = path_from_fnm(firstfilename);
290  } else {
291    temp = use_path(startingdir,firstfilename);
292    basesource = path_from_fnm(temp);
293    osfree(temp);
294  }
295
296#if 0
297  /* remove any ./../. etcs but not today */
298  temp = osstrdup(basesource);
299  realpath(temp, basesource);
300#endif
301
302  putc(BASE_SOURCE_3D, p_img->fh);
303  fputcs(basesource, p_img->fh);
304
305  /* get the actual file name */
306  temp = leaf_from_fnm(firstfilename);
307  putc(BASE_FILE_3D, p_img->fh);
308  fputcs(temp, p_img->fh);
309  osfree(temp);
310}
311
312int
313cave_close(img *p_img)
314{
315   int result = 1;
316   /* let's do the twiglet traverse! */
317   twig *twiglet = rhizome->down;
318   cave_write_base_source(p_img);
319   scount(rhizome);
320   save3d(p_img, twiglet);
321   if (p_img->fh) {
322      /* Write end of data marker */
323      putc(END_3D, p_img->fh);
324      /* and finally write how many stations there are */
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;
329   }
330   osfree(p_img);
331   return result;
332}
333
334void
335create_twig(prefix *pre, const char *fname)
336{
337  twig *twiglet;
338  twig *lib;
339  lib = get_twig(pre->up); /* get the active twig for parent's prefix */
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;
346  twiglet->drawings = twiglet->date = twiglet->tape = twiglet->instruments
347     = NULL;
348  twiglet->source = osstrdup(fname);
349  if (lib) {
350    twiglet->count = lib->count + 1;
351    /* ie we are changing the global attachment update...*/
352    if (lib == limb) limb = twiglet;
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;
363  twiglet->drawings = twiglet->source = twiglet->instruments
364     = twiglet->date = twiglet->tape = NULL;
365  twiglet->down = twiglet->right = NULL;
366  twiglet->count=0;
367  lib->down = twiglet;
368}
369
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;
380}
381
382#endif
Note: See TracBrowser for help on using the repository browser.