source: git/src/cad3d.c @ 76d6c16

RELEASE/1.0RELEASE/1.2debug-cidebug-ci-sanitisersstereowalls-data
Last change on this file since 76d6c16 was 76d6c16, checked in by Olly Betts <olly@…>, 20 years ago

Fixed dashed lines in DXF output.

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

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