2
* .3dx writing routines
3
* Copyright (C) 2000, 2001 Phil Underwood
4
* Copyright (C) 2001, 2002, 2003 Olly Betts
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.
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.
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
34
char *firstfilename, *startingdir;
35
int fUseNewFormat = 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;
46
/* put counted string */
48
fputcs(const char *s, FILE *fh)
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;
58
if (putc((unsigned char)len, fh) == EOF) return EOF;
63
/* length on disk of counted string */
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;
74
static char *basesource;
75
static int statcount = 1; /* this is the total number of things added */
82
if (twiglet->from) return 1;
84
SVX_ASSERT(twiglet->to);
90
twiglet->count += scount(lib);
92
return (twiglet->count ? 1 : 0);
96
cave_write_title(const char *title, img *p_img)
98
putc(TITLE_3D, p_img->fh);
99
fputcs(title, p_img->fh);
103
cave_write_pos(img * p_img, pos *pid, prefix *pre)
108
pid->id = (INT32_T)statcount;
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;
118
if (putc((unsigned char)len, p_img->fh) == EOF) return EOF;
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);
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);
136
cave_open_write(const char *fnm, const char *title)
139
if (fDirectory(fnm)) {
140
img_errno = IMG_DIRECTORY;
144
p_img = (img *)xosmalloc(ossizeof(img));
146
img_errno = IMG_OUTOFMEMORY;
150
p_img->fh = fopen(fnm, "wb");
153
img_errno = IMG_CANTOPENOUT;
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);
171
cave_write_source(img * p_img, const char *source)
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;
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");
186
source = source + strlen(basesource);
188
putc(SOURCE_3D, p_img->fh);
189
fputcs(source, p_img->fh);
190
osfree(allocated_source);
194
save3d(img *p_img, twig *sticky)
197
unsigned int stubcount;
198
double err, length, offset;
200
for (twiglet = sticky->right; twiglet; twiglet = twiglet->right) {
202
if (!twiglet->to) { /* fixed point */
203
cave_write_pos(p_img, twiglet->from->pos, twiglet->from);
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] +
209
hypot(twiglet->to->pos->p[0] - (twiglet->from->pos->p[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]),
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],
222
if (fabs(length) < 0.01) {
223
err = 0; /* What is the error for a leg with zero length?
224
* Phil - he say none. */
226
err = 10000.0 * offset / length;
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);
236
if (twiglet->count) {
237
putc(BRANCH_3D, p_img->fh);
238
/* number of records - legs + values */
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) {
248
put32(stubcount, p_img->fh);
250
put16((unsigned short)stubcount, p_img->fh);
252
ltag = cslen(twiglet->to->ident);
254
putc((unsigned char)ltag, p_img->fh);
257
put32(ltag, p_img->fh);
259
fputcs(twiglet->to->ident, p_img->fh);
260
if (twiglet->source) cave_write_source(p_img, twiglet->source);
262
putc(DATE_3D, p_img->fh);
263
fputcs(twiglet->date, p_img->fh);
265
if (twiglet->drawings) {
266
putc(DRAWINGS_3D, p_img->fh);
267
fputcs(twiglet->drawings, p_img->fh);
269
if (twiglet->instruments) {
270
putc(INSTRUMENTS_3D, p_img->fh);
271
fputcs(twiglet->instruments, p_img->fh);
274
putc(TAPE_3D, p_img->fh);
275
fputcs(twiglet->tape, p_img->fh);
277
save3d(p_img, twiglet->down);
284
cave_write_base_source(img *p_img)
287
/* is it an absolute? */
288
if (fAbsoluteFnm(firstfilename)) {
289
basesource = path_from_fnm(firstfilename);
291
temp = use_path(startingdir,firstfilename);
292
basesource = path_from_fnm(temp);
297
/* remove any ./../. etcs but not today */
298
temp = osstrdup(basesource);
299
realpath(temp, basesource);
302
putc(BASE_SOURCE_3D, p_img->fh);
303
fputcs(basesource, p_img->fh);
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);
313
cave_close(img *p_img)
316
/* let's do the twiglet traverse! */
317
twig *twiglet = rhizome->down;
318
cave_write_base_source(p_img);
320
save3d(p_img, twiglet);
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;
335
create_twig(prefix *pre, const char *fname)
339
lib = get_twig(pre->up); /* get the active twig for parent's prefix */
340
twiglet = osnew(twig);
341
twiglet->from = NULL;
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
348
twiglet->source = osstrdup(fname);
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;
359
twiglet = osnew(twig);
360
twiglet->to = twiglet->from = NULL;
362
twiglet->sourceval = 0;
363
twiglet->drawings = twiglet->source = twiglet->instruments
364
= twiglet->date = twiglet->tape = NULL;
365
twiglet->down = twiglet->right = NULL;
371
get_twig(prefix *pre)
374
if (pre && pre->twig_link) {
375
temp = pre->twig_link->down;
376
if (temp) while (temp->right) temp = temp->right;