1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24 package zeus.visualiser.statistics.charts;
25
26 import java.util.*;
27 import java.awt.*;
28 import zeus.util.*;
29 import zeus.gui.ColorManager;
30
31
32 public class LineGraph implements DrawObject {
33 protected static final int TYPE1 = 0;
34 protected static final int TYPE2 = 1;
35 protected static final double TINY = 1E-6;
36 protected static final int LEFT = 100;
37 protected static final int STEP = 5;
38 protected static final int TICK_SIZE = 10;
39 protected static final int KEY_DEPTH = 20;
40
41 protected String title;
42 protected Vector bars = new Vector();
43 protected int x, y = 0;
44 protected FontMetrics fm;
45 protected Font font;
46 protected int gap = 10;
47 protected double max = 0.0, min = 0.0, sum = 0.0;
48 protected int type = -1;
49 protected boolean[] is_valid;
50 protected String[] keys;
51
52 class Bar { double value; String label; Color color; double[] values; }
53
54 public LineGraph() {
55 }
56 public LineGraph(double[] values, String[] labels, String title) {
57 setData(values,labels,title);
58 }
59 public LineGraph(double[][] values, String[] labels, String[] keys,
60 String title) {
61 setData(values,labels,keys,title);
62 }
63
64 public void setData(double[] values, String[] labels, String title) {
65 type = TYPE1;
66 this.title = title;
67
68 int pos = 0;
69 bars.removeAllElements();
70 max = min = sum = 0.0;
71 for(int j=0;j<values.length;j++) {
72 if (Math.abs(values[j]-0.0) > TINY) {
73 max = Math.max(max,values[j]);
74 min = Math.min(min,values[j]);
75 Bar bar = new Bar();
76 bar.value = values[j];
77 bar.label = labels[j];
78 bar.color = ColorManager.getColor(pos++);
79 bars.addElement(bar);
80 }
81 }
82 }
83 public void setData(double[][] values, String[] labels,
84 String[] keys, String title) {
85 type = TYPE2;
86 this.title = title;
87
88 bars.removeAllElements();
89 max = min = sum = 0.0;
90 is_valid = new boolean[keys.length];
91 this.keys = new String[keys.length];
92 for( int i = 0; i < keys.length; i++ ) {
93 this.keys[i] = keys[i];
94 is_valid[i] = false;
95 }
96 double s;
97 for( int i = 0; i < values.length; i++ ) {
98 s = 0.0;
99 for( int j = 0; j < values[i].length; j++ ) {
100 if (Math.abs(values[i][j]-0.0) > TINY) {
101 is_valid[j] = true;
102 s += values[i][j];
103 max = Math.max(max,values[i][j]);
104 min = Math.min(min,values[i][j]);
105 }
106 }
107 if ( Math.abs(s-0.0) > TINY ) {
108 Bar bar = new Bar();
109 bar.values = new double[values[i].length];
110 for( int k = 0; k < bar.values.length; k++ )
111 bar.values[k] = values[i][k];
112 bar.label = labels[i];
113 bars.addElement(bar);
114 }
115 }
116 }
117
118 public void drawYourSelf(Graphics g) {
119 font = new Font("Arial", Font.BOLD, 14);
120 fm = g.getFontMetrics(font);
121 g.setFont(font);
122 int w = fm.stringWidth(title);
123 int h = fm.getHeight();
124 g.drawString(title,(x-w)/2,h);
125
126 if ( bars.isEmpty() ) return;
127
128 int mw = 0;
129 Bar bar;
130 font = new Font("Arial", Font.PLAIN, 12);
131 fm = g.getFontMetrics(font);
132 g.setFont(font);
133 for( int i = 0; i < bars.size(); i++ ) {
134 bar = (Bar) bars.elementAt(i);
135 mw = Math.max(mw,fm.stringWidth(bar.label));
136 }
137 mw += 10;
138 int length = (mw+gap)*bars.size();
139
140 double max_h = min > 0.0 ? max : Math.abs(max-min);
141
142 int x0 = 0, y0 = 0, x1, y1, x2, y2, xp, yp, px = 0, py = 0;
143 switch( type ) {
144 case TYPE1:
145 g.drawLine(LEFT,3*h,LEFT,y-2*h);
146 x0 = LEFT;
147 y0 = (int)(3.0*h + (max/max_h)*(y-5.0*h));
148 x1 = x0 + length;
149 y1 = y0;
150 g.drawLine(x0,y0,x1,y1);
151 g.setColor(Color.black);
152 for( int i = 0; i < bars.size(); i++ ) {
153 bar = (Bar) bars.elementAt(i);
154 x1 = x0 + (mw+gap)*i + (mw+gap)/2;
155 y1 = (int)(y0 - (bar.value/max)*(y0-3.0*h));
156 GraphicsSymbol.drawSymbol(g,0,10,x1,y1);
157 if ( i != 0 ) g.drawLine(px,py,x1,y1);
158 px = x1; py = y1;
159 w = fm.stringWidth(bar.label);
160 g.drawString(bar.label,x1-w/2,y0 + h);
161
162 }
163 break;
164 case TYPE2:
165 g.drawLine(LEFT,3*h,LEFT,y-2*h);
166 x0 = LEFT;
167 y0 = (int)(3.0*h + (max/max_h)*(y-5.0*h));
168 x1 = x0 + length;
169 y1 = y0;
170 g.drawLine(x0,y0,x1,y1);
171 for( int j = 0; j < keys.length; j++ ) {
172 for( int i = 0; i < bars.size(); i++ ) {
173 bar = (Bar) bars.elementAt(i);
174 x1 = x0 + (mw+gap)*i + (mw+gap)/2;
175 y1 = (int)(y0 - (bar.values[j]/max)*(y0-3.0*h));
176 g.setColor(ColorManager.getColor(j));
177 GraphicsSymbol.drawSymbol(g,j,10,x1,y1);
178 if ( i != 0 ) g.drawLine(px,py,x1,y1);
179 px = x1; py = y1;
180 }
181 }
182 for( int i = 0; i < bars.size(); i++ ) {
183 bar = (Bar) bars.elementAt(i);
184 x1 = x0 + (mw+gap)*i + (mw+gap)/2;
185 w = fm.stringWidth(bar.label);
186 g.setColor(Color.black);
187 g.drawString(bar.label,x1-w/2,y0+h);
188 }
189 break;
190 default:
191 return;
192 }
193
194 double v, dv;
195 dv = (max/STEP);
196 dv = ((int)(dv+0.51) == 0) ? dv : (double)((int)(dv+0.51));
197 int step = (int)((y0-3.0*h)*dv/max);
198 g.setColor(Color.black);
199 v = 0.0;
200 xp = x0; yp = y0;
201 while( v-TINY <= max ) {
202 String yval = Misc.decimalPlaces(v,2);
203 g.drawLine(xp,yp,xp-TICK_SIZE,yp);
204 w = fm.stringWidth(yval);
205 g.drawString(yval,xp-TICK_SIZE-w-5,yp);
206 v += dv;
207 yp -= step;
208 }
209 if ( min < 0.0 ) {
210 v = -dv;
211 xp = x0; yp = y0 + step;
212 while( v > min ) {
213 String yval = Misc.decimalPlaces(v,2);
214 g.drawLine(xp,yp,xp-TICK_SIZE,yp);
215 w = fm.stringWidth(yval);
216 g.drawString(yval,xp-TICK_SIZE-w-5,yp);
217 v -= dv;
218 yp += step;
219 }
220 }
221
222 if ( type == TYPE2 ) {
223 x1 = x0 + length + LEFT; y1 = 3*h;
224 h = fm.getHeight();
225 int dh = Math.max(h+10,KEY_DEPTH);
226 g.setColor(Color.black);
227 g.drawString("Key",x1,y1);
228 for( int i = 0; i < keys.length; i++ ) {
229 if ( is_valid[i] ) {
230 y1 += dh;
231 g.setColor(ColorManager.getColor(i));
232 GraphicsSymbol.drawSymbol(g,i,10,x1+(dh-3)/2,y1+(dh-3)/2);
233 g.setColor(Color.black);
234 g.drawString(keys[i],x1+dh,y1+(dh-3)/2);
235 }
236 }
237 }
238 }
239 public void setXY(int xc, int yc) {
240 x = xc; y = yc;
241 }
242
243 }