source: git/src/cad3d.c @ 179cfbf

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

cad3d: DXF output now puts surface legs, stations, and labels in separate
layers.

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

  • Property mode set to 100644
File size: 20.9 KB
Line 
1/* cad3d.c
2 * Converts a .3d file to CAD-like formats (DXF, Sketch) and also Compass PLT.
3 * Also useful as an example of how to use the img code in your own programs
4 */
5
6/* Copyright (C) 1994-2004 Olly Betts
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
21 */
22
23/* #define DEBUG_CAD3D */
24
25#ifdef HAVE_CONFIG_H
26#include <config.h>
27#endif
28
29#include <float.h>
30#include <math.h>
31#include <stdio.h>
32#include <stdlib.h>
33#include <string.h>
34
35#include "cmdline.h"
36#include "debug.h"
37#include "filename.h"
38#include "hash.h"
39#include "img.h"
40#include "message.h"
41#include "useful.h"
42
43/* default values - can be overridden with --htext and --msize respectively */
44#define TEXT_HEIGHT     0.6
45#define MARKER_SIZE     0.8
46
47#define GRID_SPACING    100
48
49#define POINTS_PER_INCH 72.0
50#define POINTS_PER_MM (POINTS_PER_INCH / MM_PER_INCH)
51
52/* default to DXF */
53#define FMT_DEFAULT FMT_DXF
54
55static FILE *fh;
56
57/* bounds */
58static double min_x, min_y, min_z, max_x, max_y, max_z;
59
60static double text_height; /* for station labels */
61static double marker_size; /* for station markers */
62static double grid; /* grid spacing (or 0 for no grid) */
63static double scale = 500.0;
64static double factor;
65
66static img *pimg;
67static const char *survey = NULL;
68
69static void
70dxf_header(void)
71{
72   fprintf(fh, "0\nSECTION\n");
73   fprintf(fh, "2\nHEADER\n");
74   fprintf(fh, "9\n$EXTMIN\n"); /* lower left corner of drawing */
75   fprintf(fh, "10\n%#-.6f\n", min_x); /* x */
76   fprintf(fh, "20\n%#-.6f\n", min_y); /* y */
77   fprintf(fh, "30\n%#-.6f\n", min_z); /* min z */
78   fprintf(fh, "9\n$EXTMAX\n"); /* upper right corner of drawing */
79   fprintf(fh, "10\n%#-.6f\n", max_x); /* x */
80   fprintf(fh, "20\n%#-.6f\n", max_y); /* y */
81   fprintf(fh, "30\n%#-.6f\n", max_z); /* max z */
82   fprintf(fh, "9\n$PDMODE\n70\n3\n"); /* marker style as CROSS */
83   fprintf(fh, "9\n$PDSIZE\n40\n%6.2f\n", marker_size); /* marker size */
84   fprintf(fh, "0\nENDSEC\n");
85
86   fprintf(fh, "0\nSECTION\n");
87   fprintf(fh, "2\nTABLES\n");
88   fprintf(fh, "0\nTABLE\n");
89   fprintf(fh, "2\nLAYER\n");
90   fprintf(fh, "70\n10\n"); /* max # off layers in this DXF file : 10 */
91   /* First Layer: CentreLine */
92   fprintf(fh, "0\nLAYER\n2\nCentreLine\n");
93   fprintf(fh, "70\n64\n"); /* shows layer is referenced by entities */
94   fprintf(fh, "62\n5\n"); /* color: kept the same used by SpeleoGen */
95   fprintf(fh, "6\nCONTINUOUS\n"); /* linetype */
96   /* Next Layer: Stations */
97   fprintf(fh, "0\nLAYER\n2\nStations\n");
98   fprintf(fh, "70\n64\n"); /* shows layer is referenced by entities */
99   fprintf(fh, "62\n7\n"); /* color: kept the same used by SpeleoGen */
100   fprintf(fh, "6\nCONTINUOUS\n"); /* linetype */
101   /* Next Layer: Labels */
102   fprintf(fh, "0\nLAYER\n2\nLabels\n");
103   fprintf(fh, "70\n64\n"); /* shows layer is referenced by entities */
104   fprintf(fh, "62\n7\n"); /* color: kept the same used by SpeleoGen */
105   fprintf(fh, "6\nCONTINUOUS\n"); /* linetype */
106   /* Next Layer: Surface */
107   fprintf(fh, "0\nLAYER\n2\nSurface\n");
108   fprintf(fh, "70\n64\n"); /* shows layer is referenced by entities */
109   fprintf(fh, "62\n5\n"); /* color */
110   fprintf(fh, "6\nDASHED\n"); /* linetype */
111   /* Next Layer: SurfaceStations */
112   fprintf(fh, "0\nLAYER\n2\nSurfaceStations\n");
113   fprintf(fh, "70\n64\n"); /* shows layer is referenced by entities */
114   fprintf(fh, "62\n7\n"); /* color */
115   fprintf(fh, "6\nCONTINUOUS\n"); /* linetype */
116   /* Next Layer: SurfaceLabels */
117   fprintf(fh, "0\nLAYER\n2\nSurfaceLabels\n");
118   fprintf(fh, "70\n64\n"); /* shows layer is referenced by entities */
119   fprintf(fh, "62\n7\n"); /* color */
120   fprintf(fh, "6\nCONTINUOUS\n"); /* linetype */
121   if (grid > 0) {
122      /* Next Layer: Grid */
123      fprintf(fh, "0\nLAYER\n2\nGrid\n");
124      fprintf(fh, "70\n64\n"); /* shows layer is referenced by entities */
125      fprintf(fh, "62\n7\n"); /* color: kept the same used by SpeleoGen */
126      fprintf(fh, "6\nCONTINUOUS\n"); /* linetype */
127   }
128   fprintf(fh, "0\nENDTAB\n");
129   fprintf(fh, "0\nENDSEC\n");
130
131   fprintf(fh, "0\nSECTION\n");
132   fprintf(fh, "2\nENTITIES\n");
133
134   if (grid > 0) {
135      double x, y;
136      x = floor(min_x / grid) * grid + grid;
137      y = floor(min_y / grid) * grid + grid;
138#ifdef DEBUG_CAD3D
139      printf("x_min: %f  y_min: %f\n", x, y);
140#endif
141      while (x < max_x) {
142         /* horizontal line */
143         fprintf(fh, "0\nLINE\n");
144         fprintf(fh, "8\nGrid\n"); /* Layer */
145         fprintf(fh, "10\n%6.2f\n", x);
146         fprintf(fh, "20\n%6.2f\n", min_y);
147         fprintf(fh, "30\n0\n");
148         fprintf(fh, "11\n%6.2f\n", x);
149         fprintf(fh, "21\n%6.2f\n", max_y);
150         fprintf(fh, "31\n0\n");
151         x += grid;
152      }
153      while (y < max_y) {
154         /* vertical line */
155         fprintf(fh, "0\nLINE\n");
156         fprintf(fh, "8\nGrid\n"); /* Layer */
157         fprintf(fh, "10\n%6.2f\n", min_x);
158         fprintf(fh, "20\n%6.2f\n", y);
159         fprintf(fh, "30\n0\n");
160         fprintf(fh, "11\n%6.2f\n", max_x);
161         fprintf(fh, "21\n%6.2f\n", y);
162         fprintf(fh, "31\n0\n");
163         y += grid;
164      }
165   }
166}
167
168static void
169dxf_start_pass(int layer)
170{
171   layer = layer;
172}
173
174static void
175dxf_move(const img_point *p)
176{
177   p = p; /* unused */
178}
179
180static void
181dxf_line(const img_point *p1, const img_point *p, bool fSurface)
182{
183   fprintf(fh, "0\nLINE\n");
184   fprintf(fh, fSurface ? "8\nSurface\n" : "8\nCentreLine\n"); /* Layer */
185   fprintf(fh, "10\n%6.2f\n", p1->x);
186   fprintf(fh, "20\n%6.2f\n", p1->y);
187   fprintf(fh, "30\n%6.2f\n", p1->z);
188   fprintf(fh, "11\n%6.2f\n", p->x);
189   fprintf(fh, "21\n%6.2f\n", p->y);
190   fprintf(fh, "31\n%6.2f\n", p->z);
191}
192
193static void
194dxf_label(const img_point *p, const char *s, bool fSurface)
195{
196   /* write station label to dxf file */
197   fprintf(fh, "0\nTEXT\n");
198   fprintf(fh, fSurface ? "8\nSurfaceLabels\n" : "8\nLabels\n"); /* Layer */
199   fprintf(fh, "10\n%6.2f\n", p->x);
200   fprintf(fh, "20\n%6.2f\n", p->y);
201   fprintf(fh, "30\n%6.2f\n", p->z);
202   fprintf(fh, "40\n%6.2f\n", text_height);
203   fprintf(fh, "1\n%s\n", s);
204}
205
206static void
207dxf_cross(const img_point *p, bool fSurface)
208{
209   /* write station marker to dxf file */
210   fprintf(fh, "0\nPOINT\n");
211   fprintf(fh, fSurface ? "8\nSurfaceStations\n" : "8\nStations\n"); /* Layer */
212   fprintf(fh, "10\n%6.2f\n", p->x);
213   fprintf(fh, "20\n%6.2f\n", p->y);
214   fprintf(fh, "30\n%6.2f\n", p->z);
215}
216
217static void
218dxf_footer(void)
219{
220   fprintf(fh, "000\nENDSEC\n");
221   fprintf(fh, "000\nEOF\n");
222}
223
224static void
225sketch_header(void)
226{
227   fprintf(fh, "##Sketch 1 2\n"); /* Sketch file version */
228   fprintf(fh, "document()\n");
229   fprintf(fh, "layout((%.3f,%.3f),0)\n",
230           (max_x - min_x) * factor, (max_y - min_y) * factor);
231}
232
233static const char *layer_names[] = {
234   NULL,
235   "Legs",
236   "Stations",
237   NULL,
238   "Labels"
239};
240
241static void
242sketch_start_pass(int layer)
243{
244   fprintf(fh, "layer('%s',1,1,0,0,(0,0,0))\n", layer_names[layer]);
245}
246
247static void
248sketch_move(const img_point *p)
249{
250   fprintf(fh, "b()\n");
251   fprintf(fh, "bs(%.3f,%.3f,%.3f)\n", p->x * factor, p->y * factor, 0.0);
252}
253
254static void
255sketch_line(const img_point *p1, const img_point *p, bool fSurface)
256{
257   fSurface = fSurface; /* unused */
258   p1 = p1; /* unused */
259   fprintf(fh, "bs(%.3f,%.3f,%.3f)\n", p->x * factor, p->y * factor, 0.0);
260}
261
262static void
263sketch_label(const img_point *p, const char *s, bool fSurface)
264{
265   fSurface = fSurface; /* unused */
266   fprintf(fh, "fp((0,0,0))\n");
267   fprintf(fh, "le()\n");
268   fprintf(fh, "Fn('Times-Roman')\n");
269   fprintf(fh, "Fs(5)\n");
270   fprintf(fh, "txt('");
271   while (*s) {
272      int ch = *s++;
273      if (ch == '\'' || ch == '\\') putc('\\', fh);
274      putc(ch, fh);
275   }
276   fprintf(fh, "',(%.3f,%.3f))\n", p->x * factor, p->y * factor);
277}
278
279static void
280sketch_cross(const img_point *p, bool fSurface)
281{
282   fSurface = fSurface; /* unused */
283   fprintf(fh, "b()\n");
284   fprintf(fh, "bs(%.3f,%.3f,%.3f)\n",
285           p->x * factor - MARKER_SIZE, p->y * factor - MARKER_SIZE, 0.0);
286   fprintf(fh, "bs(%.3f,%.3f,%.3f)\n",
287           p->x * factor + MARKER_SIZE, p->y * factor + MARKER_SIZE, 0.0);
288   fprintf(fh, "bn()\n");
289   fprintf(fh, "bs(%.3f,%.3f,%.3f)\n",
290           p->x * factor + MARKER_SIZE, p->y * factor - MARKER_SIZE, 0.0);
291   fprintf(fh, "bs(%.3f,%.3f,%.3f)\n",
292           p->x * factor - MARKER_SIZE, p->y * factor + MARKER_SIZE, 0.0);
293}
294
295static void
296sketch_footer(void)
297{
298   fprintf(fh, "guidelayer('Guide Lines',1,0,0,1,(0,0,1))\n");
299   if (grid) {
300      fprintf(fh, "grid((0,0,%.3f,%.3f),1,(0,0,1),'Grid')\n",
301              grid * factor, grid * factor);
302   }
303}
304
305typedef struct point {
306   img_point p;
307   const char *label;
308   struct point *next;
309} point;
310
311#define HTAB_SIZE 0x2000
312
313static point **htab;
314
315static void
316plt_header(void)
317{
318   size_t i;
319   htab = osmalloc(HTAB_SIZE * ossizeof(point *));
320   for (i = 0; i < HTAB_SIZE; ++i) htab[i] = NULL;
321   /* Survex is E, N, Alt - PLT file is N, E, Alt */
322   fprintf(fh, "Z %.3f %.3f %.3f %.3f %.3f %.3f\r\n",
323           min_y / METRES_PER_FOOT, max_y / METRES_PER_FOOT,
324           min_x / METRES_PER_FOOT, max_x / METRES_PER_FOOT,
325           min_z / METRES_PER_FOOT, max_z / METRES_PER_FOOT);
326   fprintf(fh, "N%s D 1 1 1 C%s\r\n", survey ? survey : "X", pimg->title);
327}
328
329static void
330plt_start_pass(int layer)
331{
332   layer = layer;
333}
334
335static void
336set_name(const img_point *p, const char *s)
337{
338   int hash;
339   point *pt;
340   union {
341      char data[sizeof(int) * 3];
342      int x[3];
343   } u;
344
345   u.x[0] = (int)(p->x * 100);
346   u.x[1] = (int)(p->y * 100);
347   u.x[2] = (int)(p->z * 100);
348   hash = (hash_data(u.data, sizeof(int) * 3) & (HTAB_SIZE - 1));
349   for (pt = htab[hash]; pt; pt = pt->next) {
350      if (pt->p.x == p->x && pt->p.y == p->y && pt->p.z == p->z) {
351         /* already got name for these coordinates */
352         /* FIXME: what about multiple names for the same station? */
353         return;
354      }
355   }
356
357   pt = osnew(point);
358   pt->label = osstrdup(s);
359   pt->p = *p;
360   pt->next = htab[hash];
361   htab[hash] = pt;
362
363   return;
364}
365
366static const char *
367find_name(const img_point *p)
368{
369   int hash;
370   point *pt;
371   union {
372      char data[sizeof(int) * 3];
373      int x[3];
374   } u;
375   SVX_ASSERT(p);
376
377   u.x[0] = (int)(p->x * 100);
378   u.x[1] = (int)(p->y * 100);
379   u.x[2] = (int)(p->z * 100);
380   hash = (hash_data(u.data, sizeof(int) * 3) & (HTAB_SIZE - 1));
381   for (pt = htab[hash]; pt; pt = pt->next) {
382      if (pt->p.x == p->x && pt->p.y == p->y && pt->p.z == p->z)
383         return pt->label;
384   }
385   return "?";
386}
387
388static void
389plt_move(const img_point *p)
390{
391   /* Survex is E, N, Alt - PLT file is N, E, Alt */
392   fprintf(fh, "M %.3f %.3f %.3f ",
393           p->y / METRES_PER_FOOT, p->x / METRES_PER_FOOT, p->z / METRES_PER_FOOT);
394   /* dummy passage dimensions are required to avoid compass bug */
395   fprintf(fh, "S%s P -9 -9 -9 -9\r\n", find_name(p));
396}
397
398static void
399plt_line(const img_point *p1, const img_point *p, bool fSurface)
400{
401   fSurface = fSurface; /* unused */
402   p1 = p1; /* unused */
403   /* Survex is E, N, Alt - PLT file is N, E, Alt */
404   fprintf(fh, "D %.3f %.3f %.3f ",
405           p->y / METRES_PER_FOOT, p->x / METRES_PER_FOOT, p->z / METRES_PER_FOOT);
406   /* dummy passage dimensions are required to avoid compass bug */
407   fprintf(fh, "S%s P -9 -9 -9 -9\r\n", find_name(p));
408}
409
410static void
411plt_label(const img_point *p, const char *s, bool fSurface)
412{
413   fSurface = fSurface; /* unused */
414   /* FIXME: also ctrl characters - ought to remap them, not give up */
415   if (strchr(s, ' ')) {
416      fprintf(stderr, "PLT format can't cope with spaces in station names\n");
417      exit(1);
418   }
419   set_name(p, s);
420}
421
422static void
423plt_cross(const img_point *p, bool fSurface)
424{
425   fSurface = fSurface; /* unused */
426   p = p; /* unused */
427}
428
429static void
430plt_footer(void)
431{
432   /* Survex is E, N, Alt - PLT file is N, E, Alt */
433   fprintf(fh, "X %.3f %.3f %.3f %.3f %.3f %.3f\r\n",
434           min_y / METRES_PER_FOOT, max_y / METRES_PER_FOOT,
435           min_x / METRES_PER_FOOT, max_x / METRES_PER_FOOT,
436           min_z / METRES_PER_FOOT, max_z / METRES_PER_FOOT);
437   /* Yucky DOS "end of textfile" marker */
438   putc('\x1a', fh);
439}
440
441#define LEGS 1
442#define STNS 2
443#define LABELS 4
444static int dxf_passes[] = { LEGS|STNS|LABELS, 0 };
445static int sketch_passes[] = { LEGS, STNS, LABELS, 0 };
446static int plt_passes[] = { LABELS, LEGS, 0 };
447
448int
449main(int argc, char **argv)
450{
451   char *fnm_3d, *fnm_out;
452   unsigned char labels, crosses, legs;
453   int item;
454   int fSeenMove = 0;
455   img_point p, p1;
456   int elevation = 0;
457   double elev_angle = 0;
458   double s = 0, c = 0;
459   enum { FMT_DXF = 0, FMT_SKETCH, FMT_PLT, FMT_AUTO } format;
460   static const char *extensions[] = { "dxf", "sk", "plt" };
461   int *pass;
462
463   void (*header)(void);
464   void (*start_pass)(int);
465   void (*move)(const img_point *);
466   void (*line)(const img_point *, const img_point *, bool);
467   void (*label)(const img_point *, const char *, bool);
468   void (*cross)(const img_point *, bool);
469   void (*footer)(void);
470   const char *mode = "w"; /* default to text output */
471
472   /* TRANSLATE */
473   static const struct option long_opts[] = {
474        /* const char *name; int has_arg (0 no_argument, 1 required, 2 options_*); int *flag; int val */
475        {"survey", required_argument, 0, 's'},
476        {"no-crosses", no_argument, 0, 'c'},
477        {"no-station-names", no_argument, 0, 'n'},
478        {"no-legs", no_argument, 0, 'l'},
479        {"grid", optional_argument, 0, 'g'},
480        {"text-height", required_argument, 0, 't'},
481        {"marker-size", required_argument, 0, 'm'},
482        {"elevation", required_argument, 0, 'e'},
483        {"reduction", required_argument, 0, 'r'},
484        {"dxf", no_argument, 0, 'D'},
485        {"sketch", no_argument, 0, 'S'},
486        {"plt", no_argument, 0, 'P'},
487        {"help", no_argument, 0, HLP_HELP},
488        {"version", no_argument, 0, HLP_VERSION},
489        {0,0,0,0}
490   };
491
492#define short_opts "s:cnlg::t:m:e:r:DSP"
493
494   /* TRANSLATE */
495   static struct help_msg help[] = {
496        {HLP_ENCODELONG(0), "only load the sub-survey with this prefix"},
497        {HLP_ENCODELONG(1), "do not generate station markers"},
498        {HLP_ENCODELONG(2), "do not generate station labels"},
499        {HLP_ENCODELONG(3), "do not generate the survey legs"},
500        {HLP_ENCODELONG(4), "generate grid (default "STRING(GRID_SPACING)"m)"},
501        {HLP_ENCODELONG(5), "station labels text height (default "STRING(TEXT_HEIGHT)")"},
502        {HLP_ENCODELONG(6), "station marker size (default "STRING(MARKER_SIZE)")"},
503        {HLP_ENCODELONG(7), "produce an elevation view"},
504        {HLP_ENCODELONG(8), "factor to scale down by (default 500)"},
505        {HLP_ENCODELONG(9), "produce DXF output"},
506        {HLP_ENCODELONG(10), "produce Sketch output"},
507        {HLP_ENCODELONG(11), "produce Compass PLT output for Carto"},
508        {0,0}
509   };
510
511   msg_init(argv);
512
513   /* Defaults */
514   crosses = 1;
515   labels = 1;
516   legs = 1;
517   grid = 0;
518   text_height = TEXT_HEIGHT;
519   marker_size = MARKER_SIZE;
520   format = FMT_AUTO;
521
522   cmdline_init(argc, argv, short_opts, long_opts, NULL, help, 1, 2);
523   while (1) {
524      int opt = cmdline_getopt();
525      if (opt == EOF) break;
526      switch (opt) {
527       case 'e': /* Elevation */
528         elevation = 1;
529         elev_angle = cmdline_double_arg();
530         break;
531       case 'c': /* Crosses */
532         crosses = 0;
533         break;
534       case 'n': /* Labels */
535         labels = 0;
536         break;
537       case 'l': /* Legs */
538         legs = 0;
539         break;
540       case 'g': /* Grid */
541         if (optarg) {
542            grid = cmdline_double_arg();
543         } else {
544            grid = (double)GRID_SPACING;
545         }
546         break;
547       case 'r': /* Reduction factor */
548         scale = cmdline_double_arg();
549         break;
550       case 't': /* Text height */
551         text_height = cmdline_double_arg();
552#ifdef DEBUG_CAD3D
553         printf("Text Height: `%s' input, converted to %6.2f\n", optarg, text_height);
554#endif
555         break;
556       case 'm': /* Marker size */
557         marker_size = cmdline_double_arg();
558#ifdef DEBUG_CAD3D
559         printf("Marker Size: `%s', converted to %6.2f\n", optarg, marker_size);
560#endif
561         break;
562       case 'D':
563         format = FMT_DXF;
564         break;
565       case 'S':
566         format = FMT_SKETCH;
567         break;
568       case 'P':
569         format = FMT_PLT;
570         break;
571       case 's':
572         survey = optarg;
573         break;
574#ifdef DEBUG_CAD3D
575       default:
576         printf("Internal Error: 'getopt' returned '%c' %d\n", opt, opt);
577#endif
578      }
579   }
580
581   fnm_3d = argv[optind++];
582   if (argv[optind]) {
583      fnm_out = argv[optind];
584      if (format == FMT_AUTO) {
585         size_t i;
586         size_t len = strlen(fnm_out);
587         format = FMT_DEFAULT;
588         for (i = 0; i < FMT_AUTO; ++i) {
589            size_t l = strlen(extensions[i]);
590            if (len > l + 1 && fnm_out[len - l - 1] == FNM_SEP_EXT &&
591                strcasecmp(fnm_out + len - l, extensions[i]) == 0) {
592               format = i;
593               break;
594            }
595         }
596      }
597   } else {
598      char *baseleaf = baseleaf_from_fnm(fnm_3d);
599      if (format == FMT_AUTO) format = FMT_DEFAULT;
600      /* note : memory allocated by fnm_out gets leaked in this case... */
601      fnm_out = add_ext(baseleaf, extensions[format]);
602      osfree(baseleaf);
603   }
604
605   switch (format) {
606    case FMT_DXF:
607      header = dxf_header;
608      start_pass = dxf_start_pass;
609      move = dxf_move;
610      line = dxf_line;
611      label = dxf_label;
612      cross = dxf_cross;
613      footer = dxf_footer;
614      pass = dxf_passes;
615      break;
616    case FMT_SKETCH:
617      header = sketch_header;
618      start_pass = sketch_start_pass;
619      move = sketch_move;
620      line = sketch_line;
621      label = sketch_label;
622      cross = sketch_cross;
623      footer = sketch_footer;
624      pass = sketch_passes;
625      factor = POINTS_PER_MM * 1000.0 / scale;
626      mode = "wb"; /* Binary file output */
627      break;
628    case FMT_PLT:
629      header = plt_header;
630      start_pass = plt_start_pass;
631      move = plt_move;
632      line = plt_line;
633      label = plt_label;
634      cross = plt_cross;
635      footer = plt_footer;
636      pass = plt_passes;
637      mode = "wb"; /* Binary file output */
638      break;
639    default:
640      exit(1);
641   }
642
643   pimg = img_open_survey(fnm_3d, survey);
644   if (!pimg) fatalerror(img_error(), fnm_3d);
645
646   fh = safe_fopen(fnm_out, mode);
647
648   if (elevation) {
649      s = sin(rad(elev_angle));
650      c = cos(rad(elev_angle));
651   }
652
653   /* Get drawing corners */
654   min_x = min_y = min_z = HUGE_VAL;
655   max_x = max_y = max_z = -HUGE_VAL;
656   do {
657      item = img_read_item(pimg, &p);
658
659      if (elevation) {
660         double xnew = p.x * c - p.y * s;
661         double znew = - p.x * s - p.y * c;
662         p.y = p.z;
663         p.z = znew;
664         p.x = xnew;
665      }
666
667      switch (item) {
668       case img_MOVE: case img_LINE: case img_LABEL:
669         if (p.x < min_x) min_x = p.x;
670         if (p.x > max_x) max_x = p.x;
671         if (p.y < min_y) min_y = p.y;
672         if (p.y > max_y) max_y = p.y;
673         if (p.z < min_z) min_z = p.z;
674         if (p.z > max_z) max_z = p.z;
675         break;
676      }
677   } while (item != img_STOP);
678
679   if (grid > 0) {
680      min_x -= grid / 2;
681      max_x += grid / 2;
682      min_y -= grid / 2;
683      max_y += grid / 2;
684   }
685
686   /* handle empty file gracefully */
687   if (min_x > max_x) {
688      min_x = min_y = min_z = 0;
689      max_x = max_y = max_z = 0;
690   }
691
692   /* Header */
693   header();
694
695   p1.x = p1.y = p1.z = 0; /* avoid compiler warning */
696
697   while (*pass) {
698      if (((*pass & LEGS) && legs) ||
699          ((*pass & STNS) && crosses) ||
700          ((*pass & LABELS) && labels)) {
701         img_rewind(pimg);
702         start_pass(*pass);
703         do {
704            item = img_read_item(pimg, &p);
705
706            if (format == FMT_SKETCH) {
707               p.x -= min_x;
708               p.y -= min_y;
709               p.z -= min_z;
710            }
711
712            if (elevation) {
713               double xnew = p.x * c - p.y * s;
714               double znew = - p.x * s - p.y * c;
715               p.y = p.z;
716               p.z = znew;
717               p.x = xnew;
718            }
719
720            switch (item) {
721             case img_BAD:
722               img_close(pimg);
723               fatalerror(/*Bad 3d image file `%s'*/106, fnm_3d);
724               break;
725             case img_LINE:
726#ifdef DEBUG_CAD3D
727               printf("line to %9.2f %9.2f %9.2f\n", p.x, p.y, p.z);
728#endif
729               if (!fSeenMove) {
730#ifdef DEBUG_CAD3D
731                  printf("Something is wrong -- img_LINE before any img_MOVE!\n");
732#endif
733                  img_close(pimg);
734                  fatalerror(/*Bad 3d image file `%s'*/106, fnm_3d);
735               }
736               if ((*pass & LEGS) && legs)
737                  line(&p1, &p, pimg->flags & img_FLAG_SURFACE);
738               p1 = p;
739               break;
740             case img_MOVE:
741#ifdef DEBUG_CAD3D
742               printf("move to %9.2f %9.2f %9.2f\n",x,y,z);
743#endif
744               if ((*pass & LEGS) && legs) move(&p);
745               fSeenMove = 1;
746               p1 = p;
747               break;
748             case img_LABEL:
749#ifdef DEBUG_CAD3D
750               printf("label `%s' at %9.2f %9.2f %9.2f\n",pimg->label,x,y,z);
751#endif
752               /* Use !UNDERGROUND as the criterion - we want stations where
753                * a surface and underground survey meet to be in the
754                * underground layer */
755               if ((*pass & LABELS) && labels)
756                  label(&p, pimg->label,
757                        !(pimg->flags & img_SFLAG_UNDERGROUND));
758               if ((*pass & STNS) && crosses)
759                  cross(&p, !(pimg->flags & img_SFLAG_UNDERGROUND));
760               break;
761#ifdef DEBUG_CAD3D
762             case img_STOP:
763               printf("stop\n");
764               break;
765             default:
766               printf("other info tag (code %d) ignored\n",item);
767#endif
768            }
769         } while (item != img_STOP);
770      }
771      pass++;
772   }
773   img_close(pimg);
774   footer();
775   safe_fclose(fh);
776   return 0;
777}
Note: See TracBrowser for help on using the repository browser.