| [7ee2b42] | 1 | /* extend.c | 
|---|
| [d1b1380] | 2 |  * Produce an extended elevation | 
|---|
| [736f7df] | 3 |  * Copyright (C) 1995-2002,2005,2010,2011,2013,2014 Olly Betts | 
|---|
| [d92d282] | 4 |  * Copyright (C) 2004,2005 John Pybus | 
|---|
| [846746e] | 5 |  * | 
|---|
| [89231c4] | 6 |  * This program is free software; you can redistribute it and/or modify | 
|---|
 | 7 |  * it under the terms of the GNU General Public License as published by | 
|---|
 | 8 |  * the Free Software Foundation; either version 2 of the License, or | 
|---|
 | 9 |  * (at your option) any later version. | 
|---|
| [846746e] | 10 |  * | 
|---|
 | 11 |  * This program is distributed in the hope that it will be useful, | 
|---|
 | 12 |  * but WITHOUT ANY WARRANTY; without even the implied warranty of | 
|---|
| [89231c4] | 13 |  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | 
|---|
 | 14 |  * GNU General Public License for more details. | 
|---|
| [846746e] | 15 |  * | 
|---|
| [89231c4] | 16 |  * You should have received a copy of the GNU General Public License | 
|---|
 | 17 |  * along with this program; if not, write to the Free Software | 
|---|
| [ecbc6c18] | 18 |  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA | 
|---|
| [d1b1380] | 19 |  */ | 
|---|
 | 20 |  | 
|---|
| [a420b49] | 21 | #ifdef HAVE_CONFIG_H | 
|---|
 | 22 | # include <config.h> | 
|---|
 | 23 | #endif | 
|---|
| [d1b1380] | 24 |  | 
|---|
| [e55ee28] | 25 | #include <float.h> | 
|---|
| [d1b1380] | 26 | #include <stdio.h> | 
|---|
 | 27 | #include <stdlib.h> | 
|---|
 | 28 | #include <string.h> | 
|---|
 | 29 |  | 
|---|
| [acc20b1] | 30 | #include "cmdline.h" | 
|---|
| [693388e] | 31 | #include "debug.h" | 
|---|
| [d1b1380] | 32 | #include "filelist.h" | 
|---|
| [693388e] | 33 | #include "filename.h" | 
|---|
 | 34 | #include "hash.h" | 
|---|
| [a405bc1] | 35 | #include "img_hosted.h" | 
|---|
| [693388e] | 36 | #include "message.h" | 
|---|
 | 37 | #include "useful.h" | 
|---|
| [d1b1380] | 38 |  | 
|---|
| [693388e] | 39 | /* To save memory we should probably use the prefix hash for the prefix on | 
|---|
 | 40 |  * point labels (FIXME) */ | 
|---|
| [ea1c342] | 41 |  | 
|---|
 | 42 | typedef struct stn { | 
|---|
 | 43 |    const char *label; | 
|---|
 | 44 |    int flags; | 
|---|
| [ee11c6a7] | 45 |    const struct stn *next; | 
|---|
| [ea1c342] | 46 | } stn; | 
|---|
 | 47 |  | 
|---|
| [d1b1380] | 48 | typedef struct POINT { | 
|---|
| [0ed0e16] | 49 |    img_point p; | 
|---|
| [ea1c342] | 50 |    const stn *stns; | 
|---|
| [647407d] | 51 |    unsigned int order; | 
|---|
| [d92d282] | 52 |    char dir; | 
|---|
 | 53 |    char fDone; | 
|---|
 | 54 |    char fBroken; | 
|---|
| [d1b1380] | 55 |    struct POINT *next; | 
|---|
 | 56 | } point; | 
|---|
 | 57 |  | 
|---|
 | 58 | typedef struct LEG { | 
|---|
 | 59 |    point *fr, *to; | 
|---|
| [693388e] | 60 |    const char *prefix; | 
|---|
| [d92d282] | 61 |    char dir; | 
|---|
 | 62 |    char fDone; | 
|---|
 | 63 |    char broken; | 
|---|
| [95c3272] | 64 |    int flags; | 
|---|
 | 65 |    struct LEG *next; | 
|---|
| [d1b1380] | 66 | } leg; | 
|---|
 | 67 |  | 
|---|
| [d92d282] | 68 | /* Values for leg.broken: */ | 
|---|
 | 69 | #define BREAK_FR    0x01 | 
|---|
 | 70 | #define BREAK_TO    0x02 | 
|---|
| [d1b1380] | 71 |  | 
|---|
| [d92d282] | 72 | /* Values for point.dir and leg.dir: */ | 
|---|
 | 73 | #define ELEFT  0x01 | 
|---|
 | 74 | #define ERIGHT 0x02 | 
|---|
 | 75 | #define ESWAP  0x04 | 
|---|
 | 76 |  | 
|---|
 | 77 | static point headpoint = {{0, 0, 0}, NULL, 0, 0, 0, 0, NULL}; | 
|---|
 | 78 |  | 
|---|
 | 79 | static leg headleg = {NULL, NULL, NULL, 0, 0, 0, 0, NULL}; | 
|---|
| [d1b1380] | 80 |  | 
|---|
| [31b7105] | 81 | static img *pimg_out; | 
|---|
| [d1b1380] | 82 |  | 
|---|
| [d92d282] | 83 | static void do_stn(point *, double, const char *, int, int); | 
|---|
| [d1b1380] | 84 |  | 
|---|
| [693388e] | 85 | typedef struct pfx { | 
|---|
 | 86 |    const char *label; | 
|---|
 | 87 |    struct pfx *next; | 
|---|
 | 88 | } pfx; | 
|---|
 | 89 |  | 
|---|
 | 90 | static pfx **htab; | 
|---|
 | 91 |  | 
|---|
| [63dc4eb] | 92 | #define HTAB_SIZE 0x2000 | 
|---|
 | 93 |  | 
|---|
| [693388e] | 94 | static const char * | 
|---|
 | 95 | find_prefix(const char *prefix) | 
|---|
 | 96 | { | 
|---|
 | 97 |    pfx *p; | 
|---|
 | 98 |    int hash; | 
|---|
 | 99 |  | 
|---|
| [4c07c51] | 100 |    SVX_ASSERT(prefix); | 
|---|
| [421b7d2] | 101 |  | 
|---|
| [63dc4eb] | 102 |    hash = hash_string(prefix) & (HTAB_SIZE - 1); | 
|---|
| [693388e] | 103 |    for (p = htab[hash]; p; p = p->next) { | 
|---|
 | 104 |       if (strcmp(prefix, p->label) == 0) return p->label; | 
|---|
 | 105 |    } | 
|---|
 | 106 |  | 
|---|
 | 107 |    p = osnew(pfx); | 
|---|
 | 108 |    p->label = osstrdup(prefix); | 
|---|
 | 109 |    p->next = htab[hash]; | 
|---|
 | 110 |    htab[hash] = p; | 
|---|
 | 111 |  | 
|---|
 | 112 |    return p->label; | 
|---|
 | 113 | } | 
