-/**/
+/*
+ * output format from printforforsafety is lines like this:
+ * segment <node>.<side> <node>.<side> <segment>[/<movinfo>] <distance>
+ * #... (comment)
+ * (blank)
+ * end (at end of file, mandatory)
+ * syntactic restrictions:
+ * <node> is alphanumeric and starts with a letter
+ * <side> is precisely the digit 0 or the digit 1
+ * <segment> is alphanumeric (and comes from the layout)
+ * <movinfo> is <movfeat><movpos>[<movfeat><movpos>...]*<combpos>
+ * where <movfeat> is alphabetic and <movpos> is and
+ * <combpos> are in decimal and have no unnecessary leading 0's
+ * <distance> contains only digits and perhaps decimal point
+ * semantic restrictions (not enforced by redactgraph but ought to
+ * be impossible for layout designer to violate):
+ * Each <segment>[/<movinfo>] appears exactly once.
+ * <segment> appears either once without /<movinfo> or always with.
+ * Each side of each node appears either
+ * - once as the 0th or 1th end of a <segment>
+ * - one or more times as the same end of <segment>/<movinfo>'s with
+ * the same <segment>
+ * - not at all (indicates a terminus)
+ * Refer to safety.h for info regarding <combpos>.
+ *
+ * See layout-data.h comment for info regarding layout data for
+ * control system.
+ */
+/* for debugging, runes like
+ * ./ours.redactgraph consistency movfeatsplitedges consistency movfeatrmstubs consistency movfeatsplitnodes consistency trivpairnodes consistency trivnullnodes consistency printforneato | neato -Tps >u.ps
+ * are often useful.
+ */
#include <stdarg.h>
#include <string.h>
LIST_UNLINK(all_nodes, node);
}
-/*---------- operations ----------*/
+/*---------- operations - heavyweight graph redaction ----------*/
/* We combine the individual moveable features in each segment into
* a single `feature' with the cross-product of all of the
trace(" not inner: no edges?!\n");
return 0;
}
- trace(" inner %s ",segment->segname);
+ trace(" inner %s ",all_segment->segname);
return 1;
}
edge= edgeend->edge;
mate= movfeat_findmate(edgeend);
assert(mate);
- newnode= node_create(masprintf("%s/*%d",node->pname,edge->movpos));
+ newnode= node_create(masprintf("%sx%d",node->pname,edge->movpos));
edgeend_replumb(mate, &newnode->sides[mate->node->side]);
edgeend_replumb(edgeend, &newnode->sides[edgeend->node->side]);
}
}
}
+/*---------- operations - trivial graph redaction etc. ----------*/
+
static void trivpairnodes(void) {
/* Eliminate near-trivial nodes - in this case, ones which have only
* two edges, which come in on opposite sides, have the same
continue;
}
trace(" yes:\n");
- rightedge->edge->pname=
- masprintf("%s+%s", leftedge->edge->pname, rightedge->edge->pname);
+ if (!strchr(rightedge->edge->pname, '+')) {
+ rightedge->edge->pname=
+ masprintf("%s+", rightedge->edge->pname);
+ }
rightedge->edge->distance += leftedge->edge->distance;
edgeend_replumb(rightedge, edgeend_otherend(leftedge)->node);
edge_delete(leftedge);
check("command-line request");
}
+/*---------- operations - output ----------*/
+
static void printforneato(void) {
Node *node;
EdgeEnd *edgeend;
output("}\n");
}
+static void printforforsafety(void) {
+ Node *node;
+ Edge *edge;
+ EdgeEnd *edgeend;
+ int side, end, weight, i;
+ Segment *segment;
+ MovFeat *movfeat;
+
+ FOR_ALL_NODES(node) {
+ FOR_EDGES(edge, node,side,edgeend) {
+ output("segment ");
+ FOR_BOTH(end) {
+ output("n%s.%d ",
+ edge->ends[end].node->node->pname,
+ edge->ends[end].node->side);
+ }
+ segment= edge->subseg->segment;
+ output(segment->segname);
+ if (segment->n_movfeats>1) {
+ if (!segment->starfeature) {
+ fprintf(stderr,"printforforsafety before movfeatsplitedges!\n");
+ exit(8);
+ }
+ output("/");
+ weight= 1;
+ FOR_SEGMENT_MOVFEATS(i,movfeat, segment) {
+ if (!movfeat->movfeat) continue;
+ output("%s%d", movfeat->movfeat,
+ (edge->movpos / weight) % movfeat->n_positions);
+ weight *= movfeat->n_positions;
+ }
+ output("*%d", edge->movpos);
+ }
+ output(" %f\n", edge->distance);
+ }
+ }
+ output("end\n");
+}
+
+static void printforlayoutsegjoins(void) {
+ Node *node;
+ EdgeEnd *edgeend;
+ Segment **segmentp, *segment;
+ int side;
+
+ FOR_ALL_NODES(node) {
+ output("layer ");
+ FOR_BOTH(side)
+ if (!node->sides[side].head) {
+ output("segterminus");
+ goto one_sided;
+ }
+ output("segjoin");
+ one_sided:
+ output("%d\n", (node->layermin + node->layermax)/2);
+
+ output("abs segjoin_%s",node->pname);
+ FOR_NODE_EDGEENDS(side,edgeend, node)
+ output("_%s",edgeend->edge->subseg->segment->segname);
+ output(" %f %f %f\n", node->x,node->y,node->a);
+ FOR_ALL_SEGMENTS(segmentp,segment) segment->u= 0;
+ FOR_NODE_EDGEENDS(side,edgeend, node) {
+ segment= edgeend->edge->subseg->segment;
+ if (segment->u++) continue;
+ output("segend %s\n",segment->segname);
+ output("segcmap %s 0.5 setgray\n",segment->segname);
+ }
+ output("\n");
+ }
+}
+
+/*---------- main program ----------*/
+
typedef struct {
const char *name;
void (*fn)(void);
static const OpInfo opinfos[]= {
#define OI(x) { #x, x },
OI(printforneato)
+ OI(printforforsafety)
+ OI(printforlayoutsegjoins)
OI(consistency)
OI(movfeatsplitedges)
OI(movfeatrmstubs)