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