|---|
 | 114 |  | 
|---|
| [a420b49] | 115 | static point * | 
|---|
| [0ed0e16] | 116 | find_point(const img_point *pt) | 
|---|
| [a420b49] | 117 | { | 
|---|
| [d1b1380] | 118 |    point *p; | 
|---|
| [647407d] | 119 |    for (p = headpoint.next; p != NULL; p = p->next) { | 
|---|
| [0ed0e16] | 120 |       if (pt->x == p->p.x && pt->y == p->p.y && pt->z == p->p.z) { | 
|---|
| [647407d] | 121 |          return p; | 
|---|
 | 122 |       } | 
|---|
 | 123 |    } | 
|---|
| [a420b49] | 124 |  | 
|---|
 | 125 |    p = osmalloc(ossizeof(point)); | 
|---|
| [0ed0e16] | 126 |    p->p = *pt; | 
|---|
| [ea1c342] | 127 |    p->stns = NULL; | 
|---|
| [7ee2b42] | 128 |    p->order = 0; | 
|---|
| [d92d282] | 129 |    p->dir = 0; | 
|---|
 | 130 |    p->fDone = 0; | 
|---|
| [8add4c9] | 131 |    p->fBroken = 0; | 
|---|
| [a420b49] | 132 |    p->next = headpoint.next; | 
|---|
 | 133 |    headpoint.next = p; | 
|---|
| [d1b1380] | 134 |    return p; | 
|---|
 | 135 | } | 
|---|
 | 136 |  | 
|---|
| [a420b49] | 137 | static void | 
|---|
| [693388e] | 138 | add_leg(point *fr, point *to, const char *prefix, int flags) | 
|---|
| [a420b49] | 139 | { | 
|---|
| [95c3272] | 140 |    leg *l; | 
|---|
| [7ee2b42] | 141 |    fr->order++; | 
|---|
 | 142 |    to->order++; | 
|---|
| [95c3272] | 143 |    l = osmalloc(ossizeof(leg)); | 
|---|
 | 144 |    l->fr = fr; | 
|---|
 | 145 |    l->to = to; | 
|---|
| [693388e] | 146 |    if (prefix) | 
|---|
 | 147 |       l->prefix = find_prefix(prefix); | 
|---|
 | 148 |    else | 
|---|
 | 149 |       l->prefix = NULL; | 
|---|
| [95c3272] | 150 |    l->next = headleg.next; | 
|---|
| [d92d282] | 151 |    l->dir = 0; | 
|---|
| [95c3272] | 152 |    l->fDone = 0; | 
|---|
| [8add4c9] | 153 |    l->broken = 0; | 
|---|
| [95c3272] | 154 |    l->flags = flags; | 
|---|
 | 155 |    headleg.next = l; | 
|---|
| [d1b1380] | 156 | } | 
|---|
 | 157 |  | 
|---|
| [a420b49] | 158 | static void | 
|---|
| [95c3272] | 159 | add_label(point *p, const char *label, int flags) | 
|---|
| [a420b49] | 160 | { | 
|---|
| [ea1c342] | 161 |    stn *s = osnew(stn); | 
|---|
 | 162 |    s->label = osstrdup(label); | 
|---|
 | 163 |    s->flags = flags; | 
|---|
 | 164 |    s->next = p->stns; | 
|---|
 | 165 |    p->stns = s; | 
|---|
| [d1b1380] | 166 | } | 
|---|
 | 167 |  | 
|---|
| [d92d282] | 168 | /* Read in config file */ | 
|---|
 | 169 |  | 
|---|
 | 170 |  | 
|---|
 | 171 | /* lifted from img.c Should be put somewhere common? JPNP*/ | 
|---|
 | 172 | static char * | 
|---|
 | 173 | getline_alloc(FILE *fh, size_t ilen) | 
|---|
 | 174 | { | 
|---|
 | 175 |    int ch; | 
|---|
 | 176 |    size_t i = 0; | 
|---|
 | 177 |    size_t len = ilen; | 
|---|
 | 178 |    char *buf = xosmalloc(len); | 
|---|
 | 179 |    if (!buf) return NULL; | 
|---|
 | 180 |  | 
|---|
| [e02a6a6] | 181 |    ch = GETC(fh); | 
|---|
| [d92d282] | 182 |    while (ch != '\n' && ch != '\r' && ch != EOF) { | 
|---|
 | 183 |       buf[i++] = ch; | 
|---|
 | 184 |       if (i == len - 1) { | 
|---|
 | 185 |          char *p; | 
|---|
 | 186 |          len += len; | 
|---|
 | 187 |          p = xosrealloc(buf, len); | 
|---|
 | 188 |          if (!p) { | 
|---|
 | 189 |             osfree(buf); | 
|---|
 | 190 |             return NULL; | 
|---|
 | 191 |          } | 
|---|
 | 192 |          buf = p; | 
|---|
 | 193 |       } | 
|---|
| [e02a6a6] | 194 |       ch = GETC(fh); | 
|---|
| [d92d282] | 195 |    } | 
|---|
 | 196 |    if (ch == '\n' || ch == '\r') { | 
|---|
 | 197 |       int otherone = ch ^ ('\n' ^ '\r'); | 
|---|
| [e02a6a6] | 198 |       ch = GETC(fh); | 
|---|
| [d92d282] | 199 |       /* if it's not the other eol character, put it back */ | 
|---|
 | 200 |       if (ch != otherone) ungetc(ch, fh); | 
|---|
 | 201 |    } | 
|---|
 | 202 |    buf[i++] = '\0'; | 
|---|
 | 203 |    return buf; | 
|---|
 | 204 | } | 
|---|
 | 205 |  | 
|---|
 | 206 | static int lineno = 0; | 
|---|
 | 207 | static point *start = NULL; | 
|---|
 | 208 |  | 
|---|
 | 209 | static char* | 
|---|
 | 210 | delimword(char *ln, char** lr) | 
