1 40 41 package org.jfree.chart.renderer; 42 43 import java.awt.Graphics2D ; 44 import java.awt.Paint ; 45 import java.awt.Shape ; 46 import java.awt.Stroke ; 47 import java.awt.geom.GeneralPath ; 48 import java.awt.geom.Line2D ; 49 import java.awt.geom.Rectangle2D ; 50 import java.io.IOException ; 51 import java.io.ObjectInputStream ; 52 import java.io.ObjectOutputStream ; 53 import java.io.Serializable ; 54 55 import org.jfree.chart.CrosshairInfo; 56 import org.jfree.chart.axis.ValueAxis; 57 import org.jfree.chart.entity.EntityCollection; 58 import org.jfree.chart.entity.XYItemEntity; 59 import org.jfree.chart.plot.PlotRenderingInfo; 60 import org.jfree.chart.plot.XYPlot; 61 import org.jfree.data.XYDataset; 62 import org.jfree.io.SerialUtilities; 63 import org.jfree.ui.RectangleEdge; 64 import org.jfree.util.PublicCloneable; 65 66 77 public class XYDifferenceRenderer extends AbstractXYItemRenderer implements XYItemRenderer, 78 Cloneable , 79 PublicCloneable, 80 Serializable { 81 82 83 private transient Paint positivePaint; 84 85 86 private transient Paint negativePaint; 87 88 89 private boolean plotShapes = true; 90 91 98 public XYDifferenceRenderer(Paint positivePaint, Paint negativePaint, boolean shapes) { 99 this.positivePaint = positivePaint; 100 this.negativePaint = negativePaint; 101 this.plotShapes = shapes; 102 } 103 104 118 public XYItemRendererState initialise(Graphics2D g2, 119 Rectangle2D dataArea, 120 XYPlot plot, 121 XYDataset data, 122 PlotRenderingInfo info) { 123 124 return super.initialise(g2, dataArea, plot, data, info); 125 126 } 127 128 134 public int getPassCount() { 135 return 2; 136 } 137 138 143 public Paint getPositivePaint() { 144 return this.positivePaint; 145 } 146 147 152 public Paint getNegativePaint() { 153 return this.positivePaint; 154 } 155 156 172 public void drawItem(Graphics2D g2, 173 XYItemRendererState state, 174 Rectangle2D dataArea, 175 PlotRenderingInfo info, 176 XYPlot plot, 177 ValueAxis domainAxis, 178 ValueAxis rangeAxis, 179 XYDataset dataset, 180 int series, 181 int item, 182 CrosshairInfo crosshairInfo, 183 int pass) { 184 185 if (pass == 0) { 186 drawItemPass0(g2, dataArea, info, plot, domainAxis, rangeAxis, dataset, 187 series, item, crosshairInfo); 188 } 189 else if (pass == 1) { 190 drawItemPass1(g2, dataArea, info, plot, domainAxis, rangeAxis, dataset, 191 series, item, crosshairInfo); 192 } 193 194 } 195 196 210 private void drawItemPass0(Graphics2D g2, 211 Rectangle2D dataArea, 212 PlotRenderingInfo info, 213 XYPlot plot, 214 ValueAxis domainAxis, 215 ValueAxis rangeAxis, 216 XYDataset dataset, 217 int series, 218 int item, 219 CrosshairInfo crosshairInfo) { 220 221 if (series == 0) { 222 223 Number y0n = dataset.getYValue(0, item); 225 Number x1n = dataset.getXValue(1, item); 226 Number y1n = dataset.getYValue(1, item); 227 228 RectangleEdge domainAxisLocation = plot.getDomainAxisEdge(); 229 RectangleEdge rangeAxisLocation = plot.getRangeAxisEdge(); 230 double y0 = y0n.doubleValue(); 231 double transY0 = rangeAxis.translateValueToJava2D(y0, dataArea, rangeAxisLocation); 232 233 double x1 = x1n.doubleValue(); 234 double y1 = y1n.doubleValue(); 235 double transX1 = domainAxis.translateValueToJava2D(x1, dataArea, domainAxisLocation); 236 double transY1 = rangeAxis.translateValueToJava2D(y1, dataArea, rangeAxisLocation); 237 238 if (item > 0) { 239 Number prevx0n = dataset.getXValue(0, item - 1); 242 Number prevy0n = dataset.getYValue(0, item - 1); 243 Number prevy1n = dataset.getYValue(1, item - 1); 244 245 double prevx0 = prevx0n.doubleValue(); 246 double prevy0 = prevy0n.doubleValue(); 247 double prevtransX0 = domainAxis.translateValueToJava2D(prevx0, dataArea, 248 domainAxisLocation); 249 double prevtransY0 = rangeAxis.translateValueToJava2D(prevy0, dataArea, 250 rangeAxisLocation); 251 252 double prevy1 = prevy1n.doubleValue(); 253 double prevtransY1 = rangeAxis.translateValueToJava2D(prevy1, dataArea, 254 rangeAxisLocation); 255 256 Shape positive = getPositiveArea((float) prevtransX0, 257 (float) prevtransY0, (float) prevtransY1, 258 (float) transX1, 259 (float) transY0, (float) transY1); 260 if (positive != null) { 261 g2.setPaint(this.positivePaint); 262 g2.fill(positive); 263 } 264 265 Shape negative = getNegativeArea((float) prevtransX0, 266 (float) prevtransY0, (float) prevtransY1, 267 (float) transX1, 268 (float) transY0, (float) transY1); 269 270 if (negative != null) { 271 g2.setPaint(this.negativePaint); 272 g2.fill(negative); 273 } 274 } 275 } 276 277 } 278 279 293 private void drawItemPass1(Graphics2D g2, 294 Rectangle2D dataArea, 295 PlotRenderingInfo info, 296 XYPlot plot, 297 ValueAxis domainAxis, 298 ValueAxis rangeAxis, 299 XYDataset dataset, 300 int series, 301 int item, 302 CrosshairInfo crosshairInfo) { 303 304 Shape entityArea = null; 305 EntityCollection entities = null; 306 if (info != null) { 307 entities = info.getOwner().getEntityCollection(); 308 } 309 310 Paint seriesPaint = getItemPaint(series, item); 311 Stroke seriesStroke = getItemStroke(series, item); 312 g2.setPaint(seriesPaint); 313 g2.setStroke(seriesStroke); 314 315 if (series == 0) { 316 317 Number x0n = dataset.getXValue(0, item); 319 Number y0n = dataset.getYValue(0, item); 320 Number x1n = dataset.getXValue(1, item); 321 Number y1n = dataset.getYValue(1, item); 322 323 RectangleEdge domainAxisLocation = plot.getDomainAxisEdge(); 324 RectangleEdge rangeAxisLocation = plot.getRangeAxisEdge(); 325 326 double x0 = x0n.doubleValue(); 327 double y0 = y0n.doubleValue(); 328 double transX0 = domainAxis.translateValueToJava2D(x0, dataArea, domainAxisLocation); 329 double transY0 = rangeAxis.translateValueToJava2D(y0, dataArea, rangeAxisLocation); 330 331 double x1 = x1n.doubleValue(); 332 double y1 = y1n.doubleValue(); 333 double transX1 = domainAxis.translateValueToJava2D(x1, dataArea, domainAxisLocation); 334 double transY1 = rangeAxis.translateValueToJava2D(y1, dataArea, rangeAxisLocation); 335 336 if (item > 0) { 337 Number prevx0n = dataset.getXValue(0, item - 1); 340 Number prevy0n = dataset.getYValue(0, item - 1); 341 Number prevx1n = dataset.getXValue(1, item - 1); 342 Number prevy1n = dataset.getYValue(1, item - 1); 343 344 double prevx0 = prevx0n.doubleValue(); 345 double prevy0 = prevy0n.doubleValue(); 346 double prevtransX0 = domainAxis.translateValueToJava2D(prevx0, dataArea, 347 domainAxisLocation); 348 double prevtransY0 = rangeAxis.translateValueToJava2D(prevy0, dataArea, 349 rangeAxisLocation); 350 351 double prevx1 = prevx1n.doubleValue(); 352 double prevy1 = prevy1n.doubleValue(); 353 double prevtransX1 = domainAxis.translateValueToJava2D(prevx1, dataArea, 354 domainAxisLocation); 355 double prevtransY1 = rangeAxis.translateValueToJava2D(prevy1, dataArea, 356 rangeAxisLocation); 357 358 Line2D line0 = new Line2D.Double (transX0, transY0, prevtransX0, prevtransY0); 359 if (line0.intersects(dataArea)) { 360 g2.setPaint(getItemPaint(series, item)); 361 g2.draw(line0); 362 } 363 Line2D line1 = new Line2D.Double (transX1, transY1, prevtransX1, prevtransY1); 364 if (line1.intersects(dataArea)) { 365 g2.setPaint(getItemPaint(1, item)); 366 g2.draw(line1); 367 } 368 } 369 370 if (this.plotShapes) { 371 Shape shape0 = getItemShape(series, item); 372 shape0 = createTransformedShape(shape0, transX0, transY0); 373 if (shape0.intersects(dataArea)) { 374 g2.setPaint(getItemPaint(series, item)); 375 g2.fill(shape0); 376 } 377 entityArea = shape0; 378 379 if (entities != null) { 381 if (entityArea == null) { 382 entityArea = new Rectangle2D.Double (transX0 - 2, transY0 - 2, 4, 4); 383 } 384 String tip = null; 385 if (getToolTipGenerator() != null) { 386 tip = getToolTipGenerator().generateToolTip(dataset, series, item); 387 } 388 String url = null; 389 if (getURLGenerator() != null) { 390 url = getURLGenerator().generateURL(dataset, series, item); 391 } 392 XYItemEntity entity = new XYItemEntity(entityArea, dataset, series, item, 393 tip, url); 394 entities.addEntity(entity); 395 } 396 397 Shape shape1 = getItemShape(series + 1, item); 398 shape1 = createTransformedShape(shape1, transX1, transY1); 399 if (shape1.intersects(dataArea)) { 400 g2.setPaint(getItemPaint(series + 1, item)); 401 g2.fill(shape1); 402 } 403 entityArea = shape1; 404 405 if (entities != null) { 407 if (entityArea == null) { 408 entityArea = new Rectangle2D.Double (transX1 - 2, transY1 - 2, 4, 4); 409 } 410 String tip = null; 411 if (getToolTipGenerator() != null) { 412 tip = getToolTipGenerator().generateToolTip(dataset, series + 1, item); 413 } 414 String url = null; 415 if (getURLGenerator() != null) { 416 url = getURLGenerator().generateURL(dataset, series + 1, item); 417 } 418 XYItemEntity entity = new XYItemEntity(entityArea, dataset, series + 1, item, 419 tip, url); 420 entities.addEntity(entity); 421 } 422 } 423 424 } 425 426 } 427 428 440 private Shape getPositiveArea(float x0, float y0A, float y0B, float x1, float y1A, float y1B) { 441 442 Shape result = null; 443 444 if (y0A >= y0B) { if (y1A >= y1B) { 446 } 448 else { 449 float[] p = getIntersection(x0, y0A, x1, y1A, x0, y0B, x1, y1B); 452 GeneralPath area = new GeneralPath (); 453 area.moveTo(x1, y1A); 454 area.lineTo(p[0], p[1]); 455 area.lineTo(x1, y1B); 456 area.closePath(); 457 result = area; 458 } 459 } 460 else { 461 if (y1A >= y1B) { 462 float[] p = getIntersection(x0, y0A, x1, y1A, x0, y0B, x1, y1B); 465 GeneralPath area = new GeneralPath (); 466 area.moveTo(x0, y0A); 467 area.lineTo(p[0], p[1]); 468 area.lineTo(x0, y0B); 469 area.closePath(); 470 result = area; 471 472 } 473 else { 474 GeneralPath area = new GeneralPath (); 476 area.moveTo(x0, y0A); 477 area.lineTo(x1, y1A); 478 area.lineTo(x1, y1B); 479 area.lineTo(x0, y0B); 480 area.closePath(); 481 result = area; 482 } 483 484 } 485 486 return result; 487 488 } 489 490 502 private Shape getNegativeArea(float x0, float y0A, float y0B, float x1, float y1A, float y1B) { 503 504 Shape result = null; 505 506 if (y0A >= y0B) { if (y1A >= y1B) { GeneralPath area = new GeneralPath (); 510 area.moveTo(x0, y0A); 511 area.lineTo(x1, y1A); 512 area.lineTo(x1, y1B); 513 area.lineTo(x0, y0B); 514 area.closePath(); 515 result = area; 516 } 517 else { 519 float[] p = getIntersection(x0, y0A, x1, y1A, x0, y0B, x1, y1B); 521 GeneralPath area = new GeneralPath (); 522 area.moveTo(x0, y0A); 523 area.lineTo(p[0], p[1]); 524 area.lineTo(x0, y0B); 525 area.closePath(); 526 result = area; 527 } 528 } 529 else { 530 if (y1A >= y1B) { 531 float[] p = getIntersection(x0, y0A, x1, y1A, x0, y0B, x1, y1B); 534 GeneralPath area = new GeneralPath (); 535 area.moveTo(x1, y1A); 536 area.lineTo(p[0], p[1]); 537 area.lineTo(x1, y1B); 538 area.closePath(); 539 result = area; 540 } 541 else { 542 } 544 545 } 546 547 return result; 548 549 } 550 551 565 private float[] getIntersection(float x1, float y1, float x2, float y2, 566 float x3, float y3, float x4, float y4) { 567 568 float n = (x4 - x3) * (y1 - y3) - (y4 - y3) * (x1 - x3); 569 float d = (y4 - y3) * (x2 - x1) - (x4 - x3) * (y2 - y1); 570 float u = n / d; 571 572 float[] result = new float[2]; 573 result[0] = x1 + u * (x2 - x1); 574 result[1] = y1 + u * (y2 - y1); 575 return result; 576 577 } 578 579 586 public Object clone() throws CloneNotSupportedException { 587 return super.clone(); 588 } 589 590 597 private void writeObject(ObjectOutputStream stream) throws IOException { 598 stream.defaultWriteObject(); 599 SerialUtilities.writePaint(this.positivePaint, stream); 600 SerialUtilities.writePaint(this.negativePaint, stream); 601 } 602 603 611 private void readObject(ObjectInputStream stream) throws IOException , ClassNotFoundException { 612 stream.defaultReadObject(); 613 this.positivePaint = SerialUtilities.readPaint(stream); 614 this.negativePaint = SerialUtilities.readPaint(stream); 615 } 616 617 } 618 | Popular Tags |