1:
52:
53: package ;
54:
55: import ;
56: import ;
57: import ;
58: import ;
59: import ;
60: import ;
61:
62: import ;
63: import ;
64: import ;
65: import ;
66: import ;
67: import ;
68: import ;
69: import ;
70: import ;
71: import ;
72: import ;
73: import ;
74:
75:
78: public class StackedXYAreaRenderer2 extends XYAreaRenderer2
79: implements Cloneable,
80: PublicCloneable,
81: Serializable {
82:
83:
84: private static final long serialVersionUID = 7752676509764539182L;
85:
86:
89: public StackedXYAreaRenderer2() {
90: this(null, null);
91: }
92:
93:
100: public StackedXYAreaRenderer2(XYToolTipGenerator labelGenerator,
101: XYURLGenerator urlGenerator) {
102: super(labelGenerator, urlGenerator);
103: }
104:
105:
114: public Range findRangeBounds(XYDataset dataset) {
115: if (dataset == null) {
116: return null;
117: }
118: double min = Double.POSITIVE_INFINITY;
119: double max = Double.NEGATIVE_INFINITY;
120: TableXYDataset d = (TableXYDataset) dataset;
121: int itemCount = d.getItemCount();
122: for (int i = 0; i < itemCount; i++) {
123: double[] stackValues = getStackValues((TableXYDataset) dataset,
124: d.getSeriesCount(), i);
125: min = Math.min(min, stackValues[0]);
126: max = Math.max(max, stackValues[1]);
127: }
128: if (min == Double.POSITIVE_INFINITY) {
129: return null;
130: }
131: return new Range(min, max);
132: }
133:
134:
139: public int getPassCount() {
140: return 1;
141: }
142:
143:
160: public void drawItem(Graphics2D g2,
161: XYItemRendererState state,
162: Rectangle2D dataArea,
163: PlotRenderingInfo info,
164: XYPlot plot,
165: ValueAxis domainAxis,
166: ValueAxis rangeAxis,
167: XYDataset dataset,
168: int series,
169: int item,
170: CrosshairState crosshairState,
171: int pass) {
172:
173:
174: Shape entityArea = null;
175: EntityCollection entities = null;
176: if (info != null) {
177: entities = info.getOwner().getEntityCollection();
178: }
179:
180: TableXYDataset tdataset = (TableXYDataset) dataset;
181:
182:
183: double x1 = dataset.getXValue(series, item);
184: double y1 = dataset.getYValue(series, item);
185: if (Double.isNaN(y1)) {
186: y1 = 0.0;
187: }
188: double[] stack1 = getStackValues(tdataset, series, item);
189:
190:
191:
192: double x0 = dataset.getXValue(series, Math.max(item - 1, 0));
193: double y0 = dataset.getYValue(series, Math.max(item - 1, 0));
194: if (Double.isNaN(y0)) {
195: y0 = 0.0;
196: }
197: double[] stack0 = getStackValues(tdataset, series, Math.max(item - 1,
198: 0));
199:
200: int itemCount = dataset.getItemCount(series);
201: double x2 = dataset.getXValue(series, Math.min(item + 1,
202: itemCount - 1));
203: double y2 = dataset.getYValue(series, Math.min(item + 1,
204: itemCount - 1));
205: if (Double.isNaN(y2)) {
206: y2 = 0.0;
207: }
208: double[] stack2 = getStackValues(tdataset, series, Math.min(item + 1,
209: itemCount - 1));
210:
211: double xleft = (x0 + x1) / 2.0;
212: double xright = (x1 + x2) / 2.0;
213: double[] stackLeft = averageStackValues(stack0, stack1);
214: double[] stackRight = averageStackValues(stack1, stack2);
215: double[] adjStackLeft = adjustedStackValues(stack0, stack1);
216: double[] adjStackRight = adjustedStackValues(stack1, stack2);
217:
218: RectangleEdge edge0 = plot.getDomainAxisEdge();
219: float transX1 = (float) domainAxis.valueToJava2D(x1, dataArea, edge0);
220: float transXLeft
221: = (float) domainAxis.valueToJava2D(xleft, dataArea, edge0);
222: float transXRight
223: = (float) domainAxis.valueToJava2D(xright, dataArea, edge0);
224: float transY1;
225:
226: RectangleEdge edge1 = plot.getRangeAxisEdge();
227:
228: GeneralPath left = new GeneralPath();
229: GeneralPath right = new GeneralPath();
230: if (y1 >= 0.0) {
231: transY1 = (float) rangeAxis.valueToJava2D(y1 + stack1[1], dataArea,
232: edge1);
233: float transStack1 = (float) rangeAxis.valueToJava2D(stack1[1],
234: dataArea, edge1);
235: float transStackLeft = (float) rangeAxis.valueToJava2D(
236: adjStackLeft[1], dataArea, edge1);
237:
238:
239: if (y0 >= 0.0) {
240: double yleft = (y0 + y1) / 2.0 + stackLeft[1];
241: float transYLeft
242: = (float) rangeAxis.valueToJava2D(yleft, dataArea, edge1);
243: left.moveTo(transX1, transY1);
244: left.lineTo(transX1, transStack1);
245: left.lineTo(transXLeft, transStackLeft);
246: left.lineTo(transXLeft, transYLeft);
247: left.closePath();
248: }
249: else {
250: left.moveTo(transX1, transStack1);
251: left.lineTo(transX1, transY1);
252: left.lineTo(transXLeft, transStackLeft);
253: left.closePath();
254: }
255:
256: float transStackRight = (float) rangeAxis.valueToJava2D(
257: adjStackRight[1], dataArea, edge1);
258:
259: if (y2 >= 0.0) {
260: double yright = (y1 + y2) / 2.0 + stackRight[1];
261: float transYRight
262: = (float) rangeAxis.valueToJava2D(yright, dataArea, edge1);
263: right.moveTo(transX1, transStack1);
264: right.lineTo(transX1, transY1);
265: right.lineTo(transXRight, transYRight);
266: right.lineTo(transXRight, transStackRight);
267: right.closePath();
268: }
269: else {
270: right.moveTo(transX1, transStack1);
271: right.lineTo(transX1, transY1);
272: right.lineTo(transXRight, transStackRight);
273: right.closePath();
274: }
275: }
276: else {
277: transY1 = (float) rangeAxis.valueToJava2D(y1 + stack1[0], dataArea,
278: edge1);
279: float transStack1 = (float) rangeAxis.valueToJava2D(stack1[0],
280: dataArea, edge1);
281: float transStackLeft = (float) rangeAxis.valueToJava2D(
282: adjStackLeft[0], dataArea, edge1);
283:
284:
285: if (y0 >= 0.0) {
286: left.moveTo(transX1, transStack1);
287: left.lineTo(transX1, transY1);
288: left.lineTo(transXLeft, transStackLeft);
289: left.clone();
290: }
291: else {
292: double yleft = (y0 + y1) / 2.0 + stackLeft[0];
293: float transYLeft = (float) rangeAxis.valueToJava2D(yleft,
294: dataArea, edge1);
295: left.moveTo(transX1, transY1);
296: left.lineTo(transX1, transStack1);
297: left.lineTo(transXLeft, transStackLeft);
298: left.lineTo(transXLeft, transYLeft);
299: left.closePath();
300: }
301: float transStackRight = (float) rangeAxis.valueToJava2D(
302: adjStackRight[0], dataArea, edge1);
303:
304:
305: if (y2 >= 0.0) {
306: right.moveTo(transX1, transStack1);
307: right.lineTo(transX1, transY1);
308: right.lineTo(transXRight, transStackRight);
309: right.closePath();
310: }
311: else {
312: double yright = (y1 + y2) / 2.0 + stackRight[0];
313: float transYRight = (float) rangeAxis.valueToJava2D(yright,
314: dataArea, edge1);
315: right.moveTo(transX1, transStack1);
316: right.lineTo(transX1, transY1);
317: right.lineTo(transXRight, transYRight);
318: right.lineTo(transXRight, transStackRight);
319: right.closePath();
320: }
321: }
322:
323:
324: Paint itemPaint = getItemPaint(series, item);
325: if (pass == 0) {
326: g2.setPaint(itemPaint);
327: g2.fill(left);
328: g2.fill(right);
329: }
330:
331:
332: if (entities != null) {
333: GeneralPath gp = new GeneralPath(left);
334: gp.append(right, false);
335: entityArea = gp;
336: addEntity(entities, entityArea, dataset, series, item,
337: transX1, transY1);
338: }
339:
340: }
341:
342:
354: private double[] getStackValues(TableXYDataset dataset,
355: int series, int index) {
356: double[] result = new double[2];
357: for (int i = 0; i < series; i++) {
358: double v = dataset.getYValue(i, index);
359: if (!Double.isNaN(v)) {
360: if (v >= 0.0) {
361: result[1] += v;
362: }
363: else {
364: result[0] += v;
365: }
366: }
367: }
368: return result;
369: }
370:
371:
379: private double[] averageStackValues(double[] stack1, double[] stack2) {
380: double[] result = new double[2];
381: result[0] = (stack1[0] + stack2[0]) / 2.0;
382: result[1] = (stack1[1] + stack2[1]) / 2.0;
383: return result;
384: }
385:
386:
394: private double[] adjustedStackValues(double[] stack1, double[] stack2) {
395: double[] result = new double[2];
396: if (stack1[0] == 0.0 || stack2[0] == 0.0) {
397: result[0] = 0.0;
398: }
399: else {
400: result[0] = (stack1[0] + stack2[0]) / 2.0;
401: }
402: if (stack1[1] == 0.0 || stack2[1] == 0.0) {
403: result[1] = 0.0;
404: }
405: else {
406: result[1] = (stack1[1] + stack2[1]) / 2.0;
407: }
408: return result;
409: }
410:
411:
418: public Object clone() throws CloneNotSupportedException {
419: return super.clone();
420: }
421:
422: }