|---|
 | 211 | { | 
|---|
 | 212 |    char *le; | 
|---|
 | 213 |  | 
|---|
 | 214 |    while (*ln == ' ' || *ln == '\t' || *ln == '\n' || *ln == '\r') | 
|---|
 | 215 |       ln++; | 
|---|
 | 216 |  | 
|---|
 | 217 |    le = ln; | 
|---|
 | 218 |    while (*le != ' ' && *le != '\t' && *le != '\n' && *le != '\r' && *le != ';' && *le != '\0') | 
|---|
 | 219 |       le++; | 
|---|
 | 220 |  | 
|---|
 | 221 |    if (*le == '\0' || *le == ';') { | 
|---|
 | 222 |       *lr = le; | 
|---|
 | 223 |    } else { | 
|---|
 | 224 |       *lr = le + 1; | 
|---|
 | 225 |    } | 
|---|
| [6e4a123] | 226 |  | 
|---|
| [d92d282] | 227 |    *le = '\0'; | 
|---|
 | 228 |    return ln; | 
|---|
 | 229 | } | 
|---|
 | 230 |  | 
|---|
 | 231 | static void | 
|---|
| [7926772] | 232 | parseconfigline(const char *fnm, char *ln) | 
|---|
| [d92d282] | 233 | { | 
|---|
 | 234 |    point *p; | 
|---|
 | 235 |    const stn *s; | 
|---|
 | 236 |    const stn *t; | 
|---|
 | 237 |    leg *l; | 
|---|
 | 238 |    char *lc = NULL; | 
|---|
 | 239 |  | 
|---|
 | 240 |    ln = delimword(ln, &lc); | 
|---|
 | 241 |  | 
|---|
 | 242 |    if (*ln == '\0') return; | 
|---|
 | 243 |  | 
|---|
 | 244 |    if (strcmp(ln, "*start")==0) { | 
|---|
 | 245 |       ln = delimword(lc, &lc); | 
|---|
| [7926772] | 246 |       if (*ln == 0) | 
|---|
| [0b8c321] | 247 |          /* TRANSLATORS: Here "station" is a survey station, not a train station. */ | 
|---|
| [7926772] | 248 |          fatalerror_in_file(fnm, lineno, /*Expecting station name*/28); | 
|---|
| [d92d282] | 249 |       for (p = headpoint.next; p != NULL; p = p->next) { | 
|---|
 | 250 |          for (s = p->stns; s; s = s->next) { | 
|---|
 | 251 |             if (strcmp(s->label, ln)==0) { | 
|---|
 | 252 |                start = p; | 
|---|
| [736f7df] | 253 |                /* TRANSLATORS: for extend: "extend" is starting to produce an extended elevation from station %s */ | 
|---|
| [7926772] | 254 |                printf(msg(/*Starting from station %s*/512),ln); | 
|---|
| [d92d282] | 255 |                putnl(); | 
|---|
 | 256 |                goto loopend; | 
|---|
 | 257 |             } | 
|---|
 | 258 |          } | 
|---|
 | 259 |       } | 
|---|
| [736f7df] | 260 |       /* TRANSLATORS: for extend: the user specified breaking a loop or | 
|---|
 | 261 |        * changing extend direction at this station, but we didn’t find it in | 
|---|
 | 262 |        * the 3d file */ | 
|---|
| [7926772] | 263 |       warning_in_file(fnm, lineno, /*Failed to find station %s*/510, ln); | 
|---|
| [d92d282] | 264 |    } else if (strcmp(ln, "*eleft")==0) { | 
|---|
 | 265 |       char *ll = delimword(lc, &lc); | 
|---|
| [7926772] | 266 |       if (*ll == 0) | 
|---|
 | 267 |          fatalerror_in_file(fnm, lineno, /*Expecting station name*/28); | 
|---|
| [d92d282] | 268 |       ln = delimword(lc, &lc); | 
|---|
 | 269 |       if (*ln == 0) { /* One argument, look for point to switch at. */ | 
|---|
 | 270 |          for (p = headpoint.next; p != NULL; p = p->next) { | 
|---|
 | 271 |             for (s = p->stns; s; s = s->next) { | 
|---|
 | 272 |                if (strcmp(s->label, ll)==0) { | 
|---|
| [736f7df] | 273 |                   /* TRANSLATORS: for extend: */ | 
|---|
| [7926772] | 274 |                   printf(msg(/*Extending to the left from station %s*/513), ll); | 
|---|
| [d92d282] | 275 |                   putnl(); | 
|---|
 | 276 |                   p->dir = ELEFT; | 
|---|
 | 277 |                   goto loopend; | 
|---|
 | 278 |                } | 
|---|
 | 279 |             } | 
|---|
 | 280 |          } | 
|---|
| [7926772] | 281 |          warning_in_file(fnm, lineno, /*Failed to find station %s*/510, ll); | 
|---|
| [d92d282] | 282 |       } else { /* Two arguments look for a specific leg */ | 
|---|
 | 283 |          for (l = headleg.next; l; l=l->next) { | 
|---|
 | 284 |             point * fr = l->fr; | 
|---|
 | 285 |             point * to = l->to; | 
|---|
 | 286 |             if (fr && to) { | 
|---|
 | 287 |                for (s=fr->stns; s; s=s->next) { | 
|---|
 | 288 |                   int b = 0; | 
|---|
 | 289 |                   if (strcmp(s->label,ll)==0 || (strcmp(s->label, ln)==0 && (b = 1)) ) { | 
|---|
 | 290 |                      char * lr = (b ? ll : ln); | 
|---|
 | 291 |                      for (t=to->stns; t; t=t->next) { | 
|---|
 | 292 |                         if (strcmp(t->label,lr)==0) { | 
|---|
| [736f7df] | 293 |                            /* TRANSLATORS: for extend: */ | 
|---|
| [ee7511a] | 294 |                            printf(msg(/*Extending to the left from leg %s → %s*/515), s->label, t->label); | 
|---|
| [d92d282] | 295 |                            putnl(); | 
|---|
 | 296 |                            l->dir = ELEFT; | 
|---|
 | 297 |                            goto loopend; | 
|---|
 | 298 |                         } | 
|---|
 | 299 |                      } | 
|---|
 | 300 |                   } | 
|---|
 | 301 |                } | 
|---|
 | 302 |             } | 
|---|
 | 303 |          } | 
|---|
| [736f7df] | 304 |          /* TRANSLATORS: for extend: the user specified breaking a loop or | 
|---|
 | 305 |           * changing extend direction at this leg, but we didn’t find it in the | 
|---|
 | 306 |           * 3d file */ | 
|---|
| [ee7511a] | 307 |          warning_in_file(fnm, lineno, /*Failed to find leg %s → %s*/511, ll, ln); | 
|---|
| [d92d282] | 308 |       } | 
|---|
 | 309 |    } else if (strcmp(ln, "*eright")==0) { | 
|---|
 | 310 |       char *ll = delimword(lc, &lc); | 
|---|
| [7926772] | 311 |       if (*ll == 0) | 
|---|
 | 312 |          fatalerror_in_file(fnm, lineno, /*Expecting station name*/28); | 
|---|
| [d92d282] | 313 |       ln = delimword(lc, &lc); | 
|---|
 | 314 |       if (*ln == 0) { /* One argument, look for point to switch at. */ | 
|---|
 | 315 |          for (p = headpoint.next; p != NULL; p = p->next) { | 
|---|
 | 316 |             for (s = p->stns; s; s = s->next) { | 
|---|
 | 317 |                if (strcmp(s->label, ll)==0) { | 
|---|
| [736f7df] | 318 |                   /* TRANSLATORS: for extend: */ | 
|---|
| [7926772] | 319 |                   printf(msg(/*Extending to the right from station %s*/514), ll); | 
|---|
| [d92d282] | 320 |                   putnl(); | 
|---|
 | 321 |                   p->dir = ERIGHT; | 
|---|
 | 322 |                   goto loopend; | 
|---|
 | 323 |                } | 
|---|
 | 324 |             } | 
|---|
 | 325 |          } | 
|---|
| [7926772] | 326 |          warning_in_file(fnm, lineno, /*Failed to find station %s*/510, ll); | 
|---|
| [d92d282] | 327 |       } else { /* Two arguments look for a specific leg */ | 
|---|
 | 328 |          for (l = headleg.next; l; l=l->next) { | 
|---|
 | 329 |             point * fr = l->fr; | 
|---|
 | 330 |             point * to = l->to; | 
|---|
 | 331 |             if (fr && to) { | 
|---|
 | 332 |                for (s=fr->stns; s; s=s->next) { | 
|---|
 | 333 |                   int b = 0; | 
|---|
 | 334 |                   if (strcmp(s->label,ll)==0 || (strcmp(s->label, ln)==0 && (b = 1)) ) { | 
|---|
 | 335 |                      char * lr = (b ? ll : ln); | 
|---|
 | 336 |                      for (t=to->stns; t; t=t->next) { | 
|---|
 | 337 |                         if (strcmp(t->label,lr)==0) { | 
|---|
| [736f7df] | 338 |                            /* TRANSLATORS: for extend: */ | 
|---|
| [ee7511a] | 339 |                            printf(msg(/*Extending to the right from leg %s → %s*/516), s->label, t->label); | 
|---|
| [7926772] | 340 |                            putnl(); | 
|---|
| [d92d282] | 341 |                            l->dir=ERIGHT; | 
|---|
 | 342 |                            goto loopend; | 
|---|
 | 343 |                         } | 
|---|
 | 344 |                      } | 
|---|
 | 345 |                   } | 
|---|
 | 346 |                } | 
|---|
 | 347 |             } | 
|---|
 | 348 |          } | 
|---|
| [ee7511a] | 349 |          warning_in_file(fnm, lineno, /*Failed to find leg %s → %s*/511, ll, ln); | 
|---|
| [d92d282] | 350 |       } | 
|---|
 | 351 |    } else if (strcmp(ln, "*eswap")==0) { | 
|---|
 | 352 |       char *ll = delimword(lc, &lc); | 
|---|
| [7926772] | 353 |       if (*ll == 0) | 
|---|
 | 354 |          fatalerror_in_file(fnm, lineno, /*Expecting station name*/28); | 
|---|
| [d92d282] | 355 |       ln = delimword(lc, &lc); | 
|---|
 | 356 |       if (*ln == 0) { /* One argument, look for point to switch at. */ | 
|---|
 | 357 |          for (p = headpoint.next; p != NULL; p = p->next) { | 
|---|
 | 358 |             for (s = p->stns; s; s = s->next) { | 
|---|
 | 359 |                if (strcmp(s->label, ll)==0) { | 
|---|
| [736f7df] | 360 |                   /* TRANSLATORS: for extend: */ | 
|---|
| [7926772] | 361 |                   printf(msg(/*Swapping extend direction from station %s*/519),ll); | 
|---|
| [d92d282] | 362 |                   putnl(); | 
|---|
 | 363 |                   p->dir = ESWAP; | 
|---|
 | 364 |                   goto loopend; | 
|---|
 | 365 |                } | 
|---|
 | 366 |             } | 
|---|
 | 367 |          } | 
|---|
| [7926772] | 368 |          warning_in_file(fnm, lineno, /*Failed to find station %s*/510, ll); | 
|---|
| [d92d282] | 369 |       } else { /* Two arguments look for a specific leg */ | 
|---|
 | 370 |          for (l = headleg.next; l; l=l->next) { | 
|---|
 | 371 |             point * fr = l->fr; | 
|---|
 | 372 |             point * to = l->to; | 
|---|
 | 373 |             if (fr && to) { | 
|---|
 | 374 |                for (s=fr->stns; s; s=s->next) { | 
|---|
 | 375 |                   int b = 0; | 
|---|
 | 376 |                   if (strcmp(s->label,ll)==0 || (strcmp(s->label, ln)==0 && (b = 1)) ) { | 
|---|
 | 377 |                      char * lr = (b ? ll : ln); | 
|---|
 | 378 |                      for (t=to->stns; t; t=t->next) { | 
|---|
 | 379 |                         if (strcmp(t->label,lr)==0) { | 
|---|
| [736f7df] | 380 |                            /* TRANSLATORS: for extend: */ | 
|---|
| [ee7511a] | 381 |                            printf(msg(/*Swapping extend direction from leg %s → %s*/520), s->label, t->label); | 
|---|
| [7926772] | 382 |                            putnl(); | 
|---|
| [d92d282] | 383 |                            l->dir = ESWAP; | 
|---|
 | 384 |                            goto loopend; | 
|---|
 | 385 |                         } | 
|---|
 | 386 |                      } | 
|---|
 | 387 |                   } | 
|---|
 | 388 |                } | 
|---|
 | 389 |             } | 
|---|
 | 390 |          } | 
|---|
| [ee7511a] | 391 |          warning_in_file(fnm, lineno, /*Failed to find leg %s → %s*/511, ll, ln); | 
|---|
| [d92d282] | 392 |       } | 
|---|
 | 393 |    } else if (strcmp(ln, "*break")==0) { | 
|---|
 | 394 |       char *ll = delimword(lc, &lc); | 
|---|
| [7926772] | 395 |       if (*ll == 0) | 
|---|
 | 396 |          fatalerror_in_file(fnm, lineno, /*Expecting station name*/28); | 
|---|
| [d92d282] | 397 |       ln = delimword(lc, &lc); | 
|---|
 | 398 |       if (*ln == 0) { /* One argument, look for point to break at. */ | 
|---|
 | 399 |          for (p = headpoint.next; p != NULL; p = p->next) { | 
|---|
 | 400 |             for (s = p->stns; s; s = s->next) { | 
|---|
 | 401 |                if (strcmp(s->label, ll)==0) { | 
|---|
| [736f7df] | 402 |                   /* TRANSLATORS: for extend: */ | 
|---|
| [7926772] | 403 |                   printf(msg(/*Breaking survey loop at station %s*/517), ll); | 
|---|
| [d92d282] | 404 |                   putnl(); | 
|---|
 | 405 |                   p->fBroken = 1; | 
|---|
 | 406 |                   goto loopend; | 
|---|
 | 407 |                } | 
|---|
 | 408 |             } | 
|---|
 | 409 |          } | 
|---|
| [7926772] | 410 |          warning_in_file(fnm, lineno, /*Failed to find station %s*/510, ll); | 
|---|
| [d92d282] | 411 |       } else { /* Two arguments look for a specific leg */ | 
|---|
 | 412 |          for (l = headleg.next; l; l=l->next) { | 
|---|
 | 413 |             point * fr = l->fr; | 
|---|
 | 414 |             point * to = l->to; | 
|---|
 | 415 |             if (fr && to) { | 
|---|
 | 416 |                for (s=fr->stns; s; s=s->next) { | 
|---|
 | 417 |                   int b = 0; | 
|---|
 | 418 |                   if (strcmp(s->label,ll)==0 || (strcmp(s->label, ln)==0 && (b = 1)) ) { | 
|---|
 | 419 |                      char * lr = (b ? ll : ln); | 
|---|
 | 420 |                      for (t=to->stns; t; t=t->next) { | 
|---|
 | 421 |                         if (strcmp(t->label,lr)==0) { | 
|---|
| [736f7df] | 422 |                            /* TRANSLATORS: for extend: */ | 
|---|
| [ee7511a] | 423 |                            printf(msg(/*Breaking survey loop at leg %s → %s*/518), s->label, t->label); | 
|---|
| [d92d282] | 424 |                            putnl(); | 
|---|
 | 425 |                            l->broken = (b ? BREAK_TO : BREAK_FR); | 
|---|
 | 426 |                            goto loopend; | 
|---|
 | 427 |                         } | 
|---|
 | 428 |                      } | 
|---|
 | 429 |                   } | 
|---|
 | 430 |                } | 
|---|
 | 431 |             } | 
|---|
 | 432 |          } | 
|---|
| [ee7511a] | 433 |          warning_in_file(fnm, lineno, /*Failed to find leg %s → %s*/511, ll, ln); | 
|---|
| [d92d282] | 434 |       } | 
|---|
 | 435 |    } else { | 
|---|
| [0804fbe] | 436 |       fatalerror_in_file(fnm, lineno, /*Unknown command “%s”*/12, ln); | 
|---|
| [d92d282] | 437 |    } | 
|---|
 | 438 |  loopend: | 
|---|
 | 439 |    ln = delimword(lc, &lc); | 
|---|
 | 440 |    if (*ln != 0) { | 
|---|
| [7926772] | 441 |       fatalerror_in_file(fnm, lineno, /*End of line not blank*/15); | 
|---|
 | 442 |       /* FIXME: give ln as context? */ | 
|---|
| [d92d282] | 443 |    } | 
|---|
 | 444 | } | 
