chiark / gitweb /
builds ours.graph.o !
[trains.git] / layout / redactgraph.c
1 /**/
2
3 static void extendsplits(void) {
4   /*
5    * Whenever we have a node which has one or more moveable feature
6    * subsegments, part of the same moveable feature, on one side, and
7    * fixed portion of the same segment on the other, we eliminate
8    * the fixed portion and add its length to both the moveables,
9    * so that we have one subsegspec for the whole of each position:
10    *
11    *    <---l---> <----l'--->             <---------(l+l')------>
12    *
13    *   *----A1---*----A1/P0--*  becomes  *--------A1/P0----------*
14    *              `---A1/P1---*           `-------A1/P1-----------*
15    *
16    *              <----l''--->            <---------(l+l'')------>
17    */
18
19   for (;;) {
20     pass++;
21     for (node=nodes_head; node; node=node->next) {
22       for (rightside=0; rightside<2; rightside++) {
23         trace("extendsplit pass %d node ",pass); trace_node(node);
24         trace("/%d ",rightside);
25         if ((n= count_edges(&node->sides[!rightside])) != 1) {
26           trace("no: lhs edges=%d\n", n);
27           goto no_extend_this;
28         }
29         leftedge= node->sides[!rightside].head;
30         if (leftedge->edge->movfeatpos) {
31           trace("no: lhs moveable\n");
32           goto no_extend_this;
33         }
34         if (!node->sides[rightside].head) {
35           trace("no: rhs absent\n");
36           goto no_extend_this;
37         }
38         for (rightedge= node->sides[rightside].head;
39              rightedge;
40              rightedge= rightedge->next) {
41           if (!rightedge->edge->movfeatpos) {
42             trace("no: rhs fixed ("); trace_edgeend(rightedge); trace(")\n");
43             goto no_extend_this;
44           }
45           if (strcmp(leftedge->edge->segment, rightedge->edge->segment)) {
46             trace("no: lhs seg %s, rhs seg %s (",
47                   leftedge->edge->segment
48                   rightedge->edge->segment);
49             trace_edgeend(rightedge); trace(")\n");
50             goto no_extend_this;
51           }
52         }
53         goto extend_this;
54
55       no_extend_this:;
56       }
57     }
58     return;
59
60   extend_this:
61     trace("yes, lhs "); trace_edgeend(leftedge); trace(":\n");
62     for (rightedge= node->sides[rightside].head;
63          rightedge;
64          rightedge= rightedge->next) {
65       rightedge->edge->distance += leftedge->edge->distance;
66       edge_replumb(rightedge, edgeend_otherend(leftedge)->node);
67     }
68     edge_delete(leftedge->edge);
69     node_surely_orphaned(node);
70     trace(" extendsplit operation complete\n");
71   }
72 }
73
74 static EdgeEnd *edgeend_otherend(EdgeEnd *thisend) {
75   return &thisend->edge->ends[!thisend->end];
76 }
77
78 static void elimtrivial(void) {
79   /* Eliminate trivial nodes: ones which have only two edges, which
80    * come in on opposite sides, have the same subsegspec, and with the
81    * two ends identically aligned.
82    */
83   for (node=nodes_head; node; node=next_node) {
84     next_node=node->next;
85     trace("elimtrivial node "); trace_node(node); trace(" ");
86     if (!(count_edges(&node->sides[0])==1 &&
87           count_edges(&node->sides[1])==1)) {
88       trace("no, a non-unitary side\n");
89       continue;
90     }
91     leftedge= node->sides[0].head;
92     rightedge= node->sides[0].head;
93     if (strcmp(leftedge->edge.segment,rightedge->edge.segment)) {
94       trace("no, segments differ\n");
95       continue;
96     }
97     if (!!leftedge->edge.movfeatpos != !!rightedge->edge.movfeatpos ||
98         strcmp(leftedge->edge.movfeatpos, rightedge->edge.movfeatpos)) {
99       trace("no, movfeatpos's differ\n");
100       continue;
101     }
102     if (leftedge->end == rightedge->end) {
103       trace("no, opposite alignment\n");
104       continue;
105     }
106     trace(" yes:\n");
107     rightedge->edge->distance += leftedge->edge->distance;
108     edge_replumb(rightedge, edgeend_otherend(leftedge)->node);
109     edge_delete(leftedge->edge);
110     node_surely_orphaned(node);
111     trace(" elimtrivial operation complete\n");
112   }
113