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 Histogram 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 Histogram() {
55 }
56 public Histogram(double[] values, String[] labels, String title) {
57 setData(values,labels,title);
58 }
59
60 public Histogram(double[][] values, String[] labels, String[] keys,
61 String title) {
62 setData(values,labels,keys,title);
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 }
104 }
105 max = Math.max(max,s);
106 min = Math.min(min,s);
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
119 public void drawYourSelf(Graphics g) {
120 font = new Font("Arial", Font.BOLD, 14);
121 fm = g.getFontMetrics(font);
122 g.setFont(font);
123 int w = fm.stringWidth(title);
124 int h = fm.getHeight();
125 g.drawString(title,(x-w)/2,h);
126
127 if ( bars.isEmpty() ) return;
128
129 int mw = 0;
130 Bar bar;
131 font = new Font("Arial", Font.PLAIN, 12);
132 fm = g.getFontMetrics(font);
133 g.setFont(font);
134 for( int i = 0; i < bars.size(); i++ ) {
135 bar = (Bar) bars.elementAt(i);
136 mw = Math.max(mw,fm.stringWidth(bar.label));
137 }
138 mw += 10;
139 int length = (mw+gap)*bars.size();
140
141 double max_h = min > 0.0 ? max : Math.abs(max-min);
142
143 int x0 = 0, y0 = 0, x1, y1, x2, y2, xp, yp;
144 switch( type ) {
145 case TYPE1:
146 g.drawLine(LEFT,3*h,LEFT,y-2*h);
147 x0 = LEFT;
148 y0 = (int)(3.0*h + (max/max_h)*(y-5.0*h));
149 x1 = x0 + length;
150 y1 = y0;
151 g.drawLine(x0,y0,x1,y1);
152 y1 = y0;
153 for( int i = 0; i < bars.size(); i++ ) {
154 bar = (Bar) bars.elementAt(i);
155 x1 = x0 + (mw+gap)*i + gap/2;
156 x2 = x1 + (mw+gap) - gap/2;
157 y2 = (int)(y0 - (bar.value/max)*(y0-3.0*h));
158 g.setColor(bar.color);
159 g.fillRect(Math.min(x1,x2),Math.min(y1,y2),
160 Math.abs(x2-x1),Math.abs(y2-y1));
161
162 w = fm.stringWidth(bar.label);
163 yp = bar.value > 0.0 ? y1 + h : y1 - h;
164 g.setColor(Color.black);
165 g.drawString(bar.label,x1+(mw+gap-w)/2,yp);
166 }
167 break;
168 case TYPE2:
169 g.drawLine(LEFT,3*h,LEFT,y-2*h);
170 x0 = LEFT;
171 y0 = (int)(3.0*h + (max/max_h)*(y-5.0*h));
172 x1 = x0 + length;
173 y1 = y0;
174 g.drawLine(x0,y0,x1,y1);
175 for( int i = 0; i < bars.size(); i++ ) {
176 bar = (Bar) bars.elementAt(i);
177 x1 = x0 + (mw+gap)*i + gap/2;
178 x2 = x1 + (mw+gap) - gap/2;
179 double yval = 0;
180 y2 = y1 = y0;
181 for( int j = 0; j < bar.values.length; j++ ) {
182 yval += bar.values[j];
183 y1 = y2;
184 y2 = (int)(y0 - (yval/max)*(y0-3.0*h));
185 g.setColor(ColorManager.getColor(j));
186 g.fillRect(Math.min(x1,x2),Math.min(y1,y2),
187 Math.abs(x2-x1),Math.abs(y2-y1));
188 }
189 w = fm.stringWidth(bar.label);
190 yp = yval > 0.0 ? y0 + h : y0 - h;
191 g.setColor(Color.black);
192 g.drawString(bar.label,x1+(mw+gap-w)/2,yp);
193 }
194 break;
195 default:
196 return;
197 }
198
199 double v, dv;
200 dv = (max/STEP);
201 dv = ((int)(dv+0.51) == 0) ? dv : (double)((int)(dv+0.51));
202 int step = (int)((y0-3.0*h)*dv/max);
203 g.setColor(Color.black);
204 v = 0.0;
205 xp = x0; yp = y0;
206 while( v-TINY <= max ) {
207 String yval = Double.toString(v);
208 yval = Misc.decimalPlaces(yval,2);
209 g.drawLine(xp,yp,xp-TICK_SIZE,yp);
210 w = fm.stringWidth(yval);
211 g.drawString(yval,xp-TICK_SIZE-w-5,yp);
212 v += dv;
213 yp -= step;
214 }
215 if ( min < 0.0 ) {
216 v = -dv;
217 xp = x0; yp = y0 + step;
218 while( v > min ) {
219 String yval = Double.toString(v);
220 yval = Misc.decimalPlaces(yval,2);
221 g.drawLine(xp,yp,xp-TICK_SIZE,yp);
222 w = fm.stringWidth(yval);
223 g.drawString(yval,xp-TICK_SIZE-w-5,yp);
224 v -= dv;
225 yp += step;
226 }
227 }
228
229 if ( type == TYPE2 ) {
230 x1 = x0 + length + LEFT; y1 = 3*h;
231 h = fm.getHeight();
232 int dh = Math.max(h+10,KEY_DEPTH);
233 g.setColor(Color.black);
234 g.drawString("Key",x1,y1);
235 for( int i = 0; i < keys.length; i++ ) {
236 if ( is_valid[i] ) {
237 y1 += dh;
238 g.setColor(ColorManager.getColor(i));
239 g.fillRect(x1,y1,dh-3,dh-3);
240 g.setColor(Color.black);
241 g.drawString(keys[i],x1+dh,y1+(dh-3)/2);
242 }
243 }
244 }
245 }
246
247 public void setXY(int xc, int yc) {
248 x = xc; y = yc;
249 }
250 }