1 56 57 package org.jfree.chart.renderer.xy; 58 59 import java.awt.Graphics2D ; 60 import java.awt.Paint ; 61 import java.awt.Shape ; 62 import java.awt.geom.GeneralPath ; 63 import java.awt.geom.Rectangle2D ; 64 import java.io.Serializable ; 65 66 import org.jfree.chart.axis.ValueAxis; 67 import org.jfree.chart.entity.EntityCollection; 68 import org.jfree.chart.labels.XYToolTipGenerator; 69 import org.jfree.chart.plot.CrosshairState; 70 import org.jfree.chart.plot.PlotRenderingInfo; 71 import org.jfree.chart.plot.XYPlot; 72 import org.jfree.chart.urls.XYURLGenerator; 73 import org.jfree.data.Range; 74 import org.jfree.data.xy.TableXYDataset; 75 import org.jfree.data.xy.XYDataset; 76 import org.jfree.ui.RectangleEdge; 77 import org.jfree.util.PublicCloneable; 78 79 82 public class StackedXYAreaRenderer2 extends XYAreaRenderer2 83 implements Cloneable , 84 PublicCloneable, 85 Serializable { 86 87 88 private static final long serialVersionUID = 7752676509764539182L; 89 90 99 private boolean roundXCoordinates = false; 100 101 104 public StackedXYAreaRenderer2() { 105 this(null, null); 106 } 107 108 115 public StackedXYAreaRenderer2(XYToolTipGenerator labelGenerator, 116 XYURLGenerator urlGenerator) { 117 super(labelGenerator, urlGenerator); 118 } 119 120 129 public Range findRangeBounds(XYDataset dataset) { 130 if (dataset == null) { 131 return null; 132 } 133 double min = Double.POSITIVE_INFINITY; 134 double max = Double.NEGATIVE_INFINITY; 135 TableXYDataset d = (TableXYDataset) dataset; 136 int itemCount = d.getItemCount(); 137 for (int i = 0; i < itemCount; i++) { 138 double[] stackValues = getStackValues((TableXYDataset) dataset, 139 d.getSeriesCount(), i); 140 min = Math.min(min, stackValues[0]); 141 max = Math.max(max, stackValues[1]); 142 } 143 if (min == Double.POSITIVE_INFINITY) { 144 return null; 145 } 146 return new Range(min, max); 147 } 148 149 154 public int getPassCount() { 155 return 1; 156 } 157 158 175 public void drawItem(Graphics2D g2, 176 XYItemRendererState state, 177 Rectangle2D dataArea, 178 PlotRenderingInfo info, 179 XYPlot plot, 180 ValueAxis domainAxis, 181 ValueAxis rangeAxis, 182 XYDataset dataset, 183 int series, 184 int item, 185 CrosshairState crosshairState, 186 int pass) { 187 188 Shape entityArea = null; 190 EntityCollection entities = null; 191 if (info != null) { 192 entities = info.getOwner().getEntityCollection(); 193 } 194 195 TableXYDataset tdataset = (TableXYDataset) dataset; 196 197 double x1 = dataset.getXValue(series, item); 199 double y1 = dataset.getYValue(series, item); 200 if (Double.isNaN(y1)) { 201 y1 = 0.0; 202 } 203 double[] stack1 = getStackValues(tdataset, series, item); 204 205 double x0 = dataset.getXValue(series, Math.max(item - 1, 0)); 208 double y0 = dataset.getYValue(series, Math.max(item - 1, 0)); 209 if (Double.isNaN(y0)) { 210 y0 = 0.0; 211 } 212 double[] stack0 = getStackValues(tdataset, series, Math.max(item - 1, 213 0)); 214 215 int itemCount = dataset.getItemCount(series); 216 double x2 = dataset.getXValue(series, Math.min(item + 1, 217 itemCount - 1)); 218 double y2 = dataset.getYValue(series, Math.min(item + 1, 219 itemCount - 1)); 220 if (Double.isNaN(y2)) { 221 y2 = 0.0; 222 } 223 double[] stack2 = getStackValues(tdataset, series, Math.min(item + 1, 224 itemCount - 1)); 225 226 double xleft = (x0 + x1) / 2.0; 227 double xright = (x1 + x2) / 2.0; 228 double[] stackLeft = averageStackValues(stack0, stack1); 229 double[] stackRight = averageStackValues(stack1, stack2); 230 double[] adjStackLeft = adjustedStackValues(stack0, stack1); 231 double[] adjStackRight = adjustedStackValues(stack1, stack2); 232 233 RectangleEdge edge0 = plot.getDomainAxisEdge(); 234 235 float transX1 = (float) domainAxis.valueToJava2D(x1, dataArea, edge0); 236 float transXLeft = (float) domainAxis.valueToJava2D(xleft, dataArea, 237 edge0); 238 float transXRight = (float) domainAxis.valueToJava2D(xright, dataArea, 239 edge0); 240 241 if (this.roundXCoordinates) { 242 transX1 = Math.round(transX1); 243 transXLeft = Math.round(transXLeft); 244 transXRight = Math.round(transXRight); 245 } 246 float transY1; 247 248 RectangleEdge edge1 = plot.getRangeAxisEdge(); 249 250 GeneralPath left = new GeneralPath (); 251 GeneralPath right = new GeneralPath (); 252 if (y1 >= 0.0) { transY1 = (float) rangeAxis.valueToJava2D(y1 + stack1[1], dataArea, 254 edge1); 255 float transStack1 = (float) rangeAxis.valueToJava2D(stack1[1], 256 dataArea, edge1); 257 float transStackLeft = (float) rangeAxis.valueToJava2D( 258 adjStackLeft[1], dataArea, edge1); 259 260 if (y0 >= 0.0) { 262 double yleft = (y0 + y1) / 2.0 + stackLeft[1]; 263 float transYLeft 264 = (float) rangeAxis.valueToJava2D(yleft, dataArea, edge1); 265 left.moveTo(transX1, transY1); 266 left.lineTo(transX1, transStack1); 267 left.lineTo(transXLeft, transStackLeft); 268 left.lineTo(transXLeft, transYLeft); 269 left.closePath(); 270 } 271 else { 272 left.moveTo(transX1, transStack1); 273 left.lineTo(transX1, transY1); 274 left.lineTo(transXLeft, transStackLeft); 275 left.closePath(); 276 } 277 278 float transStackRight = (float) rangeAxis.valueToJava2D( 279 adjStackRight[1], dataArea, edge1); 280 if (y2 >= 0.0) { 282 double yright = (y1 + y2) / 2.0 + stackRight[1]; 283 float transYRight 284 = (float) rangeAxis.valueToJava2D(yright, dataArea, edge1); 285 right.moveTo(transX1, transStack1); 286 right.lineTo(transX1, transY1); 287 right.lineTo(transXRight, transYRight); 288 right.lineTo(transXRight, transStackRight); 289 right.closePath(); 290 } 291 else { 292 right.moveTo(transX1, transStack1); 293 right.lineTo(transX1, transY1); 294 right.lineTo(transXRight, transStackRight); 295 right.closePath(); 296 } 297 } 298 else { transY1 = (float) rangeAxis.valueToJava2D(y1 + stack1[0], dataArea, 300 edge1); 301 float transStack1 = (float) rangeAxis.valueToJava2D(stack1[0], 302 dataArea, edge1); 303 float transStackLeft = (float) rangeAxis.valueToJava2D( 304 adjStackLeft[0], dataArea, edge1); 305 306 if (y0 >= 0.0) { 308 left.moveTo(transX1, transStack1); 309 left.lineTo(transX1, transY1); 310 left.lineTo(transXLeft, transStackLeft); 311 left.clone(); 312 } 313 else { 314 double yleft = (y0 + y1) / 2.0 + stackLeft[0]; 315 float transYLeft = (float) rangeAxis.valueToJava2D(yleft, 316 dataArea, edge1); 317 left.moveTo(transX1, transY1); 318 left.lineTo(transX1, transStack1); 319 left.lineTo(transXLeft, transStackLeft); 320 left.lineTo(transXLeft, transYLeft); 321 left.closePath(); 322 } 323 float transStackRight = (float) rangeAxis.valueToJava2D( 324 adjStackRight[0], dataArea, edge1); 325 326 if (y2 >= 0.0) { 328 right.moveTo(transX1, transStack1); 329 right.lineTo(transX1, transY1); 330 right.lineTo(transXRight, transStackRight); 331 right.closePath(); 332 } 333 else { 334 double yright = (y1 + y2) / 2.0 + stackRight[0]; 335 float transYRight = (float) rangeAxis.valueToJava2D(yright, 336 dataArea, edge1); 337 right.moveTo(transX1, transStack1); 338 right.lineTo(transX1, transY1); 339 right.lineTo(transXRight, transYRight); 340 right.lineTo(transXRight, transStackRight); 341 right.closePath(); 342 } 343 } 344 345 Paint itemPaint = getItemPaint(series, item); 347 if (pass == 0) { 348 g2.setPaint(itemPaint); 349 g2.fill(left); 350 g2.fill(right); 351 } 352 353 if (entities != null) { 355 GeneralPath gp = new GeneralPath (left); 356 gp.append(right, false); 357 entityArea = gp; 358 addEntity(entities, entityArea, dataset, series, item, 359 transX1, transY1); 360 } 361 362 } 363 364 376 private double[] getStackValues(TableXYDataset dataset, 377 int series, int index) { 378 double[] result = new double[2]; 379 for (int i = 0; i < series; i++) { 380 double v = dataset.getYValue(i, index); 381 if (!Double.isNaN(v)) { 382 if (v >= 0.0) { 383 result[1] += v; 384 } 385 else { 386 result[0] += v; 387 } 388 } 389 } 390 return result; 391 } 392 393 401 private double[] averageStackValues(double[] stack1, double[] stack2) { 402 double[] result = new double[2]; 403 result[0] = (stack1[0] + stack2[0]) / 2.0; 404 result[1] = (stack1[1] + stack2[1]) / 2.0; 405 return result; 406 } 407 408 416 private double[] adjustedStackValues(double[] stack1, double[] stack2) { 417 double[] result = new double[2]; 418 if (stack1[0] == 0.0 || stack2[0] == 0.0) { 419 result[0] = 0.0; 420 } 421 else { 422 result[0] = (stack1[0] + stack2[0]) / 2.0; 423 } 424 if (stack1[1] == 0.0 || stack2[1] == 0.0) { 425 result[1] = 0.0; 426 } 427 else { 428 result[1] = (stack1[1] + stack2[1]) / 2.0; 429 } 430 return result; 431 } 432 433 440 public Object clone() throws CloneNotSupportedException { 441 return super.clone(); 442 } 443 444 } 445 | Popular Tags |