PATCH: exttended extending extend

John Pybus john at pybus.org
Fri Dec 10 19:52:33 GMT 2004


Olly Betts wrote:

> [SNIP]    Phil's [patch] provided the ability to flip the direction
> rather [than] explicitly specifying left and right.  I think both approaches
> are useful to have.

So do I.  I almost added a *eswap command first time round -- it's easy 
enough on top of my changes -- but didn't as I wasn't using it, and it 
only meant adding more parsing code and messages.  However, it was only 
10 mins effort so here's an updated patch.

*eswap works just as *eleft and *eright but swaps the extension direction.

It hasn't had a huge amount of testing, but isn't a very complex change 
from the first patch.

Cheers,
John
-------------- next part --------------
Index: lib/messages.txt
===================================================================
RCS file: /usr/data/cvs/survex/lib/messages.txt,v
retrieving revision 1.179
diff -U3 -r1.179 messages.txt
--- lib/messages.txt	1 Oct 2004 18:54:27 -0000	1.179
+++ lib/messages.txt	10 Dec 2004 19:27:56 -0000
@@ -3536,6 +3536,41 @@
 sk:502 Zrušené: %s
 ro:502 Eliminat: %s
 #
+# for extend:
+en:600 Don't understand command `%s' in config, line %i
+#
+en:601 Unexpected content `%s' in config, line %i
+#
+en:602 Command without station name in config, line %i
+#
+en:603 Failed to find station %s in config, line %i
+#
+en:604 Starting from station %s
+#
+en:605 Plotting to the left from station %s
+#
+en:606 Failed to find leg %s -> %s in config, line %i
+#
+en:607 Plotting to the left from leg %s -> %s
+#
+en:608 Plotting to the right from station %s
+#
+en:609 Plotting to the right from leg %s -> %s
+#
+en:610 Breaking survey at station %s
+#
+en:611 Breaking survey at leg %s -> %s
+#
+en:612 Error reading line %i from spec file
+#
+en:613 Applying specfile: `%s'
+#
+en:614 Writing out .3d file...
+#
+en:615 Swapping plot direction from station %s
+#
+en:616 Swapping plot direction from leg %s -> %s
+#
 # "don't extract" messages - these are compiled into the programs
 #
 en:1000 Can't open message file `%s' using path `%s'
Index: src/extend.c
===================================================================
RCS file: /usr/data/cvs/survex/src/extend.c,v
retrieving revision 1.45
diff -U3 -r1.45 extend.c
--- src/extend.c	22 Nov 2003 00:19:26 -0000	1.45
+++ src/extend.c	10 Dec 2004 19:27:57 -0000
@@ -48,24 +48,37 @@
    img_point p;
    const stn *stns;
    unsigned int order;
+   int fDir;
+   int fDone;
    struct POINT *next;
 } point;
 
 typedef struct LEG {
    point *fr, *to;
    const char *prefix;
+   int fDir;
    int fDone;
    int flags;
    struct LEG *next;
 } leg;
 
-static point headpoint = {{0, 0, 0}, NULL, 0, NULL};
+#define DONE        0x01
+#define BREAK_FR    0x04
+#define BREAK_TO    0x08
+#define BREAK       (BREAK_FR | BREAK_TO)
+
+
+#define ELEFT  0x04
+#define ERIGHT 0x08
+#define ESWAP  0x10
 
-static leg headleg = {NULL, NULL, NULL, 1, 0, NULL};
+static point headpoint = {{0, 0, 0}, NULL, 0, 0, 0, NULL};
+
+static leg headleg = {NULL, NULL, NULL, 0, 0, 0, NULL};
 
 static img *pimg;
 
-static void do_stn(point *, double, const char *);
+static void do_stn(point *, double, const char *, int);
 
 typedef struct pfx {
    const char *label;
@@ -111,6 +124,8 @@
    p->p = *pt;
    p->stns = NULL;
    p->order = 0;
+   p->fDir = 0;
+   p->fDone = 0;
    p->next = headpoint.next;
    headpoint.next = p;
    return p;
@@ -130,6 +145,7 @@
    else
       l->prefix = NULL;
    l->next = headleg.next;
+   l->fDir = 0;
    l->fDone = 0;
    l->flags = flags;
    headleg.next = l;
@@ -145,19 +161,277 @@
    p->stns = s;
 }
 
+/* Read in config file */
+
+
+/* lifted from img.c Should be put somewhere common? JPNP*/
+static char *
+getline_alloc(FILE *fh, size_t ilen)
+{
+   int ch;
+   size_t i = 0;
+   size_t len = ilen;
+   char *buf = xosmalloc(len);
+   if (!buf) return NULL;
+
+   ch = getc(fh);
+   while (ch != '\n' && ch != '\r' && ch != EOF) {
+      buf[i++] = ch;
+      if (i == len - 1) {
+	 char *p;
+	 len += len;
+	 p = xosrealloc(buf, len);
+	 if (!p) {
+	    osfree(buf);
+	    return NULL;
+	 }
+	 buf = p;
+      }
+      ch = getc(fh);
+   }
+   if (ch == '\n' || ch == '\r') {
+      int otherone = ch ^ ('\n' ^ '\r');
+      ch = getc(fh);
+      /* if it's not the other eol character, put it back */
+      if (ch != otherone) ungetc(ch, fh);
+   }
+   buf[i++] = '\0';
+   return buf;
+}
+
+int lineno = 0;
+point *start = NULL;
+
+static char*
+delimword(char *ln, char** lr)
+{
+   char *le;
+
+   while (*ln == ' ' || *ln == '\t' || *ln == '\n' || *ln == '\r')
+      ln++;
+
+   le = ln;
+   while (*le != ' ' && *le != '\t' && *le != '\n' && *le != '\r' && *le != ';' && *le != '\0')
+      le++;
+
+   if (*le == '\0' || *le == ';') {
+      *lr = le;
+   } else {
+      *lr = le + 1;
+   }
+   
+   *le = '\0';
+   return ln;
+}
+
+static void
+parseconfigline(char *ln)
+{
+   point *p;
+   const stn *s;
+   const stn *t;
+   leg *l;
+   char *lc = NULL;
+
+   ln = delimword(ln, &lc);
+
+   if (*ln == '\0') return;
+
+   if (strcmp(ln, "*start")==0) {
+      ln = delimword(lc, &lc);
+      if (*ln == 0) fatalerror(/*Command without station name in config, line %i*/602, lineno);
+      for (p = headpoint.next; p != NULL; p = p->next) {
+	 for (s = p->stns; s; s = s->next) {
+	    if (strcmp(s->label, ln)==0) {
+	       start = p;
+	       printf(msg(/*Starting from station %s*/604),ln);
+	       putnl();
+	       goto loopend;
+	    }
+	 }
+      }
+      warning(/*Failed to find station %s in config, line %i*/603, ln, lineno);
+   } else if (strcmp(ln, "*eleft")==0) {
+      char *ll = delimword(lc, &lc);
+      if (*ll == 0) fatalerror(/*Command without station name in config, line %i*/602,lineno);
+      ln = delimword(lc, &lc);
+      if (*ln == 0) { /* One argument, look for point to switch at. */
+	 for (p = headpoint.next; p != NULL; p = p->next) {
+	    for (s = p->stns; s; s = s->next) {
+	       if (strcmp(s->label, ll)==0) {
+		  printf(msg(/*Plotting to the left from station %s*/605),ll);
+		  putnl();
+		  p->fDir = ELEFT;
+		  goto loopend;
+	       }
+	    }
+	 }
+	 warning(/*Failed to find station %s in config, line %i*/603, ll, lineno);       
+      } else { /* Two arguments look for a specific leg */
+	 for (l = headleg.next; l; l=l->next) {
+	    point * fr = l->fr;
+	    point * to = l->to;
+	    if (fr && to) {
+	       for (s=fr->stns; s; s=s->next) {
+		  int b = 0;
+		  if (strcmp(s->label,ll)==0 || (strcmp(s->label, ln)==0 && (b = 1)) ) {
+		     char * lr = (b ? ll : ln);
+		     for (t=to->stns; t; t=t->next) {
+			if (strcmp(t->label,lr)==0) {
+			   printf(msg(/*Plotting to the left from leg %s -> %s*/607), s->label, t->label);
+			   putnl();
+			   l->fDir=ELEFT;
+			   goto loopend;
+			}
+		     }
+		  }
+	       }
+	    }
+	 }
+	 warning(/*Failed to find leg %s-%s in config, line %i*/606, ll, ln, lineno);
+      }
+   } else if (strcmp(ln, "*eright")==0) {
+      char *ll = delimword(lc, &lc);
+      if (*ll == 0) fatalerror(/*Command without station name in config, line %i*/602,lineno);
+      ln = delimword(lc, &lc);
+      if (*ln == 0) { /* One argument, look for point to switch at. */
+	 for (p = headpoint.next; p != NULL; p = p->next) {
+	    for (s = p->stns; s; s = s->next) {
+	       if (strcmp(s->label, ll)==0) {
+		  printf(msg(/*Plotting to the right from station %s*/608),ll);
+		  putnl();
+		  p->fDir = ERIGHT;
+		  goto loopend;
+	       }
+	    }
+	 }
+	 warning(/*Failed to find station %s in config, line %i*/603, ll, lineno);      
+      } else { /* Two arguments look for a specific leg */
+	 for (l = headleg.next; l; l=l->next) {
+	    point * fr = l->fr;
+	    point * to = l->to;
+	    if (fr && to) {
+	       for (s=fr->stns; s; s=s->next) {
+		  int b = 0;
+		  if (strcmp(s->label,ll)==0 || (strcmp(s->label, ln)==0 && (b = 1)) ) {
+		     char * lr = (b ? ll : ln);
+		     for (t=to->stns; t; t=t->next) {
+			if (strcmp(t->label,lr)==0) {
+			   printf(msg(/*Plotting to the right from leg %s -> %s*/609), s->label, t->label);
+			   printf("\n");
+			   l->fDir=ERIGHT;
+			   goto loopend;
+			}
+		     }
+		  }
+	       }
+	    }
+	 }
+	 warning(/*Failed to find leg %s-%s in config, line %i*/606, ll, ln, lineno);
+      }
+   } else if (strcmp(ln, "*eswap")==0) {
+      char *ll = delimword(lc, &lc);
+      if (*ll == 0) fatalerror(/*Command without station name in config, line %i*/602,lineno);
+      ln = delimword(lc, &lc);
+      if (*ln == 0) { /* One argument, look for point to switch at. */
+	 for (p = headpoint.next; p != NULL; p = p->next) {
+	    for (s = p->stns; s; s = s->next) {
+	       if (strcmp(s->label, ll)==0) {
+		  printf(msg(/*Swapping plot direction from station %s*/615),ll);
+		  putnl();
+		  p->fDir = ESWAP;
+		  goto loopend;
+	       }
+	    }
+	 }
+	 warning(/*Failed to find station %s in config, line %i*/603, ll, lineno);      
+      } else { /* Two arguments look for a specific leg */
+	 for (l = headleg.next; l; l=l->next) {
+	    point * fr = l->fr;
+	    point * to = l->to;
+	    if (fr && to) {
+	       for (s=fr->stns; s; s=s->next) {
+		  int b = 0;
+		  if (strcmp(s->label,ll)==0 || (strcmp(s->label, ln)==0 && (b = 1)) ) {
+		     char * lr = (b ? ll : ln);
+		     for (t=to->stns; t; t=t->next) {
+			if (strcmp(t->label,lr)==0) {
+			   printf(msg(/*Swapping plot direction from leg %s -> %s*/616), s->label, t->label);
+			   printf("\n");
+			   l->fDir = ESWAP;
+			   goto loopend;
+			}
+		     }
+		  }
+	       }
+	    }
+	 }
+	 warning(/*Failed to find leg %s-%s in config, line %i*/606, ll, ln, lineno);
+      }
+   } else if (strcmp(ln, "*break")==0) {
+      char *ll = delimword(lc, &lc);
+      if (*ll == 0) fatalerror(/*Command without station name in config, line %i*/602,lineno);
+      ln = delimword(lc, &lc);
+      if (*ln == 0) { /* One argument, look for point to break at. */
+	 for (p = headpoint.next; p != NULL; p = p->next) {
+	    for (s = p->stns; s; s = s->next) {
+	       if (strcmp(s->label, ll)==0) {
+		  printf(msg(/*Breaking survey at station %s*/610), ll);
+		  putnl();
+		  p->fDone = BREAK;
+		  goto loopend;
+	       }
+	    }
+	 }
+	 warning(/*Failed to find station %s in config, line %i*/603, ll, lineno);  
+      } else { /* Two arguments look for a specific leg */
+	 for (l = headleg.next; l; l=l->next) {
+	    point * fr = l->fr;
+	    point * to = l->to;
+	    if (fr && to ) {
+	       for (s=fr->stns; s; s=s->next) {
+		  int b = 0;
+		  if (strcmp(s->label,ll)==0 || (strcmp(s->label, ln)==0 && (b = 1)) ) {
+		     char * lr = (b ? ll : ln);
+		     for (t=to->stns; t; t=t->next) {
+			if (strcmp(t->label,lr)==0) {
+			   printf(msg(/*Breaking survey at leg %s -> %s*/611), s->label, t->label);
+			   putnl();
+			   l->fDone = (b ? BREAK_TO : BREAK_FR);
+			   goto loopend;
+			}
+		     }
+		  }
+	       }
+	    }
+	 }
+	 warning(/*Failed to find leg %s-%s in config, line %i*/606, ll, ln, lineno);
+      }
+   } else {
+      fatalerror(/*"Don't understand command `%s' in config, line %i"*/600, ln, lineno);
+   }
+ loopend:
+   ln = delimword(lc, &lc);
+   if (*ln != 0) {
+      fatalerror(/*"Unexpected content `%s' in config, line %i"*/601, ln, lineno);
+   }
+}
+
 static const struct option long_opts[] = {
    /* const char *name; int has_arg (0 no_argument, 1 required_*, 2 optional_*); int *flag; int val; */
    {"survey", required_argument, 0, 's'},
+   {"specfile", required_argument, 0, 'p'},
    {"help", no_argument, 0, HLP_HELP},
    {"version", no_argument, 0, HLP_VERSION},
    {0, 0, 0, 0}
 };
 