|---|
 | 445 |  | 
|---|
| [acc20b1] | 446 | static const struct option long_opts[] = { | 
|---|
 | 447 |    /* const char *name; int has_arg (0 no_argument, 1 required_*, 2 optional_*); int *flag; int val; */ | 
|---|
| [76bbb7c9] | 448 |    {"survey", required_argument, 0, 's'}, | 
|---|
| [d92d282] | 449 |    {"specfile", required_argument, 0, 'p'}, | 
|---|
| [acc20b1] | 450 |    {"help", no_argument, 0, HLP_HELP}, | 
|---|
 | 451 |    {"version", no_argument, 0, HLP_VERSION}, | 
|---|
 | 452 |    {0, 0, 0, 0} | 
|---|
 | 453 | }; | 
|---|
 | 454 |  | 
|---|
| [d92d282] | 455 | #define short_opts "s:p:" | 
|---|
| [acc20b1] | 456 |  | 
|---|
 | 457 | static struct help_msg help[] = { | 
|---|
 | 458 | /*                              <-- */ | 
|---|
| [45af761] | 459 |    {HLP_ENCODELONG(0),        /*only load the sub-survey with this prefix*/199, 0}, | 
|---|
 | 460 |    {0, 0, 0} | 
|---|
| [acc20b1] | 461 | }; | 
|---|
 | 462 |  | 
