~ojwb/survex/master

« back to all changes in this revision

Viewing changes to src/new3dout.c

  • Committer: Olly Betts
  • Date: 2010-06-18 07:16:42 UTC
  • mfrom: (2003.1.853)
  • Revision ID: git-v1:75fe355c16c77b1090c4426a3dc0b8dabca31904
Rename branches/survex-1_1 to trunk.

git-svn-id: file:///home/survex-svn/survex/trunk@3454 4b37db11-9a0c-4f06-9ece-9ab7cdaee568

Show diffs side-by-side

added added

removed removed

Lines of Context:
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., 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
 
 
33
 
twig *rhizome, *limb;
34
 
char *firstfilename, *startingdir;
35
 
int fUseNewFormat = 0;
36
 
 
37
 
static 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 */
47
 
static int
48
 
fputcs(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 */
64
 
static unsigned int
65
 
cslen(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
 
 
74
 
static char *basesource;
75
 
static int statcount = 1; /* this is the total number of things added */
76
 
 
77
 
static int
78
 
scount(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
 
 
95
 
static void
96
 
cave_write_title(const char *title, img *p_img)
97
 
{
98
 
   putc(TITLE_3D, p_img->fh);
99
 
   fputcs(title, p_img->fh);
100
 
}
101
 
 
102
 
static int
103
 
cave_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
 
 
135
 
img *
136
 
cave_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
 
 
164
 
int
165
 
cave_error(void)
166
 
{
167
 
   return img_errno;
168
 
}
169
 
 
170
 
static void
171
 
cave_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
 
 
193
 
static void
194
 
save3d(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
 
 
283
 
static void
284
 
cave_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
 
 
312
 
int
313
 
cave_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
 
 
334
 
void
335
 
create_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
 
 
370
 
twig *
371
 
get_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