Source code: com/port80/graph/dot/impl/VirtualChain.java
1 //
2 // Copyright(c) 2002, Chris Leung
3 //
4
5 package com.port80.graph.dot.impl;
6
7 import java.util.Comparator;
8
9 import com.port80.util.msg;
10 import com.port80.util.sprint;
11
12 /**
13 * A chain of VirtualEdge that should be routed together.
14 * Typically represents an IEdge or a portion an an IEdge (eg. a stub or a bus).
15 *
16 * The tail of a chain is the top-most VirtualVertex.
17 * The head of a chain is the bottom-most VirtualVertex.
18 *
19 * @author chrisl
20 */
21 public class VirtualChain {
22
23 ////////////////////////////////////////////////////////////////////////
24
25 private static final String NAME = "VirtualChain";
26 private static final boolean DEBUG = false;
27
28 ////////////////////////////////////////////////////////////////////////
29
30 public VirtualVertex fTail;
31 public VirtualVertex fHead;
32 public VirtualEdge fChainTail;
33 //
34 // Note that fLength and fSlack is not valid after construction, updateLength() have
35 // to be called to calcuated the current length and slack.
36 //
37 private int fSize;
38 /** Acutal chain length by summing length of all segments. */
39 private float fLength;
40 /** Slack = chain length/minimium distance between chain tail and head. */
41 private float fSlack;
42
43 ////////////////////////////////////////////////////////////////////////
44
45 VirtualChain(VirtualEdge e) {
46 while (e.prev != null)
47 e = e.prev;
48 fChainTail = e;
49 fTail = e.getTail();
50 fSize=1;
51 while (e.next != null) {
52 e = e.next;
53 ++fSize;
54 }
55 fHead = e.getHead();
56 if (DEBUG)
57 msg.println(toString());
58 }
59
60 public int size() {
61 return fSize;
62 }
63
64 public float getLength() {
65 return fLength;
66 }
67
68 public float getSlack() {
69 return fSlack;
70 }
71
72 public float updateLength() {
73 initLength();
74 return fLength;
75 }
76
77 public String toString() {
78 return (
79 "VirtualChain: "
80 + sprint.f("length=%.4f, slack=%.4f").a(fLength).a(fSlack).end()
81 + "\n\ttail="
82 + fTail
83 + "\n\thead="
84 + fHead);
85 }
86 public String toDump() {
87 StringBuffer buf=new StringBuffer(toString());
88 buf.append("\n\t"+fTail);
89 for(VirtualEdge e=fChainTail; e!=null; e=e.next) {
90 buf.append("\n\t"+e.head);
91 }
92 return buf.toString();
93 }
94
95 ////////////////////////////////////////////////////////////////////////
96
97 /**
98 * Calculate chain length base on current coordinates.
99 */
100 private VirtualVertex initLength() {
101 int xcost, ycost;
102 int dx;
103 VirtualVertex head;
104 VirtualEdge e = fChainTail;
105 VirtualVertex tail = e.getTail();
106 fLength = 0;
107 do {
108 head = e.getHead();
109 xcost = head.x - tail.x;
110 ycost = head.y - tail.y;
111 fLength += Math.sqrt(xcost * xcost + ycost * ycost);
112 tail = head;
113 e = e.next;
114 } while (e != null);
115 xcost = head.x - fTail.x;
116 ycost = head.y - fTail.y;
117 fSlack = (float) (fLength / Math.sqrt(xcost * xcost + ycost * ycost));
118 return head;
119 }
120
121 /**
122 * Comparator based on slack (length/direct distance) of the chain (Larger first).
123 */
124 public static final class PTPSlackComparator implements Comparator {
125 public int compare(Object a, Object b) {
126 VirtualChain ea = (VirtualChain) a;
127 VirtualChain eb = (VirtualChain) b;
128 if (ea.fSlack > eb.fSlack)
129 return 1;
130 if (ea.fSlack < eb.fSlack)
131 return -1;
132 return 0;
133 }
134 }
135
136 /**
137 * Sort edge in drawing order.
138 * . Edges are drawn is the following order: STUB,CRITICAL,BUS,NORMAL,FLAT,SELF
139 * . Without each type, long edges are drawn first.
140 */
141 public static final class ChainTypeComparator implements Comparator {
142
143 /** @return 1=a>b, 0=a==b, -1=a<b */
144 public int compare(Object a, Object b) {
145 // Sort by type. STUB (first),CRITICAL,NORMAL,FLAT,SELF
146 VirtualChain ca = (VirtualChain) a;
147 VirtualChain cb = (VirtualChain) b;
148 VirtualEdge ea = ca.fChainTail;
149 VirtualEdge eb = cb.fChainTail;
150 int typea = ea.getType();
151 int typeb = eb.getType();
152 if (typea != typeb)
153 return (typeb - typea);
154 // Sort by length of edge that the VirtualEdge segment
155 // represent, short first.
156 int dx = ca.fHead.x - ca.fTail.x;
157 int dy = ca.fHead.y - ca.fTail.y;
158 int dist0 = dx * dx + dy * dy;
159 dx = cb.fHead.x - cb.fTail.x;
160 dy = cb.fHead.y - cb.fTail.y;
161 int dist1 = dx * dx + dy * dy;
162 return dist0 - dist1;
163 }
164 }
165
166 ////////////////////////////////////////////////////////////////////////
167
168 }