|---|
| [a420b49] | 463 | int | 
|---|
 | 464 | main(int argc, char **argv) | 
|---|
 | 465 | { | 
|---|
| [6f185e5] | 466 |    const char *fnm_in, *fnm_out; | 
|---|
| [a2ad284] | 467 |    char *desc; | 
|---|
| [0ed0e16] | 468 |    img_point pt; | 
|---|
| [d1b1380] | 469 |    int result; | 
|---|
| [647407d] | 470 |    point *fr = NULL, *to; | 
|---|
| [badeec8] | 471 |    double zMax = -DBL_MAX; | 
|---|
| [647407d] | 472 |    point *p; | 
|---|
| [76bbb7c9] | 473 |    const char *survey = NULL; | 
|---|
| [d92d282] | 474 |    const char *specfile = NULL; | 
|---|
| [31b7105] | 475 |    img *pimg; | 
|---|
 | 476 |    int have_xsect = 0; | 
|---|
| [d1b1380] | 477 |  | 
|---|
| [bdfe97f] | 478 |    msg_init(argv); | 
|---|
| [d1b1380] | 479 |  | 
|---|
| [736f7df] | 480 |    /* TRANSLATORS: Part of extend --help */ | 
|---|
| [d8dbdff] | 481 |    cmdline_set_syntax_message(/*INPUT_3D_FILE [OUTPUT_3D_FILE]*/267, 0, NULL); | 
|---|
| [acc20b1] | 482 |    cmdline_init(argc, argv, short_opts, long_opts, NULL, help, 1, 2); | 
|---|
| [76bbb7c9] | 483 |    while (1) { | 
|---|
 | 484 |       int opt = cmdline_getopt(); | 
|---|
 | 485 |       if (opt == EOF) break; | 
|---|
 | 486 |       if (opt == 's') survey = optarg; | 
|---|
| [d92d282] | 487 |       if (opt == 'p') specfile = optarg; | 
|---|
| [acc20b1] | 488 |    } | 
|---|
| [6f185e5] | 489 |    fnm_in = argv[optind++]; | 
|---|
| [acc20b1] | 490 |    if (argv[optind]) { | 
|---|
| [6f185e5] | 491 |       fnm_out = argv[optind]; | 
|---|
| [acc20b1] | 492 |    } else { | 
|---|
| [6379f93] | 493 |       char * base_in = base_from_fnm(fnm_in); | 
|---|
 | 494 |       char * base_out = osmalloc(strlen(base_in) + 8); | 
|---|
 | 495 |       strcpy(base_out, base_in); | 
|---|
 | 496 |       strcat(base_out, "_extend"); | 
|---|
 | 497 |       fnm_out = add_ext(base_out, EXT_SVX_3D); | 
|---|
 | 498 |       osfree(base_in); | 
|---|
 | 499 |       osfree(base_out); | 
|---|
| [d1b1380] | 500 |    } | 
|---|
 | 501 |  | 
|---|
 | 502 |    /* try to open image file, and check it has correct header */ | 
|---|
| [a2ad284] | 503 |    pimg = img_open_survey(fnm_in, survey); | 
|---|
| [a405bc1] | 504 |    if (pimg == NULL) fatalerror(img_error2msg(img_error()), fnm_in); | 
|---|
| [d1b1380] | 505 |  | 
|---|
 | 506 |    putnl(); | 
|---|
| [ee7511a] | 507 |    puts(msg(/*Reading in data - please wait…*/105)); | 
|---|
| [d1b1380] | 508 |  | 
|---|
| [63dc4eb] | 509 |    htab = osmalloc(ossizeof(pfx*) * HTAB_SIZE); | 
|---|
 | 510 |    { | 
|---|
 | 511 |        int i; | 
|---|
 | 512 |        for (i = 0; i < HTAB_SIZE; ++i) htab[i] = NULL; | 
|---|
 | 513 |    } | 
|---|
| [421b7d2] | 514 |  | 
|---|
| [d1b1380] | 515 |    do { | 
|---|
| [23f7ea7] | 516 |       result = img_read_item(pimg, &pt); | 
|---|
| [d1b1380] | 517 |       switch (result) { | 
|---|
| [a420b49] | 518 |       case img_MOVE: | 
|---|
| [421b7d2] | 519 |          fr = find_point(&pt); | 
|---|
 | 520 |          break; | 
|---|
| [a420b49] | 521 |       case img_LINE: | 
|---|
| [421b7d2] | 522 |          if (!fr) { | 
|---|
| [76bbb7c9] | 523 |             result = img_BAD; | 
|---|
 | 524 |             break; | 
|---|
| [421b7d2] | 525 |          } | 
|---|
 | 526 |          to = find_point(&pt); | 
|---|
 | 527 |          if (!(pimg->flags & (img_FLAG_SURFACE|img_FLAG_SPLAY))) | 
|---|
| [693388e] | 528 |             add_leg(fr, to, pimg->label, pimg->flags); | 
|---|
| [421b7d2] | 529 |          fr = to; | 
|---|
 | 530 |          break; | 
|---|
| [a420b49] | 531 |       case img_LABEL: | 
|---|
| [388ad50] | 532 |          to = find_point(&pt); | 
|---|
 | 533 |          add_label(to, pimg->label, pimg->flags); | 
|---|
| [421b7d2] | 534 |          break; | 
|---|
| [ed0f5b6] | 535 |       case img_BAD: | 
|---|
| [6f185e5] | 536 |          (void)img_close(pimg); | 
|---|
| [a405bc1] | 537 |          fatalerror(img_error2msg(img_error()), fnm_in); | 
|---|
| [31b7105] | 538 |          break; | 
|---|
 | 539 |       case img_XSECT: | 
|---|
 | 540 |          have_xsect = 1; | 
|---|
 | 541 |          break; | 
|---|
| [d1b1380] | 542 |       } | 
|---|
| [ed0f5b6] | 543 |    } while (result != img_STOP); | 
|---|
| [d1b1380] | 544 |  | 
|---|
| [0c50ce3] | 545 |    desc = osstrdup(pimg->title); | 
|---|
| [a2ad284] | 546 |  | 
|---|
| [d92d282] | 547 |    if (specfile) { | 
|---|
 | 548 |       FILE *fs = NULL; | 
|---|
| [7926772] | 549 |       char *fnm_used; | 
|---|
| [736f7df] | 550 |       /* TRANSLATORS: for extend: */ | 
|---|
| [0804fbe] | 551 |       printf(msg(/*Applying specfile: “%s”*/521), specfile); | 
|---|
| [d92d282] | 552 |       putnl(); | 
|---|
| [7926772] | 553 |       fs = fopenWithPthAndExt("", specfile, NULL, "r", &fnm_used); | 
|---|
| [ffee37e] | 554 |       if (fs == NULL) fatalerror(/*Couldn’t open file “%s”*/24, specfile); | 
|---|
| [d92d282] | 555 |       while (!feof(fs)) { | 
|---|
| [7926772] | 556 |          char *lbuf = getline_alloc(fs, 32); | 
|---|
| [d92d282] | 557 |          lineno++; | 
|---|
| [7926772] | 558 |          if (!lbuf) | 
|---|
 | 559 |             fatalerror_in_file(fnm_used, lineno, /*Error reading file*/18); | 
|---|
 | 560 |          parseconfigline(fnm_used, lbuf); | 
|---|
| [d92d282] | 561 |          osfree(lbuf); | 
|---|
| [647407d] | 562 |       } | 
|---|
| [7926772] | 563 |       osfree(fnm_used); | 
|---|
| [647407d] | 564 |    } | 
|---|
| [d92d282] | 565 |  | 
|---|
 | 566 |    if (start == NULL) { /* i.e. start wasn't specified in specfile */ | 
|---|
| [8add4c9] | 567 |  | 
|---|
| [d92d282] | 568 |       /* start at the highest entrance with some legs attached */ | 
|---|
| [647407d] | 569 |       for (p = headpoint.next; p != NULL; p = p->next) { | 
|---|
| [d92d282] | 570 |          if (p->order > 0 && p->p.z > zMax) { | 
|---|
 | 571 |             const stn *s; | 
|---|
 | 572 |             for (s = p->stns; s; s = s->next) { | 
|---|
 | 573 |                if (s->flags & img_SFLAG_ENTRANCE) { | 
|---|
 | 574 |                   start = p; | 
|---|
 | 575 |                   zMax = p->p.z; | 
|---|
 | 576 |                   break; | 
|---|
 | 577 |                } | 
|---|
 | 578 |             } | 
|---|
| [647407d] | 579 |          } | 
|---|
 | 580 |       } | 
|---|
 | 581 |       if (start == NULL) { | 
|---|
| [d92d282] | 582 |          /* if no entrances with legs, start at the highest 1-node */ | 
|---|
| [7ee2b42] | 583 |          for (p = headpoint.next; p != NULL; p = p->next) { | 
|---|
| [d92d282] | 584 |             if (p->order == 1 && p->p.z > zMax) { | 
|---|
| [7ee2b42] | 585 |                start = p; | 
|---|
 | 586 |                zMax = p->p.z; | 
|---|
 | 587 |             } | 
|---|
 | 588 |          } | 
|---|
| [d92d282] | 589 |          /* of course we may have no 1-nodes... */ | 
|---|
| [d216f5d] | 590 |          if (start == NULL) { | 
|---|
 | 591 |             for (p = headpoint.next; p != NULL; p = p->next) { | 
|---|
| [d92d282] | 592 |                if (p->order != 0 && p->p.z > zMax) { | 
|---|
| [d216f5d] | 593 |                   start = p; | 
|---|
 | 594 |                   zMax = p->p.z; | 
|---|
 | 595 |                } | 
|---|
 | 596 |             } | 
|---|
| [d92d282] | 597 |             if (start == NULL) { | 
|---|
 | 598 |                /* There are no legs - just pick the highest station... */ | 
|---|
 | 599 |                for (p = headpoint.next; p != NULL; p = p->next) { | 
|---|
 | 600 |                   if (p->p.z > zMax) { | 
|---|
 | 601 |                      start = p; | 
|---|
 | 602 |                      zMax = p->p.z; | 
|---|
 | 603 |                   } | 
|---|
 | 604 |                } | 
|---|
 | 605 |                if (!start) fatalerror(/*No survey data*/43); | 
|---|
 | 606 |             } | 
|---|
| [d216f5d] | 607 |          } | 
|---|
| [647407d] | 608 |       } | 
|---|
 | 609 |    } | 
|---|
| [d92d282] | 610 |  | 
|---|
| [736f7df] | 611 |    /* TRANSLATORS: for extend: | 
|---|
 | 612 |     * Used to tell the user that a file is being written - %s is the filename | 
|---|
 | 613 |     */ | 
|---|
| [ee7511a] | 614 |    printf(msg(/*Writing %s…*/522), fnm_out); | 
|---|
| [d92d282] | 615 |    putnl(); | 
|---|
| [0c50ce3] | 616 |    pimg_out = img_open_write(fnm_out, desc, img_FFLAG_EXTENDED); | 
|---|
| [d1b1380] | 617 |  | 
|---|
| [d92d282] | 618 |    /* Only does single connected component currently. */ | 
|---|
 | 619 |    do_stn(start, 0.0, NULL, ERIGHT, 0); | 
|---|
| [31b7105] | 620 |  | 
|---|
 | 621 |    if (have_xsect) { | 
|---|
 | 622 |       img_rewind(pimg); | 
|---|
| [2f1c0c0] | 623 |       /* Read ahead on pimg before writing pimg_out so we find out if an | 
|---|
 | 624 |        * img_XSECT_END comes next. */ | 
|---|
 | 625 |       char * label = NULL; | 
|---|
 | 626 |       int flags = 0; | 
|---|
| [31b7105] | 627 |       do { | 
|---|
 | 628 |          result = img_read_item(pimg, &pt); | 
|---|
| [2f1c0c0] | 629 |          if (result == img_XSECT || result == img_XSECT_END) { | 
|---|
 | 630 |             if (label) { | 
|---|
 | 631 |                if (result == img_XSECT_END) | 
|---|
 | 632 |                   flags |= img_XFLAG_END; | 
|---|
 | 633 |                img_write_item(pimg_out, img_XSECT, flags, label, 0, 0, 0); | 
|---|
 | 634 |                osfree(label); | 
|---|
 | 635 |                label = NULL; | 
|---|
 | 636 |             } | 
|---|
 | 637 |          } | 
|---|
| [31b7105] | 638 |          if (result == img_XSECT) { | 
|---|
| [2f1c0c0] | 639 |             label = osstrdup(pimg->label); | 
|---|
 | 640 |             flags = pimg->flags; | 
|---|
 | 641 |             pimg_out->l = pimg->l; | 
|---|
 | 642 |             pimg_out->r = pimg->r; | 
|---|
 | 643 |             pimg_out->u = pimg->u; | 
|---|
| [31b7105] | 644 |             pimg_out->d = pimg->d; | 
|---|
 | 645 |          } | 
|---|
 | 646 |       } while (result != img_STOP); | 
|---|
 | 647 |    } | 
|---|
| [8add4c9] | 648 |  | 
|---|
| [31b7105] | 649 |    (void)img_close(pimg); | 
|---|
 | 650 |  | 
|---|
 | 651 |    if (!img_close(pimg_out)) { | 
|---|
| [6f185e5] | 652 |       (void)remove(fnm_out); | 
|---|
| [a405bc1] | 653 |       fatalerror(img_error2msg(img_error()), fnm_out); | 
|---|
| [6f185e5] | 654 |    } | 
|---|
| [cb3d1e2] | 655 |  | 
|---|
| [d1b1380] | 656 |    return EXIT_SUCCESS; | 
|---|
 | 657 | } | 
