source: git/src/new3dout.c @ 8262132

RELEASE/1.0RELEASE/1.2debug-cidebug-ci-sanitisersfaster-cavernlogstereowalls-datawalls-data-hanging-as-warning
Last change on this file since 8262132 was ef3c9e2, checked in by Olly Betts <olly@…>, 22 years ago

Don't allocate extra space needed for producing 3dx output for
Chasm unless we're actually producing that output - saves about 8 bytes
per station.

git-svn-id: file:///home/survex-svn/survex/trunk@2252 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 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  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
95void
96cave_write_title(const char *title, img *pimg)
97{
98   putc(TITLE_3D, pimg->fh);
99   fputcs(title, pimg->fh);
100}
101
102void
103cave_write_stn(node *nod)
104{
105    nod = nod; /* avoid compiler warnings */
106}
107
108static int
109cave_write_pos(pos *pid, prefix *pre)
110{
111   if (pid->id == 0) {
112      const char *tag;
113      unsigned int len;
114      pid->id = (INT32_T)statcount;
115      tag = pre->ident;
116      len = cslen(tag) + 12 + 4;
117      /* storage station name, 12 for data, 4 for id */
118      putc(STATION_3D, pimg->fh);
119      if (len == 0 || len > 255) {
120         if (putc(0, pimg->fh) == EOF) return EOF;
121         put32((INT32_T)len, pimg->fh);
122         if (ferror(pimg->fh)) return EOF;
123      } else {
124         if (putc((unsigned char)len, pimg->fh) == EOF) return EOF;
125      }
126      put32((INT32_T)statcount, pimg->fh); /* station ID */
127      put32((INT32_T)(pid->p[0] * 100.0), pimg->fh); /* X in cm */
128      put32((INT32_T)(pid->p[1] * 100.0), pimg->fh); /* Y */
129      put32((INT32_T)(pid->p[2] * 100.0), pimg->fh); /* Z */
130      fputcs(tag, pimg->fh);
131      statcount++;
132   } else {
133      /* we've already put this in the file, so just a link is needed */
134      putc(STATLINK_3D, pimg->fh);
135      putc(0x04, pimg->fh);
136      put32((INT32_T)pid->id, pimg->fh);
137   }
138   return 0;
139}
140
141img *
142cave_open_write(const char *fnm, const char *title)
143{
144   img *pimg;
145   if (fDirectory(fnm)) {
146      img_errno = IMG_DIRECTORY;
147      return NULL;
148   }
149
150   pimg = (img *)xosmalloc(ossizeof(img));
151   if (pimg == NULL) {
152      img_errno = IMG_OUTOFMEMORY;
153      return NULL;
154   }
155
156   pimg->fh = fopen(fnm, "wb");
157   if (!pimg->fh) {
158      osfree(pimg);
159      img_errno = IMG_CANTOPENOUT;
160      return NULL;
161   }
162   fputs("SVX3d", pimg->fh);
163   putc(0x00, pimg->fh); /* Major version 0 */
164   putc(0x0A, pimg->fh); /* Minor version 10*/
165   put32(0, pimg->fh); /* dummy number for num of stations: fill later */
166   cave_write_title(title, pimg);
167   return pimg;
168}
169
170int
171cave_error(void)
172{
173   return img_errno;
174}
175
176void
177cave_write_leg(linkfor *leg)
178{
179   leg = leg; /* avoid compiler warnings */
180}
181
182void
183cave_write_source(const char *source)
184{
185  /* create a relative path, given an absolute dir, and an absolute file */
186  /* part 1. find where they differ */
187  char *allocated_source = NULL;
188  /* is it an absolute? */
189  if (!fAbsoluteFnm(source)) {
190    allocated_source = use_path(startingdir, source);
191    source = allocated_source;
192  }
193
194  /* strip source down to just a file name... */
195  if (strncmp(source, basesource, strlen(basesource)) != 0) {
196    printf("Warning: source links may not work\n");
197  } else {
198    source = source + strlen(basesource);
199  }
200  putc(SOURCE_3D, pimg->fh);
201  fputcs(source, pimg->fh);
202  osfree(allocated_source);
203}
204
205static void
206save3d(twig *sticky)
207{
208  unsigned int ltag;
209  unsigned int stubcount;
210  double err, length, offset;
211  twig *twiglet;
212  for (twiglet = sticky->right; twiglet; twiglet = twiglet->right) {
213    if (twiglet->from) {
214      if (!twiglet->to) { /* fixed point */
215        cave_write_pos(twiglet->from->pos,twiglet->from);
216      } else { /*leg */
217        /* calculate an average percentage error, based on %age change of polars */
218        /* offset is how far the _to_ point is from where we thought it would be */
219        offset = hypot(twiglet->to->pos->p[2] - (twiglet->from->pos->p[2] +
220                                                 twiglet->delta[2]),
221                       hypot(twiglet->to->pos->p[0] - (twiglet->from->pos->p[0] +
222                                                       twiglet->delta[0]),
223                             twiglet->to->pos->p[1] - (twiglet->from->pos->p[1] +
224                                                       twiglet->delta[1])));
225        /* length is our reconstituted expected length */
226        length = hypot(hypot(twiglet->delta[0], twiglet->delta[1]),
227                       twiglet->delta[2]);
228#ifdef DEBUG
229        if (strcmp(twiglet->from->ident, "86") == 0)
230          printf("deltas... %g %g %g length %g offset %g",
231                 twiglet->delta[0], twiglet->delta[1], twiglet->delta[2],
232                 length, offset);
233#endif
234        if (fabs(length) < 0.01) {
235          err = 0; /* What is the error for a leg with zero length?
236                    * Phil -  he say none. */
237        } else {
238          err = 10000.0 * offset / length;
239        }
240        putc(LEG_3D, pimg->fh);
241        put16((INT16_T)0x02, pimg->fh);
242        putc(0x04, pimg->fh);
243        put32((INT32_T)err, pimg->fh); /* output error in %*100 */
244        cave_write_pos(twiglet->from->pos, twiglet->from);
245        cave_write_pos(twiglet->to->pos, twiglet->to);
246      }
247    } else {
248      if (twiglet->count) {
249        putc(BRANCH_3D, pimg->fh);
250        /* number of records  - legs + values */
251        stubcount = 0;
252        if (twiglet->source) stubcount++;
253        if (twiglet->drawings) stubcount++;
254        if (twiglet->instruments) stubcount++;
255        if (twiglet->tape) stubcount++;
256        if (twiglet->date) stubcount++;
257        stubcount += twiglet->count;
258        if (stubcount > 32767) {
259          put16(0, pimg->fh);
260          put32(stubcount, pimg->fh);
261        } else {
262          put16((unsigned short)stubcount, pimg->fh);
263        }
264        ltag = cslen(twiglet->to->ident);
265        if (ltag <= 255) {
266          putc((unsigned char)ltag, pimg->fh);
267        } else {
268          putc(0, pimg->fh);
269          put32(ltag, pimg->fh);
270        }
271        fputcs(twiglet->to->ident, pimg->fh);
272        if (twiglet->source) cave_write_source(twiglet->source);
273        if (twiglet->date) {
274          putc(DATE_3D, pimg->fh);
275          fputcs(twiglet->date, pimg->fh);
276        }
277        if (twiglet->drawings) {
278          putc(DRAWINGS_3D, pimg->fh);
279          fputcs(twiglet->drawings, pimg->fh);
280        }
281        if (twiglet->instruments) {
282          putc(INSTRUMENTS_3D, pimg->fh);
283          fputcs(twiglet->instruments, pimg->fh);
284        }
285        if (twiglet->tape) {
286          putc(TAPE_3D, pimg->fh);
287          fputcs(twiglet->tape, pimg->fh);
288        }
289        save3d(twiglet->down);
290      }
291    }
292  }
293}
294
295static void
296cave_write_base_source(void)
297{
298  char *temp;
299  /* is it an absolute? */
300  if (fAbsoluteFnm(firstfilename)) {
301    basesource = path_from_fnm(firstfilename);
302  } else {
303    temp = use_path(startingdir,firstfilename);
304    basesource = path_from_fnm(temp);
305    osfree(temp);
306  }
307
308#if 0
309  /* remove any ./../. etcs but not today */
310  temp = osstrdup(basesource);
311  realpath(temp, basesource);
312#endif
313
314  putc(BASE_SOURCE_3D, pimg->fh);
315  fputcs(basesource, pimg->fh);
316
317  /* get the actual file name */
318  temp = leaf_from_fnm(firstfilename);
319  putc(BASE_FILE_3D, pimg->fh);
320  fputcs(temp, pimg->fh);
321  osfree(temp);
322}
323
324int
325cave_close(img *pimg)
326{
327   int result = 1;
328   /* let's do the twiglet traverse! */
329   twig *twiglet = rhizome->down;
330   cave_write_base_source();
331   scount(rhizome);
332   save3d(twiglet);
333   if (pimg->fh) {
334      /* Write end of data marker */
335      putc(END_3D, pimg->fh);
336      /* and finally write how many stations there are */
337      fseek(pimg->fh, 7L, SEEK_SET);
338      put32((INT32_T)statcount, pimg->fh);
339      if (ferror(pimg->fh)) result = 0;
340      if (fclose(pimg->fh) == EOF) result = 0;
341   }
342   osfree(pimg);
343   return result;
344}
345
346void
347create_twig(prefix *pre, const char *fname)
348{
349  twig *twiglet;
350  twig *lib;
351  lib = get_twig(pre->up); /* get the active twig for parent's prefix */
352  twiglet = osnew(twig);
353  twiglet->from = NULL;
354  twiglet->to = pre;
355  twiglet->sourceval=0; /* lowest priority */
356  pre->twig_link = twiglet; /* connect both ways */
357  twiglet->right = NULL;
358  twiglet->drawings = twiglet->date = twiglet->tape = twiglet->instruments
359     = NULL;
360  twiglet->source = osstrdup(fname);
361  if (lib) {
362    twiglet->count = lib->count + 1;
363    /* ie we are changing the global attachment update...*/
364    if (lib == limb) limb = twiglet;
365    lib->right = twiglet;
366    twiglet->up = lib->up;
367  } else {
368    twiglet->up = NULL;
369  }
370  lib = twiglet;
371  twiglet = osnew(twig);
372  twiglet->to = twiglet->from = NULL;
373  twiglet->up = lib;
374  twiglet->sourceval = 0;
375  twiglet->drawings = twiglet->source = twiglet->instruments
376     = twiglet->date = twiglet->tape = NULL;
377  twiglet->down = twiglet->right = NULL;
378  twiglet->count=0;
379  lib->down = twiglet;
380}
381
382twig *
383get_twig(prefix *pre)
384{
385   twig *temp;
386   if (pre && pre->twig_link) {
387     temp = pre->twig_link->down;
388     if (temp) while (temp->right) temp = temp->right;
389     return temp;
390   }
391   return NULL;
392}
393
394#endif
Note: See TracBrowser for help on using the repository browser.