-#define short_opts "s:"
+#define short_opts "s:p:"
 
 static struct help_msg help[] = {
 /*				<-- */
    {HLP_ENCODELONG(0),          "only load the sub-survey with this prefix"},
+   {HLP_ENCODELONG(1),          "apply specifications from the named file"},
    {0, 0}
 };
 
@@ -170,9 +444,9 @@
    int result;
    point *fr = NULL, *to;
    double zMax = -DBL_MAX;
-   point *start = NULL;
    point *p;
    const char *survey = NULL;
+   const char *specfile = NULL;
 
    msg_init(argv);
 
@@ -182,6 +456,7 @@
       int opt = cmdline_getopt();
       if (opt == EOF) break;
       if (opt == 's') survey = optarg;
+      if (opt == 'p') specfile = optarg;
    }
    fnm_in = argv[optind++];
    if (argv[optind]) {
@@ -235,50 +510,77 @@
 
    (void)img_close(pimg);
 
-   /* start at the highest entrance with some legs attached */
-   for (p = headpoint.next; p != NULL; p = p->next) {
-      if (p->order > 0 && p->p.z > zMax) {
-	 const stn *s;
-	 for (s = p->stns; s; s = s->next) {
-	    if (s->flags & img_SFLAG_ENTRANCE) {
-	       start = p;
-	       zMax = p->p.z;
-	       break;
-	    }
+   if (specfile) {
+      FILE *fs = NULL;
+      printf(msg(/*Applying specfile: `%s'*/613), specfile);
+      putnl();
+      fs = fopenWithPthAndExt("", specfile, NULL, "r", NULL);
+      if (fs == NULL) fatalerror(/*Unable to open file*/93, specfile);
+      while (!feof(fs)) {
+	 char *lbuf = NULL;
+	 lbuf = getline_alloc(fs, 32);
+	 lineno++;
+	 if (lbuf) {
+	    parseconfigline(lbuf);
+	 } else {
+	    error(/*Error reading line %i from spec file*/612, lineno);
+	    osfree(lbuf);
+	    break;
 	 }
+	 osfree(lbuf);
       }
    }
-   if (start == NULL) {
-      /* if no entrances with legs, start at the highest 1-node */
+
+   if (start == NULL) { /* i.e. start wasn't specified in specfile */
+   
+      /* start at the highest entrance with some legs attached */
       for (p = headpoint.next; p != NULL; p = p->next) {
-	 if (p->order == 1 && p->p.z > zMax) {
-	    start = p;
-	    zMax = p->p.z;
+	 if (p->order > 0 && p->p.z > zMax) {
+	    const stn *s;
+	    for (s = p->stns; s; s = s->next) {
+	       if (s->flags & img_SFLAG_ENTRANCE) {
+		  start = p;
+		  zMax = p->p.z;
+		  break;
+	       }
+	    }
 	 }
       }
-      /* of course we may have no 1-nodes... */
       if (start == NULL) {
+	 /* if no entrances with legs, start at the highest 1-node */
 	 for (p = headpoint.next; p != NULL; p = p->next) {
-	    if (p->order != 0 && p->p.z > zMax) {
+	    if (p->order == 1 && p->p.z > zMax) {
 	       start = p;
 	       zMax = p->p.z;
 	    }
 	 }
+	 /* of course we may have no 1-nodes... */
 	 if (start == NULL) {
-	    /* There are no legs - just pick the highest station... */
 	    for (p = headpoint.next; p != NULL; p = p->next) {
-	       if (p->p.z > zMax) {
+	       if (p->order != 0 && p->p.z > zMax) {
 		  start = p;
 		  zMax = p->p.z;
 	       }
 	    }
-	    if (!start) fatalerror(/*No survey data*/43);
+	    if (start == NULL) {
+	       /* There are no legs - just pick the highest station... */
+	       for (p = headpoint.next; p != NULL; p = p->next) {
+		  if (p->p.z > zMax) {
+		     start = p;
+		     zMax = p->p.z;
+		  }
+	       }
+	       if (!start) fatalerror(/*No survey data*/43);
+	    }
 	 }
       }
    }
+
+   printf(msg(/*Writing out .3d file...*/614));
+   putnl();
    pimg = img_open_write(fnm_out, desc, fTrue);
 
-   do_stn(start, 0.0, NULL); /* only does highest connected component currently */
+   do_stn(start, 0.0, NULL, ERIGHT); /* only does single connected component currently */
    if (!img_close(pimg)) {
       (void)remove(fnm_out);
       fatalerror(img_error(), fnm_out);
@@ -288,7 +590,7 @@
 }
 
 static void
-do_stn(point *p, double X, const char *prefix)
+do_stn(point *p, double X, const char *prefix, int dir)
 {
    leg *l, *lp;
    double dX;
@@ -297,62 +599,94 @@
    for (s = p->stns; s; s = s->next) {
       img_write_item(pimg, img_LABEL, s->flags, s->label, X, 0, p->p.z);
    }
+   if (p->fDone & BREAK) {
+     return;
+   }
+
    lp = &headleg;
    for (l = lp->next; l; lp = l, l = lp->next) {
-      if (l->fDone) {
-	 /* this case happens iff a recursive call causes the next leg to be
+      if (l->fDone & DONE) {
+	 /* this case happens if a recursive call causes the next leg to be
 	  * removed, leaving our next pointing to a leg which has been dealt
 	  * with... */
       } else if (l->prefix == prefix) {
 	 if (l->to == p) {
+	    if (l->fDone & BREAK_TO) continue;
 	    lp->next = l->next;
+	    /* adjust direction of extension if necessary */
+	    if (l->to->fDir == ESWAP)               dir = (dir==ERIGHT ? ELEFT : ERIGHT);
+	    else if (l->to->fDir & (ERIGHT|ELEFT))  dir = l->to->fDir;
+	    if (l->fDir == ESWAP)                   dir = (dir==ERIGHT ? ELEFT : ERIGHT);
+	    else if (l->fDir & (ERIGHT|ELEFT))      dir = l->fDir;
+
 	    dX = hypot(l->fr->p.x - l->to->p.x, l->fr->p.y - l->to->p.y);
+	    if (dir == ELEFT) dX *= -1.0;
 	    img_write_item(pimg, img_MOVE, 0, NULL, X + dX, 0, l->fr->p.z);
 	    img_write_item(pimg, img_LINE, l->flags, l->prefix,
 			   X, 0, l->to->p.z);
-	    l->fDone = 1;
-	    do_stn(l->fr, X + dX, l->prefix);
-	    /* osfree(l); */
+	    l->fDone |= DONE;
+	    do_stn(l->fr, X + dX, l->prefix, dir);
 	    l = lp;
 	 } else if (l->fr == p) {
+	    if (l->fDone & BREAK_FR) continue;
 	    lp->next = l->next;
+	    /* adjust direction of extension if necessary */
+	    if (l->fr->fDir == ESWAP)               dir = (dir==ERIGHT ? ELEFT : ERIGHT);
+	    else if (l->fr->fDir & (ERIGHT|ELEFT))  dir = l->fr->fDir;
+	    if (l->fDir == ESWAP)                   dir = (dir==ERIGHT ? ELEFT : ERIGHT);
+	    else if (l->fDir & (ERIGHT|ELEFT))      dir = l->fDir;
+
 	    dX = hypot(l->fr->p.x - l->to->p.x, l->fr->p.y - l->to->p.y);
+	    if (dir == ELEFT) dX *= -1.0;
 	    img_write_item(pimg, img_MOVE, 0, NULL, X, 0, l->fr->p.z);
 	    img_write_item(pimg, img_LINE, l->flags, l->prefix,
 			   X + dX, 0, l->to->p.z);
-	    l->fDone = 1;
-	    do_stn(l->to, X + dX, l->prefix);
-	    /* osfree(l); */
+	    l->fDone |= DONE;
+	    do_stn(l->to, X + dX, l->prefix, dir);
 	    l = lp;
 	 }
       }
    }
    lp = &headleg;
    for (l = lp->next; l; lp = l, l = lp->next) {
-      if (l->fDone) {
+      if (l->fDone & DONE) {
 	 /* this case happens iff a recursive call causes the next leg to be
 	  * removed, leaving our next pointing to a leg which has been dealt
 	  * with... */
       } else {
 	 if (l->to == p) {
+	    if (l->fDone & BREAK_TO) continue;
 	    lp->next = l->next;
+	    /* adjust direction of extension if necessary */
+	    if (l->to->fDir == ESWAP)               dir = (dir==ERIGHT ? ELEFT : ERIGHT);
+	    else if (l->to->fDir & (ERIGHT|ELEFT))  dir = l->to->fDir;
+	    if (l->fDir == ESWAP)                   dir = (dir==ERIGHT ? ELEFT : ERIGHT);
+	    else if (l->fDir & (ERIGHT|ELEFT))      dir = l->fDir;
+	    
 	    dX = hypot(l->fr->p.x - l->to->p.x, l->fr->p.y - l->to->p.y);
+	    if (dir == ELEFT) dX *= -1.0;
 	    img_write_item(pimg, img_MOVE, 0, NULL, X + dX, 0, l->fr->p.z);
 	    img_write_item(pimg, img_LINE, l->flags, l->prefix,
 			   X, 0, l->to->p.z);
-	    l->fDone = 1;
-	    do_stn(l->fr, X + dX, l->prefix);
-	    /* osfree(l); */
+	    l->fDone |= DONE;
+	    do_stn(l->fr, X + dX, l->prefix, dir);
 	    l = lp;
 	 } else if (l->fr == p) {
+	    if (l->fDone & BREAK_FR) continue;
 	    lp->next = l->next;
+	    /* adjust direction of extension if necessary */
+	    if (l->fr->fDir == ESWAP)               dir = (dir==ERIGHT ? ELEFT : ERIGHT);
+	    else if (l->fr->fDir & (ERIGHT|ELEFT))  dir = l->fr->fDir;
+	    if (l->fDir == ESWAP)                   dir = (dir==ERIGHT ? ELEFT : ERIGHT);
+	    else if (l->fDir & (ERIGHT|ELEFT))      dir = l->fDir;
+
 	    dX = hypot(l->fr->p.x - l->to->p.x, l->fr->p.y - l->to->p.y);
+	    if (dir == ELEFT) dX *= -1.0;
 	    img_write_item(pimg, img_MOVE, 0, NULL, X, 0, l->fr->p.z);
 	    img_write_item(pimg, img_LINE, l->flags, l->prefix,
 			   X + dX, 0, l->to->p.z);
-	    l->fDone = 1;
-	    do_stn(l->to, X + dX, l->prefix);
-	    /* osfree(l); */
+	    l->fDone |= DONE;
+	    do_stn(l->to, X + dX, l->prefix, dir);
 	    l = lp;
 	 }
       }


More information about the Survex mailing list