|---|
 | 658 |  | 
|---|
| [d92d282] | 659 | static int adjust_direction(int dir, int by) { | 
|---|
 | 660 |     if (by == ESWAP) | 
|---|
 | 661 |         return dir ^ (ELEFT|ERIGHT); | 
|---|
 | 662 |     if (by) | 
|---|
 | 663 |         return by; | 
|---|
 | 664 |     return dir; | 
|---|
 | 665 | } | 
|---|
 | 666 |  | 
|---|
| [a420b49] | 667 | static void | 
|---|
| [d92d282] | 668 | do_stn(point *p, double X, const char *prefix, int dir, int labOnly) | 
|---|
| [a420b49] | 669 | { | 
|---|
 | 670 |    leg *l, *lp; | 
|---|
| [badeec8] | 671 |    double dX; | 
|---|
| [ee11c6a7] | 672 |    const stn *s; | 
|---|
| [d92d282] | 673 |    int odir = dir; | 
|---|
| [ea1c342] | 674 |  | 
|---|
 | 675 |    for (s = p->stns; s; s = s->next) { | 
|---|
| [31b7105] | 676 |       img_write_item(pimg_out, img_LABEL, s->flags, s->label, X, 0, p->p.z); | 
|---|
| [ea1c342] | 677 |    } | 
|---|
| [d92d282] | 678 |    if (labOnly || p->fBroken) { | 
|---|
 | 679 |       return; | 
|---|
 | 680 |    } | 
|---|
 | 681 |  | 
|---|
| [7d9b3a9] | 682 |    lp = &headleg; | 
|---|
| [21c226e] | 683 |    for (l = lp->next; l; lp = l, l = lp->next) { | 
|---|
| [d92d282] | 684 |       dir = odir; | 
|---|
| [21c226e] | 685 |       if (l->fDone) { | 
|---|
| [d92d282] | 686 |          /* this case happens if a recursive call causes the next leg to be | 
|---|
| [21c226e] | 687 |           * removed, leaving our next pointing to a leg which has been dealt | 
|---|
 | 688 |           * with... */ | 
|---|
| [d92d282] | 689 |          continue; | 
|---|
 | 690 |       } | 
|---|
 | 691 |       if (l->prefix != prefix) { | 
|---|
 | 692 |          continue; | 
|---|
 | 693 |       } | 
|---|
 | 694 |       if (l->to == p) { | 
|---|
 | 695 |          if (l->broken & BREAK_TO) continue; | 
|---|
 | 696 |          lp->next = l->next; | 
|---|
 | 697 |          /* adjust direction of extension if necessary */ | 
|---|
 | 698 |          dir = adjust_direction(dir, l->to->dir); | 
|---|
 | 699 |          dir = adjust_direction(dir, l->dir); | 
|---|
 | 700 |  | 
|---|
 | 701 |          dX = hypot(l->fr->p.x - l->to->p.x, l->fr->p.y - l->to->p.y); | 
|---|
 | 702 |          if (dir == ELEFT) dX = -dX; | 
|---|
| [31b7105] | 703 |          img_write_item(pimg_out, img_MOVE, 0, NULL, X + dX, 0, l->fr->p.z); | 
|---|
 | 704 |          img_write_item(pimg_out, img_LINE, l->flags, l->prefix, | 
|---|
| [d92d282] | 705 |                         X, 0, l->to->p.z); | 
|---|
 | 706 |          l->fDone = 1; | 
|---|
 | 707 |          do_stn(l->fr, X + dX, l->prefix, dir, (l->broken & BREAK_FR)); | 
|---|
 | 708 |          l = lp; | 
|---|
 | 709 |       } else if (l->fr == p) { | 
|---|
 | 710 |          if (l->broken & BREAK_FR) continue; | 
|---|
 | 711 |          lp->next = l->next; | 
|---|
 | 712 |          /* adjust direction of extension if necessary */ | 
|---|
 | 713 |          dir = adjust_direction(dir, l->fr->dir); | 
|---|
 | 714 |          dir = adjust_direction(dir, l->dir); | 
|---|
 | 715 |  | 
|---|
 | 716 |          dX = hypot(l->fr->p.x - l->to->p.x, l->fr->p.y - l->to->p.y); | 
|---|
 | 717 |          if (dir == ELEFT) dX = -dX; | 
|---|
| [31b7105] | 718 |          img_write_item(pimg_out, img_MOVE, 0, NULL, X, 0, l->fr->p.z); | 
|---|
 | 719 |          img_write_item(pimg_out, img_LINE, l->flags, l->prefix, | 
|---|
| [d92d282] | 720 |                         X + dX, 0, l->to->p.z); | 
|---|
 | 721 |          l->fDone = 1; | 
|---|
 | 722 |          do_stn(l->to, X + dX, l->prefix, dir, (l->broken & BREAK_TO)); | 
|---|
 | 723 |          l = lp; | 
|---|
| [21c226e] | 724 |       } | 
|---|
 | 725 |    } | 
|---|
 | 726 |    lp = &headleg; | 
|---|
| [7d9b3a9] | 727 |    for (l = lp->next; l; lp = l, l = lp->next) { | 
|---|
| [d92d282] | 728 |       dir = odir; | 
|---|
| [7d9b3a9] | 729 |       if (l->fDone) { | 
|---|
 | 730 |          /* this case happens iff a recursive call causes the next leg to be | 
|---|
 | 731 |           * removed, leaving our next pointing to a leg which has been dealt | 
|---|
 | 732 |           * with... */ | 
|---|
| [d92d282] | 733 |          continue; | 
|---|
 | 734 |       } | 
|---|
 | 735 |       if (l->to == p) { | 
|---|
 | 736 |          if (l->broken & BREAK_TO) continue; | 
|---|
 | 737 |          lp->next = l->next; | 
|---|
 | 738 |          /* adjust direction of extension if necessary */ | 
|---|
 | 739 |          dir = adjust_direction(dir, l->to->dir); | 
|---|
 | 740 |          dir = adjust_direction(dir, l->dir); | 
|---|
 | 741 |  | 
|---|
 | 742 |          dX = hypot(l->fr->p.x - l->to->p.x, l->fr->p.y - l->to->p.y); | 
|---|
 | 743 |          if (dir == ELEFT) dX = -dX; | 
|---|
| [31b7105] | 744 |          img_write_item(pimg_out, img_MOVE, 0, NULL, X + dX, 0, l->fr->p.z); | 
|---|
 | 745 |          img_write_item(pimg_out, img_LINE, l->flags, l->prefix, | 
|---|
| [d92d282] | 746 |                         X, 0, l->to->p.z); | 
|---|
 | 747 |          l->fDone = 1; | 
|---|
 | 748 |          do_stn(l->fr, X + dX, l->prefix, dir, (l->broken & BREAK_FR)); | 
|---|
 | 749 |          l = lp; | 
|---|
 | 750 |       } else if (l->fr == p) { | 
|---|
 | 751 |          if (l->broken & BREAK_FR) continue; | 
|---|
 | 752 |          lp->next = l->next; | 
|---|
 | 753 |          /* adjust direction of extension if necessary */ | 
|---|
 | 754 |          dir = adjust_direction(dir, l->fr->dir); | 
|---|
 | 755 |          dir = adjust_direction(dir, l->dir); | 
|---|
 | 756 |  | 
|---|
 | 757 |          dX = hypot(l->fr->p.x - l->to->p.x, l->fr->p.y - l->to->p.y); | 
|---|
 | 758 |          if (dir == ELEFT) dX = -dX; | 
|---|
| [31b7105] | 759 |          img_write_item(pimg_out, img_MOVE, 0, NULL, X, 0, l->fr->p.z); | 
|---|
 | 760 |          img_write_item(pimg_out, img_LINE, l->flags, l->prefix, | 
|---|
| [d92d282] | 761 |                         X + dX, 0, l->to->p.z); | 
|---|
 | 762 |          l->fDone = 1; | 
|---|
 | 763 |          do_stn(l->to, X + dX, l->prefix, dir, (l->broken & BREAK_TO)); | 
|---|
 | 764 |          l = lp; | 
|---|
| [d1b1380] | 765 |       } | 
|---|
 | 766 |    } | 
|---|
 | 767 | } | 
|---|